summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve French <smfrench@gmail.com>2021-07-02 09:58:21 -0500
committerGitHub <noreply@github.com>2021-07-02 09:58:21 -0500
commitae9d84d6f1b1012a7829c03b9a318f499dc7719d (patch)
tree0db387e95eb0372e4e6ebb6304671603d0c9690a
parentbe8bcf8baaec8e063da56797dda48075bb8198d2 (diff)
parentaf34983e831587472333e47c86a350a2360c6093 (diff)
Merge pull request #56 from namjaejeon/cifsd-for-next
ksmbd-fixes
-rw-r--r--Documentation/filesystems/cifs/index.rst2
-rw-r--r--Documentation/filesystems/cifs/ksmbd.rst (renamed from Documentation/filesystems/cifs/cifsd.rst)10
-rw-r--r--MAINTAINERS19
-rw-r--r--fs/Kconfig2
-rw-r--r--fs/Makefile2
-rw-r--r--fs/cifsd/buffer_pool.c265
-rw-r--r--fs/cifsd/buffer_pool.h17
-rw-r--r--fs/ksmbd/Kconfig (renamed from fs/cifsd/Kconfig)15
-rw-r--r--fs/ksmbd/Makefile (renamed from fs/cifsd/Makefile)4
-rw-r--r--fs/ksmbd/asn1.c (renamed from fs/cifsd/asn1.c)3
-rw-r--r--fs/ksmbd/asn1.h (renamed from fs/cifsd/asn1.h)0
-rw-r--r--fs/ksmbd/auth.c (renamed from fs/cifsd/auth.c)49
-rw-r--r--fs/ksmbd/auth.h (renamed from fs/cifsd/auth.h)6
-rw-r--r--fs/ksmbd/connection.c (renamed from fs/cifsd/connection.c)16
-rw-r--r--fs/ksmbd/connection.h (renamed from fs/cifsd/connection.h)1
-rw-r--r--fs/ksmbd/crypto_ctx.c (renamed from fs/cifsd/crypto_ctx.c)5
-rw-r--r--fs/ksmbd/crypto_ctx.h (renamed from fs/cifsd/crypto_ctx.h)0
-rw-r--r--fs/ksmbd/glob.h (renamed from fs/cifsd/glob.h)29
-rw-r--r--fs/ksmbd/ksmbd_netlink.h (renamed from fs/cifsd/ksmbd_server.h)236
-rw-r--r--fs/ksmbd/ksmbd_spnego_negtokeninit.asn1 (renamed from fs/cifsd/ksmbd_spnego_negtokeninit.asn1)0
-rw-r--r--fs/ksmbd/ksmbd_spnego_negtokentarg.asn1 (renamed from fs/cifsd/ksmbd_spnego_negtokentarg.asn1)0
-rw-r--r--fs/ksmbd/ksmbd_work.c (renamed from fs/cifsd/ksmbd_work.c)17
-rw-r--r--fs/ksmbd/ksmbd_work.h (renamed from fs/cifsd/ksmbd_work.h)27
-rw-r--r--fs/ksmbd/mgmt/ksmbd_ida.c (renamed from fs/cifsd/mgmt/ksmbd_ida.c)0
-rw-r--r--fs/ksmbd/mgmt/ksmbd_ida.h (renamed from fs/cifsd/mgmt/ksmbd_ida.h)0
-rw-r--r--fs/ksmbd/mgmt/share_config.c (renamed from fs/cifsd/mgmt/share_config.c)3
-rw-r--r--fs/ksmbd/mgmt/share_config.h (renamed from fs/cifsd/mgmt/share_config.h)0
-rw-r--r--fs/ksmbd/mgmt/tree_connect.c (renamed from fs/cifsd/mgmt/tree_connect.c)1
-rw-r--r--fs/ksmbd/mgmt/tree_connect.h (renamed from fs/cifsd/mgmt/tree_connect.h)2
-rw-r--r--fs/ksmbd/mgmt/user_config.c (renamed from fs/cifsd/mgmt/user_config.c)1
-rw-r--r--fs/ksmbd/mgmt/user_config.h (renamed from fs/cifsd/mgmt/user_config.h)0
-rw-r--r--fs/ksmbd/mgmt/user_session.c (renamed from fs/cifsd/mgmt/user_session.c)77
-rw-r--r--fs/ksmbd/mgmt/user_session.h (renamed from fs/cifsd/mgmt/user_session.h)11
-rw-r--r--fs/ksmbd/misc.c (renamed from fs/cifsd/misc.c)2
-rw-r--r--fs/ksmbd/misc.h (renamed from fs/cifsd/misc.h)0
-rw-r--r--fs/ksmbd/ndr.c (renamed from fs/cifsd/ndr.c)72
-rw-r--r--fs/ksmbd/ndr.h (renamed from fs/cifsd/ndr.h)4
-rw-r--r--fs/ksmbd/nterr.h (renamed from fs/cifsd/nterr.h)0
-rw-r--r--fs/ksmbd/ntlmssp.h (renamed from fs/cifsd/ntlmssp.h)0
-rw-r--r--fs/ksmbd/oplock.c (renamed from fs/cifsd/oplock.c)39
-rw-r--r--fs/ksmbd/oplock.h (renamed from fs/cifsd/oplock.h)6
-rw-r--r--fs/ksmbd/server.c (renamed from fs/cifsd/server.c)24
-rw-r--r--fs/ksmbd/server.h (renamed from fs/cifsd/server.h)26
-rw-r--r--fs/ksmbd/smb2misc.c (renamed from fs/cifsd/smb2misc.c)14
-rw-r--r--fs/ksmbd/smb2ops.c (renamed from fs/cifsd/smb2ops.c)10
-rw-r--r--fs/ksmbd/smb2pdu.c (renamed from fs/cifsd/smb2pdu.c)754
-rw-r--r--fs/ksmbd/smb2pdu.h (renamed from fs/cifsd/smb2pdu.h)3
-rw-r--r--fs/ksmbd/smb_common.c (renamed from fs/cifsd/smb_common.c)13
-rw-r--r--fs/ksmbd/smb_common.h (renamed from fs/cifsd/smb_common.h)15
-rw-r--r--fs/ksmbd/smbacl.c (renamed from fs/cifsd/smbacl.c)147
-rw-r--r--fs/ksmbd/smbacl.h (renamed from fs/cifsd/smbacl.h)50
-rw-r--r--fs/ksmbd/smbfsctl.h (renamed from fs/cifsd/smbfsctl.h)0
-rw-r--r--fs/ksmbd/smbstatus.h (renamed from fs/cifsd/smbstatus.h)0
-rw-r--r--fs/ksmbd/transport_ipc.c (renamed from fs/cifsd/transport_ipc.c)66
-rw-r--r--fs/ksmbd/transport_ipc.h (renamed from fs/cifsd/transport_ipc.h)0
-rw-r--r--fs/ksmbd/transport_rdma.c (renamed from fs/cifsd/transport_rdma.c)141
-rw-r--r--fs/ksmbd/transport_rdma.h (renamed from fs/cifsd/transport_rdma.h)0
-rw-r--r--fs/ksmbd/transport_tcp.c (renamed from fs/cifsd/transport_tcp.c)21
-rw-r--r--fs/ksmbd/transport_tcp.h (renamed from fs/cifsd/transport_tcp.h)0
-rw-r--r--fs/ksmbd/unicode.c (renamed from fs/cifsd/unicode.c)0
-rw-r--r--fs/ksmbd/unicode.h (renamed from fs/cifsd/unicode.h)0
-rw-r--r--fs/ksmbd/uniupr.h (renamed from fs/cifsd/uniupr.h)0
-rw-r--r--fs/ksmbd/vfs.c (renamed from fs/cifsd/vfs.c)620
-rw-r--r--fs/ksmbd/vfs.h (renamed from fs/cifsd/vfs.h)162
-rw-r--r--fs/ksmbd/vfs_cache.c (renamed from fs/cifsd/vfs_cache.c)70
-rw-r--r--fs/ksmbd/vfs_cache.h (renamed from fs/cifsd/vfs_cache.h)11
-rw-r--r--fs/ksmbd/xattr.h122
67 files changed, 1580 insertions, 1632 deletions
diff --git a/Documentation/filesystems/cifs/index.rst b/Documentation/filesystems/cifs/index.rst
index e762586b5dc7..1c8597a679ab 100644
--- a/Documentation/filesystems/cifs/index.rst
+++ b/Documentation/filesystems/cifs/index.rst
@@ -6,5 +6,5 @@ CIFS
.. toctree::
:maxdepth: 1
- cifsd
+ ksmbd
cifsroot
diff --git a/Documentation/filesystems/cifs/cifsd.rst b/Documentation/filesystems/cifs/ksmbd.rst
index 01a0be272ce6..1e111efecd45 100644
--- a/Documentation/filesystems/cifs/cifsd.rst
+++ b/Documentation/filesystems/cifs/ksmbd.rst
@@ -1,13 +1,13 @@
.. SPDX-License-Identifier: GPL-2.0
==========================
-CIFSD - SMB3 Kernel Server
+KSMBD - SMB3 Kernel Server
==========================
-CIFSD is a linux kernel server which implements SMB3 protocol in kernel space
+KSMBD is a linux kernel server which implements SMB3 protocol in kernel space
for sharing files over network.
-CIFSD architecture
+KSMBD architecture
==================
The subset of performance related operations belong in kernelspace and
@@ -60,7 +60,7 @@ NetServerGetInfo. Complete DCE/RPC response is prepared from the user space
and passed over to the associated kernel thread for the client.
-CIFSD Feature Status
+KSMBD Feature Status
====================
============================== =================================================
@@ -138,7 +138,7 @@ How to run
6. Access share from Windows or Linux using CIFS
-Shutdown CIFSD
+Shutdown KSMBD
==============
1. kill user and kernel space daemon
diff --git a/MAINTAINERS b/MAINTAINERS
index f23bb5cbfd70..6691ac75fce5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4540,16 +4540,6 @@ T: git git://git.samba.org/sfrench/cifs-2.6.git
F: Documentation/admin-guide/cifs/
F: fs/cifs/
-COMMON INTERNET FILE SYSTEM SERVER (CIFSD)
-M: Namjae Jeon <namjae.jeon@samsung.com>
-M: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
-M: Steve French <sfrench@samba.org>
-M: Hyunchul Lee <hyc.lee@gmail.com>
-L: linux-cifs@vger.kernel.org
-L: linux-cifsd-devel@lists.sourceforge.net
-S: Maintained
-F: fs/cifsd/
-
COMPACTPCI HOTPLUG CORE
M: Scott Murray <scott@spiteful.org>
L: linux-pci@vger.kernel.org
@@ -9948,6 +9938,15 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest.git
F: Documentation/dev-tools/kselftest*
F: tools/testing/selftests/
+KERNEL SMB3 SERVER (KSMBD)
+M: Namjae Jeon <namjae.jeon@samsung.com>
+M: Sergey Senozhatsky <senozhatsky@chromium.org>
+M: Steve French <sfrench@samba.org>
+M: Hyunchul Lee <hyc.lee@gmail.com>
+L: linux-cifs@vger.kernel.org
+S: Maintained
+F: fs/ksmbd/
+
KERNEL UNIT TESTING FRAMEWORK (KUnit)
M: Brendan Higgins <brendanhiggins@google.com>
L: linux-kselftest@vger.kernel.org
diff --git a/fs/Kconfig b/fs/Kconfig
index 7462761ebd2f..720c38f484c6 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -344,7 +344,7 @@ config NFS_V4_2_SSC_HELPER
source "net/sunrpc/Kconfig"
source "fs/ceph/Kconfig"
source "fs/cifs/Kconfig"
-source "fs/cifsd/Kconfig"
+source "fs/ksmbd/Kconfig"
source "fs/coda/Kconfig"
source "fs/afs/Kconfig"
source "fs/9p/Kconfig"
diff --git a/fs/Makefile b/fs/Makefile
index 542a77374d12..e03a048b2cd8 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -98,7 +98,7 @@ obj-$(CONFIG_NLS) += nls/
obj-$(CONFIG_UNICODE) += unicode/
obj-$(CONFIG_SYSV_FS) += sysv/
obj-$(CONFIG_CIFS) += cifs/
-obj-$(CONFIG_SMB_SERVER) += cifsd/
+obj-$(CONFIG_SMB_SERVER) += ksmbd/
obj-$(CONFIG_HPFS_FS) += hpfs/
obj-$(CONFIG_NTFS_FS) += ntfs/
obj-$(CONFIG_UFS_FS) += ufs/
diff --git a/fs/cifsd/buffer_pool.c b/fs/cifsd/buffer_pool.c
deleted file mode 100644
index ea7d2d1a056a..000000000000
--- a/fs/cifsd/buffer_pool.c
+++ /dev/null
@@ -1,265 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2018 Samsung Electronics Co., Ltd.
- */
-
-#include <linux/kernel.h>
-#include <linux/wait.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/rwlock.h>
-
-#include "glob.h"
-#include "buffer_pool.h"
-#include "connection.h"
-#include "mgmt/ksmbd_ida.h"
-
-static struct kmem_cache *filp_cache;
-
-struct wm {
- struct list_head list;
- unsigned int sz;
- char buffer[0];
-};
-
-struct wm_list {
- struct list_head list;
- unsigned int sz;
-
- spinlock_t wm_lock;
- int avail_wm;
- struct list_head idle_wm;
- wait_queue_head_t wm_wait;
-};
-
-static LIST_HEAD(wm_lists);
-static DEFINE_RWLOCK(wm_lists_lock);
-
-static struct wm *wm_alloc(size_t sz, gfp_t flags)
-{
- struct wm *wm;
- size_t alloc_sz = sz + sizeof(struct wm);
-
- if (sz > SIZE_MAX - sizeof(struct wm))
- return NULL;
-
- wm = kvmalloc(alloc_sz, flags);
- if (!wm)
- return NULL;
- wm->sz = sz;
- return wm;
-}
-
-static int register_wm_size_class(size_t sz)
-{
- struct wm_list *l, *nl;
-
- nl = kmalloc(sizeof(struct wm_list), GFP_KERNEL);
- if (!nl)
- return -ENOMEM;
-
- nl->sz = sz;
- spin_lock_init(&nl->wm_lock);
- INIT_LIST_HEAD(&nl->idle_wm);
- INIT_LIST_HEAD(&nl->list);
- init_waitqueue_head(&nl->wm_wait);
- nl->avail_wm = 0;
-
- write_lock(&wm_lists_lock);
- list_for_each_entry(l, &wm_lists, list) {
- if (l->sz == sz) {
- write_unlock(&wm_lists_lock);
- kfree(nl);
- return 0;
- }
- }
-
- list_add(&nl->list, &wm_lists);
- write_unlock(&wm_lists_lock);
- return 0;
-}
-
-static struct wm_list *match_wm_list(size_t size)
-{
- struct wm_list *l, *rl = NULL;
-
- read_lock(&wm_lists_lock);
- list_for_each_entry(l, &wm_lists, list) {
- if (l->sz == size) {
- rl = l;
- break;
- }
- }
- read_unlock(&wm_lists_lock);
- return rl;
-}
-
-static struct wm *find_wm(size_t size)
-{
- struct wm_list *wm_list;
- struct wm *wm;
-
- wm_list = match_wm_list(size);
- if (!wm_list) {
- if (register_wm_size_class(size))
- return NULL;
- wm_list = match_wm_list(size);
- }
-
- if (!wm_list)
- return NULL;
-
- while (1) {
- spin_lock(&wm_list->wm_lock);
- if (!list_empty(&wm_list->idle_wm)) {
- wm = list_entry(wm_list->idle_wm.next,
- struct wm,
- list);
- list_del(&wm->list);
- spin_unlock(&wm_list->wm_lock);
- return wm;
- }
-
- if (wm_list->avail_wm > num_online_cpus()) {
- spin_unlock(&wm_list->wm_lock);
- wait_event(wm_list->wm_wait,
- !list_empty(&wm_list->idle_wm));
- continue;
- }
-
- wm_list->avail_wm++;
- spin_unlock(&wm_list->wm_lock);
-
- wm = wm_alloc(size, GFP_KERNEL);
- if (!wm) {
- spin_lock(&wm_list->wm_lock);
- wm_list->avail_wm--;
- spin_unlock(&wm_list->wm_lock);
- wait_event(wm_list->wm_wait,
- !list_empty(&wm_list->idle_wm));
- continue;
- }
- break;
- }
-
- return wm;
-}
-
-static void release_wm(struct wm *wm, struct wm_list *wm_list)
-{
- if (!wm)
- return;
-
- spin_lock(&wm_list->wm_lock);
- if (wm_list->avail_wm <= num_online_cpus()) {
- list_add(&wm->list, &wm_list->idle_wm);
- spin_unlock(&wm_list->wm_lock);
- wake_up(&wm_list->wm_wait);
- return;
- }
-
- wm_list->avail_wm--;
- spin_unlock(&wm_list->wm_lock);
- kvfree(wm);
-}
-
-static void wm_list_free(struct wm_list *l)
-{
- struct wm *wm;
-
- while (!list_empty(&l->idle_wm)) {
- wm = list_entry(l->idle_wm.next, struct wm, list);
- list_del(&wm->list);
- kvfree(wm);
- }
- kfree(l);
-}
-
-static void wm_lists_destroy(void)
-{
- struct wm_list *l;
-
- while (!list_empty(&wm_lists)) {
- l = list_entry(wm_lists.next, struct wm_list, list);
- list_del(&l->list);
- wm_list_free(l);
- }
-}
-
-void *ksmbd_find_buffer(size_t size)
-{
- struct wm *wm;
-
- wm = find_wm(size);
-
- WARN_ON(!wm);
- if (wm)
- return wm->buffer;
- return NULL;
-}
-
-void ksmbd_release_buffer(void *buffer)
-{
- struct wm_list *wm_list;
- struct wm *wm;
-
- if (!buffer)
- return;
-
- wm = container_of(buffer, struct wm, buffer);
- wm_list = match_wm_list(wm->sz);
- WARN_ON(!wm_list);
- if (wm_list)
- release_wm(wm, wm_list);
-}
-
-void *ksmbd_realloc_response(void *ptr, size_t old_sz, size_t new_sz)
-{
- size_t sz = min(old_sz, new_sz);
- void *nptr;
-
- nptr = kvmalloc(new_sz, GFP_KERNEL | __GFP_ZERO);
- if (!nptr)
- return ptr;
- memcpy(nptr, ptr, sz);
- kvfree(ptr);
- return nptr;
-}
-
-void ksmbd_free_file_struct(void *filp)
-{
- kmem_cache_free(filp_cache, filp);
-}
-
-void *ksmbd_alloc_file_struct(void)
-{
- return kmem_cache_zalloc(filp_cache, GFP_KERNEL);
-}
-
-void ksmbd_destroy_buffer_pools(void)
-{
- wm_lists_destroy();
- ksmbd_work_pool_destroy();
- kmem_cache_destroy(filp_cache);
-}
-
-int ksmbd_init_buffer_pools(void)
-{
- if (ksmbd_work_pool_init())
- goto out;
-
- filp_cache = kmem_cache_create("ksmbd_file_cache",
- sizeof(struct ksmbd_file), 0,
- SLAB_HWCACHE_ALIGN, NULL);
- if (!filp_cache)
- goto out;
-
- return 0;
-
-out:
- ksmbd_err("failed to allocate memory\n");
- ksmbd_destroy_buffer_pools();
- return -ENOMEM;
-}
diff --git a/fs/cifsd/buffer_pool.h b/fs/cifsd/buffer_pool.h
deleted file mode 100644
index 088aa07ba09b..000000000000
--- a/fs/cifsd/buffer_pool.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2018 Samsung Electronics Co., Ltd.
- */
-
-#ifndef __KSMBD_BUFFER_POOL_H__
-#define __KSMBD_BUFFER_POOL_H__
-
-void *ksmbd_find_buffer(size_t size);
-void ksmbd_release_buffer(void *buffer);
-void *ksmbd_realloc_response(void *ptr, size_t old_sz, size_t new_sz);
-void ksmbd_free_file_struct(void *filp);
-void *ksmbd_alloc_file_struct(void);
-void ksmbd_destroy_buffer_pools(void);
-int ksmbd_init_buffer_pools(void);
-
-#endif /* __KSMBD_BUFFER_POOL_H__ */
diff --git a/fs/cifsd/Kconfig b/fs/ksmbd/Kconfig
index e6448b04f46e..e9a5ac01b6e0 100644
--- a/fs/cifsd/Kconfig
+++ b/fs/ksmbd/Kconfig
@@ -1,5 +1,5 @@
config SMB_SERVER
- tristate "SMB server support (EXPERIMENTAL)"
+ tristate "SMB3 server support (EXPERIMENTAL)"
depends on INET
depends on MULTIUSER
depends on FILE_LOCKING
@@ -19,6 +19,7 @@ config SMB_SERVER
select CRYPTO_GCM
select ASN1
select OID_REGISTRY
+ select FS_POSIX_ACL
default n
help
Choose Y here if you want to allow SMB3 compliant clients
@@ -30,13 +31,13 @@ config SMB_SERVER
case you can choose N here.
You also need to install user space programs which can be found
- in cifsd-tools, available from
- https://github.com/cifsd-team/cifsd-tools.
- More detail about how to run the cifsd kernel server is
+ in ksmbd-tools, available from
+ https://github.com/cifsd-team/ksmbd-tools.
+ More detail about how to run the ksmbd kernel server is
available via README file
- (https://github.com/cifsd-team/cifsd-tools/blob/master/README).
+ (https://github.com/cifsd-team/ksmbd-tools/blob/master/README).
- cifsd kernel server includes support for auto-negotiation,
+ ksmbd kernel server includes support for auto-negotiation,
Secure negotiate, Pre-authentication integrity, oplock/lease,
compound requests, multi-credit, packet signing, RDMA(smbdirect),
smb3 encryption, copy-offload, secure per-user session
@@ -60,7 +61,7 @@ config SMB_SERVER_CHECK_CAP_NET_ADMIN
default y
help
- Prevent unprivileged processes to start the cifsd kernel server.
+ Prevent unprivileged processes to start the ksmbd kernel server.
config SMB_SERVER_KERBEROS5
bool "Support for Kerberos 5"
diff --git a/fs/cifsd/Makefile b/fs/ksmbd/Makefile
index 30f64b87cf61..7d6337a7dee4 100644
--- a/fs/cifsd/Makefile
+++ b/fs/ksmbd/Makefile
@@ -4,13 +4,13 @@
#
obj-$(CONFIG_SMB_SERVER) += ksmbd.o
-ksmbd-y := unicode.o auth.o vfs.o vfs_cache.o server.o buffer_pool.o \
+ksmbd-y := unicode.o auth.o vfs.o vfs_cache.o server.o ndr.o \
misc.o oplock.o connection.o ksmbd_work.o crypto_ctx.o \
mgmt/ksmbd_ida.o mgmt/user_config.o mgmt/share_config.o \
mgmt/tree_connect.o mgmt/user_session.o smb_common.o \
transport_tcp.o transport_ipc.o smbacl.o smb2pdu.o \
smb2ops.o smb2misc.o ksmbd_spnego_negtokeninit.asn1.o \
- ksmbd_spnego_negtokentarg.asn1.o asn1.o ndr.o
+ ksmbd_spnego_negtokentarg.asn1.o asn1.o
$(obj)/asn1.o: $(obj)/ksmbd_spnego_negtokeninit.asn1.h $(obj)/ksmbd_spnego_negtokentarg.asn1.h
diff --git a/fs/cifsd/asn1.c b/fs/ksmbd/asn1.c
index 2c63a3e5618b..b014f4638610 100644
--- a/fs/cifsd/asn1.c
+++ b/fs/ksmbd/asn1.c
@@ -66,7 +66,7 @@ static bool asn1_oid_decode(const unsigned char *value, size_t vlen,
vlen += 1;
if (vlen < 2 || vlen > UINT_MAX / sizeof(unsigned long))
- return false;
+ goto fail_nullify;
*oid = kmalloc(vlen * sizeof(unsigned long), GFP_KERNEL);
if (!*oid)
@@ -102,6 +102,7 @@ static bool asn1_oid_decode(const unsigned char *value, size_t vlen,
fail:
kfree(*oid);
+fail_nullify:
*oid = NULL;
return false;
}
diff --git a/fs/cifsd/asn1.h b/fs/ksmbd/asn1.h
index ce105f4ce305..ce105f4ce305 100644
--- a/fs/cifsd/asn1.h
+++ b/fs/ksmbd/asn1.h
diff --git a/fs/cifsd/auth.c b/fs/ksmbd/auth.c
index 5f47de49c05d..de36f12070bf 100644
--- a/fs/cifsd/auth.c
+++ b/fs/ksmbd/auth.c
@@ -29,7 +29,6 @@
#include "mgmt/user_config.h"
#include "crypto_ctx.h"
#include "transport_ipc.h"
-#include "buffer_pool.h"
/*
* Fixed format data defining GSS header and fixed string
@@ -343,7 +342,7 @@ int ksmbd_auth_ntlm(struct ksmbd_session *sess, char *pw_buf)
memcpy(p21, user_passkey(sess->user), CIFS_NTHASH_SIZE);
rc = ksmbd_enc_p24(p21, sess->ntlmssp.cryptkey, key);
if (rc) {
- ksmbd_err("password processing failed\n");
+ pr_err("password processing failed\n");
return rc;
}
@@ -462,7 +461,7 @@ static int __ksmbd_auth_ntlmv2(struct ksmbd_session *sess, char *client_nonce,
client_nonce,
(char *)sess->ntlmssp.cryptkey, 8);
if (rc) {
- ksmbd_err("password processing failed\n");
+ pr_err("password processing failed\n");
goto out;
}
@@ -470,7 +469,7 @@ static int __ksmbd_auth_ntlmv2(struct ksmbd_session *sess, char *client_nonce,
memcpy(p21, user_passkey(sess->user), CIFS_NTHASH_SIZE);
rc = ksmbd_enc_p24(p21, sess_key, key);
if (rc) {
- ksmbd_err("password processing failed\n");
+ pr_err("password processing failed\n");
goto out;
}
@@ -921,13 +920,14 @@ smb3signkey_ret:
}
static int generate_smb3signingkey(struct ksmbd_session *sess,
+ struct ksmbd_conn *conn,
const struct derivation *signing)
{
int rc;
struct channel *chann;
char *key;
- chann = lookup_chann_list(sess);
+ chann = lookup_chann_list(sess, conn);
if (!chann)
return 0;
@@ -953,7 +953,8 @@ static int generate_smb3signingkey(struct ksmbd_session *sess,
return 0;
}
-int ksmbd_gen_smb30_signingkey(struct ksmbd_session *sess)
+int ksmbd_gen_smb30_signingkey(struct ksmbd_session *sess,
+ struct ksmbd_conn *conn)
{
struct derivation d;
@@ -961,22 +962,32 @@ int ksmbd_gen_smb30_signingkey(struct ksmbd_session *sess)
d.label.iov_len = 12;
d.context.iov_base = "SmbSign";
d.context.iov_len = 8;
- d.binding = false;
+ d.binding = conn->binding;
- return generate_smb3signingkey(sess, &d);
+ return generate_smb3signingkey(sess, conn, &d);
}
-int ksmbd_gen_smb311_signingkey(struct ksmbd_session *sess)
+int ksmbd_gen_smb311_signingkey(struct ksmbd_session *sess,
+ struct ksmbd_conn *conn)
{
struct derivation d;
d.label.iov_base = "SMBSigningKey";
d.label.iov_len = 14;
- d.context.iov_base = sess->Preauth_HashValue;
+ if (conn->binding) {
+ struct preauth_session *preauth_sess;
+
+ preauth_sess = ksmbd_preauth_session_lookup(conn, sess->id);
+ if (!preauth_sess)
+ return -ENOENT;
+ d.context.iov_base = preauth_sess->Preauth_HashValue;
+ } else {
+ d.context.iov_base = sess->Preauth_HashValue;
+ }
d.context.iov_len = 64;
- d.binding = false;
+ d.binding = conn->binding;
- return generate_smb3signingkey(sess, &d);
+ return generate_smb3signingkey(sess, conn, &d);
}
struct derivation_twin {
@@ -1148,7 +1159,7 @@ static int ksmbd_get_encryption_key(struct ksmbd_conn *conn, __u64 ses_id,
struct ksmbd_session *sess;
u8 *ses_enc_key;
- sess = ksmbd_session_lookup(conn, ses_id);
+ sess = ksmbd_session_lookup_all(conn, ses_id);
if (!sess)
return -EINVAL;
@@ -1258,7 +1269,7 @@ int ksmbd_crypt_message(struct ksmbd_conn *conn, struct kvec *iov,
enc,
key);
if (rc) {
- ksmbd_err("Could not get %scryption key\n", enc ? "en" : "de");
+ pr_err("Could not get %scryption key\n", enc ? "en" : "de");
return rc;
}
@@ -1268,7 +1279,7 @@ int ksmbd_crypt_message(struct ksmbd_conn *conn, struct kvec *iov,
else
ctx = ksmbd_crypto_ctx_find_ccm();
if (!ctx) {
- ksmbd_err("crypto alloc failed\n");
+ pr_err("crypto alloc failed\n");
return -ENOMEM;
}
@@ -1284,19 +1295,18 @@ int ksmbd_crypt_message(struct ksmbd_conn *conn, struct kvec *iov,
else
rc = crypto_aead_setkey(tfm, key, SMB3_GCM128_CRYPTKEY_SIZE);
if (rc) {
- ksmbd_err("Failed to set aead key %d\n", rc);
+ pr_err("Failed to set aead key %d\n", rc);
goto free_ctx;
}
rc = crypto_aead_setauthsize(tfm, SMB2_SIGNATURE_SIZE);
if (rc) {
- ksmbd_err("Failed to set authsize %d\n", rc);
+ pr_err("Failed to set authsize %d\n", rc);
goto free_ctx;
}
req = aead_request_alloc(tfm, GFP_KERNEL);
if (!req) {
- ksmbd_err("Failed to alloc aead request\n");
rc = -ENOMEM;
goto free_ctx;
}
@@ -1308,7 +1318,7 @@ int ksmbd_crypt_message(struct ksmbd_conn *conn, struct kvec *iov,
sg = ksmbd_init_sg(iov, nvec, sign);
if (!sg) {
- ksmbd_err("Failed to init sg\n");
+ pr_err("Failed to init sg\n");
rc = -ENOMEM;
goto free_req;
}
@@ -1316,7 +1326,6 @@ int ksmbd_crypt_message(struct ksmbd_conn *conn, struct kvec *iov,
iv_len = crypto_aead_ivsize(tfm);
iv = kzalloc(iv_len, GFP_KERNEL);
if (!iv) {
- ksmbd_err("Failed to alloc IV\n");
rc = -ENOMEM;
goto free_sg;
}
diff --git a/fs/cifsd/auth.h b/fs/ksmbd/auth.h
index 650bd7dd6750..9c2d4badd05d 100644
--- a/fs/cifsd/auth.h
+++ b/fs/ksmbd/auth.h
@@ -54,8 +54,10 @@ int ksmbd_sign_smb2_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov,
int n_vec, char *sig);
int ksmbd_sign_smb3_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov,
int n_vec, char *sig);
-int ksmbd_gen_smb30_signingkey(struct ksmbd_session *sess);
-int ksmbd_gen_smb311_signingkey(struct ksmbd_session *sess);
+int ksmbd_gen_smb30_signingkey(struct ksmbd_session *sess,
+ struct ksmbd_conn *conn);
+int ksmbd_gen_smb311_signingkey(struct ksmbd_session *sess,
+ struct ksmbd_conn *conn);
int ksmbd_gen_smb30_encryptionkey(struct ksmbd_session *sess);
int ksmbd_gen_smb311_encryptionkey(struct ksmbd_session *sess);
int ksmbd_gen_preauth_integrity_hash(struct ksmbd_conn *conn, char *buf,
diff --git a/fs/cifsd/connection.c b/fs/ksmbd/connection.c
index 06c42309be72..928e22e19def 100644
--- a/fs/cifsd/connection.c
+++ b/fs/ksmbd/connection.c
@@ -9,7 +9,6 @@
#include <linux/module.h>
#include "server.h"
-#include "buffer_pool.h"
#include "smb_common.h"
#include "mgmt/ksmbd_ida.h"
#include "connection.h"
@@ -161,7 +160,7 @@ int ksmbd_conn_write(struct ksmbd_work *work)
ksmbd_conn_try_dequeue_request(work);
if (!rsp_hdr) {
- ksmbd_err("NULL response header\n");
+ pr_err("NULL response header\n");
return -EINVAL;
}
@@ -193,7 +192,7 @@ int ksmbd_conn_write(struct ksmbd_work *work)
ksmbd_conn_unlock(conn);
if (sent < 0) {
- ksmbd_err("Failed to send message: %d\n", sent);
+ pr_err("Failed to send message: %d\n", sent);
return sent;
}
@@ -316,24 +315,23 @@ int ksmbd_conn_handler_loop(void *p)
*/
size = t->ops->read(t, conn->request_buf + 4, pdu_size);
if (size < 0) {
- ksmbd_err("sock_read failed: %d\n", size);
+ pr_err("sock_read failed: %d\n", size);
break;
}
if (size != pdu_size) {
- ksmbd_err("PDU error. Read: %d, Expected: %d\n",
- size,
- pdu_size);
+ pr_err("PDU error. Read: %d, Expected: %d\n",
+ size, pdu_size);
continue;
}
if (!default_conn_ops.process_fn) {
- ksmbd_err("No connection request callback\n");
+ pr_err("No connection request callback\n");
break;
}
if (default_conn_ops.process_fn(conn)) {
- ksmbd_err("Cannot handle request\n");
+ pr_err("Cannot handle request\n");
break;
}
}
diff --git a/fs/cifsd/connection.h b/fs/ksmbd/connection.h
index 1658442b27b0..98108b41f739 100644
--- a/fs/cifsd/connection.h
+++ b/fs/ksmbd/connection.h
@@ -106,6 +106,7 @@ struct ksmbd_conn {
__le16 cipher_type;
__le16 compress_algorithm;
bool posix_ext_supported;
+ bool binding;
};
struct ksmbd_conn_ops {
diff --git a/fs/cifsd/crypto_ctx.c b/fs/ksmbd/crypto_ctx.c
index cfea4c4db30f..5f4b1008d17e 100644
--- a/fs/cifsd/crypto_ctx.c
+++ b/fs/ksmbd/crypto_ctx.c
@@ -12,7 +12,6 @@
#include "glob.h"
#include "crypto_ctx.h"
-#include "buffer_pool.h"
struct crypto_ctx_list {
spinlock_t ctx_lock;
@@ -49,12 +48,12 @@ static struct crypto_aead *alloc_aead(int id)
tfm = crypto_alloc_aead("ccm(aes)", 0, 0);
break;
default:
- ksmbd_err("Does not support encrypt ahead(id : %d)\n", id);
+ pr_err("Does not support encrypt ahead(id : %d)\n", id);
return NULL;
}
if (IS_ERR(tfm)) {
- ksmbd_err("Failed to alloc encrypt aead : %ld\n", PTR_ERR(tfm));
+ pr_err("Failed to alloc encrypt aead : %ld\n", PTR_ERR(tfm));
return NULL;
}
diff --git a/fs/cifsd/crypto_ctx.h b/fs/ksmbd/crypto_ctx.h
index ef11154b43df..ef11154b43df 100644
--- a/fs/cifsd/crypto_ctx.h
+++ b/fs/ksmbd/crypto_ctx.h
diff --git a/fs/cifsd/glob.h b/fs/ksmbd/glob.h
index ffeaf8aa5595..49a5a3afa118 100644
--- a/fs/cifsd/glob.h
+++ b/fs/ksmbd/glob.h
@@ -14,13 +14,8 @@
#define KSMBD_VERSION "3.1.9"
-/* @FIXME clean up this code */
-
extern int ksmbd_debug_types;
-#define DATA_STREAM 1
-#define DIR_STREAM 2
-
#define KSMBD_DEBUG_SMB BIT(0)
#define KSMBD_DEBUG_AUTH BIT(1)
#define KSMBD_DEBUG_VFS BIT(2)
@@ -33,32 +28,22 @@ extern int ksmbd_debug_types;
KSMBD_DEBUG_IPC | KSMBD_DEBUG_CONN | \
KSMBD_DEBUG_RDMA)
-#ifndef ksmbd_pr_fmt
+#ifdef pr_fmt
+#undef pr_fmt
+#endif
+
#ifdef SUBMOD_NAME
-#define ksmbd_pr_fmt(fmt) "ksmbd: " SUBMOD_NAME ": " fmt
+#define pr_fmt(fmt) "ksmbd: " SUBMOD_NAME ": " fmt
#else
-#define ksmbd_pr_fmt(fmt) "ksmbd: " fmt
-#endif
+#define pr_fmt(fmt) "ksmbd: " fmt
#endif
#define ksmbd_debug(type, fmt, ...) \
do { \
if (ksmbd_debug_types & KSMBD_DEBUG_##type) \
- pr_info(ksmbd_pr_fmt("%s:%d: " fmt), \
- __func__, \
- __LINE__, \
- ##__VA_ARGS__); \
+ pr_info(fmt, ##__VA_ARGS__); \
} while (0)
-#define ksmbd_info(fmt, ...) \
- pr_info(ksmbd_pr_fmt(fmt), ##__VA_ARGS__)
-
-#define ksmbd_err(fmt, ...) \
- pr_err(ksmbd_pr_fmt("%s:%d: " fmt), \
- __func__, \
- __LINE__, \
- ##__VA_ARGS__)
-
#define UNICODE_LEN(x) ((x) * 2)
#endif /* __KSMBD_GLOB_H */
diff --git a/fs/cifsd/ksmbd_server.h b/fs/ksmbd/ksmbd_netlink.h
index 442077a1e77b..2fbe2bc1e093 100644
--- a/fs/cifsd/ksmbd_server.h
+++ b/fs/ksmbd/ksmbd_netlink.h
@@ -10,17 +10,59 @@
#include <linux/types.h>
+/*
+ * This is a userspace ABI to communicate data between ksmbd and user IPC
+ * daemon using netlink. This is added to track and cache user account DB
+ * and share configuration info from userspace.
+ *
+ * - KSMBD_EVENT_HEARTBEAT_REQUEST(ksmbd_heartbeat)
+ * This event is to check whether user IPC daemon is alive. If user IPC
+ * daemon is dead, ksmbd keep existing connection till disconnecting and
+ * new connection will be denied.
+ *
+ * - KSMBD_EVENT_STARTING_UP(ksmbd_startup_request)
+ * This event is to receive the information that initializes the ksmbd
+ * server from the user IPC daemon and to start the server. The global
+ * section parameters are given from smb.conf as initialization
+ * information.
+ *
+ * - KSMBD_EVENT_SHUTTING_DOWN(ksmbd_shutdown_request)
+ * This event is to shutdown ksmbd server.
+ *
+ * - KSMBD_EVENT_LOGIN_REQUEST/RESPONSE(ksmbd_login_request/response)
+ * This event is to get user account info to user IPC daemon.
+ *
+ * - KSMBD_EVENT_SHARE_CONFIG_REQUEST/RESPONSE(ksmbd_share_config_request/response)
+ * This event is to get net share configuration info.
+ *
+ * - KSMBD_EVENT_TREE_CONNECT_REQUEST/RESPONSE(ksmbd_tree_connect_request/response)
+ * This event is to get session and tree connect info.
+ *
+ * - KSMBD_EVENT_TREE_DISCONNECT_REQUEST(ksmbd_tree_disconnect_request)
+ * This event is to send tree disconnect info to user IPC daemon.
+ *
+ * - KSMBD_EVENT_LOGOUT_REQUEST(ksmbd_logout_request)
+ * This event is to send logout request to user IPC daemon.
+ *
+ * - KSMBD_EVENT_RPC_REQUEST/RESPONSE(ksmbd_rpc_command)
+ * This event is to make DCE/RPC request like srvsvc, wkssvc, lsarpc,
+ * samr to be processed in userspace.
+ *
+ * - KSMBD_EVENT_SPNEGO_AUTHEN_REQUEST/RESPONSE(ksmbd_spnego_authen_request/response)
+ * This event is to make kerberos authentication to be processed in
+ * userspace.
+ */
+
#define KSMBD_GENL_NAME "SMBD_GENL"
#define KSMBD_GENL_VERSION 0x01
-#ifndef ____ksmbd_align
-#define ____ksmbd_align __aligned(4)
-#endif
-
#define KSMBD_REQ_MAX_ACCOUNT_NAME_SZ 48
#define KSMBD_REQ_MAX_HASH_SZ 18
#define KSMBD_REQ_MAX_SHARE_NAME 64
+/*
+ * IPC heartbeat frame to check whether user IPC daemon is alive.
+ */
struct ksmbd_heartbeat {
__u32 handle;
};
@@ -30,57 +72,82 @@ struct ksmbd_heartbeat {
*/
#define KSMBD_GLOBAL_FLAG_INVALID (0)
#define KSMBD_GLOBAL_FLAG_SMB2_LEASES BIT(0)
-#define KSMBD_GLOBAL_FLAG_CACHE_TBUF BIT(1)
-#define KSMBD_GLOBAL_FLAG_CACHE_RBUF BIT(2)
-#define KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION BIT(3)
+#define KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION BIT(1)
+#define KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL BIT(2)
+/*
+ * IPC request for ksmbd server startup
+ */
struct ksmbd_startup_request {
- __u32 flags;
- __s32 signing;
- __s8 min_prot[16];
- __s8 max_prot[16];
+ __u32 flags; /* Flags for global config */
+ __s32 signing; /* Signing enabled */
+ __s8 min_prot[16]; /* The minimum SMB protocol version */
+ __s8 max_prot[16]; /* The maximum SMB protocol version */
__s8 netbios_name[16];
- __s8 work_group[64];
- __s8 server_string[64];
- __u16 tcp_port;
- __u16 ipc_timeout;
- __u32 deadtime;
- __u32 file_max;
- __u32 smb2_max_write;
- __u32 smb2_max_read;
- __u32 smb2_max_trans;
- __u32 share_fake_fscaps;
- __u32 sub_auth[3];
- __u32 ifc_list_sz;
- __s8 ____payload[0];
-} ____ksmbd_align;
+ __s8 work_group[64]; /* Workgroup */
+ __s8 server_string[64]; /* Server string */
+ __u16 tcp_port; /* tcp port */
+ __u16 ipc_timeout; /*
+ * specifies the number of seconds
+ * server will wait for the userspace to
+ * reply to heartbeat frames.
+ */
+ __u32 deadtime; /* Number of minutes of inactivity */
+ __u32 file_max; /* Limits the maximum number of open files */
+ __u32 smb2_max_write; /* MAX write size */
+ __u32 smb2_max_read; /* MAX read size */
+ __u32 smb2_max_trans; /* MAX trans size */
+ __u32 share_fake_fscaps; /*
+ * Support some special application that
+ * makes QFSINFO calls to check whether
+ * we set the SPARSE_FILES bit (0x40).
+ */
+ __u32 sub_auth[3]; /* Subauth value for Security ID */
+ __u32 ifc_list_sz; /* interfaces list size */
+ __s8 ____payload[];
+};
#define KSMBD_STARTUP_CONFIG_INTERFACES(s) ((s)->____payload)
+/*
+ * IPC request to shutdown ksmbd server.
+ */
struct ksmbd_shutdown_request {
__s32 reserved;
-} ____ksmbd_align;
+};
+/*
+ * IPC user login request.
+ */
struct ksmbd_login_request {
__u32 handle;
- __s8 account[KSMBD_REQ_MAX_ACCOUNT_NAME_SZ];
-} ____ksmbd_align;
+ __s8 account[KSMBD_REQ_MAX_ACCOUNT_NAME_SZ]; /* user account name */
+};
+/*
+ * IPC user login response.
+ */
struct ksmbd_login_response {
__u32 handle;
- __u32 gid;
- __u32 uid;
- __s8 account[KSMBD_REQ_MAX_ACCOUNT_NAME_SZ];
+ __u32 gid; /* group id */
+ __u32 uid; /* user id */
+ __s8 account[KSMBD_REQ_MAX_ACCOUNT_NAME_SZ]; /* user account name */
__u16 status;
- __u16 hash_sz;
- __s8 hash[KSMBD_REQ_MAX_HASH_SZ];
-} ____ksmbd_align;
+ __u16 hash_sz; /* hash size */
+ __s8 hash[KSMBD_REQ_MAX_HASH_SZ]; /* password hash */
+};
+/*
+ * IPC request to fetch net share config.
+ */
struct ksmbd_share_config_request {
__u32 handle;
- __s8 share_name[KSMBD_REQ_MAX_SHARE_NAME];
-} ____ksmbd_align;
+ __s8 share_name[KSMBD_REQ_MAX_SHARE_NAME]; /* share name */
+};
+/*
+ * IPC response to the net share config request.
+ */
struct ksmbd_share_config_response {
__u32 handle;
__u32 flags;
@@ -91,18 +158,26 @@ struct ksmbd_share_config_response {
__u16 force_uid;
__u16 force_gid;
__u32 veto_list_sz;
- __s8 ____payload[0];
-} ____ksmbd_align;
+ __s8 ____payload[];
+};
#define KSMBD_SHARE_CONFIG_VETO_LIST(s) ((s)->____payload)
-#define KSMBD_SHARE_CONFIG_PATH(s) \
- ({ \
- char *p = (s)->____payload; \
- if ((s)->veto_list_sz) \
- p += (s)->veto_list_sz + 1; \
- p; \
- })
+static inline char *
+ksmbd_share_config_path(struct ksmbd_share_config_response *sc)
+{
+ char *p = sc->____payload;
+
+ if (sc->veto_list_sz)
+ p += sc->veto_list_sz + 1;
+
+ return p;
+}
+
+/*
+ * IPC request for tree connection. This request include session and tree
+ * connect info from client.
+ */
struct ksmbd_tree_connect_request {
__u32 handle;
__u16 account_flags;
@@ -112,43 +187,74 @@ struct ksmbd_tree_connect_request {
__s8 account[KSMBD_REQ_MAX_ACCOUNT_NAME_SZ];
__s8 share[KSMBD_REQ_MAX_SHARE_NAME];
__s8 peer_addr[64];
-} ____ksmbd_align;
+};
+/*
+ * IPC Response structure for tree connection.
+ */
struct ksmbd_tree_connect_response {
__u32 handle;
__u16 status;
__u16 connection_flags;
-} ____ksmbd_align;
+};
+/*
+ * IPC Request struture to disconnect tree connection.
+ */
struct ksmbd_tree_disconnect_request {
- __u64 session_id;
- __u64 connect_id;
-} ____ksmbd_align;
+ __u64 session_id; /* session id */
+ __u64 connect_id; /* tree connection id */
+};
+/*
+ * IPC Response structure to logout user account.
+ */
struct ksmbd_logout_request {
- __s8 account[KSMBD_REQ_MAX_ACCOUNT_NAME_SZ];
-} ____ksmbd_align;
+ __s8 account[KSMBD_REQ_MAX_ACCOUNT_NAME_SZ]; /* user account name */
+};
+/*
+ * RPC command structure to send rpc request like srvsvc or wkssvc to
+ * IPC user daemon.
+ */
struct ksmbd_rpc_command {
__u32 handle;
__u32 flags;
__u32 payload_sz;
- __u8 payload[0];
-} ____ksmbd_align;
+ __u8 payload[];
+};
+/*
+ * IPC Request Kerberos authentication
+ */
struct ksmbd_spnego_authen_request {
__u32 handle;
- __u16 spnego_blob_len;
- __u8 spnego_blob[0];
-} ____ksmbd_align;
+ __u16 spnego_blob_len; /* the length of spnego_blob */
+ __u8 spnego_blob[0]; /*
+ * the GSS token from SecurityBuffer of
+ * SMB2 SESSION SETUP request
+ */
+};
+/*
+ * Response data which includes the GSS token and the session key generated by
+ * user daemon.
+ */
struct ksmbd_spnego_authen_response {
__u32 handle;
- struct ksmbd_login_response login_response;
- __u16 session_key_len;
- __u16 spnego_blob_len;
- __u8 payload[0]; /* session key + AP_REP */
-} ____ksmbd_align;
+ struct ksmbd_login_response login_response; /*
+ * the login response with
+ * a user identified by the
+ * GSS token from a client
+ */
+ __u16 session_key_len; /* the length of the session key */
+ __u16 spnego_blob_len; /*
+ * the length of the GSS token which will be
+ * stored in SecurityBuffer of SMB2 SESSION
+ * SETUP response
+ */
+ __u8 payload[]; /* session key + AP_REP */
+};
/*
* This also used as NETLINK attribute type value.
@@ -186,6 +292,9 @@ enum ksmbd_event {
KSMBD_EVENT_MAX
};
+/*
+ * Enumeration for IPC tree connect status.
+ */
enum KSMBD_TREE_CONN_STATUS {
KSMBD_TREE_CONN_STATUS_OK = 0,
KSMBD_TREE_CONN_STATUS_NOMEM,
@@ -263,6 +372,9 @@ enum KSMBD_TREE_CONN_STATUS {
#define KSMBD_RPC_LSARPC_METHOD_INVOKE BIT(11)
#define KSMBD_RPC_LSARPC_METHOD_RETURN (KSMBD_RPC_LSARPC_METHOD_INVOKE | KSMBD_RPC_METHOD_RETURN)
+/*
+ * RPC status definitions.
+ */
#define KSMBD_RPC_OK 0
#define KSMBD_RPC_EBAD_FUNC 0x00000001
#define KSMBD_RPC_EACCESS_DENIED 0x00000005
diff --git a/fs/cifsd/ksmbd_spnego_negtokeninit.asn1 b/fs/ksmbd/ksmbd_spnego_negtokeninit.asn1
index 0065f191b54b..0065f191b54b 100644
--- a/fs/cifsd/ksmbd_spnego_negtokeninit.asn1
+++ b/fs/ksmbd/ksmbd_spnego_negtokeninit.asn1
diff --git a/fs/cifsd/ksmbd_spnego_negtokentarg.asn1 b/fs/ksmbd/ksmbd_spnego_negtokentarg.asn1
index 1151933e7b9c..1151933e7b9c 100644
--- a/fs/cifsd/ksmbd_spnego_negtokentarg.asn1
+++ b/fs/ksmbd/ksmbd_spnego_negtokentarg.asn1
diff --git a/fs/cifsd/ksmbd_work.c b/fs/ksmbd/ksmbd_work.c
index f284a2a803d6..fd58eb4809f6 100644
--- a/fs/cifsd/ksmbd_work.c
+++ b/fs/ksmbd/ksmbd_work.c
@@ -11,12 +11,8 @@
#include "server.h"
#include "connection.h"
#include "ksmbd_work.h"
-#include "buffer_pool.h"
#include "mgmt/ksmbd_ida.h"
-/* @FIXME */
-#include "ksmbd_server.h"
-
static struct kmem_cache *work_cache;
static struct workqueue_struct *ksmbd_wq;
@@ -38,18 +34,9 @@ struct ksmbd_work *ksmbd_alloc_work_struct(void)
void ksmbd_free_work_struct(struct ksmbd_work *work)
{
WARN_ON(work->saved_cred != NULL);
- if (server_conf.flags & KSMBD_GLOBAL_FLAG_CACHE_TBUF &&
- work->set_trans_buf)
- ksmbd_release_buffer(work->response_buf);
- else
- kvfree(work->response_buf);
-
- if (server_conf.flags & KSMBD_GLOBAL_FLAG_CACHE_RBUF &&
- work->set_read_buf)
- ksmbd_release_buffer(work->aux_payload_buf);
- else
- kvfree(work->aux_payload_buf);
+ kvfree(work->response_buf);
+ kvfree(work->aux_payload_buf);
kfree(work->tr_buf);
kvfree(work->request_buf);
if (work->async_id)
diff --git a/fs/cifsd/ksmbd_work.h b/fs/ksmbd/ksmbd_work.h
index 28a1692ed37f..c655bf371ce5 100644
--- a/fs/cifsd/ksmbd_work.h
+++ b/fs/ksmbd/ksmbd_work.h
@@ -70,8 +70,6 @@ struct ksmbd_work {
/* Is this SYNC or ASYNC ksmbd_work */
bool syncronous:1;
bool need_invalidate_rkey:1;
- bool set_trans_buf:1;
- bool set_read_buf:1;
unsigned int remote_key;
/* cancel works */
@@ -88,14 +86,23 @@ struct ksmbd_work {
struct list_head interim_entry;
};
-#define WORK_CANCELLED(w) ((w)->state == KSMBD_WORK_CANCELLED)
-#define WORK_CLOSED(w) ((w)->state == KSMBD_WORK_CLOSED)
-#define WORK_ACTIVE(w) ((w)->state == KSMBD_WORK_ACTIVE)
-
-#define RESPONSE_BUF_NEXT(w) \
- (((w)->response_buf + (w)->next_smb2_rsp_hdr_off))
-#define REQUEST_BUF_NEXT(w) \
- (((w)->request_buf + (w)->next_smb2_rcv_hdr_off))
+/**
+ * ksmbd_resp_buf_next - Get next buffer on compound response.
+ * @work: smb work containing response buffer
+ */
+static inline void *ksmbd_resp_buf_next(struct ksmbd_work *work)
+{
+ return work->response_buf + work->next_smb2_rsp_hdr_off;
+}
+
+/**
+ * ksmbd_req_buf_next - Get next buffer on compound request.
+ * @work: smb work containing response buffer
+ */
+static inline void *ksmbd_req_buf_next(struct ksmbd_work *work)
+{
+ return work->request_buf + work->next_smb2_rcv_hdr_off;
+}
struct ksmbd_work *ksmbd_alloc_work_struct(void);
void ksmbd_free_work_struct(struct ksmbd_work *work);
diff --git a/fs/cifsd/mgmt/ksmbd_ida.c b/fs/ksmbd/mgmt/ksmbd_ida.c
index 54194d959a5e..54194d959a5e 100644
--- a/fs/cifsd/mgmt/ksmbd_ida.c
+++ b/fs/ksmbd/mgmt/ksmbd_ida.c
diff --git a/fs/cifsd/mgmt/ksmbd_ida.h b/fs/ksmbd/mgmt/ksmbd_ida.h
index 2bc07b16cfde..2bc07b16cfde 100644
--- a/fs/cifsd/mgmt/ksmbd_ida.h
+++ b/fs/ksmbd/mgmt/ksmbd_ida.h
diff --git a/fs/cifsd/mgmt/share_config.c b/fs/ksmbd/mgmt/share_config.c
index bcc4ae4381b9..cb72d30f5b71 100644
--- a/fs/cifsd/mgmt/share_config.c
+++ b/fs/ksmbd/mgmt/share_config.c
@@ -15,7 +15,6 @@
#include "share_config.h"
#include "user_config.h"
#include "user_session.h"
-#include "../buffer_pool.h"
#include "../transport_ipc.h"
#define SHARE_HASH_BITS 3
@@ -140,7 +139,7 @@ static struct ksmbd_share_config *share_config_request(char *name)
share->name = kstrdup(name, GFP_KERNEL);
if (!test_share_config_flag(share, KSMBD_SHARE_FLAG_PIPE)) {
- share->path = kstrdup(KSMBD_SHARE_CONFIG_PATH(resp),
+ share->path = kstrdup(ksmbd_share_config_path(resp),
GFP_KERNEL);
if (share->path)
share->path_sz = strlen(share->path);
diff --git a/fs/cifsd/mgmt/share_config.h b/fs/ksmbd/mgmt/share_config.h
index 953befc94e84..953befc94e84 100644
--- a/fs/cifsd/mgmt/share_config.h
+++ b/fs/ksmbd/mgmt/share_config.h
diff --git a/fs/cifsd/mgmt/tree_connect.c b/fs/ksmbd/mgmt/tree_connect.c
index 029a9e81e844..0d28e723a28c 100644
--- a/fs/cifsd/mgmt/tree_connect.c
+++ b/fs/ksmbd/mgmt/tree_connect.c
@@ -7,7 +7,6 @@
#include <linux/slab.h>
#include <linux/xarray.h>
-#include "../buffer_pool.h"
#include "../transport_ipc.h"
#include "../connection.h"
diff --git a/fs/cifsd/mgmt/tree_connect.h b/fs/ksmbd/mgmt/tree_connect.h
index 4e40ec3f4774..18e2a996e0aa 100644
--- a/fs/cifsd/mgmt/tree_connect.h
+++ b/fs/ksmbd/mgmt/tree_connect.h
@@ -8,7 +8,7 @@
#include <linux/hashtable.h>
-#include "../ksmbd_server.h"
+#include "../ksmbd_netlink.h"
struct ksmbd_share_config;
struct ksmbd_user;
diff --git a/fs/cifsd/mgmt/user_config.c b/fs/ksmbd/mgmt/user_config.c
index 7f898c5bda25..d21629ae5c89 100644
--- a/fs/cifsd/mgmt/user_config.c
+++ b/fs/ksmbd/mgmt/user_config.c
@@ -7,7 +7,6 @@
#include <linux/mm.h>
#include "user_config.h"
-#include "../buffer_pool.h"
#include "../transport_ipc.h"
struct ksmbd_user *ksmbd_login_user(const char *account)
diff --git a/fs/cifsd/mgmt/user_config.h b/fs/ksmbd/mgmt/user_config.h
index b2bb074a0150..b2bb074a0150 100644
--- a/fs/cifsd/mgmt/user_config.h
+++ b/fs/ksmbd/mgmt/user_config.h
diff --git a/fs/cifsd/mgmt/user_session.c b/fs/ksmbd/mgmt/user_session.c
index 739588a6c96a..8d8ffd8c6f19 100644
--- a/fs/cifsd/mgmt/user_session.c
+++ b/fs/ksmbd/mgmt/user_session.c
@@ -14,7 +14,6 @@
#include "tree_connect.h"
#include "../transport_ipc.h"
#include "../connection.h"
-#include "../buffer_pool.h"
#include "../vfs_cache.h"
static DEFINE_IDA(session_ida);
@@ -31,15 +30,12 @@ struct ksmbd_session_rpc {
static void free_channel_list(struct ksmbd_session *sess)
{
- struct channel *chann;
- struct list_head *tmp, *t;
-
- list_for_each_safe(tmp, t, &sess->ksmbd_chann_list) {
- chann = list_entry(tmp, struct channel, chann_list);
- if (chann) {
- list_del(&chann->chann_list);
- kfree(chann);
- }
+ struct channel *chann, *tmp;
+
+ list_for_each_entry_safe(chann, tmp, &sess->ksmbd_chann_list,
+ chann_list) {
+ list_del(&chann->chann_list);
+ kfree(chann);
}
}
@@ -88,7 +84,7 @@ static int __rpc_method(char *rpc_name)
if (!strcmp(rpc_name, "\\lsarpc") || !strcmp(rpc_name, "lsarpc"))
return KSMBD_RPC_LSARPC_METHOD_INVOKE;
- ksmbd_err("Unsupported RPC: %s\n", rpc_name);
+ pr_err("Unsupported RPC: %s\n", rpc_name);
return 0;
}
@@ -158,11 +154,9 @@ void ksmbd_session_destroy(struct ksmbd_session *sess)
list_del(&sess->sessions_entry);
- if (IS_SMB2(sess->conn)) {
- down_write(&sessions_table_lock);
- hash_del(&sess->hlist);
- up_write(&sessions_table_lock);
- }
+ down_write(&sessions_table_lock);
+ hash_del(&sess->hlist);
+ up_write(&sessions_table_lock);
if (sess->user)
ksmbd_free_user(sess->user);
@@ -207,7 +201,8 @@ void ksmbd_sessions_deregister(struct ksmbd_conn *conn)
}
}
-bool ksmbd_session_id_match(struct ksmbd_session *sess, unsigned long long id)
+static bool ksmbd_session_id_match(struct ksmbd_session *sess,
+ unsigned long long id)
{
return sess->id == id;
}
@@ -232,7 +227,7 @@ int get_session(struct ksmbd_session *sess)
void put_session(struct ksmbd_session *sess)
{
if (atomic_dec_and_test(&sess->refcnt))
- ksmbd_err("get/%s seems to be mismatched.", __func__);
+ pr_err("get/%s seems to be mismatched.", __func__);
}
struct ksmbd_session *ksmbd_session_lookup_slowpath(unsigned long long id)
@@ -250,6 +245,52 @@ struct ksmbd_session *ksmbd_session_lookup_slowpath(unsigned long long id)
return sess;
}
+struct ksmbd_session *ksmbd_session_lookup_all(struct ksmbd_conn *conn,
+ unsigned long long id)
+{
+ struct ksmbd_session *sess;
+
+ sess = ksmbd_session_lookup(conn, id);
+ if (!sess && conn->binding)
+ sess = ksmbd_session_lookup_slowpath(id);
+ return sess;
+}
+
+struct preauth_session *ksmbd_preauth_session_alloc(struct ksmbd_conn *conn,
+ u64 sess_id)
+{
+ struct preauth_session *sess;
+
+ sess = kmalloc(sizeof(struct preauth_session), GFP_KERNEL);
+ if (!sess)
+ return NULL;
+
+ sess->id = sess_id;
+ memcpy(sess->Preauth_HashValue, conn->preauth_info->Preauth_HashValue,
+ PREAUTH_HASHVALUE_SIZE);
+ list_add(&sess->preauth_entry, &conn->preauth_sess_table);
+
+ return sess;
+}
+
+static bool ksmbd_preauth_session_id_match(struct preauth_session *sess,
+ unsigned long long id)
+{
+ return sess->id == id;
+}
+
+struct preauth_session *ksmbd_preauth_session_lookup(struct ksmbd_conn *conn,
+ unsigned long long id)
+{
+ struct preauth_session *sess = NULL;
+
+ list_for_each_entry(sess, &conn->preauth_sess_table, preauth_entry) {
+ if (ksmbd_preauth_session_id_match(sess, id))
+ return sess;
+ }
+ return NULL;
+}
+
static int __init_smb2_session(struct ksmbd_session *sess)
{
int id = ksmbd_acquire_smb2_uid(&session_ida);
diff --git a/fs/cifsd/mgmt/user_session.h b/fs/ksmbd/mgmt/user_session.h
index 761bf4776cf1..82289c3cbd2b 100644
--- a/fs/cifsd/mgmt/user_session.h
+++ b/fs/ksmbd/mgmt/user_session.h
@@ -26,8 +26,8 @@ struct channel {
struct preauth_session {
__u8 Preauth_HashValue[PREAUTH_HASHVALUE_SIZE];
- u64 sess_id;
- struct list_head list_entry;
+ u64 id;
+ struct list_head preauth_entry;
};
struct ksmbd_session {
@@ -82,13 +82,18 @@ struct ksmbd_session *ksmbd_smb2_session_create(void);
void ksmbd_session_destroy(struct ksmbd_session *sess);
-bool ksmbd_session_id_match(struct ksmbd_session *sess, unsigned long long id);
struct ksmbd_session *ksmbd_session_lookup_slowpath(unsigned long long id);
struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn,
unsigned long long id);
void ksmbd_session_register(struct ksmbd_conn *conn,
struct ksmbd_session *sess);
void ksmbd_sessions_deregister(struct ksmbd_conn *conn);
+struct ksmbd_session *ksmbd_session_lookup_all(struct ksmbd_conn *conn,
+ unsigned long long id);
+struct preauth_session *ksmbd_preauth_session_alloc(struct ksmbd_conn *conn,
+ u64 sess_id);
+struct preauth_session *ksmbd_preauth_session_lookup(struct ksmbd_conn *conn,
+ unsigned long long id);
int ksmbd_acquire_tree_conn_id(struct ksmbd_session *sess);
void ksmbd_release_tree_conn_id(struct ksmbd_session *sess, int id);
diff --git a/fs/cifsd/misc.c b/fs/ksmbd/misc.c
index 1c6ed20f4a18..0b307ca28a19 100644
--- a/fs/cifsd/misc.c
+++ b/fs/ksmbd/misc.c
@@ -107,7 +107,7 @@ static int ksmbd_validate_stream_name(char *stream_name)
stream_name++;
if (c == '/' || c == ':' || c == '\\') {
- ksmbd_err("Stream name validation failed: %c\n", c);
+ pr_err("Stream name validation failed: %c\n", c);
return -ENOENT;
}
}
diff --git a/fs/cifsd/misc.h b/fs/ksmbd/misc.h
index af8717d4d85b..af8717d4d85b 100644
--- a/fs/cifsd/misc.h
+++ b/fs/ksmbd/misc.h
diff --git a/fs/cifsd/ndr.c b/fs/ksmbd/ndr.c
index 14189832c65e..cf0df78259c9 100644
--- a/fs/cifsd/ndr.c
+++ b/fs/ksmbd/ndr.c
@@ -9,21 +9,9 @@
#include "glob.h"
#include "ndr.h"
-#define PAYLOAD_HEAD(d) ((d)->data + (d)->offset)
-
-#define KSMBD_ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))
-
-#define KSMBD_ALIGN(x, a) \
- ({ \
- typeof(x) ret = (x); \
- if (((x) & ((typeof(x))(a) - 1)) != 0) \
- ret = KSMBD_ALIGN_MASK(x, (typeof(x))(a) - 1); \
- ret; \
- })
-
-static void align_offset(struct ndr *ndr, int n)
+static inline char *ndr_get_field(struct ndr *n)
{
- ndr->offset = KSMBD_ALIGN(ndr->offset, n);
+ return n->data + n->offset;
}
static int try_to_realloc_ndr_blob(struct ndr *n, size_t sz)
@@ -45,7 +33,7 @@ static void ndr_write_int16(struct ndr *n, __u16 value)
if (n->length <= n->offset + sizeof(value))
try_to_realloc_ndr_blob(n, sizeof(value));
- *(__le16 *)PAYLOAD_HEAD(n) = cpu_to_le16(value);
+ *(__le16 *)ndr_get_field(n) = cpu_to_le16(value);
n->offset += sizeof(value);
}
@@ -54,7 +42,7 @@ static void ndr_write_int32(struct ndr *n, __u32 value)
if (n->length <= n->offset + sizeof(value))
try_to_realloc_ndr_blob(n, sizeof(value));
- *(__le32 *)PAYLOAD_HEAD(n) = cpu_to_le32(value);
+ *(__le32 *)ndr_get_field(n) = cpu_to_le32(value);
n->offset += sizeof(value);
}
@@ -63,7 +51,7 @@ static void ndr_write_int64(struct ndr *n, __u64 value)
if (n->length <= n->offset + sizeof(value))
try_to_realloc_ndr_blob(n, sizeof(value));
- *(__le64 *)PAYLOAD_HEAD(n) = cpu_to_le64(value);
+ *(__le64 *)ndr_get_field(n) = cpu_to_le64(value);
n->offset += sizeof(value);
}
@@ -72,7 +60,7 @@ static int ndr_write_bytes(struct ndr *n, void *value, size_t sz)
if (n->length <= n->offset + sz)
try_to_realloc_ndr_blob(n, sz);
- memcpy(PAYLOAD_HEAD(n), value, sz);
+ memcpy(ndr_get_field(n), value, sz);
n->offset += sz;
return 0;
}
@@ -82,27 +70,27 @@ static int ndr_write_string(struct ndr *n, void *value, size_t sz)
if (n->length <= n->offset + sz)
try_to_realloc_ndr_blob(n, sz);
- strncpy(PAYLOAD_HEAD(n), value, sz);
+ strncpy(ndr_get_field(n), value, sz);
sz++;
n->offset += sz;
- align_offset(n, 2);
+ n->offset = ALIGN(n->offset, 2);
return 0;
}
static int ndr_read_string(struct ndr *n, void *value, size_t sz)
{
- int len = strnlen(PAYLOAD_HEAD(n), sz);
+ int len = strnlen(ndr_get_field(n), sz);
- memcpy(value, PAYLOAD_HEAD(n), len);
+ memcpy(value, ndr_get_field(n), len);
len++;
n->offset += len;
- align_offset(n, 2);
+ n->offset = ALIGN(n->offset, 2);
return 0;
}
static int ndr_read_bytes(struct ndr *n, void *value, size_t sz)
{
- memcpy(value, PAYLOAD_HEAD(n), sz);
+ memcpy(value, ndr_get_field(n), sz);
n->offset += sz;
return 0;
}
@@ -111,7 +99,7 @@ static __u16 ndr_read_int16(struct ndr *n)
{
__u16 ret;
- ret = le16_to_cpu(*(__le16 *)PAYLOAD_HEAD(n));
+ ret = le16_to_cpu(*(__le16 *)ndr_get_field(n));
n->offset += sizeof(__u16);
return ret;
}
@@ -120,7 +108,7 @@ static __u32 ndr_read_int32(struct ndr *n)
{
__u32 ret;
- ret = le32_to_cpu(*(__le32 *)PAYLOAD_HEAD(n));
+ ret = le32_to_cpu(*(__le32 *)ndr_get_field(n));
n->offset += sizeof(__u32);
return ret;
}
@@ -129,7 +117,7 @@ static __u64 ndr_read_int64(struct ndr *n)
{
__u64 ret;
- ret = le64_to_cpu(*(__le64 *)PAYLOAD_HEAD(n));
+ ret = le64_to_cpu(*(__le64 *)ndr_get_field(n));
n->offset += sizeof(__u64);
return ret;
}
@@ -178,14 +166,14 @@ int ndr_decode_dos_attr(struct ndr *n, struct xattr_dos_attrib *da)
da->version = ndr_read_int16(n);
if (da->version != 3 && da->version != 4) {
- ksmbd_err("v%d version is not supported\n", da->version);
+ pr_err("v%d version is not supported\n", da->version);
return -EINVAL;
}
version2 = ndr_read_int32(n);
if (da->version != version2) {
- ksmbd_err("ndr version mismatched(version: %d, version2: %d)\n",
- da->version, version2);
+ pr_err("ndr version mismatched(version: %d, version2: %d)\n",
+ da->version, version2);
return -EINVAL;
}
@@ -210,20 +198,20 @@ static int ndr_encode_posix_acl_entry(struct ndr *n, struct xattr_smb_acl *acl)
int i;
ndr_write_int32(n, acl->count);
- align_offset(n, 8);
+ n->offset = ALIGN(n->offset, 8);
ndr_write_int32(n, acl->count);
ndr_write_int32(n, 0);
for (i = 0; i < acl->count; i++) {
- align_offset(n, 8);
+ n->offset = ALIGN(n->offset, 8);
ndr_write_int16(n, acl->entries[i].type);
ndr_write_int16(n, acl->entries[i].type);
if (acl->entries[i].type == SMB_ACL_USER) {
- align_offset(n, 8);
+ n->offset = ALIGN(n->offset, 8);
ndr_write_int64(n, acl->entries[i].uid);
} else if (acl->entries[i].type == SMB_ACL_GROUP) {
- align_offset(n, 8);
+ n->offset = ALIGN(n->offset, 8);
ndr_write_int64(n, acl->entries[i].gid);
}
@@ -234,7 +222,9 @@ static int ndr_encode_posix_acl_entry(struct ndr *n, struct xattr_smb_acl *acl)
return 0;
}
-int ndr_encode_posix_acl(struct ndr *n, struct inode *inode,
+int ndr_encode_posix_acl(struct ndr *n,
+ struct user_namespace *user_ns,
+ struct inode *inode,
struct xattr_smb_acl *acl,
struct xattr_smb_acl *def_acl)
{
@@ -262,8 +252,8 @@ int ndr_encode_posix_acl(struct ndr *n, struct inode *inode,
ndr_write_int32(n, 0);
}
- ndr_write_int64(n, from_kuid(&init_user_ns, inode->i_uid));
- ndr_write_int64(n, from_kgid(&init_user_ns, inode->i_gid));
+ ndr_write_int64(n, from_kuid(user_ns, inode->i_uid));
+ ndr_write_int64(n, from_kgid(user_ns, inode->i_gid));
ndr_write_int32(n, inode->i_mode);
if (acl) {
@@ -309,14 +299,14 @@ int ndr_decode_v4_ntacl(struct ndr *n, struct xattr_ntacl *acl)
n->offset = 0;
acl->version = ndr_read_int16(n);
if (acl->version != 4) {
- ksmbd_err("v%d version is not supported\n", acl->version);
+ pr_err("v%d version is not supported\n", acl->version);
return -EINVAL;
}
version2 = ndr_read_int32(n);
if (acl->version != version2) {
- ksmbd_err("ndr version mismatched(version: %d, version2: %d)\n",
- acl->version, version2);
+ pr_err("ndr version mismatched(version: %d, version2: %d)\n",
+ acl->version, version2);
return -EINVAL;
}
@@ -329,7 +319,7 @@ int ndr_decode_v4_ntacl(struct ndr *n, struct xattr_ntacl *acl)
ndr_read_bytes(n, acl->desc, 10);
if (strncmp(acl->desc, "posix_acl", 9)) {
- ksmbd_err("Invalid acl description : %s\n", acl->desc);
+ pr_err("Invalid acl description : %s\n", acl->desc);
return -EINVAL;
}
diff --git a/fs/cifsd/ndr.h b/fs/ksmbd/ndr.h
index 77b2d1ac93a0..60ca265d1bb0 100644
--- a/fs/cifsd/ndr.h
+++ b/fs/ksmbd/ndr.h
@@ -14,8 +14,8 @@ struct ndr {
int ndr_encode_dos_attr(struct ndr *n, struct xattr_dos_attrib *da);
int ndr_decode_dos_attr(struct ndr *n, struct xattr_dos_attrib *da);
-int ndr_encode_posix_acl(struct ndr *n, struct inode *inode,
- struct xattr_smb_acl *acl,
+int ndr_encode_posix_acl(struct ndr *n, struct user_namespace *user_ns,
+ struct inode *inode, struct xattr_smb_acl *acl,
struct xattr_smb_acl *def_acl);
int ndr_encode_v4_ntacl(struct ndr *n, struct xattr_ntacl *acl);
int ndr_encode_v3_ntacl(struct ndr *n, struct xattr_ntacl *acl);
diff --git a/fs/cifsd/nterr.h b/fs/ksmbd/nterr.h
index 2f358f88a018..2f358f88a018 100644
--- a/fs/cifsd/nterr.h
+++ b/fs/ksmbd/nterr.h
diff --git a/fs/cifsd/ntlmssp.h b/fs/ksmbd/ntlmssp.h
index adaf4c0cbe8f..adaf4c0cbe8f 100644
--- a/fs/cifsd/ntlmssp.h
+++ b/fs/ksmbd/ntlmssp.h
diff --git a/fs/cifsd/oplock.c b/fs/ksmbd/oplock.c
index 5868cdca7187..5484b5bf75b0 100644
--- a/fs/cifsd/oplock.c
+++ b/fs/ksmbd/oplock.c
@@ -11,7 +11,6 @@
#include "smb_common.h"
#include "smbstatus.h"
-#include "buffer_pool.h"
#include "connection.h"
#include "mgmt/user_session.h"
#include "mgmt/share_config.h"
@@ -40,7 +39,7 @@ static struct oplock_info *alloc_opinfo(struct ksmbd_work *work,
opinfo->sess = sess;
opinfo->conn = sess->conn;
- opinfo->level = OPLOCK_NONE;
+ opinfo->level = SMB2_OPLOCK_LEVEL_NONE;
opinfo->op_state = OPLOCK_STATE_NONE;
opinfo->pending_break = 0;
opinfo->fid = id;
@@ -231,9 +230,9 @@ int opinfo_write_to_read(struct oplock_info *opinfo)
if (!(opinfo->level == SMB2_OPLOCK_LEVEL_BATCH ||
opinfo->level == SMB2_OPLOCK_LEVEL_EXCLUSIVE)) {
- ksmbd_err("bad oplock(0x%x)\n", opinfo->level);
+ pr_err("bad oplock(0x%x)\n", opinfo->level);
if (opinfo->is_lease)
- ksmbd_err("lease state(0x%x)\n", lease->state);
+ pr_err("lease state(0x%x)\n", lease->state);
return -EINVAL;
}
opinfo->level = SMB2_OPLOCK_LEVEL_II;
@@ -270,9 +269,9 @@ int opinfo_write_to_none(struct oplock_info *opinfo)
if (!(opinfo->level == SMB2_OPLOCK_LEVEL_BATCH ||
opinfo->level == SMB2_OPLOCK_LEVEL_EXCLUSIVE)) {
- ksmbd_err("bad oplock(0x%x)\n", opinfo->level);
+ pr_err("bad oplock(0x%x)\n", opinfo->level);
if (opinfo->is_lease)
- ksmbd_err("lease state(0x%x)\n", lease->state);
+ pr_err("lease state(0x%x)\n", lease->state);
return -EINVAL;
}
opinfo->level = SMB2_OPLOCK_LEVEL_NONE;
@@ -292,9 +291,9 @@ int opinfo_read_to_none(struct oplock_info *opinfo)
struct lease *lease = opinfo->o_lease;
if (opinfo->level != SMB2_OPLOCK_LEVEL_II) {
- ksmbd_err("bad oplock(0x%x)\n", opinfo->level);
+ pr_err("bad oplock(0x%x)\n", opinfo->level);
if (opinfo->is_lease)
- ksmbd_err("lease state(0x%x)\n", lease->state);
+ pr_err("lease state(0x%x)\n", lease->state);
return -EINVAL;
}
opinfo->level = SMB2_OPLOCK_LEVEL_NONE;
@@ -623,7 +622,7 @@ static void __smb2_oplock_break_noti(struct work_struct *wk)
}
if (allocate_oplock_break_buf(work)) {
- ksmbd_err("smb2_allocate_rsp_buf failed! ");
+ pr_err("smb2_allocate_rsp_buf failed! ");
atomic_dec(&conn->r_count);
ksmbd_fd_put(work, fp);
ksmbd_free_work_struct(work);
@@ -632,7 +631,8 @@ static void __smb2_oplock_break_noti(struct work_struct *wk)
rsp_hdr = work->response_buf;
memset(rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
- rsp_hdr->smb2_buf_length = cpu_to_be32(HEADER_SIZE_NO_BUF_LEN(conn));
+ rsp_hdr->smb2_buf_length =
+ cpu_to_be32(smb2_hdr_size_no_buflen(conn->vals));
rsp_hdr->ProtocolId = SMB2_PROTO_NUMBER;
rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE;
rsp_hdr->CreditRequest = cpu_to_le16(0);
@@ -738,7 +738,8 @@ static void __smb2_lease_break_noti(struct work_struct *wk)
rsp_hdr = work->response_buf;
memset(rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
- rsp_hdr->smb2_buf_length = cpu_to_be32(HEADER_SIZE_NO_BUF_LEN(conn));
+ rsp_hdr->smb2_buf_length =
+ cpu_to_be32(smb2_hdr_size_no_buflen(conn->vals));
rsp_hdr->ProtocolId = SMB2_PROTO_NUMBER;
rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE;
rsp_hdr->CreditRequest = cpu_to_le16(0);
@@ -1110,7 +1111,9 @@ int smb_grant_oplock(struct ksmbd_work *work, int req_op_level, u64 pid,
goto set_lev;
/* grant none-oplock if second open is trunc */
- if (ATTR_FP(fp)) {
+ if (fp->attrib_only && fp->cdoption != FILE_OVERWRITE_IF_LE &&
+ fp->cdoption != FILE_OVERWRITE_LE &&
+ fp->cdoption != FILE_SUPERSEDE_LE) {
req_op_level = SMB2_OPLOCK_LEVEL_NONE;
goto set_lev;
}
@@ -1578,7 +1581,7 @@ void create_disk_id_rsp_buf(char *cc, __u64 file_id, __u64 vol_id)
void create_posix_rsp_buf(char *cc, struct ksmbd_file *fp)
{
struct create_posix_rsp *buf;
- struct inode *inode = FP_INODE(fp);
+ struct inode *inode = file_inode(fp->filp);
buf = (struct create_posix_rsp *)cc;
memset(buf, 0, sizeof(struct create_posix_rsp));
@@ -1609,9 +1612,9 @@ void create_posix_rsp_buf(char *cc, struct ksmbd_file *fp)
buf->nlink = cpu_to_le32(inode->i_nlink);
buf->reparse_tag = cpu_to_le32(fp->volatile_id);
buf->mode = cpu_to_le32(inode->i_mode);
- id_to_sid(from_kuid(&init_user_ns, inode->i_uid),
+ id_to_sid(from_kuid(file_mnt_user_ns(fp->filp), inode->i_uid),
SIDNFS_USER, (struct smb_sid *)&buf->SidBuffer[0]);
- id_to_sid(from_kgid(&init_user_ns, inode->i_gid),
+ id_to_sid(from_kgid(file_mnt_user_ns(fp->filp), inode->i_gid),
SIDNFS_GROUP, (struct smb_sid *)&buf->SidBuffer[20]);
}
@@ -1681,18 +1684,18 @@ int smb2_check_durable_oplock(struct ksmbd_file *fp,
if (opinfo && opinfo->is_lease) {
if (!lctx) {
- ksmbd_err("open does not include lease\n");
+ pr_err("open does not include lease\n");
ret = -EBADF;
goto out;
}
if (memcmp(opinfo->o_lease->lease_key, lctx->lease_key,
SMB2_LEASE_KEY_SIZE)) {
- ksmbd_err("invalid lease key\n");
+ pr_err("invalid lease key\n");
ret = -EBADF;
goto out;
}
if (name && strcmp(fp->filename, name)) {
- ksmbd_err("invalid name reconnect %s\n", name);
+ pr_err("invalid name reconnect %s\n", name);
ret = -EINVAL;
goto out;
}
diff --git a/fs/cifsd/oplock.h b/fs/ksmbd/oplock.h
index 9fb7ea74e86c..119b8047cfbd 100644
--- a/fs/cifsd/oplock.h
+++ b/fs/ksmbd/oplock.h
@@ -11,12 +11,6 @@
#define OPLOCK_WAIT_TIME (35 * HZ)
-/* SMB Oplock levels */
-#define OPLOCK_NONE 0
-#define OPLOCK_EXCLUSIVE 1
-#define OPLOCK_BATCH 2
-#define OPLOCK_READ 3 /* level 2 oplock */
-
/* SMB2 Oplock levels */
#define SMB2_OPLOCK_LEVEL_NONE 0x00
#define SMB2_OPLOCK_LEVEL_II 0x01
diff --git a/fs/cifsd/server.c b/fs/ksmbd/server.c
index a99963b849d5..a8c59e96a2f7 100644
--- a/fs/cifsd/server.c
+++ b/fs/ksmbd/server.c
@@ -16,7 +16,6 @@
#include "server.h"
#include "smb_common.h"
#include "smbstatus.h"
-#include "buffer_pool.h"
#include "connection.h"
#include "transport_ipc.h"
#include "mgmt/user_session.h"
@@ -278,7 +277,7 @@ static int queue_ksmbd_work(struct ksmbd_conn *conn)
work = ksmbd_alloc_work_struct();
if (!work) {
- ksmbd_err("allocation for work failed\n");
+ pr_err("allocation for work failed\n");
return -ENOMEM;
}
@@ -443,7 +442,7 @@ static ssize_t kill_server_store(struct class *class,
if (!sysfs_streq(buf, "hard"))
return len;
- ksmbd_info("kill command received\n");
+ pr_info("kill command received\n");
mutex_lock(&ctrl_lock);
WRITE_ONCE(server_conf.state, SERVER_STATE_RESETTING);
__module_get(THIS_MODULE);
@@ -536,7 +535,8 @@ static int ksmbd_server_shutdown(void)
ksmbd_crypto_destroy();
ksmbd_free_global_file_table();
destroy_lease_table(NULL);
- ksmbd_destroy_buffer_pools();
+ ksmbd_work_pool_destroy();
+ ksmbd_exit_file_cache();
server_conf_free();
return 0;
}
@@ -547,7 +547,7 @@ static int __init ksmbd_server_init(void)
ret = class_register(&ksmbd_control_class);
if (ret) {
- ksmbd_err("Unable to register ksmbd-control class\n");
+ pr_err("Unable to register ksmbd-control class\n");
return ret;
}
@@ -557,13 +557,17 @@ static int __init ksmbd_server_init(void)
if (ret)
goto err_unregister;
- ret = ksmbd_init_buffer_pools();
+ ret = ksmbd_work_pool_init();
if (ret)
goto err_unregister;
+ ret = ksmbd_init_file_cache();
+ if (ret)
+ goto err_destroy_work_pools;
+
ret = ksmbd_ipc_init();
if (ret)
- goto err_free_session_table;
+ goto err_exit_file_cache;
ret = ksmbd_init_global_file_table();
if (ret)
@@ -590,8 +594,10 @@ err_destroy_file_table:
ksmbd_free_global_file_table();
err_ipc_release:
ksmbd_ipc_release();
-err_free_session_table:
- ksmbd_destroy_buffer_pools();
+err_exit_file_cache:
+ ksmbd_exit_file_cache();
+err_destroy_work_pools:
+ ksmbd_work_pool_destroy();
err_unregister:
class_unregister(&ksmbd_control_class);
diff --git a/fs/cifsd/server.h b/fs/ksmbd/server.h
index b682d28963e8..ac9d932f8c8a 100644
--- a/fs/cifsd/server.h
+++ b/fs/ksmbd/server.h
@@ -8,14 +8,24 @@
#include "smbacl.h"
-#define SERVER_STATE_STARTING_UP 0
-#define SERVER_STATE_RUNNING 1
-#define SERVER_STATE_RESETTING 2
-#define SERVER_STATE_SHUTTING_DOWN 3
-
-#define SERVER_CONF_NETBIOS_NAME 0
-#define SERVER_CONF_SERVER_STRING 1
-#define SERVER_CONF_WORK_GROUP 2
+/*
+ * Server state type
+ */
+enum {
+ SERVER_STATE_STARTING_UP,
+ SERVER_STATE_RUNNING,
+ SERVER_STATE_RESETTING,
+ SERVER_STATE_SHUTTING_DOWN,
+};
+
+/*
+ * Server global config string index
+ */
+enum {
+ SERVER_CONF_NETBIOS_NAME,
+ SERVER_CONF_SERVER_STRING,
+ SERVER_CONF_WORK_GROUP,
+};
struct ksmbd_server_config {
unsigned int flags;
diff --git a/fs/cifsd/smb2misc.c b/fs/ksmbd/smb2misc.c
index c4b870dbf683..4508631c5706 100644
--- a/fs/cifsd/smb2misc.c
+++ b/fs/ksmbd/smb2misc.c
@@ -317,15 +317,13 @@ static int smb2_validate_credit_charge(struct smb2_hdr *hdr)
return 0;
}
+ credit_charge = max(1, credit_charge);
max_len = max(req_len, expect_resp_len);
calc_credit_num = DIV_ROUND_UP(max_len, SMB2_MAX_BUFFER_SIZE);
- if (!credit_charge && max_len > SMB2_MAX_BUFFER_SIZE) {
- ksmbd_err("credit charge is zero and payload size(%d) is bigger than 64K\n",
- max_len);
- return 1;
- } else if (credit_charge < calc_credit_num) {
- ksmbd_err("credit charge : %d, calc_credit_num : %d\n",
- credit_charge, calc_credit_num);
+
+ if (credit_charge < calc_credit_num) {
+ pr_err("Insufficient credit charge, given: %d, needed: %d\n",
+ credit_charge, calc_credit_num);
return 1;
}
@@ -341,7 +339,7 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work)
__u32 len = get_rfc1002_len(pdu);
if (work->next_smb2_rcv_hdr_off) {
- pdu = REQUEST_BUF_NEXT(work);
+ pdu = ksmbd_req_buf_next(work);
hdr = &pdu->hdr;
}
diff --git a/fs/cifsd/smb2ops.c b/fs/ksmbd/smb2ops.c
index 8999c3faf4fc..8262908e467c 100644
--- a/fs/cifsd/smb2ops.c
+++ b/fs/ksmbd/smb2ops.c
@@ -12,7 +12,6 @@
#include "connection.h"
#include "smb_common.h"
#include "server.h"
-#include "ksmbd_server.h"
static struct smb_version_values smb21_server_values = {
.version_string = SMB21_VERSION_STRING,
@@ -229,6 +228,9 @@ void init_smb3_0_server(struct ksmbd_conn *conn)
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION &&
conn->cli_cap & SMB2_GLOBAL_CAP_ENCRYPTION)
conn->vals->capabilities |= SMB2_GLOBAL_CAP_ENCRYPTION;
+
+ if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL)
+ conn->vals->capabilities |= SMB2_GLOBAL_CAP_MULTI_CHANNEL;
}
/**
@@ -250,6 +252,9 @@ void init_smb3_02_server(struct ksmbd_conn *conn)
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION &&
conn->cli_cap & SMB2_GLOBAL_CAP_ENCRYPTION)
conn->vals->capabilities |= SMB2_GLOBAL_CAP_ENCRYPTION;
+
+ if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL)
+ conn->vals->capabilities |= SMB2_GLOBAL_CAP_MULTI_CHANNEL;
}
/**
@@ -271,6 +276,9 @@ int init_smb3_11_server(struct ksmbd_conn *conn)
if (conn->cipher_type)
conn->vals->capabilities |= SMB2_GLOBAL_CAP_ENCRYPTION;
+ if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL)
+ conn->vals->capabilities |= SMB2_GLOBAL_CAP_MULTI_CHANNEL;
+
INIT_LIST_HEAD(&conn->preauth_sess_table);
return 0;
}
diff --git a/fs/cifsd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index ac15a9287310..dda90812feef 100644
--- a/fs/cifsd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -10,6 +10,7 @@
#include <linux/namei.h>
#include <linux/statfs.h>
#include <linux/ethtool.h>
+#include <linux/falloc.h>
#include "glob.h"
#include "smb2pdu.h"
@@ -19,7 +20,6 @@
#include "auth.h"
#include "asn1.h"
-#include "buffer_pool.h"
#include "connection.h"
#include "transport_ipc.h"
#include "vfs.h"
@@ -40,8 +40,8 @@
static void __wbuf(struct ksmbd_work *work, void **req, void **rsp)
{
if (work->next_smb2_rcv_hdr_off) {
- *req = REQUEST_BUF_NEXT(work);
- *rsp = RESPONSE_BUF_NEXT(work);
+ *req = ksmbd_req_buf_next(work);
+ *rsp = ksmbd_resp_buf_next(work);
} else {
*req = work->request_buf;
*rsp = work->response_buf;
@@ -64,21 +64,19 @@ static inline int check_session_id(struct ksmbd_conn *conn, u64 id)
if (id == 0 || id == -1)
return 0;
- sess = ksmbd_session_lookup(conn, id);
+ sess = ksmbd_session_lookup_all(conn, id);
if (sess)
return 1;
- ksmbd_err("Invalid user session id: %llu\n", id);
+ pr_err("Invalid user session id: %llu\n", id);
return 0;
}
-struct channel *lookup_chann_list(struct ksmbd_session *sess)
+struct channel *lookup_chann_list(struct ksmbd_session *sess, struct ksmbd_conn *conn)
{
struct channel *chann;
- struct list_head *t;
- list_for_each(t, &sess->ksmbd_chann_list) {
- chann = list_entry(t, struct channel, chann_list);
- if (chann && chann->conn == sess->conn)
+ list_for_each_entry(chann, &sess->ksmbd_chann_list, chann_list) {
+ if (chann->conn == conn)
return chann;
}
@@ -112,7 +110,7 @@ int smb2_get_ksmbd_tcon(struct ksmbd_work *work)
tree_id = le32_to_cpu(req_hdr->Id.SyncId.TreeId);
work->tcon = ksmbd_tree_conn_lookup(work->sess, tree_id);
if (!work->tcon) {
- ksmbd_err("Invalid tid %d\n", tree_id);
+ pr_err("Invalid tid %d\n", tree_id);
return -1;
}
@@ -128,7 +126,7 @@ void smb2_set_err_rsp(struct ksmbd_work *work)
struct smb2_err_rsp *err_rsp;
if (work->next_smb2_rcv_hdr_off)
- err_rsp = RESPONSE_BUF_NEXT(work);
+ err_rsp = ksmbd_resp_buf_next(work);
else
err_rsp = work->response_buf;
@@ -198,7 +196,7 @@ u16 get_smb2_cmd_val(struct ksmbd_work *work)
struct smb2_hdr *rcv_hdr;
if (work->next_smb2_rcv_hdr_off)
- rcv_hdr = REQUEST_BUF_NEXT(work);
+ rcv_hdr = ksmbd_req_buf_next(work);
else
rcv_hdr = work->request_buf;
return le16_to_cpu(rcv_hdr->Command);
@@ -214,7 +212,7 @@ void set_smb2_rsp_status(struct ksmbd_work *work, __le32 err)
struct smb2_hdr *rsp_hdr;
if (work->next_smb2_rcv_hdr_off)
- rsp_hdr = RESPONSE_BUF_NEXT(work);
+ rsp_hdr = ksmbd_resp_buf_next(work);
else
rsp_hdr = work->response_buf;
rsp_hdr->Status = err;
@@ -245,7 +243,7 @@ int init_smb2_neg_rsp(struct ksmbd_work *work)
memset(rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
rsp_hdr->smb2_buf_length =
- cpu_to_be32(HEADER_SIZE_NO_BUF_LEN(conn));
+ cpu_to_be32(smb2_hdr_size_no_buflen(conn->vals));
rsp_hdr->ProtocolId = SMB2_PROTO_NUMBER;
rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE;
@@ -317,8 +315,8 @@ static int smb2_consume_credit_charge(struct ksmbd_work *work,
*/
int smb2_set_rsp_credits(struct ksmbd_work *work)
{
- struct smb2_hdr *req_hdr = REQUEST_BUF_NEXT(work);
- struct smb2_hdr *hdr = RESPONSE_BUF_NEXT(work);
+ struct smb2_hdr *req_hdr = ksmbd_req_buf_next(work);
+ struct smb2_hdr *hdr = ksmbd_resp_buf_next(work);
struct ksmbd_conn *conn = work->conn;
unsigned short credits_requested = le16_to_cpu(req_hdr->CreditRequest);
unsigned short credit_charge = 1, credits_granted = 0;
@@ -332,7 +330,7 @@ int smb2_set_rsp_credits(struct ksmbd_work *work)
min_credits = conn->max_credits >> 4;
if (conn->total_credits >= conn->max_credits) {
- ksmbd_err("Total credits overflow: %d\n", conn->total_credits);
+ pr_err("Total credits overflow: %d\n", conn->total_credits);
conn->total_credits = min_credits;
}
@@ -385,8 +383,8 @@ out:
*/
static void init_chained_smb2_rsp(struct ksmbd_work *work)
{
- struct smb2_hdr *req = REQUEST_BUF_NEXT(work);
- struct smb2_hdr *rsp = RESPONSE_BUF_NEXT(work);
+ struct smb2_hdr *req = ksmbd_req_buf_next(work);
+ struct smb2_hdr *rsp = ksmbd_resp_buf_next(work);
struct smb2_hdr *rsp_hdr;
struct smb2_hdr *rcv_hdr;
int next_hdr_offset = 0;
@@ -424,8 +422,8 @@ static void init_chained_smb2_rsp(struct ksmbd_work *work)
new_len, work->next_smb2_rcv_hdr_off,
work->next_smb2_rsp_hdr_off);
- rsp_hdr = RESPONSE_BUF_NEXT(work);
- rcv_hdr = REQUEST_BUF_NEXT(work);
+ rsp_hdr = ksmbd_resp_buf_next(work);
+ rcv_hdr = ksmbd_req_buf_next(work);
if (!(rcv_hdr->Flags & SMB2_FLAGS_RELATED_OPERATIONS)) {
ksmbd_debug(SMB, "related flag should be set\n");
@@ -464,7 +462,7 @@ bool is_chained_smb2_message(struct ksmbd_work *work)
if (hdr->ProtocolId != SMB2_PROTO_NUMBER)
return false;
- hdr = REQUEST_BUF_NEXT(work);
+ hdr = ksmbd_req_buf_next(work);
if (le32_to_cpu(hdr->NextCommand) > 0) {
ksmbd_debug(SMB, "got SMB2 chained command\n");
init_chained_smb2_rsp(work);
@@ -499,7 +497,8 @@ int init_smb2_rsp_hdr(struct ksmbd_work *work)
struct ksmbd_conn *conn = work->conn;
memset(rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
- rsp_hdr->smb2_buf_length = cpu_to_be32(HEADER_SIZE_NO_BUF_LEN(conn));
+ rsp_hdr->smb2_buf_length =
+ cpu_to_be32(smb2_hdr_size_no_buflen(conn->vals));
rsp_hdr->ProtocolId = rcv_hdr->ProtocolId;
rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE;
rsp_hdr->Command = rcv_hdr->Command;
@@ -538,10 +537,8 @@ int smb2_allocate_rsp_buf(struct ksmbd_work *work)
size_t sz = small_sz;
int cmd = le16_to_cpu(hdr->Command);
- if (cmd == SMB2_IOCTL_HE || cmd == SMB2_QUERY_DIRECTORY_HE) {
+ if (cmd == SMB2_IOCTL_HE || cmd == SMB2_QUERY_DIRECTORY_HE)
sz = large_sz;
- work->set_trans_buf = true;
- }
if (cmd == SMB2_QUERY_INFO_HE) {
struct smb2_query_info_req *req;
@@ -549,22 +546,15 @@ int smb2_allocate_rsp_buf(struct ksmbd_work *work)
req = work->request_buf;
if (req->InfoType == SMB2_O_INFO_FILE &&
(req->FileInfoClass == FILE_FULL_EA_INFORMATION ||
- req->FileInfoClass == FILE_ALL_INFORMATION)) {
+ req->FileInfoClass == FILE_ALL_INFORMATION))
sz = large_sz;
- work->set_trans_buf = true;
- }
}
/* allocate large response buf for chained commands */
if (le32_to_cpu(hdr->NextCommand) > 0)
sz = large_sz;
- if (server_conf.flags & KSMBD_GLOBAL_FLAG_CACHE_TBUF &&
- work->set_trans_buf)
- work->response_buf = ksmbd_find_buffer(sz);
- else
- work->response_buf = kvmalloc(sz, GFP_KERNEL | __GFP_ZERO);
-
+ work->response_buf = kvmalloc(sz, GFP_KERNEL | __GFP_ZERO);
if (!work->response_buf)
return -ENOMEM;
@@ -600,7 +590,7 @@ int smb2_check_user_session(struct ksmbd_work *work)
sess_id = le64_to_cpu(req_hdr->SessionId);
/* Check for validity of user session */
- work->sess = ksmbd_session_lookup(conn, sess_id);
+ work->sess = ksmbd_session_lookup_all(conn, sess_id);
if (work->sess)
return 1;
ksmbd_debug(SMB, "Invalid user session, Uid %llu\n", sess_id);
@@ -646,7 +636,7 @@ smb2_get_name(struct ksmbd_share_config *share, const char *src,
name = smb_strndup_from_utf16(src, maxlen, 1, local_nls);
if (IS_ERR(name)) {
- ksmbd_err("failed to get name %ld\n", PTR_ERR(name));
+ pr_err("failed to get name %ld\n", PTR_ERR(name));
return name;
}
@@ -657,7 +647,7 @@ smb2_get_name(struct ksmbd_share_config *share, const char *src,
unixname = convert_to_unix_name(share, name);
kfree(name);
if (!unixname) {
- ksmbd_err("can not convert absolute name\n");
+ pr_err("can not convert absolute name\n");
return ERR_PTR(-ENOMEM);
}
@@ -676,7 +666,7 @@ int setup_async_work(struct ksmbd_work *work, void (*fn)(void **), void **arg)
id = ksmbd_acquire_async_msg_id(&conn->async_ida);
if (id < 0) {
- ksmbd_err("Failed to alloc async message id\n");
+ pr_err("Failed to alloc async message id\n");
return id;
}
work->syncronous = false;
@@ -1017,13 +1007,13 @@ int smb2_handle_negotiate(struct ksmbd_work *work)
ksmbd_debug(SMB, "Received negotiate request\n");
conn->need_neg = false;
if (ksmbd_conn_good(work)) {
- ksmbd_err("conn->tcp_status is already in CifsGood State\n");
+ pr_err("conn->tcp_status is already in CifsGood State\n");
work->send_no_response = 1;
return rc;
}
if (req->DialectCount == 0) {
- ksmbd_err("malformed packet\n");
+ pr_err("malformed packet\n");
rsp->hdr.Status = STATUS_INVALID_PARAMETER;
rc = -EINVAL;
goto err_out;
@@ -1043,8 +1033,8 @@ int smb2_handle_negotiate(struct ksmbd_work *work)
status = deassemble_neg_contexts(conn, req);
if (status != STATUS_SUCCESS) {
- ksmbd_err("deassemble_neg_contexts error(0x%x)\n",
- status);
+ pr_err("deassemble_neg_contexts error(0x%x)\n",
+ status);
rsp->hdr.Status = status;
rc = -EINVAL;
goto err_out;
@@ -1165,18 +1155,30 @@ static int generate_preauth_hash(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
struct ksmbd_session *sess = work->sess;
+ u8 *preauth_hash;
if (conn->dialect != SMB311_PROT_ID)
return 0;
- if (!sess->Preauth_HashValue) {
- if (alloc_preauth_hash(sess, conn))
- return -ENOMEM;
+ if (conn->binding) {
+ struct preauth_session *preauth_sess;
+
+ preauth_sess = ksmbd_preauth_session_lookup(conn, sess->id);
+ if (!preauth_sess) {
+ preauth_sess = ksmbd_preauth_session_alloc(conn, sess->id);
+ if (!preauth_sess)
+ return -ENOMEM;
+ }
+
+ preauth_hash = preauth_sess->Preauth_HashValue;
+ } else {
+ if (!sess->Preauth_HashValue)
+ if (alloc_preauth_hash(sess, conn))
+ return -ENOMEM;
+ preauth_hash = sess->Preauth_HashValue;
}
- ksmbd_gen_preauth_integrity_hash(conn,
- work->request_buf,
- sess->Preauth_HashValue);
+ ksmbd_gen_preauth_integrity_hash(conn, work->request_buf, preauth_hash);
return 0;
}
@@ -1293,7 +1295,7 @@ static struct ksmbd_user *session_user(struct ksmbd_conn *conn,
true,
conn->local_nls);
if (IS_ERR(name)) {
- ksmbd_err("cannot allocate memory\n");
+ pr_err("cannot allocate memory\n");
return NULL;
}
@@ -1383,15 +1385,19 @@ static int ntlm_authenticate(struct ksmbd_work *work)
* that it is reauthentication. And the user/password
* has been verified, so return it here.
*/
- if (sess->state == SMB2_SESSION_VALID)
+ if (sess->state == SMB2_SESSION_VALID) {
+ if (conn->binding)
+ goto binding_session;
return 0;
+ }
if ((conn->sign || server_conf.enforced_signing) ||
(req->SecurityMode & SMB2_NEGOTIATE_SIGNING_REQUIRED))
sess->sign = true;
if (conn->vals->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION &&
- conn->ops->generate_encryptionkey) {
+ conn->ops->generate_encryptionkey &&
+ !(req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) {
rc = conn->ops->generate_encryptionkey(sess);
if (rc) {
ksmbd_debug(SMB,
@@ -1409,8 +1415,9 @@ static int ntlm_authenticate(struct ksmbd_work *work)
}
}
+binding_session:
if (conn->dialect >= SMB30_PROT_ID) {
- chann = lookup_chann_list(sess);
+ chann = lookup_chann_list(sess, conn);
if (!chann) {
chann = kmalloc(sizeof(struct channel), GFP_KERNEL);
if (!chann)
@@ -1423,7 +1430,7 @@ static int ntlm_authenticate(struct ksmbd_work *work)
}
if (conn->ops->generate_signingkey) {
- rc = conn->ops->generate_signingkey(sess);
+ rc = conn->ops->generate_signingkey(sess, conn);
if (rc) {
ksmbd_debug(SMB, "SMB3 signing key generation failed\n");
rsp->hdr.Status = STATUS_LOGON_FAILURE;
@@ -1433,7 +1440,7 @@ static int ntlm_authenticate(struct ksmbd_work *work)
if (conn->dialect > SMB20_PROT_ID) {
if (!ksmbd_conn_lookup_dialect(conn)) {
- ksmbd_err("fail to verify the dialect\n");
+ pr_err("fail to verify the dialect\n");
rsp->hdr.Status = STATUS_USER_SESSION_DELETED;
return -EPERM;
}
@@ -1500,7 +1507,7 @@ static int krb5_authenticate(struct ksmbd_work *work)
}
if (conn->dialect >= SMB30_PROT_ID) {
- chann = lookup_chann_list(sess);
+ chann = lookup_chann_list(sess, conn);
if (!chann) {
chann = kmalloc(sizeof(struct channel), GFP_KERNEL);
if (!chann)
@@ -1513,7 +1520,7 @@ static int krb5_authenticate(struct ksmbd_work *work)
}
if (conn->ops->generate_signingkey) {
- retval = conn->ops->generate_signingkey(sess);
+ retval = conn->ops->generate_signingkey(sess, conn);
if (retval) {
ksmbd_debug(SMB, "SMB3 signing key generation failed\n");
rsp->hdr.Status = STATUS_LOGON_FAILURE;
@@ -1523,7 +1530,7 @@ static int krb5_authenticate(struct ksmbd_work *work)
if (conn->dialect > SMB20_PROT_ID) {
if (!ksmbd_conn_lookup_dialect(conn)) {
- ksmbd_err("fail to verify the dialect\n");
+ pr_err("fail to verify the dialect\n");
rsp->hdr.Status = STATUS_USER_SESSION_DELETED;
return -EPERM;
}
@@ -1562,12 +1569,59 @@ int smb2_sess_setup(struct ksmbd_work *work)
}
rsp->hdr.SessionId = cpu_to_le64(sess->id);
ksmbd_session_register(conn, sess);
+ } else if (conn->dialect >= SMB30_PROT_ID &&
+ (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL) &&
+ req->Flags & SMB2_SESSION_REQ_FLAG_BINDING) {
+ u64 sess_id = le64_to_cpu(req->hdr.SessionId);
+
+ sess = ksmbd_session_lookup_slowpath(sess_id);
+ if (!sess) {
+ rc = -ENOENT;
+ goto out_err;
+ }
+
+ if (conn->dialect != sess->conn->dialect) {
+ rc = -EINVAL;
+ goto out_err;
+ }
+
+ if (!(req->hdr.Flags & SMB2_FLAGS_SIGNED)) {
+ rc = -EINVAL;
+ goto out_err;
+ }
+
+ if (strncmp(conn->ClientGUID, sess->conn->ClientGUID,
+ SMB2_CLIENT_GUID_SIZE)) {
+ rc = -ENOENT;
+ goto out_err;
+ }
+
+ if (sess->state == SMB2_SESSION_IN_PROGRESS) {
+ rc = -EACCES;
+ goto out_err;
+ }
+
+ if (sess->state == SMB2_SESSION_EXPIRED) {
+ rc = -EFAULT;
+ goto out_err;
+ }
+
+ if (ksmbd_session_lookup(conn, sess_id)) {
+ rc = -EACCES;
+ goto out_err;
+ }
+
+ conn->binding = true;
+ } else if ((conn->dialect < SMB30_PROT_ID ||
+ server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL) &&
+ (req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) {
+ rc = -EACCES;
+ goto out_err;
} else {
sess = ksmbd_session_lookup(conn,
le64_to_cpu(req->hdr.SessionId));
if (!sess) {
rc = -ENOENT;
- rsp->hdr.Status = STATUS_USER_SESSION_DELETED;
goto out_err;
}
}
@@ -1585,15 +1639,15 @@ int smb2_sess_setup(struct ksmbd_work *work)
}
if (server_conf.auth_mechs & conn->auth_mechs) {
+ rc = generate_preauth_hash(work);
+ if (rc)
+ goto out_err;
+
if (conn->preferred_auth_mech &
(KSMBD_AUTH_KRB5 | KSMBD_AUTH_MSKRB5)) {
- rc = generate_preauth_hash(work);
- if (rc)
- goto out_err;
-
rc = krb5_authenticate(work);
if (rc) {
- rsp->hdr.Status = STATUS_INVALID_PARAMETER;
+ rc = -EINVAL;
goto out_err;
}
@@ -1602,10 +1656,6 @@ int smb2_sess_setup(struct ksmbd_work *work)
kfree(sess->Preauth_HashValue);
sess->Preauth_HashValue = NULL;
} else if (conn->preferred_auth_mech == KSMBD_AUTH_NTLMSSP) {
- rc = generate_preauth_hash(work);
- if (rc)
- goto out_err;
-
if (negblob->MessageType == NtLmNegotiate) {
rc = ntlm_negotiate(work, negblob);
if (rc)
@@ -1625,22 +1675,41 @@ int smb2_sess_setup(struct ksmbd_work *work)
ksmbd_conn_set_good(work);
sess->state = SMB2_SESSION_VALID;
+ if (conn->binding) {
+ struct preauth_session *preauth_sess;
+
+ preauth_sess =
+ ksmbd_preauth_session_lookup(conn, sess->id);
+ if (preauth_sess) {
+ list_del(&preauth_sess->preauth_entry);
+ kfree(preauth_sess);
+ }
+ }
kfree(sess->Preauth_HashValue);
sess->Preauth_HashValue = NULL;
}
} else {
/* TODO: need one more negotiation */
- ksmbd_err("Not support the preferred authentication\n");
+ pr_err("Not support the preferred authentication\n");
rc = -EINVAL;
- rsp->hdr.Status = STATUS_INVALID_PARAMETER;
}
} else {
- ksmbd_err("Not support authentication\n");
+ pr_err("Not support authentication\n");
rc = -EINVAL;
- rsp->hdr.Status = STATUS_INVALID_PARAMETER;
}
out_err:
+ if (rc == -EINVAL)
+ rsp->hdr.Status = STATUS_INVALID_PARAMETER;
+ else if (rc == -ENOENT)
+ rsp->hdr.Status = STATUS_USER_SESSION_DELETED;
+ else if (rc == -EACCES)
+ rsp->hdr.Status = STATUS_REQUEST_NOT_ACCEPTED;
+ else if (rc == -EFAULT)
+ rsp->hdr.Status = STATUS_NETWORK_SESSION_EXPIRED;
+ else if (rc)
+ rsp->hdr.Status = STATUS_LOGON_FAILURE;
+
if (conn->use_spnego && conn->mechToken) {
kfree(conn->mechToken);
conn->mechToken = NULL;
@@ -1675,7 +1744,7 @@ int smb2_tree_connect(struct ksmbd_work *work)
le16_to_cpu(req->PathLength), true,
conn->local_nls);
if (IS_ERR(treename)) {
- ksmbd_err("treename is NULL\n");
+ pr_err("treename is NULL\n");
status.ret = KSMBD_TREE_CONN_STATUS_ERROR;
goto out_err1;
}
@@ -1768,21 +1837,27 @@ out_err1:
* @file_present: is file already present
* @access: file access flags
* @disposition: file disposition flags
+ * @may_flags: set with MAY_ flags
*
* Return: file open flags
*/
static int smb2_create_open_flags(bool file_present, __le32 access,
- __le32 disposition)
+ __le32 disposition,
+ int *may_flags)
{
int oflags = O_NONBLOCK | O_LARGEFILE;
if (access & FILE_READ_DESIRED_ACCESS_LE &&
- access & FILE_WRITE_DESIRE_ACCESS_LE)
+ access & FILE_WRITE_DESIRE_ACCESS_LE) {
oflags |= O_RDWR;
- else if (access & FILE_WRITE_DESIRE_ACCESS_LE)
+ *may_flags = MAY_OPEN | MAY_READ | MAY_WRITE;
+ } else if (access & FILE_WRITE_DESIRE_ACCESS_LE) {
oflags |= O_WRONLY;
- else
+ *may_flags = MAY_OPEN | MAY_WRITE;
+ } else {
oflags |= O_RDONLY;
+ *may_flags = MAY_OPEN | MAY_READ;
+ }
if (access == FILE_READ_ATTRIBUTES_LE)
oflags |= O_PATH;
@@ -1816,6 +1891,7 @@ static int smb2_create_open_flags(bool file_present, __le32 access,
break;
}
}
+
return oflags;
}
@@ -1919,7 +1995,7 @@ static noinline int create_smb2_pipe(struct ksmbd_work *work)
id = ksmbd_session_rpc_open(work->sess, name);
if (id < 0) {
- ksmbd_err("Unable to open RPC pipe: %d\n", id);
+ pr_err("Unable to open RPC pipe: %d\n", id);
err = id;
goto out;
}
@@ -2005,14 +2081,16 @@ static int smb2_set_ea(struct smb2_ea_info *eabuf, struct path *path)
value = (char *)&eabuf->name + eabuf->EaNameLength + 1;
if (!eabuf->EaValueLength) {
- rc = ksmbd_vfs_casexattr_len(path->dentry,
+ rc = ksmbd_vfs_casexattr_len(mnt_user_ns(path->mnt),
+ path->dentry,
attr_name,
XATTR_USER_PREFIX_LEN +
eabuf->EaNameLength);
/* delete the EA only when it exits */
if (rc > 0) {
- rc = ksmbd_vfs_remove_xattr(path->dentry,
+ rc = ksmbd_vfs_remove_xattr(mnt_user_ns(path->mnt),
+ path->dentry,
attr_name);
if (rc < 0) {
@@ -2026,7 +2104,8 @@ static int smb2_set_ea(struct smb2_ea_info *eabuf, struct path *path)
/* if the EA doesn't exist, just do nothing. */
rc = 0;
} else {
- rc = ksmbd_vfs_setxattr(path->dentry, attr_name, value,
+ rc = ksmbd_vfs_setxattr(mnt_user_ns(path->mnt),
+ path->dentry, attr_name, value,
le16_to_cpu(eabuf->EaValueLength), 0);
if (rc < 0) {
ksmbd_debug(SMB,
@@ -2053,7 +2132,7 @@ static inline int check_context_err(void *ctx, char *str)
ksmbd_debug(SMB, "find context %s err %d\n", str, err);
if (err == -EINVAL) {
- ksmbd_err("bad name length\n");
+ pr_err("bad name length\n");
return err;
}
@@ -2079,7 +2158,8 @@ static noinline int smb2_set_stream_name_xattr(struct path *path,
fp->stream.size = xattr_stream_size;
/* Check if there is stream prefix in xattr space */
- rc = ksmbd_vfs_casexattr_len(path->dentry,
+ rc = ksmbd_vfs_casexattr_len(mnt_user_ns(path->mnt),
+ path->dentry,
xattr_stream_name,
xattr_stream_size);
if (rc >= 0)
@@ -2090,19 +2170,20 @@ static noinline int smb2_set_stream_name_xattr(struct path *path,
return -EBADF;
}
- rc = ksmbd_vfs_setxattr(path->dentry, xattr_stream_name, NULL, 0, 0);
+ rc = ksmbd_vfs_setxattr(mnt_user_ns(path->mnt),
+ path->dentry, xattr_stream_name, NULL, 0, 0);
if (rc < 0)
- ksmbd_err("Failed to store XATTR stream name :%d\n", rc);
+ pr_err("Failed to store XATTR stream name :%d\n", rc);
return 0;
}
-static int smb2_remove_smb_xattrs(struct dentry *dentry)
+static int smb2_remove_smb_xattrs(struct path *path)
{
char *name, *xattr_list = NULL;
ssize_t xattr_list_len;
int err = 0;
- xattr_list_len = ksmbd_vfs_listxattr(dentry, &xattr_list);
+ xattr_list_len = ksmbd_vfs_listxattr(path->dentry, &xattr_list);
if (xattr_list_len < 0) {
goto out;
} else if (!xattr_list_len) {
@@ -2120,7 +2201,8 @@ static int smb2_remove_smb_xattrs(struct dentry *dentry)
strncmp(&name[XATTR_USER_PREFIX_LEN], STREAM_PREFIX, STREAM_PREFIX_LEN))
continue;
- err = ksmbd_vfs_remove_xattr(dentry, name);
+ err = ksmbd_vfs_remove_xattr(mnt_user_ns(path->mnt),
+ path->dentry, name);
if (err)
ksmbd_debug(SMB, "remove xattr failed : %s\n", name);
}
@@ -2134,11 +2216,11 @@ static int smb2_create_truncate(struct path *path)
int rc = vfs_truncate(path, 0);
if (rc) {
- ksmbd_err("vfs_truncate failed, rc %d\n", rc);
+ pr_err("vfs_truncate failed, rc %d\n", rc);
return rc;
}
- rc = smb2_remove_smb_xattrs(path->dentry);
+ rc = smb2_remove_smb_xattrs(path);
if (rc == -EOPNOTSUPP)
rc = 0;
if (rc)
@@ -2164,7 +2246,8 @@ static void smb2_new_xattrs(struct ksmbd_tree_connect *tcon, struct path *path,
da.flags = XATTR_DOSINFO_ATTRIB | XATTR_DOSINFO_CREATE_TIME |
XATTR_DOSINFO_ITIME;
- rc = ksmbd_vfs_set_dos_attrib_xattr(path->dentry, &da);
+ rc = ksmbd_vfs_set_dos_attrib_xattr(mnt_user_ns(path->mnt),
+ path->dentry, &da);
if (rc)
ksmbd_debug(SMB, "failed to store file attribute into xattr\n");
}
@@ -2182,7 +2265,8 @@ static void smb2_update_xattrs(struct ksmbd_tree_connect *tcon,
KSMBD_SHARE_FLAG_STORE_DOS_ATTRS))
return;
- rc = ksmbd_vfs_get_dos_attrib_xattr(path->dentry, &da);
+ rc = ksmbd_vfs_get_dos_attrib_xattr(mnt_user_ns(path->mnt),
+ path->dentry, &da);
if (rc > 0) {
fp->f_ci->m_fattr = cpu_to_le32(da.attr);
fp->create_time = da.create_time;
@@ -2220,8 +2304,8 @@ static int smb2_creat(struct ksmbd_work *work, struct path *path, char *name,
rc = ksmbd_vfs_kern_path(name, 0, path, 0);
if (rc) {
- ksmbd_err("cannot get linux path (%s), err = %d\n",
- name, rc);
+ pr_err("cannot get linux path (%s), err = %d\n",
+ name, rc);
return rc;
}
return 0;
@@ -2229,7 +2313,7 @@ static int smb2_creat(struct ksmbd_work *work, struct path *path, char *name,
static int smb2_create_sd_buffer(struct ksmbd_work *work,
struct smb2_create_req *req,
- struct dentry *dentry)
+ struct path *path)
{
struct create_context *context;
int rc = -ENOENT;
@@ -2245,7 +2329,8 @@ static int smb2_create_sd_buffer(struct ksmbd_work *work,
ksmbd_debug(SMB,
"Set ACLs using SMB2_CREATE_SD_BUFFER context\n");
sd_buf = (struct create_sd_buf_req *)context;
- rc = set_info_sec(work->conn, work->tcon, dentry, &sd_buf->ntsd,
+ rc = set_info_sec(work->conn, work->tcon,
+ path, &sd_buf->ntsd,
le32_to_cpu(sd_buf->ccontext.DataLength), true);
}
@@ -2259,9 +2344,9 @@ static void ksmbd_acls_fattr(struct smb_fattr *fattr, struct inode *inode)
fattr->cf_mode = inode->i_mode;
fattr->cf_dacls = NULL;
- fattr->cf_acls = ksmbd_vfs_get_acl(inode, ACL_TYPE_ACCESS);
+ fattr->cf_acls = get_acl(inode, ACL_TYPE_ACCESS);
if (S_ISDIR(inode->i_mode))
- fattr->cf_dacls = ksmbd_vfs_get_acl(inode, ACL_TYPE_DEFAULT);
+ fattr->cf_dacls = get_acl(inode, ACL_TYPE_DEFAULT);
}
/**
@@ -2287,7 +2372,7 @@ int smb2_open(struct ksmbd_work *work)
struct create_ea_buf_req *ea_buf = NULL;
struct oplock_info *opinfo;
__le32 *next_ptr = NULL;
- int req_op_level = 0, open_flags = 0, file_info = 0;
+ int req_op_level = 0, open_flags = 0, may_flags = 0, file_info = 0;
int rc = 0, len = 0;
int contxt_cnt = 0, query_disk_id = 0;
int maximal_access_ctxt = 0, posix_ctxt = 0;
@@ -2320,7 +2405,7 @@ int smb2_open(struct ksmbd_work *work)
if (req->NameLength) {
if ((req->CreateOptions & FILE_DIRECTORY_FILE_LE) &&
*(char *)req->Buffer == '\\') {
- ksmbd_err("not allow directory name included leading slash\n");
+ pr_err("not allow directory name included leading slash\n");
rc = -EINVAL;
goto err_out1;
}
@@ -2377,16 +2462,16 @@ int smb2_open(struct ksmbd_work *work)
lc = parse_lease_state(req);
if (le32_to_cpu(req->ImpersonationLevel) > le32_to_cpu(IL_DELEGATE_LE)) {
- ksmbd_err("Invalid impersonationlevel : 0x%x\n",
- le32_to_cpu(req->ImpersonationLevel));
+ pr_err("Invalid impersonationlevel : 0x%x\n",
+ le32_to_cpu(req->ImpersonationLevel));
rc = -EIO;
rsp->hdr.Status = STATUS_BAD_IMPERSONATION_LEVEL;
goto err_out1;
}
if (req->CreateOptions && !(req->CreateOptions & CREATE_OPTIONS_MASK)) {
- ksmbd_err("Invalid create options : 0x%x\n",
- le32_to_cpu(req->CreateOptions));
+ pr_err("Invalid create options : 0x%x\n",
+ le32_to_cpu(req->CreateOptions));
rc = -EINVAL;
goto err_out1;
} else {
@@ -2413,22 +2498,22 @@ int smb2_open(struct ksmbd_work *work)
if (le32_to_cpu(req->CreateDisposition) >
le32_to_cpu(FILE_OVERWRITE_IF_LE)) {
- ksmbd_err("Invalid create disposition : 0x%x\n",
- le32_to_cpu(req->CreateDisposition));
+ pr_err("Invalid create disposition : 0x%x\n",
+ le32_to_cpu(req->CreateDisposition));
rc = -EINVAL;
goto err_out1;
}
if (!(req->DesiredAccess & DESIRED_ACCESS_MASK)) {
- ksmbd_err("Invalid desired access : 0x%x\n",
- le32_to_cpu(req->DesiredAccess));
+ pr_err("Invalid desired access : 0x%x\n",
+ le32_to_cpu(req->DesiredAccess));
rc = -EACCES;
goto err_out1;
}
if (req->FileAttributes && !(req->FileAttributes & ATTR_MASK_LE)) {
- ksmbd_err("Invalid file attribute : 0x%x\n",
- le32_to_cpu(req->FileAttributes));
+ pr_err("Invalid file attribute : 0x%x\n",
+ le32_to_cpu(req->FileAttributes));
rc = -EINVAL;
goto err_out1;
}
@@ -2557,7 +2642,7 @@ int smb2_open(struct ksmbd_work *work)
rc = 0;
} else {
file_present = true;
- generic_fillattr(&init_user_ns, d_inode(path.dentry), &stat);
+ generic_fillattr(mnt_user_ns(path.mnt), d_inode(path.dentry), &stat);
}
if (stream_name) {
if (req->CreateOptions & FILE_DIRECTORY_FILE_LE) {
@@ -2608,7 +2693,7 @@ int smb2_open(struct ksmbd_work *work)
daccess = smb_map_generic_desired_access(req->DesiredAccess);
if (file_present && !(req->CreateOptions & FILE_DELETE_ON_CLOSE_LE)) {
- rc = smb_check_perm_dacl(conn, path.dentry, &daccess,
+ rc = smb_check_perm_dacl(conn, &path, &daccess,
sess->user->uid);
if (rc)
goto err_out;
@@ -2618,7 +2703,8 @@ int smb2_open(struct ksmbd_work *work)
if (!file_present) {
daccess = cpu_to_le32(GENERIC_ALL_FLAGS);
} else {
- rc = ksmbd_vfs_query_maximal_access(path.dentry,
+ rc = ksmbd_vfs_query_maximal_access(mnt_user_ns(path.mnt),
+ path.dentry,
&daccess);
if (rc)
goto err_out;
@@ -2628,7 +2714,8 @@ int smb2_open(struct ksmbd_work *work)
}
open_flags = smb2_create_open_flags(file_present, daccess,
- req->CreateDisposition);
+ req->CreateDisposition,
+ &may_flags);
if (!test_tree_conn_flag(tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
if (open_flags & O_CREAT) {
@@ -2655,21 +2742,24 @@ int smb2_open(struct ksmbd_work *work)
goto err_out;
}
} else if (!already_permitted) {
- bool may_delete;
-
- may_delete = daccess & FILE_DELETE_LE ||
- req->CreateOptions & FILE_DELETE_ON_CLOSE_LE;
-
/* FILE_READ_ATTRIBUTE is allowed without inode_permission,
* because execute(search) permission on a parent directory,
* is already granted.
*/
if (daccess & ~(FILE_READ_ATTRIBUTES_LE | FILE_READ_CONTROL_LE)) {
- rc = ksmbd_vfs_inode_permission(path.dentry,
- open_flags & O_ACCMODE,
- may_delete);
+ rc = inode_permission(mnt_user_ns(path.mnt),
+ d_inode(path.dentry),
+ may_flags);
if (rc)
goto err_out;
+
+ if ((daccess & FILE_DELETE_LE) ||
+ (req->CreateOptions & FILE_DELETE_ON_CLOSE_LE)) {
+ rc = ksmbd_vfs_may_delete(mnt_user_ns(path.mnt),
+ path.dentry);
+ if (rc)
+ goto err_out;
+ }
}
}
@@ -2683,7 +2773,7 @@ int smb2_open(struct ksmbd_work *work)
filp = dentry_open(&path, open_flags, current_cred());
if (IS_ERR(filp)) {
rc = PTR_ERR(filp);
- ksmbd_err("dentry open for dir failed, rc %d\n", rc);
+ pr_err("dentry open for dir failed, rc %d\n", rc);
goto err_out;
}
@@ -2729,21 +2819,24 @@ int smb2_open(struct ksmbd_work *work)
int posix_acl_rc;
struct inode *inode = d_inode(path.dentry);
- posix_acl_rc = ksmbd_vfs_inherit_posix_acl(inode, d_inode(path.dentry->d_parent));
+ posix_acl_rc = ksmbd_vfs_inherit_posix_acl(mnt_user_ns(path.mnt),
+ inode,
+ d_inode(path.dentry->d_parent));
if (posix_acl_rc)
ksmbd_debug(SMB, "inherit posix acl failed : %d\n", posix_acl_rc);
if (test_share_config_flag(work->tcon->share_conf,
KSMBD_SHARE_FLAG_ACL_XATTR)) {
- rc = smb_inherit_dacl(conn, path.dentry, sess->user->uid,
+ rc = smb_inherit_dacl(conn, &path, sess->user->uid,
sess->user->gid);
}
if (rc) {
- rc = smb2_create_sd_buffer(work, req, path.dentry);
+ rc = smb2_create_sd_buffer(work, req, &path);
if (rc) {
if (posix_acl_rc)
- ksmbd_vfs_set_init_posix_acl(inode);
+ ksmbd_vfs_set_init_posix_acl(mnt_user_ns(path.mnt),
+ inode);
if (test_share_config_flag(work->tcon->share_conf,
KSMBD_SHARE_FLAG_ACL_XATTR)) {
@@ -2765,22 +2858,24 @@ int smb2_open(struct ksmbd_work *work)
if (!pntsd)
goto err_out;
- rc = build_sec_desc(pntsd, NULL,
+ rc = build_sec_desc(mnt_user_ns(path.mnt),
+ pntsd, NULL,
OWNER_SECINFO |
- GROUP_SECINFO |
- DACL_SECINFO,
+ GROUP_SECINFO |
+ DACL_SECINFO,
&pntsd_size, &fattr);
posix_acl_release(fattr.cf_acls);
posix_acl_release(fattr.cf_dacls);
rc = ksmbd_vfs_set_sd_xattr(conn,
+ mnt_user_ns(path.mnt),
path.dentry,
pntsd,
pntsd_size);
kfree(pntsd);
if (rc)
- ksmbd_err("failed to store ntacl in xattr : %d\n",
- rc);
+ pr_err("failed to store ntacl in xattr : %d\n",
+ rc);
}
}
}
@@ -2815,7 +2910,7 @@ int smb2_open(struct ksmbd_work *work)
rc = ksmbd_vfs_getattr(&path, &stat);
if (rc) {
- generic_fillattr(&init_user_ns, d_inode(path.dentry), &stat);
+ generic_fillattr(mnt_user_ns(path.mnt), d_inode(path.dentry), &stat);
rc = 0;
}
@@ -2829,7 +2924,7 @@ int smb2_open(struct ksmbd_work *work)
if (!test_share_config_flag(work->tcon->share_conf, KSMBD_SHARE_FLAG_OPLOCKS) ||
(req_op_level == SMB2_OPLOCK_LEVEL_LEASE &&
!(conn->vals->capabilities & SMB2_GLOBAL_CAP_LEASING))) {
- if (share_ret < 0 && !S_ISDIR(FP_INODE(fp)->i_mode)) {
+ if (share_ret < 0 && !S_ISDIR(file_inode(fp->filp)->i_mode)) {
rc = share_ret;
goto err_out;
}
@@ -2881,10 +2976,12 @@ int smb2_open(struct ksmbd_work *work)
ksmbd_debug(SMB,
"request smb2 create allocate size : %llu\n",
alloc_size);
- err = ksmbd_vfs_alloc_size(work, fp, alloc_size);
+ smb_break_all_levII_oplock(work, fp, 1);
+ err = vfs_fallocate(fp->filp, FALLOC_FL_KEEP_SIZE, 0,
+ alloc_size);
if (err < 0)
ksmbd_debug(SMB,
- "ksmbd_vfs_alloc_size is failed : %d\n",
+ "vfs_fallocate is failed : %d\n",
err);
}
@@ -2914,7 +3011,8 @@ int smb2_open(struct ksmbd_work *work)
memcpy(fp->client_guid, conn->ClientGUID, SMB2_CLIENT_GUID_SIZE);
- generic_fillattr(&init_user_ns, FP_INODE(fp), &stat);
+ generic_fillattr(file_mnt_user_ns(fp->filp), file_inode(fp->filp),
+ &stat);
rsp->StructureSize = cpu_to_le16(89);
rcu_read_lock();
@@ -2966,7 +3064,8 @@ int smb2_open(struct ksmbd_work *work)
struct create_context *mxac_ccontext;
if (maximal_access == 0)
- ksmbd_vfs_query_maximal_access(path.dentry,
+ ksmbd_vfs_query_maximal_access(mnt_user_ns(path.mnt),
+ path.dentry,
&maximal_access);
mxac_ccontext = (struct create_context *)(rsp->Buffer +
le32_to_cpu(rsp->CreateContextsLength));
@@ -3169,6 +3268,7 @@ static int dentry_name(struct ksmbd_dir_info *d_info, int info_level)
* @conn: connection instance
* @info_level: smb information level
* @d_info: structure included variables for query dir
+ * @user_ns: user namespace
* @ksmbd_kstat: ksmbd wrapper of dirent stat information
*
* if directory has many entries, find first can't read it fully.
@@ -3178,6 +3278,7 @@ static int dentry_name(struct ksmbd_dir_info *d_info, int info_level)
*/
static int smb2_populate_readdir_entry(struct ksmbd_conn *conn, int info_level,
struct ksmbd_dir_info *d_info,
+ struct user_namespace *user_ns,
struct ksmbd_kstat *ksmbd_kstat)
{
int next_entry_offset = 0;
@@ -3330,9 +3431,9 @@ static int smb2_populate_readdir_entry(struct ksmbd_conn *conn, int info_level,
S_ISDIR(ksmbd_kstat->kstat->mode) ? ATTR_DIRECTORY_LE : ATTR_ARCHIVE_LE;
if (d_info->hide_dot_file && d_info->name[0] == '.')
posix_info->DosAttributes |= ATTR_HIDDEN_LE;
- id_to_sid(from_kuid(&init_user_ns, ksmbd_kstat->kstat->uid),
+ id_to_sid(from_kuid(user_ns, ksmbd_kstat->kstat->uid),
SIDNFS_USER, (struct smb_sid *)&posix_info->SidBuffer[0]);
- id_to_sid(from_kgid(&init_user_ns, ksmbd_kstat->kstat->gid),
+ id_to_sid(from_kgid(user_ns, ksmbd_kstat->kstat->gid),
SIDNFS_GROUP, (struct smb_sid *)&posix_info->SidBuffer[20]);
memcpy(posix_info->name, conv_name, conv_len);
posix_info->name_len = cpu_to_le32(conv_len);
@@ -3414,12 +3515,14 @@ static int process_query_dir_entries(struct smb2_query_dir_private *priv)
ksmbd_kstat.kstat = &kstat;
if (priv->info_level != FILE_NAMES_INFORMATION)
ksmbd_vfs_fill_dentry_attrs(priv->work,
+ file_mnt_user_ns(priv->dir_fp->filp),
dent,
&ksmbd_kstat);
rc = smb2_populate_readdir_entry(priv->work->conn,
priv->info_level,
priv->d_info,
+ file_mnt_user_ns(priv->dir_fp->filp),
&ksmbd_kstat);
dput(dent);
if (rc)
@@ -3628,16 +3731,17 @@ int smb2_query_dir(struct ksmbd_work *work)
}
if (!(dir_fp->daccess & FILE_LIST_DIRECTORY_LE) ||
- inode_permission(&init_user_ns, file_inode(dir_fp->filp),
+ inode_permission(file_mnt_user_ns(dir_fp->filp),
+ file_inode(dir_fp->filp),
MAY_READ | MAY_EXEC)) {
- ksmbd_err("no right to enumerate directory (%s)\n",
- FP_FILENAME(dir_fp));
+ pr_err("no right to enumerate directory (%pd)\n",
+ dir_fp->filp->f_path.dentry);
rc = -EACCES;
goto err_out2;
}
if (!S_ISDIR(file_inode(dir_fp->filp)->i_mode)) {
- ksmbd_err("can't do query dir for a file\n");
+ pr_err("can't do query dir for a file\n");
rc = -EINVAL;
goto err_out2;
}
@@ -3695,7 +3799,7 @@ int smb2_query_dir(struct ksmbd_work *work)
dir_fp->readdir_data.private = &query_dir_private;
set_ctx_actor(&dir_fp->readdir_data.ctx, __query_dir);
- rc = ksmbd_vfs_readdir(dir_fp->filp, &dir_fp->readdir_data);
+ rc = iterate_dir(dir_fp->filp, &dir_fp->readdir_data.ctx);
if (rc == 0)
restart_ctx(&dir_fp->readdir_data.ctx);
if (rc == -ENOSPC)
@@ -3738,7 +3842,7 @@ int smb2_query_dir(struct ksmbd_work *work)
return 0;
err_out:
- ksmbd_err("error while processing smb2 query dir rc = %d\n", rc);
+ pr_err("error while processing smb2 query dir rc = %d\n", rc);
kfree(srch_ptr);
err_out2:
@@ -3776,7 +3880,7 @@ static int buffer_check_err(int reqOutputBufferLength,
{
if (reqOutputBufferLength < le32_to_cpu(rsp->OutputBufferLength)) {
if (reqOutputBufferLength < infoclass_size) {
- ksmbd_err("Invalid Buffer Size Requested\n");
+ pr_err("Invalid Buffer Size Requested\n");
rsp->hdr.Status = STATUS_INFO_LENGTH_MISMATCH;
rsp->hdr.smb2_buf_length = cpu_to_be32(sizeof(struct smb2_hdr) - 4);
return -EINVAL;
@@ -3879,8 +3983,8 @@ static int smb2_get_ea(struct ksmbd_work *work, struct ksmbd_file *fp,
struct path *path;
if (!(fp->daccess & FILE_READ_EA_LE)) {
- ksmbd_err("Not permitted to read ext attr : 0x%x\n",
- fp->daccess);
+ pr_err("Not permitted to read ext attr : 0x%x\n",
+ fp->daccess);
return -EACCES;
}
@@ -3953,7 +4057,8 @@ static int smb2_get_ea(struct ksmbd_work *work, struct ksmbd_file *fp,
buf_free_len -= (offsetof(struct smb2_ea_info, name) +
name_len + 1);
/* bailout if xattr can't fit in buf_free_len */
- value_len = ksmbd_vfs_getxattr(path->dentry, name, &buf);
+ value_len = ksmbd_vfs_getxattr(mnt_user_ns(path->mnt),
+ path->dentry, name, &buf);
if (value_len <= 0) {
rc = -ENOENT;
rsp->hdr.Status = STATUS_INVALID_HANDLE;
@@ -4036,13 +4141,14 @@ static int get_file_basic_info(struct smb2_query_info_rsp *rsp,
u64 time;
if (!(fp->daccess & FILE_READ_ATTRIBUTES_LE)) {
- ksmbd_err("no right to read the attributes : 0x%x\n",
- fp->daccess);
+ pr_err("no right to read the attributes : 0x%x\n",
+ fp->daccess);
return -EACCES;
}
basic_info = (struct smb2_file_all_info *)rsp->Buffer;
- generic_fillattr(&init_user_ns, FP_INODE(fp), &stat);
+ generic_fillattr(file_mnt_user_ns(fp->filp), file_inode(fp->filp),
+ &stat);
basic_info->CreationTime = cpu_to_le64(fp->create_time);
time = ksmbd_UnixTimeToNT(stat.atime);
basic_info->LastAccessTime = cpu_to_le64(time);
@@ -4082,8 +4188,8 @@ static void get_file_standard_info(struct smb2_query_info_rsp *rsp,
struct inode *inode;
struct kstat stat;
- inode = FP_INODE(fp);
- generic_fillattr(&init_user_ns, inode, &stat);
+ inode = file_inode(fp->filp);
+ generic_fillattr(file_mnt_user_ns(fp->filp), inode, &stat);
sinfo = (struct smb2_file_standard_info *)rsp->Buffer;
delete_pending = ksmbd_inode_pending_delete(fp);
@@ -4137,8 +4243,8 @@ static int get_file_all_info(struct ksmbd_work *work,
if (!filename)
return -ENOMEM;
- inode = FP_INODE(fp);
- generic_fillattr(&init_user_ns, inode, &stat);
+ inode = file_inode(fp->filp);
+ generic_fillattr(file_mnt_user_ns(fp->filp), inode, &stat);
ksmbd_debug(SMB, "filename = %s\n", filename);
delete_pending = ksmbd_inode_pending_delete(fp);
@@ -4185,14 +4291,15 @@ static void get_file_alternate_info(struct ksmbd_work *work,
{
struct ksmbd_conn *conn = work->conn;
struct smb2_file_alt_name_info *file_info;
+ struct dentry *dentry = fp->filp->f_path.dentry;
int conv_len;
- char *filename;
- filename = (char *)FP_FILENAME(fp);
+ spin_lock(&dentry->d_lock);
file_info = (struct smb2_file_alt_name_info *)rsp->Buffer;
conv_len = ksmbd_extract_shortname(conn,
- filename,
+ dentry->d_name.name,
file_info->FileName);
+ spin_unlock(&dentry->d_lock);
file_info->FileNameLength = cpu_to_le32(conv_len);
rsp->OutputBufferLength =
cpu_to_le32(sizeof(struct smb2_file_alt_name_info) + conv_len);
@@ -4212,7 +4319,8 @@ static void get_file_stream_info(struct ksmbd_work *work,
ssize_t xattr_list_len;
int nbytes = 0, streamlen, stream_name_len, next, idx = 0;
- generic_fillattr(&init_user_ns, FP_INODE(fp), &stat);
+ generic_fillattr(file_mnt_user_ns(fp->filp), file_inode(fp->filp),
+ &stat);
file_info = (struct smb2_file_stream_info *)rsp->Buffer;
xattr_list_len = ksmbd_vfs_listxattr(path->dentry, &xattr_list);
@@ -4291,7 +4399,8 @@ static void get_file_internal_info(struct smb2_query_info_rsp *rsp,
struct smb2_file_internal_info *file_info;
struct kstat stat;
- generic_fillattr(&init_user_ns, FP_INODE(fp), &stat);
+ generic_fillattr(file_mnt_user_ns(fp->filp), file_inode(fp->filp),
+ &stat);
file_info = (struct smb2_file_internal_info *)rsp->Buffer;
file_info->IndexNumber = cpu_to_le64(stat.ino);
rsp->OutputBufferLength =
@@ -4308,15 +4417,15 @@ static int get_file_network_open_info(struct smb2_query_info_rsp *rsp,
u64 time;
if (!(fp->daccess & FILE_READ_ATTRIBUTES_LE)) {
- ksmbd_err("no right to read the attributes : 0x%x\n",
- fp->daccess);
+ pr_err("no right to read the attributes : 0x%x\n",
+ fp->daccess);
return -EACCES;
}
file_info = (struct smb2_file_ntwrk_info *)rsp->Buffer;
- inode = FP_INODE(fp);
- generic_fillattr(&init_user_ns, inode, &stat);
+ inode = file_inode(fp->filp);
+ generic_fillattr(file_mnt_user_ns(fp->filp), inode, &stat);
file_info->CreationTime = cpu_to_le64(fp->create_time);
time = ksmbd_UnixTimeToNT(stat.atime);
@@ -4377,7 +4486,8 @@ static void get_file_compression_info(struct smb2_query_info_rsp *rsp,
struct smb2_file_comp_info *file_info;
struct kstat stat;
- generic_fillattr(&init_user_ns, FP_INODE(fp), &stat);
+ generic_fillattr(file_mnt_user_ns(fp->filp), file_inode(fp->filp),
+ &stat);
file_info = (struct smb2_file_comp_info *)rsp->Buffer;
file_info->CompressedFileSize = cpu_to_le64(stat.blocks << 9);
@@ -4398,8 +4508,8 @@ static int get_file_attribute_tag_info(struct smb2_query_info_rsp *rsp,
struct smb2_file_attr_tag_info *file_info;
if (!(fp->daccess & FILE_READ_ATTRIBUTES_LE)) {
- ksmbd_err("no right to read the attributes : 0x%x\n",
- fp->daccess);
+ pr_err("no right to read the attributes : 0x%x\n",
+ fp->daccess);
return -EACCES;
}
@@ -4416,7 +4526,7 @@ static int find_file_posix_info(struct smb2_query_info_rsp *rsp,
struct ksmbd_file *fp, void *rsp_org)
{
struct smb311_posix_qinfo *file_info;
- struct inode *inode = FP_INODE(fp);
+ struct inode *inode = file_inode(fp->filp);
u64 time;
file_info = (struct smb311_posix_qinfo *)rsp->Buffer;
@@ -4553,7 +4663,7 @@ static int smb2_get_info_file(struct ksmbd_work *work,
break;
case SMB_FIND_FILE_POSIX_INFO:
if (!work->tcon->posix_extensions) {
- ksmbd_err("client doesn't negotiate with SMB3.1.1 POSIX Extensions\n");
+ pr_err("client doesn't negotiate with SMB3.1.1 POSIX Extensions\n");
rc = -EOPNOTSUPP;
} else {
rc = find_file_posix_info(rsp, fp, rsp_org);
@@ -4592,13 +4702,13 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
rc = ksmbd_vfs_kern_path(share->path, lookup_flags, &path, 0);
if (rc) {
- ksmbd_err("cannot create vfs path\n");
+ pr_err("cannot create vfs path\n");
return -EIO;
}
rc = vfs_statfs(&path, &stfs);
if (rc) {
- ksmbd_err("cannot do stat of path %s\n", share->path);
+ pr_err("cannot do stat of path %s\n", share->path);
path_put(&path);
return -EIO;
}
@@ -4669,16 +4779,12 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
case FS_SIZE_INFORMATION:
{
struct filesystem_info *info;
- unsigned short logical_sector_size;
info = (struct filesystem_info *)(rsp->Buffer);
- logical_sector_size =
- ksmbd_vfs_logical_sector_size(d_inode(path.dentry));
-
info->TotalAllocationUnits = cpu_to_le64(stfs.f_blocks);
info->FreeAllocationUnits = cpu_to_le64(stfs.f_bfree);
- info->SectorsPerAllocationUnit = cpu_to_le32(stfs.f_bsize >> 9);
- info->BytesPerSector = cpu_to_le32(logical_sector_size);
+ info->SectorsPerAllocationUnit = cpu_to_le32(1);
+ info->BytesPerSector = cpu_to_le32(stfs.f_bsize);
rsp->OutputBufferLength = cpu_to_le32(24);
inc_rfc1001_len(rsp_org, 24);
fs_infoclass_size = FS_SIZE_INFORMATION_SIZE;
@@ -4687,19 +4793,15 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
case FS_FULL_SIZE_INFORMATION:
{
struct smb2_fs_full_size_info *info;
- unsigned short logical_sector_size;
info = (struct smb2_fs_full_size_info *)(rsp->Buffer);
- logical_sector_size =
- ksmbd_vfs_logical_sector_size(d_inode(path.dentry));
-
info->TotalAllocationUnits = cpu_to_le64(stfs.f_blocks);
info->CallerAvailableAllocationUnits =
cpu_to_le64(stfs.f_bavail);
info->ActualAvailableAllocationUnits =
cpu_to_le64(stfs.f_bfree);
- info->SectorsPerAllocationUnit = cpu_to_le32(stfs.f_bsize >> 9);
- info->BytesPerSector = cpu_to_le32(logical_sector_size);
+ info->SectorsPerAllocationUnit = cpu_to_le32(1);
+ info->BytesPerSector = cpu_to_le32(stfs.f_bsize);
rsp->OutputBufferLength = cpu_to_le32(32);
inc_rfc1001_len(rsp_org, 32);
fs_infoclass_size = FS_FULL_SIZE_INFORMATION_SIZE;
@@ -4729,19 +4831,15 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
case FS_SECTOR_SIZE_INFORMATION:
{
struct smb3_fs_ss_info *info;
- struct ksmbd_fs_sector_size fs_ss;
info = (struct smb3_fs_ss_info *)(rsp->Buffer);
- ksmbd_vfs_smb2_sector_size(d_inode(path.dentry), &fs_ss);
- info->LogicalBytesPerSector =
- cpu_to_le32(fs_ss.logical_sector_size);
+ info->LogicalBytesPerSector = cpu_to_le32(stfs.f_bsize);
info->PhysicalBytesPerSectorForAtomicity =
- cpu_to_le32(fs_ss.physical_sector_size);
- info->PhysicalBytesPerSectorForPerf =
- cpu_to_le32(fs_ss.optimal_io_size);
+ cpu_to_le32(stfs.f_bsize);
+ info->PhysicalBytesPerSectorForPerf = cpu_to_le32(stfs.f_bsize);
info->FSEffPhysicalBytesPerSectorForAtomicity =
- cpu_to_le32(fs_ss.optimal_io_size);
+ cpu_to_le32(stfs.f_bsize);
info->Flags = cpu_to_le32(SSINFO_FLAGS_ALIGNED_DEVICE |
SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
info->ByteOffsetForSectorAlignment = 0;
@@ -4776,16 +4874,13 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
case FS_POSIX_INFORMATION:
{
struct filesystem_posix_info *info;
- unsigned short logical_sector_size;
if (!work->tcon->posix_extensions) {
- ksmbd_err("client doesn't negotiate with SMB3.1.1 POSIX Extensions\n");
+ pr_err("client doesn't negotiate with SMB3.1.1 POSIX Extensions\n");
rc = -EOPNOTSUPP;
} else {
info = (struct filesystem_posix_info *)(rsp->Buffer);
- logical_sector_size =
- ksmbd_vfs_logical_sector_size(d_inode(path.dentry));
- info->OptimalTransferSize = cpu_to_le32(logical_sector_size);
+ info->OptimalTransferSize = cpu_to_le32(stfs.f_bsize);
info->BlockSize = cpu_to_le32(stfs.f_bsize);
info->TotalBlocks = cpu_to_le64(stfs.f_blocks);
info->BlocksAvail = cpu_to_le64(stfs.f_bfree);
@@ -4822,9 +4917,11 @@ static int smb2_get_info_sec(struct ksmbd_work *work,
int addition_info = le32_to_cpu(req->AdditionalInformation);
int rc;
- if (addition_info & ~(OWNER_SECINFO | GROUP_SECINFO | DACL_SECINFO)) {
- ksmbd_debug(SMB, "Unsupported addition info: 0x%x)\n",
- addition_info);
+ if (addition_info & ~(OWNER_SECINFO | GROUP_SECINFO | DACL_SECINFO |
+ PROTECTED_DACL_SECINFO |
+ UNPROTECTED_DACL_SECINFO)) {
+ pr_err("Unsupported addition info: 0x%x)\n",
+ addition_info);
pntsd->revision = cpu_to_le16(1);
pntsd->type = cpu_to_le16(SELF_RELATIVE | DACL_PROTECTED);
@@ -4858,14 +4955,16 @@ static int smb2_get_info_sec(struct ksmbd_work *work,
if (!fp)
return -ENOENT;
- inode = FP_INODE(fp);
+ inode = file_inode(fp->filp);
ksmbd_acls_fattr(&fattr, inode);
if (test_share_config_flag(work->tcon->share_conf,
KSMBD_SHARE_FLAG_ACL_XATTR))
- ksmbd_vfs_get_sd_xattr(work->conn, fp->filp->f_path.dentry, &ppntsd);
+ ksmbd_vfs_get_sd_xattr(work->conn, file_mnt_user_ns(fp->filp),
+ fp->filp->f_path.dentry, &ppntsd);
- rc = build_sec_desc(pntsd, ppntsd, addition_info, &secdesclen, &fattr);
+ rc = build_sec_desc(file_mnt_user_ns(fp->filp),
+ pntsd, ppntsd, addition_info, &secdesclen, &fattr);
posix_acl_release(fattr.cf_acls);
posix_acl_release(fattr.cf_dacls);
kfree(ppntsd);
@@ -5040,7 +5139,7 @@ int smb2_close(struct ksmbd_work *work)
goto out;
}
- inode = FP_INODE(fp);
+ inode = file_inode(fp->filp);
rsp->Flags = SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB;
rsp->AllocationSize = S_ISDIR(inode->i_mode) ? 0 :
cpu_to_le64(inode->i_blocks << 9);
@@ -5146,7 +5245,7 @@ static int smb2_rename(struct ksmbd_work *work, struct ksmbd_file *fp,
len = strlen(new_name);
if (new_name[len - 1] != '/') {
- ksmbd_err("not allow base filename in rename\n");
+ pr_err("not allow base filename in rename\n");
rc = -ESHARE;
goto out;
}
@@ -5158,12 +5257,13 @@ static int smb2_rename(struct ksmbd_work *work, struct ksmbd_file *fp,
if (rc)
goto out;
- rc = ksmbd_vfs_setxattr(fp->filp->f_path.dentry,
+ rc = ksmbd_vfs_setxattr(file_mnt_user_ns(fp->filp),
+ fp->filp->f_path.dentry,
xattr_stream_name,
NULL, 0, 0);
if (rc < 0) {
- ksmbd_err("failed to store stream name in xattr: %d\n",
- rc);
+ pr_err("failed to store stream name in xattr: %d\n",
+ rc);
rc = -EINVAL;
goto out;
}
@@ -5322,7 +5422,7 @@ static int set_file_basic_info(struct ksmbd_file *fp, char *buf,
if (file_info->Attributes) {
if (!S_ISDIR(inode->i_mode) &&
file_info->Attributes & ATTR_DIRECTORY_LE) {
- ksmbd_err("can't change a file to a directory\n");
+ pr_err("can't change a file to a directory\n");
return -EINVAL;
}
@@ -5342,7 +5442,8 @@ static int set_file_basic_info(struct ksmbd_file *fp, char *buf,
da.flags = XATTR_DOSINFO_ATTRIB | XATTR_DOSINFO_CREATE_TIME |
XATTR_DOSINFO_ITIME;
- rc = ksmbd_vfs_set_dos_attrib_xattr(filp->f_path.dentry, &da);
+ rc = ksmbd_vfs_set_dos_attrib_xattr(file_mnt_user_ns(filp),
+ filp->f_path.dentry, &da);
if (rc)
ksmbd_debug(SMB,
"failed to restore file attribute in EA\n");
@@ -5363,14 +5464,14 @@ static int set_file_basic_info(struct ksmbd_file *fp, char *buf,
if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
return -EACCES;
- rc = setattr_prepare(&init_user_ns, dentry, &attrs);
+ rc = setattr_prepare(file_mnt_user_ns(filp), dentry, &attrs);
if (rc)
return -EINVAL;
inode_lock(inode);
- setattr_copy(&init_user_ns, inode, &attrs);
+ setattr_copy(file_mnt_user_ns(filp), inode, &attrs);
attrs.ia_valid &= ~ATTR_CTIME;
- rc = notify_change(&init_user_ns, dentry, &attrs, NULL);
+ rc = notify_change(file_mnt_user_ns(filp), dentry, &attrs, NULL);
inode_unlock(inode);
}
return 0;
@@ -5398,9 +5499,11 @@ static int set_file_allocation_info(struct ksmbd_work *work,
inode = file_inode(fp->filp);
if (alloc_blks > inode->i_blocks) {
- rc = ksmbd_vfs_alloc_size(work, fp, alloc_blks * 512);
+ smb_break_all_levII_oplock(work, fp, 1);
+ rc = vfs_fallocate(fp->filp, FALLOC_FL_KEEP_SIZE, 0,
+ alloc_blks * 512);
if (rc && rc != -EOPNOTSUPP) {
- ksmbd_err("ksmbd_vfs_alloc_size is failed : %d\n", rc);
+ pr_err("vfs_fallocate is failed : %d\n", rc);
return rc;
}
} else if (alloc_blks < inode->i_blocks) {
@@ -5416,8 +5519,8 @@ static int set_file_allocation_info(struct ksmbd_work *work,
size = i_size_read(inode);
rc = ksmbd_vfs_truncate(work, NULL, fp, alloc_blks * 512);
if (rc) {
- ksmbd_err("truncate failed! filename : %s, err %d\n",
- fp->filename, rc);
+ pr_err("truncate failed! filename : %s, err %d\n",
+ fp->filename, rc);
return rc;
}
if (size < alloc_blks * 512)
@@ -5467,19 +5570,32 @@ static int set_rename_info(struct ksmbd_work *work, struct ksmbd_file *fp,
char *buf)
{
struct ksmbd_file *parent_fp;
+ struct dentry *parent;
+ struct dentry *dentry = fp->filp->f_path.dentry;
+ int ret;
if (!(fp->daccess & FILE_DELETE_LE)) {
- ksmbd_err("no right to delete : 0x%x\n", fp->daccess);
+ pr_err("no right to delete : 0x%x\n", fp->daccess);
return -EACCES;
}
if (ksmbd_stream_fd(fp))
goto next;
- parent_fp = ksmbd_lookup_fd_inode(PARENT_INODE(fp));
+ parent = dget_parent(dentry);
+ ret = ksmbd_vfs_lock_parent(parent, dentry);
+ if (ret) {
+ dput(parent);
+ return ret;
+ }
+
+ parent_fp = ksmbd_lookup_fd_inode(d_inode(parent));
+ inode_unlock(d_inode(parent));
+ dput(parent);
+
if (parent_fp) {
if (parent_fp->daccess & FILE_DELETE_LE) {
- ksmbd_err("parent dir is opened with delete access\n");
+ pr_err("parent dir is opened with delete access\n");
return -ESHARE;
}
}
@@ -5495,7 +5611,7 @@ static int set_file_disposition_info(struct ksmbd_file *fp, char *buf)
struct inode *inode;
if (!(fp->daccess & FILE_DELETE_LE)) {
- ksmbd_err("no right to delete : 0x%x\n", fp->daccess);
+ pr_err("no right to delete : 0x%x\n", fp->daccess);
return -EACCES;
}
@@ -5516,19 +5632,19 @@ static int set_file_position_info(struct ksmbd_file *fp, char *buf)
{
struct smb2_file_pos_info *file_info;
loff_t current_byte_offset;
- unsigned short sector_size;
+ unsigned long sector_size;
struct inode *inode;
inode = file_inode(fp->filp);
file_info = (struct smb2_file_pos_info *)buf;
current_byte_offset = le64_to_cpu(file_info->CurrentByteOffset);
- sector_size = ksmbd_vfs_logical_sector_size(inode);
+ sector_size = inode->i_sb->s_blocksize;
if (current_byte_offset < 0 ||
(fp->coption == FILE_NO_INTERMEDIATE_BUFFERING_LE &&
current_byte_offset & (sector_size - 1))) {
- ksmbd_err("CurrentByteOffset is not valid : %llu\n",
- current_byte_offset);
+ pr_err("CurrentByteOffset is not valid : %llu\n",
+ current_byte_offset);
return -EINVAL;
}
@@ -5547,7 +5663,7 @@ static int set_file_mode_info(struct ksmbd_file *fp, char *buf)
if ((mode & ~FILE_MODE_INFO_MASK) ||
(mode & FILE_SYNCHRONOUS_IO_ALERT_LE &&
mode & FILE_SYNCHRONOUS_IO_NONALERT_LE)) {
- ksmbd_err("Mode is not valid : 0x%x\n", le32_to_cpu(mode));
+ pr_err("Mode is not valid : 0x%x\n", le32_to_cpu(mode));
return -EINVAL;
}
@@ -5608,8 +5724,8 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
case FILE_FULL_EA_INFORMATION:
{
if (!(fp->daccess & FILE_WRITE_EA_LE)) {
- ksmbd_err("Not permitted to write ext attr: 0x%x\n",
- fp->daccess);
+ pr_err("Not permitted to write ext attr: 0x%x\n",
+ fp->daccess);
return -EACCES;
}
@@ -5624,7 +5740,7 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
return set_file_mode_info(fp, buf);
}
- ksmbd_err("Unimplemented Fileinfoclass :%d\n", info_class);
+ pr_err("Unimplemented Fileinfoclass :%d\n", info_class);
return -EOPNOTSUPP;
}
@@ -5635,7 +5751,7 @@ static int smb2_set_info_sec(struct ksmbd_file *fp, int addition_info,
fp->saccess |= FILE_SHARE_DELETE_LE;
- return set_info_sec(fp->conn, fp->tcon, fp->filp->f_path.dentry, pntsd,
+ return set_info_sec(fp->conn, fp->tcon, &fp->filp->f_path, pntsd,
buf_len, false);
}
@@ -5657,8 +5773,8 @@ int smb2_set_info(struct ksmbd_work *work)
rsp_org = work->response_buf;
if (work->next_smb2_rcv_hdr_off) {
- req = REQUEST_BUF_NEXT(work);
- rsp = RESPONSE_BUF_NEXT(work);
+ req = ksmbd_req_buf_next(work);
+ rsp = ksmbd_resp_buf_next(work);
if (!HAS_FILE_ID(le64_to_cpu(req->VolatileFileId))) {
ksmbd_debug(SMB, "Compound request set FID = %u\n",
work->compound_fid);
@@ -5852,7 +5968,7 @@ int smb2_read(struct ksmbd_work *work)
}
if (!(fp->daccess & (FILE_READ_DATA_LE | FILE_READ_ATTRIBUTES_LE))) {
- ksmbd_err("Not permitted to read : 0x%x\n", fp->daccess);
+ pr_err("Not permitted to read : 0x%x\n", fp->daccess);
err = -EACCES;
goto out;
}
@@ -5868,16 +5984,10 @@ int smb2_read(struct ksmbd_work *work)
goto out;
}
- ksmbd_debug(SMB, "filename %s, offset %lld, len %zu\n", FP_FILENAME(fp),
- offset, length);
+ ksmbd_debug(SMB, "filename %pd, offset %lld, len %zu\n",
+ fp->filp->f_path.dentry, offset, length);
- if (server_conf.flags & KSMBD_GLOBAL_FLAG_CACHE_RBUF) {
- work->aux_payload_buf =
- ksmbd_find_buffer(conn->vals->max_read_size);
- work->set_read_buf = true;
- } else {
- work->aux_payload_buf = kvmalloc(length, GFP_KERNEL | __GFP_ZERO);
- }
+ work->aux_payload_buf = kvmalloc(length, GFP_KERNEL | __GFP_ZERO);
if (!work->aux_payload_buf) {
err = -ENOMEM;
goto out;
@@ -5890,10 +6000,7 @@ int smb2_read(struct ksmbd_work *work)
}
if ((nbytes == 0 && length != 0) || nbytes < mincount) {
- if (server_conf.flags & KSMBD_GLOBAL_FLAG_CACHE_RBUF)
- ksmbd_release_buffer(work->aux_payload_buf);
- else
- kvfree(work->aux_payload_buf);
+ kvfree(work->aux_payload_buf);
work->aux_payload_buf = NULL;
rsp->hdr.Status = STATUS_END_OF_FILE;
smb2_set_err_rsp(work);
@@ -5910,10 +6017,7 @@ int smb2_read(struct ksmbd_work *work)
remain_bytes = smb2_read_rdma_channel(work, req,
work->aux_payload_buf,
nbytes);
- if (server_conf.flags & KSMBD_GLOBAL_FLAG_CACHE_RBUF)
- ksmbd_release_buffer(work->aux_payload_buf);
- else
- kvfree(work->aux_payload_buf);
+ kvfree(work->aux_payload_buf);
work->aux_payload_buf = NULL;
nbytes = 0;
@@ -5984,9 +6088,9 @@ static noinline int smb2_write_pipe(struct ksmbd_work *work)
} else {
if ((le16_to_cpu(req->DataOffset) > get_rfc1002_len(req)) ||
(le16_to_cpu(req->DataOffset) + length > get_rfc1002_len(req))) {
- ksmbd_err("invalid write data offset %u, smb_len %u\n",
- le16_to_cpu(req->DataOffset),
- get_rfc1002_len(req));
+ pr_err("invalid write data offset %u, smb_len %u\n",
+ le16_to_cpu(req->DataOffset),
+ get_rfc1002_len(req));
err = -EINVAL;
goto out;
}
@@ -6117,7 +6221,7 @@ int smb2_write(struct ksmbd_work *work)
}
if (!(fp->daccess & (FILE_WRITE_DATA_LE | FILE_READ_ATTRIBUTES_LE))) {
- ksmbd_err("Not permitted to write : 0x%x\n", fp->daccess);
+ pr_err("Not permitted to write : 0x%x\n", fp->daccess);
err = -EACCES;
goto out;
}
@@ -6143,9 +6247,9 @@ int smb2_write(struct ksmbd_work *work)
} else {
if ((le16_to_cpu(req->DataOffset) > get_rfc1002_len(req)) ||
(le16_to_cpu(req->DataOffset) + length > get_rfc1002_len(req))) {
- ksmbd_err("invalid write data offset %u, smb_len %u\n",
- le16_to_cpu(req->DataOffset),
- get_rfc1002_len(req));
+ pr_err("invalid write data offset %u, smb_len %u\n",
+ le16_to_cpu(req->DataOffset),
+ get_rfc1002_len(req));
err = -EINVAL;
goto out;
}
@@ -6158,8 +6262,8 @@ int smb2_write(struct ksmbd_work *work)
if (le32_to_cpu(req->Flags) & SMB2_WRITEFLAG_WRITE_THROUGH)
writethrough = true;
- ksmbd_debug(SMB, "filename %s, offset %lld, len %zu\n",
- FP_FILENAME(fp), offset, length);
+ ksmbd_debug(SMB, "filename %pd, offset %lld, len %zu\n",
+ fp->filp->f_path.dentry, offset, length);
err = ksmbd_vfs_write(work, fp, data_buf, length, &offset,
writethrough, &nbytes);
if (err < 0)
@@ -6258,7 +6362,6 @@ int smb2_cancel(struct ksmbd_work *work)
struct smb2_hdr *hdr = work->request_buf;
struct smb2_hdr *chdr;
struct ksmbd_work *cancel_work = NULL;
- struct list_head *tmp;
int canceled = 0;
struct list_head *command_list;
@@ -6269,9 +6372,8 @@ int smb2_cancel(struct ksmbd_work *work)
command_list = &conn->async_requests;
spin_lock(&conn->request_lock);
- list_for_each(tmp, command_list) {
- cancel_work = list_entry(tmp, struct ksmbd_work,
- async_request_entry);
+ list_for_each_entry(cancel_work, command_list,
+ async_request_entry) {
chdr = cancel_work->request_buf;
if (cancel_work->async_id !=
@@ -6290,9 +6392,7 @@ int smb2_cancel(struct ksmbd_work *work)
command_list = &conn->requests;
spin_lock(&conn->request_lock);
- list_for_each(tmp, command_list) {
- cancel_work = list_entry(tmp, struct ksmbd_work,
- request_entry);
+ list_for_each_entry(cancel_work, command_list, request_entry) {
chdr = cancel_work->request_buf;
if (chdr->MessageId != hdr->MessageId ||
@@ -6479,7 +6579,7 @@ int smb2_lock(struct ksmbd_work *work)
lock_start = le64_to_cpu(lock_ele[i].Offset);
lock_length = le64_to_cpu(lock_ele[i].Length);
if (lock_start > U64_MAX - lock_length) {
- ksmbd_err("Invalid lock range requested\n");
+ pr_err("Invalid lock range requested\n");
rsp->hdr.Status = STATUS_INVALID_LOCK_RANGE;
goto out;
}
@@ -6509,7 +6609,7 @@ int smb2_lock(struct ksmbd_work *work)
cmp_lock->fl->fl_end >= flock->fl_end) {
if (cmp_lock->fl->fl_type != F_UNLCK &&
flock->fl_type != F_UNLCK) {
- ksmbd_err("conflict two locks in one request\n");
+ pr_err("conflict two locks in one request\n");
rsp->hdr.Status =
STATUS_INVALID_PARAMETER;
goto out;
@@ -6582,7 +6682,7 @@ int smb2_lock(struct ksmbd_work *work)
if (cmp_lock->zero_len && !smb_lock->zero_len &&
cmp_lock->start > smb_lock->start &&
cmp_lock->start < smb_lock->end) {
- ksmbd_err("previous lock conflict with zero byte lock range\n");
+ pr_err("previous lock conflict with zero byte lock range\n");
rsp->hdr.Status = STATUS_LOCK_NOT_GRANTED;
goto out;
}
@@ -6590,7 +6690,7 @@ int smb2_lock(struct ksmbd_work *work)
if (smb_lock->zero_len && !cmp_lock->zero_len &&
smb_lock->start > cmp_lock->start &&
smb_lock->start < cmp_lock->end) {
- ksmbd_err("current lock conflict with zero byte lock range\n");
+ pr_err("current lock conflict with zero byte lock range\n");
rsp->hdr.Status = STATUS_LOCK_NOT_GRANTED;
goto out;
}
@@ -6599,7 +6699,7 @@ int smb2_lock(struct ksmbd_work *work)
cmp_lock->end > smb_lock->start) ||
(cmp_lock->start < smb_lock->end && cmp_lock->end >= smb_lock->end)) &&
!cmp_lock->zero_len && !smb_lock->zero_len) {
- ksmbd_err("Not allow lock operation on exclusive lock range\n");
+ pr_err("Not allow lock operation on exclusive lock range\n");
rsp->hdr.Status =
STATUS_LOCK_NOT_GRANTED;
goto out;
@@ -6607,7 +6707,7 @@ int smb2_lock(struct ksmbd_work *work)
}
if (smb_lock->fl->fl_type == F_UNLCK && nolock) {
- ksmbd_err("Try to unlock nolocked range\n");
+ pr_err("Try to unlock nolocked range\n");
rsp->hdr.Status = STATUS_RANGE_NOT_LOCKED;
goto out;
}
@@ -6621,7 +6721,7 @@ no_check_gl:
flock = smb_lock->fl;
list_del(&smb_lock->llist);
retry:
- err = ksmbd_vfs_lock(filp, smb_lock->cmd, flock);
+ err = vfs_lock_file(filp, smb_lock->cmd, flock, NULL);
skip:
if (flags & SMB2_LOCKFLAG_UNLOCK) {
if (!err) {
@@ -6665,12 +6765,12 @@ skip:
err = ksmbd_vfs_posix_lock_wait(flock);
- if (!WORK_ACTIVE(work)) {
+ if (work->state != KSMBD_WORK_ACTIVE) {
list_del(&smb_lock->llist);
list_del(&smb_lock->glist);
locks_free_lock(flock);
- if (WORK_CANCELLED(work)) {
+ if (work->state == KSMBD_WORK_CANCELLED) {
spin_lock(&fp->f_lock);
list_del(&work->fp_entry);
spin_unlock(&fp->f_lock);
@@ -6734,9 +6834,9 @@ out:
rlock->fl_start = smb_lock->start;
rlock->fl_end = smb_lock->end;
- err = ksmbd_vfs_lock(filp, 0, rlock);
+ err = vfs_lock_file(filp, 0, rlock, NULL);
if (err)
- ksmbd_err("rollback unlock fail : %d\n", err);
+ pr_err("rollback unlock fail : %d\n", err);
list_del(&smb_lock->llist);
list_del(&smb_lock->glist);
locks_free_lock(smb_lock->fl);
@@ -6923,8 +7023,8 @@ static int fsctl_query_iface_info_ioctl(struct ksmbd_conn *conn,
netdev->ethtool_ops->get_link_ksettings(netdev, &cmd);
speed = cmd.base.speed;
} else {
- ksmbd_err("%s %s\n", netdev->name,
- "speed is unknown, defaulting to 1Gb/sec");
+ pr_err("%s %s\n", netdev->name,
+ "speed is unknown, defaulting to 1Gb/sec");
speed = SPEED_1000;
}
@@ -7119,12 +7219,14 @@ static inline int fsctl_set_sparse(struct ksmbd_work *work, u64 id,
KSMBD_SHARE_FLAG_STORE_DOS_ATTRS)) {
struct xattr_dos_attrib da;
- ret = ksmbd_vfs_get_dos_attrib_xattr(fp->filp->f_path.dentry, &da);
+ ret = ksmbd_vfs_get_dos_attrib_xattr(file_mnt_user_ns(fp->filp),
+ fp->filp->f_path.dentry, &da);
if (ret <= 0)
goto out;
da.attr = le32_to_cpu(fp->f_ci->m_fattr);
- ret = ksmbd_vfs_set_dos_attrib_xattr(fp->filp->f_path.dentry, &da);
+ ret = ksmbd_vfs_set_dos_attrib_xattr(file_mnt_user_ns(fp->filp),
+ fp->filp->f_path.dentry, &da);
if (ret)
fp->f_ci->m_fattr = old_fattr;
}
@@ -7172,8 +7274,8 @@ int smb2_ioctl(struct ksmbd_work *work)
rsp_org = work->response_buf;
if (work->next_smb2_rcv_hdr_off) {
- req = REQUEST_BUF_NEXT(work);
- rsp = RESPONSE_BUF_NEXT(work);
+ req = ksmbd_req_buf_next(work);
+ rsp = ksmbd_resp_buf_next(work);
if (!HAS_FILE_ID(le64_to_cpu(req->VolatileFileId))) {
ksmbd_debug(SMB, "Compound request set FID = %u\n",
work->compound_fid);
@@ -7336,13 +7438,13 @@ int smb2_ioctl(struct ksmbd_work *work)
reparse_ptr = (struct reparse_data_buffer *)&rsp->Buffer[0];
fp = ksmbd_lookup_fd_fast(work, id);
if (!fp) {
- ksmbd_err("not found fp!!\n");
+ pr_err("not found fp!!\n");
ret = -ENOENT;
goto out;
}
reparse_ptr->ReparseTag =
- smb2_get_reparse_tag_special_file(FP_INODE(fp)->i_mode);
+ smb2_get_reparse_tag_special_file(file_inode(fp->filp)->i_mode);
reparse_ptr->ReparseDataLength = 0;
ksmbd_fd_put(work, fp);
nbytes = sizeof(struct reparse_data_buffer);
@@ -7359,14 +7461,14 @@ int smb2_ioctl(struct ksmbd_work *work)
fp_in = ksmbd_lookup_fd_slow(work, dup_ext->VolatileFileHandle,
dup_ext->PersistentFileHandle);
if (!fp_in) {
- ksmbd_err("not found file handle in duplicate extent to file\n");
+ pr_err("not found file handle in duplicate extent to file\n");
ret = -ENOENT;
goto out;
}
fp_out = ksmbd_lookup_fd_fast(work, id);
if (!fp_out) {
- ksmbd_err("not found fp\n");
+ pr_err("not found fp\n");
ret = -ENOENT;
goto dup_ext_out;
}
@@ -7380,8 +7482,8 @@ int smb2_ioctl(struct ksmbd_work *work)
ret = -EOPNOTSUPP;
goto dup_ext_out;
} else if (cloned != length) {
- cloned = ksmbd_vfs_copy_file_range(fp_in->filp, src_off,
- fp_out->filp, dst_off, length);
+ cloned = vfs_copy_file_range(fp_in->filp, src_off,
+ fp_out->filp, dst_off, length, 0);
if (cloned != length) {
if (cloned < 0)
ret = cloned;
@@ -7463,7 +7565,7 @@ static void smb20_oplock_break_ack(struct ksmbd_work *work)
opinfo = opinfo_get(fp);
if (!opinfo) {
- ksmbd_err("unexpected null oplock_info\n");
+ pr_err("unexpected null oplock_info\n");
rsp->hdr.Status = STATUS_INVALID_OPLOCK_PROTOCOL;
smb2_set_err_rsp(work);
ksmbd_fd_put(work, fp);
@@ -7526,8 +7628,8 @@ static void smb20_oplock_break_ack(struct ksmbd_work *work)
rsp_oplevel = SMB2_OPLOCK_LEVEL_NONE;
break;
default:
- ksmbd_err("unknown oplock change 0x%x -> 0x%x\n",
- opinfo->level, rsp_oplevel);
+ pr_err("unknown oplock change 0x%x -> 0x%x\n",
+ opinfo->level, rsp_oplevel);
}
if (ret < 0) {
@@ -7603,8 +7705,8 @@ static void smb21_lease_break_ack(struct ksmbd_work *work)
lease = opinfo->o_lease;
if (opinfo->op_state == OPLOCK_STATE_NONE) {
- ksmbd_err("unexpected lease break state 0x%x\n",
- opinfo->op_state);
+ pr_err("unexpected lease break state 0x%x\n",
+ opinfo->op_state);
rsp->hdr.Status = STATUS_UNSUCCESSFUL;
goto err_out;
}
@@ -7796,7 +7898,7 @@ int smb2_check_sign_req(struct ksmbd_work *work)
hdr_org = hdr = work->request_buf;
if (work->next_smb2_rcv_hdr_off)
- hdr = REQUEST_BUF_NEXT(work);
+ hdr = ksmbd_req_buf_next(work);
if (!hdr->NextCommand && !work->next_smb2_rcv_hdr_off)
len = be32_to_cpu(hdr_org->smb2_buf_length);
@@ -7817,7 +7919,7 @@ int smb2_check_sign_req(struct ksmbd_work *work)
return 0;
if (memcmp(signature, signature_req, SMB2_SIGNATURE_SIZE)) {
- ksmbd_err("bad smb2 signature\n");
+ pr_err("bad smb2 signature\n");
return 0;
}
@@ -7840,9 +7942,9 @@ void smb2_set_sign_rsp(struct ksmbd_work *work)
hdr_org = hdr = work->response_buf;
if (work->next_smb2_rsp_hdr_off)
- hdr = RESPONSE_BUF_NEXT(work);
+ hdr = ksmbd_resp_buf_next(work);
- req_hdr = REQUEST_BUF_NEXT(work);
+ req_hdr = ksmbd_req_buf_next(work);
if (!work->next_smb2_rsp_hdr_off) {
len = get_rfc1002_len(hdr_org);
@@ -7883,7 +7985,7 @@ void smb2_set_sign_rsp(struct ksmbd_work *work)
*/
int smb3_check_sign_req(struct ksmbd_work *work)
{
- struct ksmbd_conn *conn;
+ struct ksmbd_conn *conn = work->conn;
char *signing_key;
struct smb2_hdr *hdr, *hdr_org;
struct channel *chann;
@@ -7894,7 +7996,7 @@ int smb3_check_sign_req(struct ksmbd_work *work)
hdr_org = hdr = work->request_buf;
if (work->next_smb2_rcv_hdr_off)
- hdr = REQUEST_BUF_NEXT(work);
+ hdr = ksmbd_req_buf_next(work);
if (!hdr->NextCommand && !work->next_smb2_rcv_hdr_off)
len = be32_to_cpu(hdr_org->smb2_buf_length);
@@ -7906,17 +8008,15 @@ int smb3_check_sign_req(struct ksmbd_work *work)
if (le16_to_cpu(hdr->Command) == SMB2_SESSION_SETUP_HE) {
signing_key = work->sess->smb3signingkey;
- conn = work->sess->conn;
} else {
- chann = lookup_chann_list(work->sess);
+ chann = lookup_chann_list(work->sess, conn);
if (!chann)
return 0;
signing_key = chann->smb3signingkey;
- conn = chann->conn;
}
if (!signing_key) {
- ksmbd_err("SMB3 signing key is not generated\n");
+ pr_err("SMB3 signing key is not generated\n");
return 0;
}
@@ -7929,7 +8029,7 @@ int smb3_check_sign_req(struct ksmbd_work *work)
return 0;
if (memcmp(signature, signature_req, SMB2_SIGNATURE_SIZE)) {
- ksmbd_err("bad smb2 signature\n");
+ pr_err("bad smb2 signature\n");
return 0;
}
@@ -7943,7 +8043,7 @@ int smb3_check_sign_req(struct ksmbd_work *work)
*/
void smb3_set_sign_rsp(struct ksmbd_work *work)
{
- struct ksmbd_conn *conn;
+ struct ksmbd_conn *conn = work->conn;
struct smb2_hdr *req_hdr;
struct smb2_hdr *hdr, *hdr_org;
struct channel *chann;
@@ -7955,9 +8055,9 @@ void smb3_set_sign_rsp(struct ksmbd_work *work)
hdr_org = hdr = work->response_buf;
if (work->next_smb2_rsp_hdr_off)
- hdr = RESPONSE_BUF_NEXT(work);
+ hdr = ksmbd_resp_buf_next(work);
- req_hdr = REQUEST_BUF_NEXT(work);
+ req_hdr = ksmbd_req_buf_next(work);
if (!work->next_smb2_rsp_hdr_off) {
len = get_rfc1002_len(hdr_org);
@@ -7970,13 +8070,11 @@ void smb3_set_sign_rsp(struct ksmbd_work *work)
if (le16_to_cpu(hdr->Command) == SMB2_SESSION_SETUP_HE) {
signing_key = work->sess->smb3signingkey;
- conn = work->sess->conn;
} else {
- chann = lookup_chann_list(work->sess);
+ chann = lookup_chann_list(work->sess, work->conn);
if (!chann)
return;
signing_key = chann->smb3signingkey;
- conn = chann->conn;
}
if (!signing_key)
@@ -8020,11 +8118,21 @@ void smb3_preauth_hash_rsp(struct ksmbd_work *work)
ksmbd_gen_preauth_integrity_hash(conn, (char *)rsp,
conn->preauth_info->Preauth_HashValue);
- if (le16_to_cpu(rsp->Command) == SMB2_SESSION_SETUP_HE &&
- sess && sess->state == SMB2_SESSION_IN_PROGRESS) {
+ if (le16_to_cpu(rsp->Command) == SMB2_SESSION_SETUP_HE && sess) {
__u8 *hash_value;
- hash_value = sess->Preauth_HashValue;
+ if (conn->binding) {
+ struct preauth_session *preauth_sess;
+
+ preauth_sess = ksmbd_preauth_session_lookup(conn, sess->id);
+ if (!preauth_sess)
+ return;
+ hash_value = preauth_sess->Preauth_HashValue;
+ } else {
+ hash_value = sess->Preauth_HashValue;
+ if (!hash_value)
+ return;
+ }
ksmbd_gen_preauth_integrity_hash(conn, (char *)rsp,
hash_value);
}
@@ -8116,22 +8224,22 @@ int smb3_decrypt_req(struct ksmbd_work *work)
unsigned int orig_len = le32_to_cpu(tr_hdr->OriginalMessageSize);
int rc = 0;
- sess = ksmbd_session_lookup(conn, le64_to_cpu(tr_hdr->SessionId));
+ sess = ksmbd_session_lookup_all(conn, le64_to_cpu(tr_hdr->SessionId));
if (!sess) {
- ksmbd_err("invalid session id(%llx) in transform header\n",
- le64_to_cpu(tr_hdr->SessionId));
+ pr_err("invalid session id(%llx) in transform header\n",
+ le64_to_cpu(tr_hdr->SessionId));
return -ECONNABORTED;
}
if (pdu_length + 4 <
sizeof(struct smb2_transform_hdr) + sizeof(struct smb2_hdr)) {
- ksmbd_err("Transform message is too small (%u)\n",
- pdu_length);
+ pr_err("Transform message is too small (%u)\n",
+ pdu_length);
return -ECONNABORTED;
}
if (pdu_length + 4 < orig_len + sizeof(struct smb2_transform_hdr)) {
- ksmbd_err("Transform message is broken\n");
+ pr_err("Transform message is broken\n");
return -ECONNABORTED;
}
@@ -8159,7 +8267,7 @@ bool smb3_11_final_sess_setup_resp(struct ksmbd_work *work)
return false;
if (work->next_smb2_rcv_hdr_off)
- rsp = RESPONSE_BUF_NEXT(work);
+ rsp = ksmbd_resp_buf_next(work);
if (le16_to_cpu(rsp->Command) == SMB2_SESSION_SETUP_HE &&
rsp->Status == STATUS_SUCCESS)
diff --git a/fs/cifsd/smb2pdu.h b/fs/ksmbd/smb2pdu.h
index 0d5349e75dd9..0eac40e1ba65 100644
--- a/fs/cifsd/smb2pdu.h
+++ b/fs/ksmbd/smb2pdu.h
@@ -1647,7 +1647,8 @@ struct file_lock *smb_flock_init(struct file *f);
int setup_async_work(struct ksmbd_work *work, void (*fn)(void **),
void **arg);
void smb2_send_interim_resp(struct ksmbd_work *work, __le32 status);
-struct channel *lookup_chann_list(struct ksmbd_session *sess);
+struct channel *lookup_chann_list(struct ksmbd_session *sess,
+ struct ksmbd_conn *conn);
void smb3_preauth_hash_rsp(struct ksmbd_work *work);
int smb3_is_transform_hdr(void *buf);
int smb3_decrypt_req(struct ksmbd_work *work);
diff --git a/fs/cifsd/smb_common.c b/fs/ksmbd/smb_common.c
index 039030968b50..f770f3ffb840 100644
--- a/fs/cifsd/smb_common.c
+++ b/fs/ksmbd/smb_common.c
@@ -274,6 +274,7 @@ int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work, int info_level,
char *search_pattern,
int (*fn)(struct ksmbd_conn *, int,
struct ksmbd_dir_info *,
+ struct user_namespace *,
struct ksmbd_kstat *))
{
int i, rc = 0;
@@ -300,9 +301,11 @@ int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work, int info_level,
ksmbd_kstat.kstat = &kstat;
ksmbd_vfs_fill_dentry_attrs(work,
+ file_mnt_user_ns(dir->filp),
dir->filp->f_path.dentry->d_parent,
&ksmbd_kstat);
- rc = fn(conn, info_level, d_info, &ksmbd_kstat);
+ rc = fn(conn, info_level, d_info,
+ file_mnt_user_ns(dir->filp), &ksmbd_kstat);
if (rc)
break;
if (d_info->out_buf_len <= 0)
@@ -447,7 +450,7 @@ int ksmbd_smb_negotiate_common(struct ksmbd_work *work, unsigned int command)
return smb_handle_negotiate(work);
}
- ksmbd_err("Unknown SMB negotiation command: %u\n", command);
+ pr_err("Unknown SMB negotiation command: %u\n", command);
return -EINVAL;
}
@@ -481,16 +484,14 @@ int ksmbd_smb_check_shared_mode(struct file *filp, struct ksmbd_file *curr_fp)
{
int rc = 0;
struct ksmbd_file *prev_fp;
- struct list_head *cur;
/*
* Lookup fp in master fp list, and check desired access and
* shared mode between previous open and current open.
*/
read_lock(&curr_fp->f_ci->m_lock);
- list_for_each(cur, &curr_fp->f_ci->m_fp_list) {
- prev_fp = list_entry(cur, struct ksmbd_file, node);
- if (file_inode(filp) != FP_INODE(prev_fp))
+ list_for_each_entry(prev_fp, &curr_fp->f_ci->m_fp_list, node) {
+ if (file_inode(filp) != file_inode(prev_fp->filp))
continue;
if (filp == prev_fp->filp)
diff --git a/fs/cifsd/smb_common.h b/fs/ksmbd/smb_common.h
index 6e7404b8db96..6ab28aa33024 100644
--- a/fs/cifsd/smb_common.h
+++ b/fs/ksmbd/smb_common.h
@@ -50,12 +50,6 @@
extern struct list_head global_lock_list;
-#define IS_SMB2(x) ((x)->vals->protocol_id != SMB10_PROT_ID)
-
-#define HEADER_SIZE(conn) ((conn)->vals->header_size)
-#define HEADER_SIZE_NO_BUF_LEN(conn) ((conn)->vals->header_size - 4)
-#define MAX_HEADER_SIZE(conn) ((conn)->vals->max_header_size)
-
/* RFC 1002 session packet types */
#define RFC1002_SESSION_MESSAGE 0x00
#define RFC1002_SESSION_REQUEST 0x81
@@ -479,7 +473,7 @@ struct smb_version_ops {
bool (*is_sign_req)(struct ksmbd_work *work, unsigned int command);
int (*check_sign_req)(struct ksmbd_work *work);
void (*set_sign_rsp)(struct ksmbd_work *work);
- int (*generate_signingkey)(struct ksmbd_session *sess);
+ int (*generate_signingkey)(struct ksmbd_session *sess, struct ksmbd_conn *conn);
int (*generate_encryptionkey)(struct ksmbd_session *sess);
int (*is_transform_hdr)(void *buf);
int (*decrypt_req)(struct ksmbd_work *work);
@@ -490,6 +484,12 @@ struct smb_version_cmds {
int (*proc)(struct ksmbd_work *swork);
};
+static inline size_t
+smb2_hdr_size_no_buflen(struct smb_version_values *vals)
+{
+ return vals->header_size - 4;
+}
+
int ksmbd_min_protocol(void);
int ksmbd_max_protocol(void);
@@ -514,6 +514,7 @@ int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work,
int (*fn)(struct ksmbd_conn *,
int,
struct ksmbd_dir_info *,
+ struct user_namespace *,
struct ksmbd_kstat *));
int ksmbd_extract_shortname(struct ksmbd_conn *conn,
diff --git a/fs/cifsd/smbacl.c b/fs/ksmbd/smbacl.c
index 63db8c015f9d..4ee714b9b351 100644
--- a/fs/cifsd/smbacl.c
+++ b/fs/ksmbd/smbacl.c
@@ -14,7 +14,6 @@
#include "smb_common.h"
#include "server.h"
#include "misc.h"
-#include "ksmbd_server.h"
#include "mgmt/share_config.h"
static const struct smb_sid domain = {1, 4, {0, 0, 0, 0, 0, 5},
@@ -254,7 +253,8 @@ void id_to_sid(unsigned int cid, uint sidtype, struct smb_sid *ssid)
ssid->num_subauth++;
}
-static int sid_to_id(struct smb_sid *psid, uint sidtype,
+static int sid_to_id(struct user_namespace *user_ns,
+ struct smb_sid *psid, uint sidtype,
struct smb_fattr *fattr)
{
int rc = -EINVAL;
@@ -264,8 +264,8 @@ static int sid_to_id(struct smb_sid *psid, uint sidtype,
* Just return an error.
*/
if (unlikely(psid->num_subauth > SID_MAX_SUB_AUTHORITIES)) {
- ksmbd_err("%s: %u subauthorities is too many!\n",
- __func__, psid->num_subauth);
+ pr_err("%s: %u subauthorities is too many!\n",
+ __func__, psid->num_subauth);
return -EIO;
}
@@ -275,8 +275,8 @@ static int sid_to_id(struct smb_sid *psid, uint sidtype,
id = le32_to_cpu(psid->sub_auth[psid->num_subauth - 1]);
if (id > 0) {
- uid = make_kuid(&init_user_ns, id);
- if (uid_valid(uid) && kuid_has_mapping(&init_user_ns, uid)) {
+ uid = make_kuid(user_ns, id);
+ if (uid_valid(uid) && kuid_has_mapping(user_ns, uid)) {
fattr->cf_uid = uid;
rc = 0;
}
@@ -287,8 +287,8 @@ static int sid_to_id(struct smb_sid *psid, uint sidtype,
id = le32_to_cpu(psid->sub_auth[psid->num_subauth - 1]);
if (id > 0) {
- gid = make_kgid(&init_user_ns, id);
- if (gid_valid(gid) && kgid_has_mapping(&init_user_ns, gid)) {
+ gid = make_kgid(user_ns, id);
+ if (gid_valid(gid) && kgid_has_mapping(user_ns, gid)) {
fattr->cf_gid = gid;
rc = 0;
}
@@ -363,7 +363,8 @@ void free_acl_state(struct posix_acl_state *state)
kfree(state->groups);
}
-static void parse_dacl(struct smb_acl *pdacl, char *end_of_acl,
+static void parse_dacl(struct user_namespace *user_ns,
+ struct smb_acl *pdacl, char *end_of_acl,
struct smb_sid *pownersid, struct smb_sid *pgrpsid,
struct smb_fattr *fattr)
{
@@ -383,7 +384,7 @@ static void parse_dacl(struct smb_acl *pdacl, char *end_of_acl,
/* validate that we do not go past end of acl */
if (end_of_acl <= (char *)pdacl ||
end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
- ksmbd_err("ACL too small to parse DACL\n");
+ pr_err("ACL too small to parse DACL\n");
return;
}
@@ -475,10 +476,10 @@ static void parse_dacl(struct smb_acl *pdacl, char *end_of_acl,
acl_mode = access_flags_to_mode(fattr, ppace[i]->access_req,
ppace[i]->type);
temp_fattr.cf_uid = INVALID_UID;
- ret = sid_to_id(&ppace[i]->sid, SIDOWNER, &temp_fattr);
+ ret = sid_to_id(user_ns, &ppace[i]->sid, SIDOWNER, &temp_fattr);
if (ret || uid_eq(temp_fattr.cf_uid, INVALID_UID)) {
- ksmbd_err("%s: Error %d mapping Owner SID to uid\n",
- __func__, ret);
+ pr_err("%s: Error %d mapping Owner SID to uid\n",
+ __func__, ret);
continue;
}
@@ -532,7 +533,7 @@ static void parse_dacl(struct smb_acl *pdacl, char *end_of_acl,
if (acl_state.users->n || acl_state.groups->n) {
acl_state.mask.allow = 0x07;
- fattr->cf_acls = ksmbd_vfs_posix_acl_alloc(acl_state.users->n +
+ fattr->cf_acls = posix_acl_alloc(acl_state.users->n +
acl_state.groups->n + 4, GFP_KERNEL);
if (fattr->cf_acls) {
cf_pace = fattr->cf_acls->a_entries;
@@ -543,7 +544,7 @@ static void parse_dacl(struct smb_acl *pdacl, char *end_of_acl,
if (default_acl_state.users->n || default_acl_state.groups->n) {
default_acl_state.mask.allow = 0x07;
fattr->cf_dacls =
- ksmbd_vfs_posix_acl_alloc(default_acl_state.users->n +
+ posix_acl_alloc(default_acl_state.users->n +
default_acl_state.groups->n + 4, GFP_KERNEL);
if (fattr->cf_dacls) {
cf_pdace = fattr->cf_dacls->a_entries;
@@ -554,7 +555,8 @@ static void parse_dacl(struct smb_acl *pdacl, char *end_of_acl,
free_acl_state(&default_acl_state);
}
-static void set_posix_acl_entries_dacl(struct smb_ace *pndace,
+static void set_posix_acl_entries_dacl(struct user_namespace *user_ns,
+ struct smb_ace *pndace,
struct smb_fattr *fattr, u32 *num_aces,
u16 *size, u32 nt_aces_num)
{
@@ -578,14 +580,14 @@ static void set_posix_acl_entries_dacl(struct smb_ace *pndace,
uid_t uid;
unsigned int sid_type = SIDOWNER;
- uid = from_kuid(&init_user_ns, pace->e_uid);
+ uid = from_kuid(user_ns, pace->e_uid);
if (!uid)
sid_type = SIDUNIX_USER;
id_to_sid(uid, sid_type, sid);
} else if (pace->e_tag == ACL_GROUP) {
gid_t gid;
- gid = from_kgid(&init_user_ns, pace->e_gid);
+ gid = from_kgid(user_ns, pace->e_gid);
id_to_sid(gid, SIDUNIX_GROUP, sid);
} else if (pace->e_tag == ACL_OTHER && !nt_aces_num) {
smb_copy_sid(sid, &sid_everyone);
@@ -644,12 +646,12 @@ posix_default_acl:
if (pace->e_tag == ACL_USER) {
uid_t uid;
- uid = from_kuid(&init_user_ns, pace->e_uid);
+ uid = from_kuid(user_ns, pace->e_uid);
id_to_sid(uid, SIDCREATOR_OWNER, sid);
} else if (pace->e_tag == ACL_GROUP) {
gid_t gid;
- gid = from_kgid(&init_user_ns, pace->e_gid);
+ gid = from_kgid(user_ns, pace->e_gid);
id_to_sid(gid, SIDCREATOR_GROUP, sid);
} else {
kfree(sid);
@@ -667,7 +669,9 @@ posix_default_acl:
}
}
-static void set_ntacl_dacl(struct smb_acl *pndacl, struct smb_acl *nt_dacl,
+static void set_ntacl_dacl(struct user_namespace *user_ns,
+ struct smb_acl *pndacl,
+ struct smb_acl *nt_dacl,
const struct smb_sid *pownersid,
const struct smb_sid *pgrpsid,
struct smb_fattr *fattr)
@@ -688,12 +692,14 @@ static void set_ntacl_dacl(struct smb_acl *pndacl, struct smb_acl *nt_dacl,
}
}
- set_posix_acl_entries_dacl(pndace, fattr, &num_aces, &size, nt_num_aces);
+ set_posix_acl_entries_dacl(user_ns, pndace, fattr,
+ &num_aces, &size, nt_num_aces);
pndacl->num_aces = cpu_to_le32(num_aces);
pndacl->size = cpu_to_le16(le16_to_cpu(pndacl->size) + size);
}
-static void set_mode_dacl(struct smb_acl *pndacl, struct smb_fattr *fattr)
+static void set_mode_dacl(struct user_namespace *user_ns,
+ struct smb_acl *pndacl, struct smb_fattr *fattr)
{
struct smb_ace *pace, *pndace;
u32 num_aces = 0;
@@ -704,12 +710,13 @@ static void set_mode_dacl(struct smb_acl *pndacl, struct smb_fattr *fattr)
pace = pndace = (struct smb_ace *)((char *)pndacl + sizeof(struct smb_acl));
if (fattr->cf_acls) {
- set_posix_acl_entries_dacl(pndace, fattr, &num_aces, &size, num_aces);
+ set_posix_acl_entries_dacl(user_ns, pndace, fattr,
+ &num_aces, &size, num_aces);
goto out;
}
/* owner RID */
- uid = from_kuid(&init_user_ns, fattr->cf_uid);
+ uid = from_kuid(user_ns, fattr->cf_uid);
if (uid)
sid = &server_conf.domain_sid;
else
@@ -726,7 +733,7 @@ static void set_mode_dacl(struct smb_acl *pndacl, struct smb_fattr *fattr)
ace_size = fill_ace_for_sid(pace, &sid_unix_groups,
ACCESS_ALLOWED, 0, fattr->cf_mode, 0070);
pace->sid.sub_auth[pace->sid.num_subauth++] =
- cpu_to_le32(from_kgid(&init_user_ns, fattr->cf_gid));
+ cpu_to_le32(from_kgid(user_ns, fattr->cf_gid));
pace->size = cpu_to_le16(ace_size + 4);
size += le16_to_cpu(pace->size);
pace = (struct smb_ace *)((char *)pndace + size);
@@ -764,7 +771,7 @@ static int parse_sid(struct smb_sid *psid, char *end_of_acl)
* bytes long (assuming no sub-auths - e.g. the null SID
*/
if (end_of_acl < (char *)psid + 8) {
- ksmbd_err("ACL too small to parse SID %p\n", psid);
+ pr_err("ACL too small to parse SID %p\n", psid);
return -EINVAL;
}
@@ -772,8 +779,8 @@ static int parse_sid(struct smb_sid *psid, char *end_of_acl)
}
/* Convert CIFS ACL to POSIX form */
-int parse_sec_desc(struct smb_ntsd *pntsd, int acl_len,
- struct smb_fattr *fattr)
+int parse_sec_desc(struct user_namespace *user_ns, struct smb_ntsd *pntsd,
+ int acl_len, struct smb_fattr *fattr)
{
int rc = 0;
struct smb_sid *owner_sid_ptr, *group_sid_ptr;
@@ -808,14 +815,14 @@ int parse_sec_desc(struct smb_ntsd *pntsd, int acl_len,
if (pntsd->osidoffset) {
rc = parse_sid(owner_sid_ptr, end_of_acl);
if (rc) {
- ksmbd_err("%s: Error %d parsing Owner SID\n", __func__, rc);
+ pr_err("%s: Error %d parsing Owner SID\n", __func__, rc);
return rc;
}
- rc = sid_to_id(owner_sid_ptr, SIDOWNER, fattr);
+ rc = sid_to_id(user_ns, owner_sid_ptr, SIDOWNER, fattr);
if (rc) {
- ksmbd_err("%s: Error %d mapping Owner SID to uid\n",
- __func__, rc);
+ pr_err("%s: Error %d mapping Owner SID to uid\n",
+ __func__, rc);
owner_sid_ptr = NULL;
}
}
@@ -823,14 +830,14 @@ int parse_sec_desc(struct smb_ntsd *pntsd, int acl_len,
if (pntsd->gsidoffset) {
rc = parse_sid(group_sid_ptr, end_of_acl);
if (rc) {
- ksmbd_err("%s: Error %d mapping Owner SID to gid\n",
- __func__, rc);
+ pr_err("%s: Error %d mapping Owner SID to gid\n",
+ __func__, rc);
return rc;
}
- rc = sid_to_id(group_sid_ptr, SIDUNIX_GROUP, fattr);
+ rc = sid_to_id(user_ns, group_sid_ptr, SIDUNIX_GROUP, fattr);
if (rc) {
- ksmbd_err("%s: Error %d mapping Group SID to gid\n",
- __func__, rc);
+ pr_err("%s: Error %d mapping Group SID to gid\n",
+ __func__, rc);
group_sid_ptr = NULL;
}
}
@@ -842,15 +849,16 @@ int parse_sec_desc(struct smb_ntsd *pntsd, int acl_len,
pntsd->type |= cpu_to_le16(DACL_PROTECTED);
if (dacloffset) {
- parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, group_sid_ptr,
- fattr);
+ parse_dacl(user_ns, dacl_ptr, end_of_acl,
+ owner_sid_ptr, group_sid_ptr, fattr);
}
return 0;
}
/* Convert permission bits from mode to equivalent CIFS ACL */
-int build_sec_desc(struct smb_ntsd *pntsd, struct smb_ntsd *ppntsd,
+int build_sec_desc(struct user_namespace *user_ns,
+ struct smb_ntsd *pntsd, struct smb_ntsd *ppntsd,
int addition_info, __u32 *secdesclen,
struct smb_fattr *fattr)
{
@@ -867,7 +875,7 @@ int build_sec_desc(struct smb_ntsd *pntsd, struct smb_ntsd *ppntsd,
if (!nowner_sid_ptr)
return -ENOMEM;
- uid = from_kuid(&init_user_ns, fattr->cf_uid);
+ uid = from_kuid(user_ns, fattr->cf_uid);
if (!uid)
sid_type = SIDUNIX_USER;
id_to_sid(uid, sid_type, nowner_sid_ptr);
@@ -878,7 +886,7 @@ int build_sec_desc(struct smb_ntsd *pntsd, struct smb_ntsd *ppntsd,
return -ENOMEM;
}
- gid = from_kgid(&init_user_ns, fattr->cf_gid);
+ gid = from_kgid(user_ns, fattr->cf_gid);
id_to_sid(gid, SIDUNIX_GROUP, ngroup_sid_ptr);
offset = sizeof(struct smb_ntsd);
@@ -910,7 +918,7 @@ int build_sec_desc(struct smb_ntsd *pntsd, struct smb_ntsd *ppntsd,
dacl_ptr->num_aces = 0;
if (!ppntsd) {
- set_mode_dacl(dacl_ptr, fattr);
+ set_mode_dacl(user_ns, dacl_ptr, fattr);
} else if (!ppntsd->dacloffset) {
goto out;
} else {
@@ -918,8 +926,8 @@ int build_sec_desc(struct smb_ntsd *pntsd, struct smb_ntsd *ppntsd,
ppdacl_ptr = (struct smb_acl *)((char *)ppntsd +
le32_to_cpu(ppntsd->dacloffset));
- set_ntacl_dacl(dacl_ptr, ppdacl_ptr, nowner_sid_ptr,
- ngroup_sid_ptr, fattr);
+ set_ntacl_dacl(user_ns, dacl_ptr, ppdacl_ptr,
+ nowner_sid_ptr, ngroup_sid_ptr, fattr);
}
pntsd->dacloffset = cpu_to_le32(offset);
offset += le16_to_cpu(dacl_ptr->size);
@@ -942,7 +950,8 @@ static void smb_set_ace(struct smb_ace *ace, const struct smb_sid *sid, u8 type,
ace->size = cpu_to_le16(1 + 1 + 2 + 4 + 1 + 1 + 6 + (sid->num_subauth * 4));
}
-int smb_inherit_dacl(struct ksmbd_conn *conn, struct dentry *dentry,
+int smb_inherit_dacl(struct ksmbd_conn *conn,
+ struct path *path,
unsigned int uid, unsigned int gid)
{
const struct smb_sid *psid, *creator = NULL;
@@ -950,13 +959,14 @@ int smb_inherit_dacl(struct ksmbd_conn *conn, struct dentry *dentry,
struct smb_acl *parent_pdacl;
struct smb_ntsd *parent_pntsd = NULL;
struct smb_sid owner_sid, group_sid;
- struct dentry *parent = dentry->d_parent;
+ struct dentry *parent = path->dentry->d_parent;
int inherited_flags = 0, flags = 0, i, ace_cnt = 0, nt_size = 0;
int rc = -ENOENT, num_aces, dacloffset, pntsd_type, acl_len;
char *aces_base;
- bool is_dir = S_ISDIR(d_inode(dentry)->i_mode);
+ bool is_dir = S_ISDIR(d_inode(path->dentry)->i_mode);
- acl_len = ksmbd_vfs_get_sd_xattr(conn, parent, &parent_pntsd);
+ acl_len = ksmbd_vfs_get_sd_xattr(conn, mnt_user_ns(path->mnt),
+ parent, &parent_pntsd);
if (acl_len <= 0)
return rc;
dacloffset = le32_to_cpu(parent_pntsd->dacloffset);
@@ -1087,7 +1097,8 @@ pass:
pntsd_size += sizeof(struct smb_acl) + nt_size;
}
- ksmbd_vfs_set_sd_xattr(conn, dentry, pntsd, pntsd_size);
+ ksmbd_vfs_set_sd_xattr(conn, mnt_user_ns(path->mnt),
+ path->dentry, pntsd, pntsd_size);
kfree(pntsd);
rc = 0;
}
@@ -1110,7 +1121,7 @@ bool smb_inherit_flags(int flags, bool is_dir)
return false;
}
-int smb_check_perm_dacl(struct ksmbd_conn *conn, struct dentry *dentry,
+int smb_check_perm_dacl(struct ksmbd_conn *conn, struct path *path,
__le32 *pdaccess, int uid)
{
struct smb_ntsd *pntsd = NULL;
@@ -1128,7 +1139,8 @@ int smb_check_perm_dacl(struct ksmbd_conn *conn, struct dentry *dentry,
char *end_of_acl;
ksmbd_debug(SMB, "check permission using windows acl\n");
- acl_size = ksmbd_vfs_get_sd_xattr(conn, dentry, &pntsd);
+ acl_size = ksmbd_vfs_get_sd_xattr(conn, mnt_user_ns(path->mnt),
+ path->dentry, &pntsd);
if (acl_size <= 0 || !pntsd || !pntsd->dacloffset) {
kfree(pntsd);
return 0;
@@ -1202,16 +1214,18 @@ int smb_check_perm_dacl(struct ksmbd_conn *conn, struct dentry *dentry,
granted = GENERIC_ALL_FLAGS;
}
- posix_acls = ksmbd_vfs_get_acl(d_inode(dentry), ACL_TYPE_ACCESS);
+ posix_acls = get_acl(d_inode(path->dentry), ACL_TYPE_ACCESS);
if (posix_acls && !found) {
unsigned int id = -1;
pa_entry = posix_acls->a_entries;
for (i = 0; i < posix_acls->a_count; i++, pa_entry++) {
if (pa_entry->e_tag == ACL_USER)
- id = from_kuid(&init_user_ns, pa_entry->e_uid);
+ id = from_kuid(mnt_user_ns(path->mnt),
+ pa_entry->e_uid);
else if (pa_entry->e_tag == ACL_GROUP)
- id = from_kgid(&init_user_ns, pa_entry->e_gid);
+ id = from_kgid(mnt_user_ns(path->mnt),
+ pa_entry->e_gid);
else
continue;
@@ -1262,18 +1276,18 @@ err_out:
}
int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon,
- struct dentry *dentry, struct smb_ntsd *pntsd, int ntsd_len,
+ struct path *path, struct smb_ntsd *pntsd, int ntsd_len,
bool type_check)
{
int rc;
struct smb_fattr fattr = {{0}};
- struct inode *inode = d_inode(dentry);
+ struct inode *inode = d_inode(path->dentry);
fattr.cf_uid = INVALID_UID;
fattr.cf_gid = INVALID_GID;
fattr.cf_mode = inode->i_mode;
- rc = parse_sec_desc(pntsd, ntsd_len, &fattr);
+ rc = parse_sec_desc(mnt_user_ns(path->mnt), pntsd, ntsd_len, &fattr);
if (rc)
goto out;
@@ -1284,14 +1298,14 @@ int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon,
inode->i_gid = fattr.cf_gid;
mark_inode_dirty(inode);
- ksmbd_vfs_remove_acl_xattrs(dentry);
+ ksmbd_vfs_remove_acl_xattrs(mnt_user_ns(path->mnt), path->dentry);
/* Update posix acls */
if (fattr.cf_dacls) {
- rc = ksmbd_vfs_set_posix_acl(inode, ACL_TYPE_ACCESS,
- fattr.cf_acls);
+ rc = set_posix_acl(mnt_user_ns(path->mnt), inode,
+ ACL_TYPE_ACCESS, fattr.cf_acls);
if (S_ISDIR(inode->i_mode) && fattr.cf_dacls)
- rc = ksmbd_vfs_set_posix_acl(inode, ACL_TYPE_DEFAULT,
- fattr.cf_dacls);
+ rc = set_posix_acl(mnt_user_ns(path->mnt), inode,
+ ACL_TYPE_DEFAULT, fattr.cf_dacls);
}
/* Check it only calling from SD BUFFER context */
@@ -1300,8 +1314,9 @@ int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon,
if (test_share_config_flag(tcon->share_conf, KSMBD_SHARE_FLAG_ACL_XATTR)) {
/* Update WinACL in xattr */
- ksmbd_vfs_remove_sd_xattrs(dentry);
- ksmbd_vfs_set_sd_xattr(conn, dentry, pntsd, ntsd_len);
+ ksmbd_vfs_remove_sd_xattrs(mnt_user_ns(path->mnt), path->dentry);
+ ksmbd_vfs_set_sd_xattr(conn, mnt_user_ns(path->mnt),
+ path->dentry, pntsd, ntsd_len);
}
out:
diff --git a/fs/cifsd/smbacl.h b/fs/ksmbd/smbacl.h
index fb5480f0aa89..940f686a1d95 100644
--- a/fs/cifsd/smbacl.h
+++ b/fs/ksmbd/smbacl.h
@@ -17,18 +17,28 @@
#define NUM_AUTHS (6) /* number of authority fields */
#define SID_MAX_SUB_AUTHORITIES (15) /* max number of sub authority fields */
-#define ACCESS_ALLOWED 0
-#define ACCESS_DENIED 1
-
-#define SIDOWNER 1
-#define SIDGROUP 2
-#define SIDCREATOR_OWNER 3
-#define SIDCREATOR_GROUP 4
-#define SIDUNIX_USER 5
-#define SIDUNIX_GROUP 6
-#define SIDNFS_USER 7
-#define SIDNFS_GROUP 8
-#define SIDNFS_MODE 9
+/*
+ * ACE types - see MS-DTYP 2.4.4.1
+ */
+enum {
+ ACCESS_ALLOWED,
+ ACCESS_DENIED,
+};
+
+/*
+ * Security ID types
+ */
+enum {
+ SIDOWNER = 1,
+ SIDGROUP,
+ SIDCREATOR_OWNER,
+ SIDCREATOR_GROUP,
+ SIDUNIX_USER,
+ SIDUNIX_GROUP,
+ SIDNFS_USER,
+ SIDNFS_GROUP,
+ SIDNFS_MODE,
+};
/* Revision for ACLs */
#define SD_REVISION 1
@@ -179,23 +189,23 @@ struct posix_acl_state {
struct posix_ace_state_array *groups;
};
-int parse_sec_desc(struct smb_ntsd *pntsd, int acl_len,
- struct smb_fattr *fattr);
-int build_sec_desc(struct smb_ntsd *pntsd, struct smb_ntsd *ppntsd,
- int addition_info, __u32 *secdesclen,
- struct smb_fattr *fattr);
+int parse_sec_desc(struct user_namespace *user_ns, struct smb_ntsd *pntsd,
+ int acl_len, struct smb_fattr *fattr);
+int build_sec_desc(struct user_namespace *user_ns, struct smb_ntsd *pntsd,
+ struct smb_ntsd *ppntsd, int addition_info,
+ __u32 *secdesclen, struct smb_fattr *fattr);
int init_acl_state(struct posix_acl_state *state, int cnt);
void free_acl_state(struct posix_acl_state *state);
void posix_state_to_acl(struct posix_acl_state *state,
struct posix_acl_entry *pace);
int compare_sids(const struct smb_sid *ctsid, const struct smb_sid *cwsid);
bool smb_inherit_flags(int flags, bool is_dir);
-int smb_inherit_dacl(struct ksmbd_conn *conn, struct dentry *dentry,
+int smb_inherit_dacl(struct ksmbd_conn *conn, struct path *path,
unsigned int uid, unsigned int gid);
-int smb_check_perm_dacl(struct ksmbd_conn *conn, struct dentry *dentry,
+int smb_check_perm_dacl(struct ksmbd_conn *conn, struct path *path,
__le32 *pdaccess, int uid);
int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon,
- struct dentry *dentry, struct smb_ntsd *pntsd, int ntsd_len,
+ struct path *path, struct smb_ntsd *pntsd, int ntsd_len,
bool type_check);
void id_to_sid(unsigned int cid, uint sidtype, struct smb_sid *ssid);
void ksmbd_init_domain(u32 *sub_auth);
diff --git a/fs/cifsd/smbfsctl.h b/fs/ksmbd/smbfsctl.h
index b98418aae20c..b98418aae20c 100644
--- a/fs/cifsd/smbfsctl.h
+++ b/fs/ksmbd/smbfsctl.h
diff --git a/fs/cifsd/smbstatus.h b/fs/ksmbd/smbstatus.h
index 108a8b6ed24a..108a8b6ed24a 100644
--- a/fs/cifsd/smbstatus.h
+++ b/fs/ksmbd/smbstatus.h
diff --git a/fs/cifsd/transport_ipc.c b/fs/ksmbd/transport_ipc.c
index b09df832431f..ca5099118fdf 100644
--- a/fs/cifsd/transport_ipc.c
+++ b/fs/ksmbd/transport_ipc.c
@@ -16,7 +16,6 @@
#include "vfs_cache.h"
#include "transport_ipc.h"
-#include "buffer_pool.h"
#include "server.h"
#include "smb_common.h"
@@ -39,16 +38,14 @@ static DEFINE_IDA(ipc_ida);
static unsigned int ksmbd_tools_pid;
-#define KSMBD_IPC_MSG_HANDLE(m) (*(unsigned int *)m)
-
static bool ksmbd_ipc_validate_version(struct genl_info *m)
{
if (m->genlhdr->version != KSMBD_GENL_VERSION) {
- ksmbd_err("%s. ksmbd: %d, kernel module: %d. %s.\n",
- "Daemon and kernel module version mismatch",
- m->genlhdr->version,
- KSMBD_GENL_VERSION,
- "User-space ksmbd should terminate");
+ pr_err("%s. ksmbd: %d, kernel module: %d. %s.\n",
+ "Daemon and kernel module version mismatch",
+ m->genlhdr->version,
+ KSMBD_GENL_VERSION,
+ "User-space ksmbd should terminate");
return false;
}
return true;
@@ -57,12 +54,9 @@ static bool ksmbd_ipc_validate_version(struct genl_info *m)
struct ksmbd_ipc_msg {
unsigned int type;
unsigned int sz;
- unsigned char ____payload[0];
+ unsigned char payload[];
};
-#define KSMBD_IPC_MSG_PAYLOAD(m) \
- ((void *)(((struct ksmbd_ipc_msg *)(m))->____payload))
-
struct ipc_msg_table_entry {
unsigned int handle;
unsigned int type;
@@ -252,7 +246,7 @@ static void ipc_msg_handle_free(int handle)
static int handle_response(int type, void *payload, size_t sz)
{
- int handle = KSMBD_IPC_MSG_HANDLE(payload);
+ unsigned int handle = *(unsigned int *)payload;
struct ipc_msg_table_entry *entry;
int ret = 0;
@@ -268,8 +262,8 @@ static int handle_response(int type, void *payload, size_t sz)
* request message type + 1.
*/
if (entry->type + 1 != type) {
- ksmbd_err("Waiting for IPC type %d, got %d. Ignore.\n",
- entry->type + 1, type);
+ pr_err("Waiting for IPC type %d, got %d. Ignore.\n",
+ entry->type + 1, type);
}
entry->response = kvmalloc(sz, GFP_KERNEL | __GFP_ZERO);
@@ -314,9 +308,9 @@ static int ipc_server_config_on_startup(struct ksmbd_startup_request *req)
ret |= ksmbd_tcp_set_interfaces(KSMBD_STARTUP_CONFIG_INTERFACES(req),
req->ifc_list_sz);
if (ret) {
- ksmbd_err("Server configuration error: %s %s %s\n",
- req->netbios_name, req->server_string,
- req->work_group);
+ pr_err("Server configuration error: %s %s %s\n",
+ req->netbios_name, req->server_string,
+ req->work_group);
return ret;
}
@@ -354,7 +348,7 @@ static int handle_startup_event(struct sk_buff *skb, struct genl_info *info)
mutex_lock(&startup_lock);
if (!ksmbd_server_configurable()) {
mutex_unlock(&startup_lock);
- ksmbd_err("Server reset is in progress, can't start daemon\n");
+ pr_err("Server reset is in progress, can't start daemon\n");
return -EINVAL;
}
@@ -364,7 +358,7 @@ static int handle_startup_event(struct sk_buff *skb, struct genl_info *info)
goto out;
}
- ksmbd_err("Reconnect to a new user space daemon\n");
+ pr_err("Reconnect to a new user space daemon\n");
} else {
struct ksmbd_startup_request *req;
@@ -385,7 +379,7 @@ out:
static int handle_unsupported_event(struct sk_buff *skb, struct genl_info *info)
{
- ksmbd_err("Unknown IPC event: %d, ignore.\n", info->genlhdr->cmd);
+ pr_err("Unknown IPC event: %d, ignore.\n", info->genlhdr->cmd);
return -EINVAL;
}
@@ -433,7 +427,7 @@ static int ipc_msg_send(struct ksmbd_ipc_msg *msg)
if (!nlh)
goto out;
- ret = nla_put(skb, msg->type, msg->sz, KSMBD_IPC_MSG_PAYLOAD(msg));
+ ret = nla_put(skb, msg->type, msg->sz, msg->payload);
if (ret) {
genlmsg_cancel(skb, nlh);
goto out;
@@ -510,7 +504,7 @@ struct ksmbd_login_response *ksmbd_ipc_login_request(const char *account)
return NULL;
msg->type = KSMBD_EVENT_LOGIN_REQUEST;
- req = KSMBD_IPC_MSG_PAYLOAD(msg);
+ req = (struct ksmbd_login_request *)msg->payload;
req->handle = ksmbd_acquire_id(&ipc_ida);
strscpy(req->account, account, KSMBD_REQ_MAX_ACCOUNT_NAME_SZ);
@@ -533,7 +527,7 @@ ksmbd_ipc_spnego_authen_request(const char *spnego_blob, int blob_len)
return NULL;
msg->type = KSMBD_EVENT_SPNEGO_AUTHEN_REQUEST;
- req = KSMBD_IPC_MSG_PAYLOAD(msg);
+ req = (struct ksmbd_spnego_authen_request *)msg->payload;
req->handle = ksmbd_acquire_id(&ipc_ida);
req->spnego_blob_len = blob_len;
memcpy(req->spnego_blob, spnego_blob, blob_len);
@@ -565,7 +559,7 @@ ksmbd_ipc_tree_connect_request(struct ksmbd_session *sess,
return NULL;
msg->type = KSMBD_EVENT_TREE_CONNECT_REQUEST;
- req = KSMBD_IPC_MSG_PAYLOAD(msg);
+ req = (struct ksmbd_tree_connect_request *)msg->payload;
req->handle = ksmbd_acquire_id(&ipc_ida);
req->account_flags = sess->user->flags;
@@ -598,7 +592,7 @@ int ksmbd_ipc_tree_disconnect_request(unsigned long long session_id,
return -ENOMEM;
msg->type = KSMBD_EVENT_TREE_DISCONNECT_REQUEST;
- req = KSMBD_IPC_MSG_PAYLOAD(msg);
+ req = (struct ksmbd_tree_disconnect_request *)msg->payload;
req->session_id = session_id;
req->connect_id = connect_id;
@@ -621,7 +615,7 @@ int ksmbd_ipc_logout_request(const char *account)
return -ENOMEM;
msg->type = KSMBD_EVENT_LOGOUT_REQUEST;
- req = KSMBD_IPC_MSG_PAYLOAD(msg);
+ req = (struct ksmbd_logout_request *)msg->payload;
strscpy(req->account, account, KSMBD_REQ_MAX_ACCOUNT_NAME_SZ);
ret = ipc_msg_send(msg);
@@ -644,7 +638,7 @@ ksmbd_ipc_share_config_request(const char *name)
return NULL;
msg->type = KSMBD_EVENT_SHARE_CONFIG_REQUEST;
- req = KSMBD_IPC_MSG_PAYLOAD(msg);
+ req = (struct ksmbd_share_config_request *)msg->payload;
req->handle = ksmbd_acquire_id(&ipc_ida);
strscpy(req->share_name, name, KSMBD_REQ_MAX_SHARE_NAME);
@@ -665,7 +659,7 @@ struct ksmbd_rpc_command *ksmbd_rpc_open(struct ksmbd_session *sess, int handle)
return NULL;
msg->type = KSMBD_EVENT_RPC_REQUEST;
- req = KSMBD_IPC_MSG_PAYLOAD(msg);
+ req = (struct ksmbd_rpc_command *)msg->payload;
req->handle = handle;
req->flags = ksmbd_session_rpc_method(sess, handle);
req->flags |= KSMBD_RPC_OPEN_METHOD;
@@ -687,7 +681,7 @@ struct ksmbd_rpc_command *ksmbd_rpc_close(struct ksmbd_session *sess, int handle
return NULL;
msg->type = KSMBD_EVENT_RPC_REQUEST;
- req = KSMBD_IPC_MSG_PAYLOAD(msg);
+ req = (struct ksmbd_rpc_command *)msg->payload;
req->handle = handle;
req->flags = ksmbd_session_rpc_method(sess, handle);
req->flags |= KSMBD_RPC_CLOSE_METHOD;
@@ -710,7 +704,7 @@ struct ksmbd_rpc_command *ksmbd_rpc_write(struct ksmbd_session *sess, int handle
return NULL;
msg->type = KSMBD_EVENT_RPC_REQUEST;
- req = KSMBD_IPC_MSG_PAYLOAD(msg);
+ req = (struct ksmbd_rpc_command *)msg->payload;
req->handle = handle;
req->flags = ksmbd_session_rpc_method(sess, handle);
req->flags |= rpc_context_flags(sess);
@@ -734,7 +728,7 @@ struct ksmbd_rpc_command *ksmbd_rpc_read(struct ksmbd_session *sess, int handle)
return NULL;
msg->type = KSMBD_EVENT_RPC_REQUEST;
- req = KSMBD_IPC_MSG_PAYLOAD(msg);
+ req = (struct ksmbd_rpc_command *)msg->payload;
req->handle = handle;
req->flags = ksmbd_session_rpc_method(sess, handle);
req->flags |= rpc_context_flags(sess);
@@ -758,7 +752,7 @@ struct ksmbd_rpc_command *ksmbd_rpc_ioctl(struct ksmbd_session *sess, int handle
return NULL;
msg->type = KSMBD_EVENT_RPC_REQUEST;
- req = KSMBD_IPC_MSG_PAYLOAD(msg);
+ req = (struct ksmbd_rpc_command *)req->payload;
req->handle = handle;
req->flags = ksmbd_session_rpc_method(sess, handle);
req->flags |= rpc_context_flags(sess);
@@ -783,7 +777,7 @@ struct ksmbd_rpc_command *ksmbd_rpc_rap(struct ksmbd_session *sess, void *payloa
return NULL;
msg->type = KSMBD_EVENT_RPC_REQUEST;
- req = KSMBD_IPC_MSG_PAYLOAD(msg);
+ req = (struct ksmbd_rpc_command *)req->payload;
req->handle = ksmbd_acquire_id(&ipc_ida);
req->flags = rpc_context_flags(sess);
req->flags |= KSMBD_RPC_RAP_METHOD;
@@ -828,7 +822,7 @@ static int __ipc_heartbeat(void)
WRITE_ONCE(server_conf.state, SERVER_STATE_RESETTING);
server_conf.ipc_last_active = 0;
ksmbd_tools_pid = 0;
- ksmbd_err("No IPC daemon response for %lus\n", delta / HZ);
+ pr_err("No IPC daemon response for %lus\n", delta / HZ);
mutex_unlock(&startup_lock);
return -EINVAL;
}
@@ -872,7 +866,7 @@ int ksmbd_ipc_init(void)
ret = genl_register_family(&ksmbd_genl_family);
if (ret) {
- ksmbd_err("Failed to register KSMBD netlink interface %d\n", ret);
+ pr_err("Failed to register KSMBD netlink interface %d\n", ret);
cancel_delayed_work_sync(&ipc_timer_work);
}
diff --git a/fs/cifsd/transport_ipc.h b/fs/ksmbd/transport_ipc.h
index 9eacc895ffdb..9eacc895ffdb 100644
--- a/fs/cifsd/transport_ipc.h
+++ b/fs/ksmbd/transport_ipc.h
diff --git a/fs/cifsd/transport_rdma.c b/fs/ksmbd/transport_rdma.c
index efaa9776841f..171fb3dd018a 100644
--- a/fs/cifsd/transport_rdma.c
+++ b/fs/ksmbd/transport_rdma.c
@@ -33,7 +33,6 @@
#include "connection.h"
#include "smb_common.h"
#include "smbstatus.h"
-#include "buffer_pool.h"
#include "transport_rdma.h"
#define SMB_DIRECT_PORT 5445
@@ -159,8 +158,6 @@ struct smb_direct_transport {
};
#define KSMBD_TRANS(t) ((struct ksmbd_transport *)&((t)->transport))
-#define SMB_DIRECT_TRANS(t) ((struct smb_direct_transport *)container_of(t, \
- struct smb_direct_transport, transport))
enum {
SMB_DIRECT_MSG_NEGOTIATE_REQ = 0,
@@ -205,9 +202,11 @@ struct smb_direct_rdma_rw_msg {
struct scatterlist sg_list[0];
};
-#define BUFFER_NR_PAGES(buf, len) \
- (DIV_ROUND_UP((unsigned long)(buf) + (len), PAGE_SIZE) \
- - (unsigned long)(buf) / PAGE_SIZE)
+static inline int get_buf_page_count(void *buf, int size)
+{
+ return DIV_ROUND_UP((uintptr_t)buf + size, PAGE_SIZE) -
+ (uintptr_t)buf / PAGE_SIZE;
+}
static void smb_direct_destroy_pools(struct smb_direct_transport *transport);
static void smb_direct_post_recv_credits(struct work_struct *work);
@@ -216,6 +215,12 @@ static int smb_direct_post_send_data(struct smb_direct_transport *t,
struct kvec *iov, int niov,
int remaining_data_length);
+static inline struct smb_direct_transport *
+smb_trans_direct_transfort(struct ksmbd_transport *t)
+{
+ return container_of(t, struct smb_direct_transport, transport);
+}
+
static inline void
*smb_direct_recvmsg_payload(struct smb_direct_recvmsg *recvmsg)
{
@@ -526,9 +531,9 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
if (wc->status != IB_WC_SUCCESS || wc->opcode != IB_WC_RECV) {
if (wc->status != IB_WC_WR_FLUSH_ERR) {
- ksmbd_err("Recv error. status='%s (%d)' opcode=%d\n",
- ib_wc_status_msg(wc->status), wc->status,
- wc->opcode);
+ pr_err("Recv error. status='%s (%d)' opcode=%d\n",
+ ib_wc_status_msg(wc->status), wc->status,
+ wc->opcode);
smb_direct_disconnect_rdma_connection(t);
}
put_empty_recvmsg(t, recvmsg);
@@ -624,7 +629,7 @@ static int smb_direct_post_recv(struct smb_direct_transport *t,
ret = ib_post_recv(t->qp, &wr, NULL);
if (ret) {
- ksmbd_err("Can't post recv: %d\n", ret);
+ pr_err("Can't post recv: %d\n", ret);
ib_dma_unmap_single(t->cm_id->device,
recvmsg->sge.addr, recvmsg->sge.length,
DMA_FROM_DEVICE);
@@ -642,11 +647,11 @@ static int smb_direct_read(struct ksmbd_transport *t, char *buf,
int to_copy, to_read, data_read, offset;
u32 data_length, remaining_data_length, data_offset;
int rc;
- struct smb_direct_transport *st = SMB_DIRECT_TRANS(t);
+ struct smb_direct_transport *st = smb_trans_direct_transfort(t);
again:
if (st->status != SMB_DIRECT_CS_CONNECTED) {
- ksmbd_err("disconnected\n");
+ pr_err("disconnected\n");
return -ENOTCONN;
}
@@ -795,7 +800,7 @@ static void smb_direct_post_recv_credits(struct work_struct *work)
ret = smb_direct_post_recv(t, recvmsg);
if (ret) {
- ksmbd_err("Can't post recv: %d\n", ret);
+ pr_err("Can't post recv: %d\n", ret);
put_recvmsg(t, recvmsg);
break;
}
@@ -830,9 +835,9 @@ static void send_done(struct ib_cq *cq, struct ib_wc *wc)
wc->opcode);
if (wc->status != IB_WC_SUCCESS || wc->opcode != IB_WC_SEND) {
- ksmbd_err("Send error. status='%s (%d)', opcode=%d\n",
- ib_wc_status_msg(wc->status), wc->status,
- wc->opcode);
+ pr_err("Send error. status='%s (%d)', opcode=%d\n",
+ ib_wc_status_msg(wc->status), wc->status,
+ wc->opcode);
smb_direct_disconnect_rdma_connection(t);
}
@@ -881,7 +886,7 @@ static int smb_direct_post_send(struct smb_direct_transport *t,
ret = ib_post_send(t->qp, wr, NULL);
if (ret) {
- ksmbd_err("failed to post send: %d\n", ret);
+ pr_err("failed to post send: %d\n", ret);
if (wr->num_sge > 1) {
if (atomic_dec_and_test(&t->send_payload_pending))
wake_up(&t->wait_send_payload_pending);
@@ -1049,7 +1054,7 @@ static int get_sg_list(void *buf, int size, struct scatterlist *sg_list, int nen
int offset, len;
int i = 0;
- if (nentries < BUFFER_NR_PAGES(buf, size))
+ if (nentries < get_buf_page_count(buf, size))
return -EINVAL;
offset = offset_in_page(buf);
@@ -1159,11 +1164,11 @@ static int smb_direct_post_send_data(struct smb_direct_transport *t,
sg, SMB_DIRECT_MAX_SEND_SGES - 1,
DMA_TO_DEVICE);
if (sg_cnt <= 0) {
- ksmbd_err("failed to map buffer\n");
+ pr_err("failed to map buffer\n");
ret = -ENOMEM;
goto err;
} else if (sg_cnt + msg->num_sge > SMB_DIRECT_MAX_SEND_SGES - 1) {
- ksmbd_err("buffer not fitted into sges\n");
+ pr_err("buffer not fitted into sges\n");
ret = -E2BIG;
ib_dma_unmap_sg(t->cm_id->device, sg, sg_cnt,
DMA_TO_DEVICE);
@@ -1193,7 +1198,7 @@ static int smb_direct_writev(struct ksmbd_transport *t,
struct kvec *iov, int niovs, int buflen,
bool need_invalidate, unsigned int remote_key)
{
- struct smb_direct_transport *st = SMB_DIRECT_TRANS(t);
+ struct smb_direct_transport *st = smb_trans_direct_transfort(t);
int remaining_data_length;
int start, i, j;
int max_iov_size = st->max_send_size -
@@ -1291,8 +1296,8 @@ static void read_write_done(struct ib_cq *cq, struct ib_wc *wc,
struct smb_direct_transport *t = msg->t;
if (wc->status != IB_WC_SUCCESS) {
- ksmbd_err("read/write error. opcode = %d, status = %s(%d)\n",
- wc->opcode, ib_wc_status_msg(wc->status), wc->status);
+ pr_err("read/write error. opcode = %d, status = %s(%d)\n",
+ wc->opcode, ib_wc_status_msg(wc->status), wc->status);
smb_direct_disconnect_rdma_connection(t);
}
@@ -1339,7 +1344,7 @@ static int smb_direct_rdma_xmit(struct smb_direct_transport *t, void *buf,
msg->sgt.sgl = &msg->sg_list[0];
ret = sg_alloc_table_chained(&msg->sgt,
- BUFFER_NR_PAGES(buf, buf_len),
+ get_buf_page_count(buf, buf_len),
msg->sg_list, SG_CHUNK_SIZE);
if (ret) {
atomic_inc(&t->rw_avail_ops);
@@ -1349,16 +1354,16 @@ static int smb_direct_rdma_xmit(struct smb_direct_transport *t, void *buf,
ret = get_sg_list(buf, buf_len, msg->sgt.sgl, msg->sgt.orig_nents);
if (ret <= 0) {
- ksmbd_err("failed to get pages\n");
+ pr_err("failed to get pages\n");
goto err;
}
ret = rdma_rw_ctx_init(&msg->rw_ctx, t->qp, t->qp->port,
- msg->sg_list, BUFFER_NR_PAGES(buf, buf_len),
+ msg->sg_list, get_buf_page_count(buf, buf_len),
0, remote_offset, remote_key,
is_read ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
if (ret < 0) {
- ksmbd_err("failed to init rdma_rw_ctx: %d\n", ret);
+ pr_err("failed to init rdma_rw_ctx: %d\n", ret);
goto err;
}
@@ -1370,7 +1375,7 @@ static int smb_direct_rdma_xmit(struct smb_direct_transport *t, void *buf,
ret = ib_post_send(t->qp, first_wr, NULL);
if (ret) {
- ksmbd_err("failed to post send wr: %d\n", ret);
+ pr_err("failed to post send wr: %d\n", ret);
goto err;
}
@@ -1392,7 +1397,7 @@ static int smb_direct_rdma_write(struct ksmbd_transport *t, void *buf,
unsigned int buflen, u32 remote_key,
u64 remote_offset, u32 remote_len)
{
- return smb_direct_rdma_xmit(SMB_DIRECT_TRANS(t), buf, buflen,
+ return smb_direct_rdma_xmit(smb_trans_direct_transfort(t), buf, buflen,
remote_key, remote_offset,
remote_len, false);
}
@@ -1401,14 +1406,14 @@ static int smb_direct_rdma_read(struct ksmbd_transport *t, void *buf,
unsigned int buflen, u32 remote_key,
u64 remote_offset, u32 remote_len)
{
- return smb_direct_rdma_xmit(SMB_DIRECT_TRANS(t), buf, buflen,
+ return smb_direct_rdma_xmit(smb_trans_direct_transfort(t), buf, buflen,
remote_key, remote_offset,
remote_len, true);
}
static void smb_direct_disconnect(struct ksmbd_transport *t)
{
- struct smb_direct_transport *st = SMB_DIRECT_TRANS(t);
+ struct smb_direct_transport *st = smb_trans_direct_transfort(t);
ksmbd_debug(RDMA, "Disconnecting cm_id=%p\n", st->cm_id);
@@ -1446,9 +1451,9 @@ static int smb_direct_cm_handler(struct rdma_cm_id *cm_id,
break;
}
default:
- ksmbd_err("Unexpected RDMA CM event. cm_id=%p, event=%s (%d)\n",
- cm_id, rdma_event_msg(event->event),
- event->event);
+ pr_err("Unexpected RDMA CM event. cm_id=%p, event=%s (%d)\n",
+ cm_id, rdma_event_msg(event->event),
+ event->event);
break;
}
return 0;
@@ -1558,7 +1563,7 @@ static int smb_direct_accept_client(struct smb_direct_transport *t)
ret = rdma_accept(t->cm_id, &conn_param);
if (ret) {
- ksmbd_err("error at rdma_accept: %d\n", ret);
+ pr_err("error at rdma_accept: %d\n", ret);
return ret;
}
@@ -1582,14 +1587,14 @@ static int smb_direct_negotiate(struct smb_direct_transport *t)
ret = smb_direct_post_recv(t, recvmsg);
if (ret) {
- ksmbd_err("Can't post recv: %d\n", ret);
+ pr_err("Can't post recv: %d\n", ret);
goto out;
}
t->negotiation_requested = false;
ret = smb_direct_accept_client(t);
if (ret) {
- ksmbd_err("Can't accept client\n");
+ pr_err("Can't accept client\n");
goto out;
}
@@ -1636,7 +1641,7 @@ static int smb_direct_init_params(struct smb_direct_transport *t,
t->max_send_size = smb_direct_max_send_size;
max_send_sges = DIV_ROUND_UP(t->max_send_size, PAGE_SIZE) + 2;
if (max_send_sges > SMB_DIRECT_MAX_SEND_SGES) {
- ksmbd_err("max_send_size %d is too large\n", t->max_send_size);
+ pr_err("max_send_size %d is too large\n", t->max_send_size);
return -EINVAL;
}
@@ -1656,31 +1661,31 @@ static int smb_direct_init_params(struct smb_direct_transport *t,
max_send_wrs = smb_direct_send_credit_target + max_rw_wrs;
if (max_send_wrs > device->attrs.max_cqe ||
max_send_wrs > device->attrs.max_qp_wr) {
- ksmbd_err("consider lowering send_credit_target = %d, or max_outstanding_rw_ops = %d\n",
- smb_direct_send_credit_target,
- smb_direct_max_outstanding_rw_ops);
- ksmbd_err("Possible CQE overrun, device reporting max_cqe %d max_qp_wr %d\n",
- device->attrs.max_cqe, device->attrs.max_qp_wr);
+ pr_err("consider lowering send_credit_target = %d, or max_outstanding_rw_ops = %d\n",
+ smb_direct_send_credit_target,
+ smb_direct_max_outstanding_rw_ops);
+ pr_err("Possible CQE overrun, device reporting max_cqe %d max_qp_wr %d\n",
+ device->attrs.max_cqe, device->attrs.max_qp_wr);
return -EINVAL;
}
if (smb_direct_receive_credit_max > device->attrs.max_cqe ||
smb_direct_receive_credit_max > device->attrs.max_qp_wr) {
- ksmbd_err("consider lowering receive_credit_max = %d\n",
- smb_direct_receive_credit_max);
- ksmbd_err("Possible CQE overrun, device reporting max_cpe %d max_qp_wr %d\n",
- device->attrs.max_cqe, device->attrs.max_qp_wr);
+ pr_err("consider lowering receive_credit_max = %d\n",
+ smb_direct_receive_credit_max);
+ pr_err("Possible CQE overrun, device reporting max_cpe %d max_qp_wr %d\n",
+ device->attrs.max_cqe, device->attrs.max_qp_wr);
return -EINVAL;
}
if (device->attrs.max_send_sge < SMB_DIRECT_MAX_SEND_SGES) {
- ksmbd_err("warning: device max_send_sge = %d too small\n",
- device->attrs.max_send_sge);
+ pr_err("warning: device max_send_sge = %d too small\n",
+ device->attrs.max_send_sge);
return -EINVAL;
}
if (device->attrs.max_recv_sge < SMB_DIRECT_MAX_RECV_SGES) {
- ksmbd_err("warning: device max_recv_sge = %d too small\n",
- device->attrs.max_recv_sge);
+ pr_err("warning: device max_recv_sge = %d too small\n",
+ device->attrs.max_recv_sge);
return -EINVAL;
}
@@ -1789,7 +1794,7 @@ static int smb_direct_create_qpair(struct smb_direct_transport *t,
t->pd = ib_alloc_pd(t->cm_id->device, 0);
if (IS_ERR(t->pd)) {
- ksmbd_err("Can't create RDMA PD\n");
+ pr_err("Can't create RDMA PD\n");
ret = PTR_ERR(t->pd);
t->pd = NULL;
return ret;
@@ -1798,7 +1803,7 @@ static int smb_direct_create_qpair(struct smb_direct_transport *t,
t->send_cq = ib_alloc_cq(t->cm_id->device, t,
t->send_credit_target, 0, IB_POLL_WORKQUEUE);
if (IS_ERR(t->send_cq)) {
- ksmbd_err("Can't create RDMA send CQ\n");
+ pr_err("Can't create RDMA send CQ\n");
ret = PTR_ERR(t->send_cq);
t->send_cq = NULL;
goto err;
@@ -1808,7 +1813,7 @@ static int smb_direct_create_qpair(struct smb_direct_transport *t,
cap->max_send_wr + cap->max_rdma_ctxs,
0, IB_POLL_WORKQUEUE);
if (IS_ERR(t->recv_cq)) {
- ksmbd_err("Can't create RDMA recv CQ\n");
+ pr_err("Can't create RDMA recv CQ\n");
ret = PTR_ERR(t->recv_cq);
t->recv_cq = NULL;
goto err;
@@ -1826,7 +1831,7 @@ static int smb_direct_create_qpair(struct smb_direct_transport *t,
ret = rdma_create_qp(t->cm_id, t->pd, &qp_attr);
if (ret) {
- ksmbd_err("Can't create RDMA QP: %d\n", ret);
+ pr_err("Can't create RDMA QP: %d\n", ret);
goto err;
}
@@ -1856,31 +1861,31 @@ err:
static int smb_direct_prepare(struct ksmbd_transport *t)
{
- struct smb_direct_transport *st = SMB_DIRECT_TRANS(t);
+ struct smb_direct_transport *st = smb_trans_direct_transfort(t);
int ret;
struct ib_qp_cap qp_cap;
ret = smb_direct_init_params(st, &qp_cap);
if (ret) {
- ksmbd_err("Can't configure RDMA parameters\n");
+ pr_err("Can't configure RDMA parameters\n");
return ret;
}
ret = smb_direct_create_pools(st);
if (ret) {
- ksmbd_err("Can't init RDMA pool: %d\n", ret);
+ pr_err("Can't init RDMA pool: %d\n", ret);
return ret;
}
ret = smb_direct_create_qpair(st, &qp_cap);
if (ret) {
- ksmbd_err("Can't accept RDMA client: %d\n", ret);
+ pr_err("Can't accept RDMA client: %d\n", ret);
return ret;
}
ret = smb_direct_negotiate(st);
if (ret) {
- ksmbd_err("Can't negotiate: %d\n", ret);
+ pr_err("Can't negotiate: %d\n", ret);
return ret;
}
@@ -1918,7 +1923,7 @@ static int smb_direct_handle_connect_request(struct rdma_cm_id *new_cm_id)
if (IS_ERR(KSMBD_TRANS(t)->handler)) {
int ret = PTR_ERR(KSMBD_TRANS(t)->handler);
- ksmbd_err("Can't start thread\n");
+ pr_err("Can't start thread\n");
free_transport(t);
return ret;
}
@@ -1934,7 +1939,7 @@ static int smb_direct_listen_handler(struct rdma_cm_id *cm_id,
int ret = smb_direct_handle_connect_request(cm_id);
if (ret) {
- ksmbd_err("Can't create transport: %d\n", ret);
+ pr_err("Can't create transport: %d\n", ret);
return ret;
}
@@ -1943,8 +1948,8 @@ static int smb_direct_listen_handler(struct rdma_cm_id *cm_id,
break;
}
default:
- ksmbd_err("Unexpected listen event. cm_id=%p, event=%s (%d)\n",
- cm_id, rdma_event_msg(event->event), event->event);
+ pr_err("Unexpected listen event. cm_id=%p, event=%s (%d)\n",
+ cm_id, rdma_event_msg(event->event), event->event);
break;
}
return 0;
@@ -1963,13 +1968,13 @@ static int smb_direct_listen(int port)
cm_id = rdma_create_id(&init_net, smb_direct_listen_handler,
&smb_direct_listener, RDMA_PS_TCP, IB_QPT_RC);
if (IS_ERR(cm_id)) {
- ksmbd_err("Can't create cm id: %ld\n", PTR_ERR(cm_id));
+ pr_err("Can't create cm id: %ld\n", PTR_ERR(cm_id));
return PTR_ERR(cm_id);
}
ret = rdma_bind_addr(cm_id, (struct sockaddr *)&sin);
if (ret) {
- ksmbd_err("Can't bind: %d\n", ret);
+ pr_err("Can't bind: %d\n", ret);
goto err;
}
@@ -1977,7 +1982,7 @@ static int smb_direct_listen(int port)
ret = rdma_listen(cm_id, 10);
if (ret) {
- ksmbd_err("Can't listen: %d\n", ret);
+ pr_err("Can't listen: %d\n", ret);
goto err;
}
return 0;
@@ -2007,7 +2012,7 @@ int ksmbd_rdma_init(void)
if (ret) {
destroy_workqueue(smb_direct_wq);
smb_direct_wq = NULL;
- ksmbd_err("Can't listen: %d\n", ret);
+ pr_err("Can't listen: %d\n", ret);
return ret;
}
diff --git a/fs/cifsd/transport_rdma.h b/fs/ksmbd/transport_rdma.h
index da60fcec3ede..da60fcec3ede 100644
--- a/fs/cifsd/transport_rdma.h
+++ b/fs/ksmbd/transport_rdma.h
diff --git a/fs/cifsd/transport_tcp.c b/fs/ksmbd/transport_tcp.c
index d6d5c0038dea..56ec11ff5a9f 100644
--- a/fs/cifsd/transport_tcp.c
+++ b/fs/ksmbd/transport_tcp.c
@@ -9,7 +9,6 @@
#include "smb_common.h"
#include "server.h"
#include "auth.h"
-#include "buffer_pool.h"
#include "connection.h"
#include "transport_tcp.h"
@@ -191,7 +190,7 @@ static int ksmbd_tcp_new_connection(struct socket *client_sk)
csin = KSMBD_TCP_PEER_SOCKADDR(KSMBD_TRANS(t)->conn);
if (kernel_getpeername(client_sk, csin) < 0) {
- ksmbd_err("client ip resolution failed\n");
+ pr_err("client ip resolution failed\n");
rc = -EINVAL;
goto out_error;
}
@@ -201,7 +200,7 @@ static int ksmbd_tcp_new_connection(struct socket *client_sk)
"ksmbd:%u",
ksmbd_tcp_get_port(csin));
if (IS_ERR(KSMBD_TRANS(t)->handler)) {
- ksmbd_err("cannot start conn thread\n");
+ pr_err("cannot start conn thread\n");
rc = PTR_ERR(KSMBD_TRANS(t)->handler);
free_transport(t);
}
@@ -381,7 +380,7 @@ static void tcp_destroy_socket(struct socket *ksmbd_socket)
ret = kernel_sock_shutdown(ksmbd_socket, SHUT_RDWR);
if (ret)
- ksmbd_err("Failed to shutdown socket: %d\n", ret);
+ pr_err("Failed to shutdown socket: %d\n", ret);
else
sock_release(ksmbd_socket);
}
@@ -401,11 +400,11 @@ static int create_socket(struct interface *iface)
ret = sock_create(PF_INET6, SOCK_STREAM, IPPROTO_TCP, &ksmbd_socket);
if (ret) {
- ksmbd_err("Can't create socket for ipv6, try ipv4: %d\n", ret);
+ pr_err("Can't create socket for ipv6, try ipv4: %d\n", ret);
ret = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP,
&ksmbd_socket);
if (ret) {
- ksmbd_err("Can't create socket for ipv4: %d\n", ret);
+ pr_err("Can't create socket for ipv4: %d\n", ret);
goto out_error;
}
@@ -428,7 +427,7 @@ static int create_socket(struct interface *iface)
KERNEL_SOCKPTR(iface->name),
strlen(iface->name));
if (ret != -ENODEV && ret < 0) {
- ksmbd_err("Failed to set SO_BINDTODEVICE: %d\n", ret);
+ pr_err("Failed to set SO_BINDTODEVICE: %d\n", ret);
goto out_error;
}
@@ -439,7 +438,7 @@ static int create_socket(struct interface *iface)
ret = kernel_bind(ksmbd_socket, (struct sockaddr *)&sin6,
sizeof(sin6));
if (ret) {
- ksmbd_err("Failed to bind socket: %d\n", ret);
+ pr_err("Failed to bind socket: %d\n", ret);
goto out_error;
}
@@ -448,14 +447,14 @@ static int create_socket(struct interface *iface)
ret = kernel_listen(ksmbd_socket, KSMBD_SOCKET_BACKLOG);
if (ret) {
- ksmbd_err("Port listen() error: %d\n", ret);
+ pr_err("Port listen() error: %d\n", ret);
goto out_error;
}
iface->ksmbd_socket = ksmbd_socket;
ret = ksmbd_tcp_run_kthread(iface);
if (ret) {
- ksmbd_err("Can't start ksmbd main kthread: %d\n", ret);
+ pr_err("Can't start ksmbd main kthread: %d\n", ret);
goto out_error;
}
iface->state = IFACE_STATE_CONFIGURED;
@@ -541,7 +540,7 @@ static void tcp_stop_kthread(struct task_struct *kthread)
ret = kthread_stop(kthread);
if (ret)
- ksmbd_err("failed to stop forker thread\n");
+ pr_err("failed to stop forker thread\n");
}
void ksmbd_tcp_destroy(void)
diff --git a/fs/cifsd/transport_tcp.h b/fs/ksmbd/transport_tcp.h
index e338bebe322f..e338bebe322f 100644
--- a/fs/cifsd/transport_tcp.h
+++ b/fs/ksmbd/transport_tcp.h
diff --git a/fs/cifsd/unicode.c b/fs/ksmbd/unicode.c
index a0db699ddafd..a0db699ddafd 100644
--- a/fs/cifsd/unicode.c
+++ b/fs/ksmbd/unicode.c
diff --git a/fs/cifsd/unicode.h b/fs/ksmbd/unicode.h
index 5593024230ae..5593024230ae 100644
--- a/fs/cifsd/unicode.h
+++ b/fs/ksmbd/unicode.h
diff --git a/fs/cifsd/uniupr.h b/fs/ksmbd/uniupr.h
index 26583b776897..26583b776897 100644
--- a/fs/cifsd/uniupr.h
+++ b/fs/ksmbd/uniupr.h
diff --git a/fs/cifsd/vfs.c b/fs/ksmbd/vfs.c
index 9111b485d611..0f5a4fb8215f 100644
--- a/fs/cifsd/vfs.c
+++ b/fs/ksmbd/vfs.c
@@ -12,7 +12,6 @@
#include <linux/xattr.h>
#include <linux/falloc.h>
#include <linux/genhd.h>
-#include <linux/blkdev.h>
#include <linux/fsnotify.h>
#include <linux/dcache.h>
#include <linux/slab.h>
@@ -23,7 +22,6 @@
#include "glob.h"
#include "oplock.h"
#include "connection.h"
-#include "buffer_pool.h"
#include "vfs.h"
#include "vfs_cache.h"
#include "smbacl.h"
@@ -46,7 +44,7 @@ static char *extract_last_component(char *path)
p++;
} else {
p = NULL;
- ksmbd_err("Invalid path %s\n", path);
+ pr_err("Invalid path %s\n", path);
}
return p;
}
@@ -62,92 +60,92 @@ static void ksmbd_vfs_inherit_owner(struct ksmbd_work *work,
i_uid_write(inode, i_uid_read(parent_inode));
}
-int ksmbd_vfs_inode_permission(struct dentry *dentry, int acc_mode, bool delete)
+/**
+ * ksmbd_vfs_lock_parent() - lock parent dentry if it is stable
+ *
+ * the parent dentry got by dget_parent or @parent could be
+ * unstable, we try to lock a parent inode and lookup the
+ * child dentry again.
+ *
+ * the reference count of @parent isn't incremented.
+ */
+int ksmbd_vfs_lock_parent(struct dentry *parent, struct dentry *child)
{
- int mask, ret = 0;
-
- mask = 0;
- acc_mode &= O_ACCMODE;
-
- if (acc_mode == O_RDONLY)
- mask = MAY_READ;
- else if (acc_mode == O_WRONLY)
- mask = MAY_WRITE;
- else if (acc_mode == O_RDWR)
- mask = MAY_READ | MAY_WRITE;
+ struct dentry *dentry;
+ int ret = 0;
- if (inode_permission(&init_user_ns, d_inode(dentry), mask | MAY_OPEN))
- return -EACCES;
+ inode_lock_nested(d_inode(parent), I_MUTEX_PARENT);
+ dentry = lookup_one_len(child->d_name.name, parent,
+ child->d_name.len);
+ if (IS_ERR(dentry)) {
+ ret = PTR_ERR(dentry);
+ goto out_err;
+ }
- if (delete) {
- struct dentry *child, *parent;
+ if (dentry != child) {
+ ret = -ESTALE;
+ dput(dentry);
+ goto out_err;
+ }
- parent = dget_parent(dentry);
- inode_lock_nested(d_inode(parent), I_MUTEX_PARENT);
- child = lookup_one_len(dentry->d_name.name, parent,
- dentry->d_name.len);
- if (IS_ERR(child)) {
- ret = PTR_ERR(child);
- goto out_lock;
- }
+ dput(dentry);
+ return 0;
+out_err:
+ inode_unlock(d_inode(parent));
+ return ret;
+}
- if (child != dentry) {
- ret = -ESTALE;
- dput(child);
- goto out_lock;
- }
- dput(child);
+int ksmbd_vfs_may_delete(struct user_namespace *user_ns,
+ struct dentry *dentry)
+{
+ struct dentry *parent;
+ int ret;
- if (inode_permission(&init_user_ns, d_inode(parent), MAY_EXEC | MAY_WRITE)) {
- ret = -EACCES;
- goto out_lock;
- }
-out_lock:
- inode_unlock(d_inode(parent));
+ parent = dget_parent(dentry);
+ ret = ksmbd_vfs_lock_parent(parent, dentry);
+ if (ret) {
dput(parent);
+ return ret;
}
+
+ ret = inode_permission(user_ns, d_inode(parent),
+ MAY_EXEC | MAY_WRITE);
+
+ inode_unlock(d_inode(parent));
+ dput(parent);
return ret;
}
-int ksmbd_vfs_query_maximal_access(struct dentry *dentry, __le32 *daccess)
+int ksmbd_vfs_query_maximal_access(struct user_namespace *user_ns,
+ struct dentry *dentry, __le32 *daccess)
{
- struct dentry *parent, *child;
+ struct dentry *parent;
int ret = 0;
*daccess = cpu_to_le32(FILE_READ_ATTRIBUTES | READ_CONTROL);
- if (!inode_permission(&init_user_ns, d_inode(dentry), MAY_OPEN | MAY_WRITE))
+ if (!inode_permission(user_ns, d_inode(dentry), MAY_OPEN | MAY_WRITE))
*daccess |= cpu_to_le32(WRITE_DAC | WRITE_OWNER | SYNCHRONIZE |
FILE_WRITE_DATA | FILE_APPEND_DATA |
FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES |
FILE_DELETE_CHILD);
- if (!inode_permission(&init_user_ns, d_inode(dentry), MAY_OPEN | MAY_READ))
+ if (!inode_permission(user_ns, d_inode(dentry), MAY_OPEN | MAY_READ))
*daccess |= FILE_READ_DATA_LE | FILE_READ_EA_LE;
- if (!inode_permission(&init_user_ns, d_inode(dentry), MAY_OPEN | MAY_EXEC))
+ if (!inode_permission(user_ns, d_inode(dentry), MAY_OPEN | MAY_EXEC))
*daccess |= FILE_EXECUTE_LE;
parent = dget_parent(dentry);
- inode_lock_nested(d_inode(parent), I_MUTEX_PARENT);
- child = lookup_one_len(dentry->d_name.name, parent,
- dentry->d_name.len);
- if (IS_ERR(child)) {
- ret = PTR_ERR(child);
- goto out_lock;
- }
-
- if (child != dentry) {
- ret = -ESTALE;
- dput(child);
- goto out_lock;
+ ret = ksmbd_vfs_lock_parent(parent, dentry);
+ if (ret) {
+ dput(parent);
+ return ret;
}
- dput(child);
- if (!inode_permission(&init_user_ns, d_inode(parent), MAY_EXEC | MAY_WRITE))
+ if (!inode_permission(user_ns, d_inode(parent), MAY_EXEC | MAY_WRITE))
*daccess |= FILE_DELETE_LE;
-out_lock:
inode_unlock(d_inode(parent));
dput(parent);
return ret;
@@ -171,18 +169,19 @@ int ksmbd_vfs_create(struct ksmbd_work *work, const char *name, umode_t mode)
if (IS_ERR(dentry)) {
err = PTR_ERR(dentry);
if (err != -ENOENT)
- ksmbd_err("path create failed for %s, err %d\n",
- name, err);
+ pr_err("path create failed for %s, err %d\n",
+ name, err);
return err;
}
mode |= S_IFREG;
- err = vfs_create(&init_user_ns, d_inode(path.dentry), dentry, mode, true);
+ err = vfs_create(mnt_user_ns(path.mnt), d_inode(path.dentry),
+ dentry, mode, true);
if (!err) {
ksmbd_vfs_inherit_owner(work, d_inode(path.dentry),
d_inode(dentry));
} else {
- ksmbd_err("File(%s): creation failed (err:%d)\n", name, err);
+ pr_err("File(%s): creation failed (err:%d)\n", name, err);
}
done_path_create(&path, dentry);
return err;
@@ -212,7 +211,8 @@ int ksmbd_vfs_mkdir(struct ksmbd_work *work, const char *name, umode_t mode)
}
mode |= S_IFDIR;
- err = vfs_mkdir(&init_user_ns, d_inode(path.dentry), dentry, mode);
+ err = vfs_mkdir(mnt_user_ns(path.mnt), d_inode(path.dentry),
+ dentry, mode);
if (err) {
goto out;
} else if (d_unhashed(dentry)) {
@@ -236,11 +236,12 @@ int ksmbd_vfs_mkdir(struct ksmbd_work *work, const char *name, umode_t mode)
out:
done_path_create(&path, dentry);
if (err)
- ksmbd_err("mkdir(%s): creation failed (err:%d)\n", name, err);
+ pr_err("mkdir(%s): creation failed (err:%d)\n", name, err);
return err;
}
-static ssize_t ksmbd_vfs_getcasexattr(struct dentry *dentry, char *attr_name,
+static ssize_t ksmbd_vfs_getcasexattr(struct user_namespace *user_ns,
+ struct dentry *dentry, char *attr_name,
int attr_name_len, char **attr_value)
{
char *name, *xattr_list = NULL;
@@ -256,11 +257,12 @@ static ssize_t ksmbd_vfs_getcasexattr(struct dentry *dentry, char *attr_name,
if (strncasecmp(attr_name, name, attr_name_len))
continue;
- value_len = ksmbd_vfs_getxattr(dentry,
+ value_len = ksmbd_vfs_getxattr(user_ns,
+ dentry,
name,
attr_value);
if (value_len < 0)
- ksmbd_err("failed to get xattr in file\n");
+ pr_err("failed to get xattr in file\n");
break;
}
@@ -278,7 +280,8 @@ static int ksmbd_vfs_stream_read(struct ksmbd_file *fp, char *buf, loff_t *pos,
ksmbd_debug(VFS, "read stream data pos : %llu, count : %zd\n",
*pos, count);
- v_len = ksmbd_vfs_getcasexattr(fp->filp->f_path.dentry,
+ v_len = ksmbd_vfs_getcasexattr(file_mnt_user_ns(fp->filp),
+ fp->filp->f_path.dentry,
fp->stream.name,
fp->stream.size,
&stream_buf);
@@ -325,7 +328,7 @@ static int check_lock_range(struct file *filp, loff_t start, loff_t end,
if (flock->fl_end >= start && end >= flock->fl_start) {
if (flock->fl_type == F_RDLCK) {
if (type == WRITE) {
- ksmbd_err("not allow write by shared lock\n");
+ pr_err("not allow write by shared lock\n");
error = 1;
goto out;
}
@@ -333,7 +336,7 @@ static int check_lock_range(struct file *filp, loff_t start, loff_t end,
/* check owner in lock */
if (flock->fl_file != filp) {
error = 1;
- ksmbd_err("not allow rw access by exclusive lock from other opens\n");
+ pr_err("not allow rw access by exclusive lock from other opens\n");
goto out;
}
}
@@ -356,14 +359,11 @@ out:
int ksmbd_vfs_read(struct ksmbd_work *work, struct ksmbd_file *fp, size_t count,
loff_t *pos)
{
- struct file *filp;
+ struct file *filp = fp->filp;
ssize_t nbytes = 0;
- char *rbuf;
- struct inode *inode;
+ char *rbuf = work->aux_payload_buf;
+ struct inode *inode = file_inode(filp);
- rbuf = work->aux_payload_buf;
- filp = fp->filp;
- inode = file_inode(filp);
if (S_ISDIR(inode->i_mode))
return -EISDIR;
@@ -372,7 +372,8 @@ int ksmbd_vfs_read(struct ksmbd_work *work, struct ksmbd_file *fp, size_t count,
if (work->conn->connection_type) {
if (!(fp->daccess & (FILE_READ_DATA_LE | FILE_EXECUTE_LE))) {
- ksmbd_err("no right to read(%s)\n", FP_FILENAME(fp));
+ pr_err("no right to read(%pd)\n",
+ fp->filp->f_path.dentry);
return -EACCES;
}
}
@@ -385,15 +386,15 @@ int ksmbd_vfs_read(struct ksmbd_work *work, struct ksmbd_file *fp, size_t count,
ret = check_lock_range(filp, *pos, *pos + count - 1, READ);
if (ret) {
- ksmbd_err("unable to read due to lock\n");
+ pr_err("unable to read due to lock\n");
return -EAGAIN;
}
}
nbytes = kernel_read(filp, rbuf, count, pos);
if (nbytes < 0) {
- ksmbd_err("smb read failed for (%s), err = %zd\n",
- fp->filename, nbytes);
+ pr_err("smb read failed for (%s), err = %zd\n",
+ fp->filename, nbytes);
return nbytes;
}
@@ -417,12 +418,13 @@ static int ksmbd_vfs_stream_write(struct ksmbd_file *fp, char *buf, loff_t *pos,
count = (*pos + count) - XATTR_SIZE_MAX;
}
- v_len = ksmbd_vfs_getcasexattr(fp->filp->f_path.dentry,
+ v_len = ksmbd_vfs_getcasexattr(file_mnt_user_ns(fp->filp),
+ fp->filp->f_path.dentry,
fp->stream.name,
fp->stream.size,
&stream_buf);
if ((int)v_len < 0) {
- ksmbd_err("not found stream in xattr : %zd\n", v_len);
+ pr_err("not found stream in xattr : %zd\n", v_len);
err = (int)v_len;
goto out;
}
@@ -442,7 +444,8 @@ static int ksmbd_vfs_stream_write(struct ksmbd_file *fp, char *buf, loff_t *pos,
memcpy(&stream_buf[*pos], buf, count);
- err = ksmbd_vfs_setxattr(fp->filp->f_path.dentry,
+ err = ksmbd_vfs_setxattr(file_mnt_user_ns(fp->filp),
+ fp->filp->f_path.dentry,
fp->stream.name,
(void *)stream_buf,
size,
@@ -480,7 +483,8 @@ int ksmbd_vfs_write(struct ksmbd_work *work, struct ksmbd_file *fp,
if (sess->conn->connection_type) {
if (!(fp->daccess & FILE_WRITE_DATA_LE)) {
- ksmbd_err("no right to write(%s)\n", FP_FILENAME(fp));
+ pr_err("no right to write(%pd)\n",
+ fp->filp->f_path.dentry);
err = -EACCES;
goto out;
}
@@ -498,7 +502,7 @@ int ksmbd_vfs_write(struct ksmbd_work *work, struct ksmbd_file *fp,
if (!work->tcon->posix_extensions) {
err = check_lock_range(filp, *pos, *pos + count - 1, WRITE);
if (err) {
- ksmbd_err("unable to write due to lock\n");
+ pr_err("unable to write due to lock\n");
err = -EAGAIN;
goto out;
}
@@ -519,8 +523,8 @@ int ksmbd_vfs_write(struct ksmbd_work *work, struct ksmbd_file *fp,
if (sync) {
err = vfs_fsync_range(filp, offset, offset + *written, 0);
if (err < 0)
- ksmbd_err("fsync failed for filename = %s, err = %d\n",
- FP_FILENAME(fp), err);
+ pr_err("fsync failed for filename = %pd, err = %d\n",
+ fp->filp->f_path.dentry, err);
}
out:
@@ -541,7 +545,7 @@ int ksmbd_vfs_getattr(struct path *path, struct kstat *stat)
err = vfs_getattr(path, stat, STATX_BTIME, AT_STATX_SYNC_AS_STAT);
if (err)
- ksmbd_err("getattr failed, err %d\n", err);
+ pr_err("getattr failed, err %d\n", err);
return err;
}
@@ -559,12 +563,12 @@ int ksmbd_vfs_fsync(struct ksmbd_work *work, u64 fid, u64 p_id)
fp = ksmbd_lookup_fd_slow(work, fid, p_id);
if (!fp) {
- ksmbd_err("failed to get filp for fid %llu\n", fid);
+ pr_err("failed to get filp for fid %llu\n", fid);
return -ENOENT;
}
err = vfs_fsync(fp->filp, 0);
if (err < 0)
- ksmbd_err("smb fsync failed, err = %d\n", err);
+ pr_err("smb fsync failed, err = %d\n", err);
ksmbd_fd_put(work, fp);
return err;
}
@@ -578,7 +582,7 @@ int ksmbd_vfs_fsync(struct ksmbd_work *work, u64 fid, u64 p_id)
int ksmbd_vfs_remove_file(struct ksmbd_work *work, char *name)
{
struct path path;
- struct dentry *dentry, *parent;
+ struct dentry *parent;
int err;
int flags = 0;
@@ -597,35 +601,33 @@ int ksmbd_vfs_remove_file(struct ksmbd_work *work, char *name)
}
parent = dget_parent(path.dentry);
- inode_lock_nested(d_inode(parent), I_MUTEX_PARENT);
- dentry = lookup_one_len(path.dentry->d_name.name, parent,
- strlen(path.dentry->d_name.name));
- if (IS_ERR(dentry)) {
- err = PTR_ERR(dentry);
- ksmbd_debug(VFS, "%s: lookup failed, err %d\n",
- path.dentry->d_name.name, err);
- goto out_err;
+ err = ksmbd_vfs_lock_parent(parent, path.dentry);
+ if (err) {
+ dput(parent);
+ path_put(&path);
+ ksmbd_revert_fsids(work);
+ return err;
}
- if (!d_inode(dentry) || !d_inode(dentry)->i_nlink) {
- dput(dentry);
+ if (!d_inode(path.dentry)->i_nlink) {
err = -ENOENT;
goto out_err;
}
- if (S_ISDIR(d_inode(dentry)->i_mode)) {
- err = vfs_rmdir(&init_user_ns, d_inode(parent), dentry);
+ if (S_ISDIR(d_inode(path.dentry)->i_mode)) {
+ err = vfs_rmdir(mnt_user_ns(path.mnt), d_inode(parent),
+ path.dentry);
if (err && err != -ENOTEMPTY)
ksmbd_debug(VFS, "%s: rmdir failed, err %d\n", name,
err);
} else {
- err = vfs_unlink(&init_user_ns, d_inode(parent), dentry, NULL);
+ err = vfs_unlink(mnt_user_ns(path.mnt), d_inode(parent),
+ path.dentry, NULL);
if (err)
ksmbd_debug(VFS, "%s: unlink failed, err %d\n", name,
err);
}
- dput(dentry);
out_err:
inode_unlock(d_inode(parent));
dput(parent);
@@ -658,8 +660,8 @@ int ksmbd_vfs_link(struct ksmbd_work *work, const char *oldname,
err = kern_path(oldname, flags, &oldpath);
if (err) {
- ksmbd_err("cannot get linux path for %s, err = %d\n",
- oldname, err);
+ pr_err("cannot get linux path for %s, err = %d\n",
+ oldname, err);
goto out1;
}
@@ -667,17 +669,18 @@ int ksmbd_vfs_link(struct ksmbd_work *work, const char *oldname,
flags | LOOKUP_REVAL);
if (IS_ERR(dentry)) {
err = PTR_ERR(dentry);
- ksmbd_err("path create err for %s, err %d\n", newname, err);
+ pr_err("path create err for %s, err %d\n", newname, err);
goto out2;
}
err = -EXDEV;
if (oldpath.mnt != newpath.mnt) {
- ksmbd_err("vfs_link failed err %d\n", err);
+ pr_err("vfs_link failed err %d\n", err);
goto out3;
}
- err = vfs_link(oldpath.dentry, &init_user_ns, d_inode(newpath.dentry),
+ err = vfs_link(oldpath.dentry, mnt_user_ns(newpath.mnt),
+ d_inode(newpath.dentry),
dentry, NULL);
if (err)
ksmbd_debug(VFS, "vfs_link failed err %d\n", err);
@@ -691,9 +694,34 @@ out1:
return err;
}
+static int ksmbd_validate_entry_in_use(struct dentry *src_dent)
+{
+ struct dentry *dst_dent;
+
+ spin_lock(&src_dent->d_lock);
+ list_for_each_entry(dst_dent, &src_dent->d_subdirs, d_child) {
+ struct ksmbd_file *child_fp;
+
+ if (d_really_is_negative(dst_dent))
+ continue;
+
+ child_fp = ksmbd_lookup_fd_inode(d_inode(dst_dent));
+ if (child_fp) {
+ spin_unlock(&src_dent->d_lock);
+ ksmbd_debug(VFS, "Forbid rename, sub file/dir is in use\n");
+ return -EACCES;
+ }
+ }
+ spin_unlock(&src_dent->d_lock);
+
+ return 0;
+}
+
static int __ksmbd_vfs_rename(struct ksmbd_work *work,
+ struct user_namespace *src_user_ns,
struct dentry *src_dent_parent,
struct dentry *src_dent,
+ struct user_namespace *dst_user_ns,
struct dentry *dst_dent_parent,
struct dentry *trap_dent,
char *dst_name)
@@ -702,21 +730,9 @@ static int __ksmbd_vfs_rename(struct ksmbd_work *work,
int err;
if (!work->tcon->posix_extensions) {
- spin_lock(&src_dent->d_lock);
- list_for_each_entry(dst_dent, &src_dent->d_subdirs, d_child) {
- struct ksmbd_file *child_fp;
-
- if (d_really_is_negative(dst_dent))
- continue;
-
- child_fp = ksmbd_lookup_fd_inode(d_inode(dst_dent));
- if (child_fp) {
- spin_unlock(&src_dent->d_lock);
- ksmbd_debug(VFS, "Forbid rename, sub file/dir is in use\n");
- return -EACCES;
- }
- }
- spin_unlock(&src_dent->d_lock);
+ err = ksmbd_validate_entry_in_use(src_dent);
+ if (err)
+ return err;
}
if (d_really_is_negative(src_dent_parent))
@@ -734,24 +750,24 @@ static int __ksmbd_vfs_rename(struct ksmbd_work *work,
dst_dent = lookup_one_len(dst_name, dst_dent_parent, strlen(dst_name));
err = PTR_ERR(dst_dent);
if (IS_ERR(dst_dent)) {
- ksmbd_err("lookup failed %s [%d]\n", dst_name, err);
+ pr_err("lookup failed %s [%d]\n", dst_name, err);
goto out;
}
err = -ENOTEMPTY;
if (dst_dent != trap_dent && !d_really_is_positive(dst_dent)) {
struct renamedata rd = {
- .old_mnt_userns = &init_user_ns,
+ .old_mnt_userns = src_user_ns,
.old_dir = d_inode(src_dent_parent),
.old_dentry = src_dent,
- .new_mnt_userns = &init_user_ns,
+ .new_mnt_userns = dst_user_ns,
.new_dir = d_inode(dst_dent_parent),
.new_dentry = dst_dent,
};
err = vfs_rename(&rd);
}
if (err)
- ksmbd_err("vfs_rename failed err %d\n", err);
+ pr_err("vfs_rename failed err %d\n", err);
if (dst_dent)
dput(dst_dent);
out:
@@ -806,8 +822,10 @@ int ksmbd_vfs_fp_rename(struct ksmbd_work *work, struct ksmbd_file *fp,
dput(src_child);
err = __ksmbd_vfs_rename(work,
+ file_mnt_user_ns(fp->filp),
src_dent_parent,
src_dent,
+ mnt_user_ns(dst_path.mnt),
dst_dent_parent,
trap_dent,
dst_name);
@@ -839,14 +857,14 @@ int ksmbd_vfs_truncate(struct ksmbd_work *work, const char *name,
if (name) {
err = kern_path(name, 0, &path);
if (err) {
- ksmbd_err("cannot get linux path for %s, err %d\n",
- name, err);
+ pr_err("cannot get linux path for %s, err %d\n",
+ name, err);
return err;
}
err = vfs_truncate(&path, size);
if (err)
- ksmbd_err("truncate failed for %s err %d\n",
- name, err);
+ pr_err("truncate failed for %s err %d\n",
+ name, err);
path_put(&path);
} else {
struct file *filp;
@@ -868,15 +886,15 @@ int ksmbd_vfs_truncate(struct ksmbd_work *work, const char *name,
}
if (err) {
- ksmbd_err("failed due to lock\n");
+ pr_err("failed due to lock\n");
return -EAGAIN;
}
}
err = vfs_truncate(&filp->f_path, size);
if (err)
- ksmbd_err("truncate failed for filename : %s err %d\n",
- fp->filename, err);
+ pr_err("truncate failed for filename : %s err %d\n",
+ fp->filename, err);
}
return err;
@@ -914,27 +932,30 @@ ssize_t ksmbd_vfs_listxattr(struct dentry *dentry, char **list)
return size;
}
-static ssize_t ksmbd_vfs_xattr_len(struct dentry *dentry, char *xattr_name)
+static ssize_t ksmbd_vfs_xattr_len(struct user_namespace *user_ns,
+ struct dentry *dentry, char *xattr_name)
{
- return vfs_getxattr(&init_user_ns, dentry, xattr_name, NULL, 0);
+ return vfs_getxattr(user_ns, dentry, xattr_name, NULL, 0);
}
/**
* ksmbd_vfs_getxattr() - vfs helper for smb get extended attributes value
+ * @user_ns: user namespace
* @dentry: dentry of file for getting xattrs
* @xattr_name: name of xattr name to query
* @xattr_buf: destination buffer xattr value
*
* Return: read xattr value length on success, otherwise error
*/
-ssize_t ksmbd_vfs_getxattr(struct dentry *dentry, char *xattr_name,
- char **xattr_buf)
+ssize_t ksmbd_vfs_getxattr(struct user_namespace *user_ns,
+ struct dentry *dentry,
+ char *xattr_name, char **xattr_buf)
{
ssize_t xattr_len;
char *buf;
*xattr_buf = NULL;
- xattr_len = ksmbd_vfs_xattr_len(dentry, xattr_name);
+ xattr_len = ksmbd_vfs_xattr_len(user_ns, dentry, xattr_name);
if (xattr_len < 0)
return xattr_len;
@@ -942,7 +963,7 @@ ssize_t ksmbd_vfs_getxattr(struct dentry *dentry, char *xattr_name,
if (!buf)
return -ENOMEM;
- xattr_len = vfs_getxattr(&init_user_ns, dentry, xattr_name,
+ xattr_len = vfs_getxattr(user_ns, dentry, xattr_name,
(void *)buf, xattr_len);
if (xattr_len > 0)
*xattr_buf = buf;
@@ -953,6 +974,7 @@ ssize_t ksmbd_vfs_getxattr(struct dentry *dentry, char *xattr_name,
/**
* ksmbd_vfs_setxattr() - vfs helper for smb set extended attributes value
+ * @user_ns: user namespace
* @dentry: dentry to set XATTR at
* @name: xattr name for setxattr
* @value: xattr value to set
@@ -961,12 +983,14 @@ ssize_t ksmbd_vfs_getxattr(struct dentry *dentry, char *xattr_name,
*
* Return: 0 on success, otherwise error
*/
-int ksmbd_vfs_setxattr(struct dentry *dentry, const char *attr_name,
+int ksmbd_vfs_setxattr(struct user_namespace *user_ns,
+ struct dentry *dentry, const char *attr_name,
const void *attr_value, size_t attr_size, int flags)
{
int err;
- err = vfs_setxattr(&init_user_ns, dentry,
+ err = vfs_setxattr(user_ns,
+ dentry,
attr_name,
attr_value,
attr_size,
@@ -1004,32 +1028,6 @@ void ksmbd_vfs_set_fadvise(struct file *filp, __le32 option)
}
}
-/**
- * ksmbd_vfs_lock() - vfs helper for smb file locking
- * @filp: the file to apply the lock to
- * @cmd: type of locking operation (F_SETLK, F_GETLK, etc.)
- * @flock: The lock to be applied
- *
- * Return: 0 on success, otherwise error
- */
-int ksmbd_vfs_lock(struct file *filp, int cmd, struct file_lock *flock)
-{
- ksmbd_debug(VFS, "calling vfs_lock_file\n");
- return vfs_lock_file(filp, cmd, flock, NULL);
-}
-
-int ksmbd_vfs_readdir(struct file *file, struct ksmbd_readdir_data *rdata)
-{
- return iterate_dir(file, &rdata->ctx);
-}
-
-int ksmbd_vfs_alloc_size(struct ksmbd_work *work, struct ksmbd_file *fp,
- loff_t len)
-{
- smb_break_all_levII_oplock(work, fp, 1);
- return vfs_fallocate(fp->filp, FALLOC_FL_KEEP_SIZE, 0, len);
-}
-
int ksmbd_vfs_zero_data(struct ksmbd_work *work, struct ksmbd_file *fp,
loff_t off, loff_t len)
{
@@ -1047,7 +1045,7 @@ int ksmbd_vfs_fqar_lseek(struct ksmbd_file *fp, loff_t start, loff_t length,
int in_count, int *out_count)
{
struct file *f = fp->filp;
- struct inode *inode = FP_INODE(fp);
+ struct inode *inode = file_inode(fp->filp);
loff_t maxbytes = (u64)inode->i_sb->s_maxbytes, end;
loff_t extent_start, extent_end;
int ret = 0;
@@ -1099,37 +1097,27 @@ int ksmbd_vfs_fqar_lseek(struct ksmbd_file *fp, loff_t start, loff_t length,
return ret;
}
-int ksmbd_vfs_remove_xattr(struct dentry *dentry, char *attr_name)
+int ksmbd_vfs_remove_xattr(struct user_namespace *user_ns,
+ struct dentry *dentry, char *attr_name)
{
- return vfs_removexattr(&init_user_ns, dentry, attr_name);
+ return vfs_removexattr(user_ns, dentry, attr_name);
}
-int ksmbd_vfs_unlink(struct dentry *dir, struct dentry *dentry)
+int ksmbd_vfs_unlink(struct user_namespace *user_ns,
+ struct dentry *dir, struct dentry *dentry)
{
- struct dentry *child;
int err = 0;
- inode_lock_nested(d_inode(dir), I_MUTEX_PARENT);
+ err = ksmbd_vfs_lock_parent(dir, dentry);
+ if (err)
+ return err;
dget(dentry);
- child = lookup_one_len(dentry->d_name.name, dir, dentry->d_name.len);
- if (IS_ERR(child)) {
- err = PTR_ERR(child);
- goto out;
- }
-
- if (child != dentry) {
- err = -ESTALE;
- dput(child);
- goto out;
- }
- dput(child);
if (S_ISDIR(d_inode(dentry)->i_mode))
- err = vfs_rmdir(&init_user_ns, d_inode(dir), dentry);
+ err = vfs_rmdir(user_ns, d_inode(dir), dentry);
else
- err = vfs_unlink(&init_user_ns, d_inode(dir), dentry, NULL);
+ err = vfs_unlink(user_ns, d_inode(dir), dentry, NULL);
-out:
dput(dentry);
inode_unlock(d_inode(dir));
if (err)
@@ -1138,59 +1126,6 @@ out:
return err;
}
-/*
- * ksmbd_vfs_get_logical_sector_size() - get logical sector size from inode
- * @inode: inode
- *
- * Return: logical sector size
- */
-unsigned short ksmbd_vfs_logical_sector_size(struct inode *inode)
-{
- struct request_queue *q;
- unsigned short ret_val = 512;
-
- if (!inode->i_sb->s_bdev)
- return ret_val;
-
- q = inode->i_sb->s_bdev->bd_disk->queue;
-
- if (q && q->limits.logical_block_size)
- ret_val = q->limits.logical_block_size;
-
- return ret_val;
-}
-
-/*
- * ksmbd_vfs_get_smb2_sector_size() - get fs sector sizes
- * @inode: inode
- * @fs_ss: fs sector size struct
- */
-void ksmbd_vfs_smb2_sector_size(struct inode *inode,
- struct ksmbd_fs_sector_size *fs_ss)
-{
- struct request_queue *q;
-
- fs_ss->logical_sector_size = 512;
- fs_ss->physical_sector_size = 512;
- fs_ss->optimal_io_size = 512;
-
- if (!inode->i_sb->s_bdev)
- return;
-
- q = inode->i_sb->s_bdev->bd_disk->queue;
-
- if (q) {
- if (q->limits.logical_block_size)
- fs_ss->logical_sector_size =
- q->limits.logical_block_size;
- if (q->limits.physical_block_size)
- fs_ss->physical_sector_size =
- q->limits.physical_block_size;
- if (q->limits.io_opt)
- fs_ss->optimal_io_size = q->limits.io_opt;
- }
-}
-
static int __dir_empty(struct dir_context *ctx, const char *name, int namlen,
loff_t offset, u64 ino, unsigned int d_type)
{
@@ -1220,7 +1155,7 @@ int ksmbd_vfs_empty_dir(struct ksmbd_file *fp)
set_ctx_actor(&readdir_data.ctx, __dir_empty);
readdir_data.dirent_count = 0;
- err = ksmbd_vfs_readdir(fp->filp, &readdir_data);
+ err = iterate_dir(fp->filp, &readdir_data.ctx);
if (readdir_data.dirent_count > 2)
err = -ENOTEMPTY;
else
@@ -1270,7 +1205,7 @@ static int ksmbd_vfs_lookup_in_dir(struct path *dir, char *name, size_t namelen)
if (IS_ERR(dfilp))
return PTR_ERR(dfilp);
- ret = ksmbd_vfs_readdir(dfilp, &readdir_data);
+ ret = iterate_dir(dfilp, &readdir_data.ctx);
if (readdir_data.dirent_count > 0)
ret = 0;
fput(dfilp);
@@ -1355,7 +1290,8 @@ out:
return err;
}
-int ksmbd_vfs_remove_acl_xattrs(struct dentry *dentry)
+int ksmbd_vfs_remove_acl_xattrs(struct user_namespace *user_ns,
+ struct dentry *dentry)
{
char *name, *xattr_list = NULL;
ssize_t xattr_list_len;
@@ -1377,7 +1313,7 @@ int ksmbd_vfs_remove_acl_xattrs(struct dentry *dentry)
sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1) ||
!strncmp(name, XATTR_NAME_POSIX_ACL_DEFAULT,
sizeof(XATTR_NAME_POSIX_ACL_DEFAULT) - 1)) {
- err = ksmbd_vfs_remove_xattr(dentry, name);
+ err = ksmbd_vfs_remove_xattr(user_ns, dentry, name);
if (err)
ksmbd_debug(SMB,
"remove acl xattr failed : %s\n", name);
@@ -1388,7 +1324,8 @@ out:
return err;
}
-int ksmbd_vfs_remove_sd_xattrs(struct dentry *dentry)
+int ksmbd_vfs_remove_sd_xattrs(struct user_namespace *user_ns,
+ struct dentry *dentry)
{
char *name, *xattr_list = NULL;
ssize_t xattr_list_len;
@@ -1407,7 +1344,7 @@ int ksmbd_vfs_remove_sd_xattrs(struct dentry *dentry)
ksmbd_debug(SMB, "%s, len %zd\n", name, strlen(name));
if (!strncmp(name, XATTR_NAME_SD, XATTR_NAME_SD_LEN)) {
- err = ksmbd_vfs_remove_xattr(dentry, name);
+ err = ksmbd_vfs_remove_xattr(user_ns, dentry, name);
if (err)
ksmbd_debug(SMB, "remove xattr failed : %s\n", name);
}
@@ -1417,7 +1354,8 @@ out:
return err;
}
-static struct xattr_smb_acl *ksmbd_vfs_make_xattr_posix_acl(struct inode *inode,
+static struct xattr_smb_acl *ksmbd_vfs_make_xattr_posix_acl(struct user_namespace *user_ns,
+ struct inode *inode,
int acl_type)
{
struct xattr_smb_acl *smb_acl = NULL;
@@ -1426,7 +1364,7 @@ static struct xattr_smb_acl *ksmbd_vfs_make_xattr_posix_acl(struct inode *inode,
struct xattr_acl_entry *xa_entry;
int i;
- posix_acls = ksmbd_vfs_get_acl(inode, acl_type);
+ posix_acls = get_acl(inode, acl_type);
if (!posix_acls)
return NULL;
@@ -1443,14 +1381,14 @@ static struct xattr_smb_acl *ksmbd_vfs_make_xattr_posix_acl(struct inode *inode,
switch (pa_entry->e_tag) {
case ACL_USER:
xa_entry->type = SMB_ACL_USER;
- xa_entry->uid = from_kuid(&init_user_ns, pa_entry->e_uid);
+ xa_entry->uid = from_kuid(user_ns, pa_entry->e_uid);
break;
case ACL_USER_OBJ:
xa_entry->type = SMB_ACL_USER_OBJ;
break;
case ACL_GROUP:
xa_entry->type = SMB_ACL_GROUP;
- xa_entry->gid = from_kgid(&init_user_ns, pa_entry->e_gid);
+ xa_entry->gid = from_kgid(user_ns, pa_entry->e_gid);
break;
case ACL_GROUP_OBJ:
xa_entry->type = SMB_ACL_GROUP_OBJ;
@@ -1462,7 +1400,7 @@ static struct xattr_smb_acl *ksmbd_vfs_make_xattr_posix_acl(struct inode *inode,
xa_entry->type = SMB_ACL_MASK;
break;
default:
- ksmbd_err("unknown type : 0x%x\n", pa_entry->e_tag);
+ pr_err("unknown type : 0x%x\n", pa_entry->e_tag);
goto out;
}
@@ -1478,7 +1416,9 @@ out:
return smb_acl;
}
-int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn, struct dentry *dentry,
+int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn,
+ struct user_namespace *user_ns,
+ struct dentry *dentry,
struct smb_ntsd *pntsd, int len)
{
int rc;
@@ -1506,38 +1446,41 @@ int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn, struct dentry *dentry,
rc = ksmbd_gen_sd_hash(conn, acl.sd_buf, acl.sd_size, acl.hash);
if (rc) {
- ksmbd_err("failed to generate hash for ndr acl\n");
+ pr_err("failed to generate hash for ndr acl\n");
return rc;
}
- smb_acl = ksmbd_vfs_make_xattr_posix_acl(inode, ACL_TYPE_ACCESS);
+ smb_acl = ksmbd_vfs_make_xattr_posix_acl(user_ns, inode,
+ ACL_TYPE_ACCESS);
if (S_ISDIR(inode->i_mode))
- def_smb_acl = ksmbd_vfs_make_xattr_posix_acl(inode,
+ def_smb_acl = ksmbd_vfs_make_xattr_posix_acl(user_ns, inode,
ACL_TYPE_DEFAULT);
- rc = ndr_encode_posix_acl(&acl_ndr, inode, smb_acl, def_smb_acl);
+ rc = ndr_encode_posix_acl(&acl_ndr, user_ns, inode,
+ smb_acl, def_smb_acl);
if (rc) {
- ksmbd_err("failed to encode ndr to posix acl\n");
+ pr_err("failed to encode ndr to posix acl\n");
goto out;
}
rc = ksmbd_gen_sd_hash(conn, acl_ndr.data, acl_ndr.offset,
acl.posix_acl_hash);
if (rc) {
- ksmbd_err("failed to generate hash for ndr acl\n");
+ pr_err("failed to generate hash for ndr acl\n");
goto out;
}
rc = ndr_encode_v4_ntacl(&sd_ndr, &acl);
if (rc) {
- ksmbd_err("failed to encode ndr to posix acl\n");
+ pr_err("failed to encode ndr to posix acl\n");
goto out;
}
- rc = ksmbd_vfs_setxattr(dentry, XATTR_NAME_SD, sd_ndr.data,
+ rc = ksmbd_vfs_setxattr(user_ns, dentry,
+ XATTR_NAME_SD, sd_ndr.data,
sd_ndr.offset, 0);
if (rc < 0)
- ksmbd_err("Failed to store XATTR ntacl :%d\n", rc);
+ pr_err("Failed to store XATTR ntacl :%d\n", rc);
kfree(sd_ndr.data);
out:
@@ -1547,13 +1490,15 @@ out:
return rc;
}
-int ksmbd_vfs_get_sd_xattr(struct ksmbd_conn *conn, struct dentry *dentry,
+int ksmbd_vfs_get_sd_xattr(struct ksmbd_conn *conn,
+ struct user_namespace *user_ns,
+ struct dentry *dentry,
struct smb_ntsd **pntsd)
{
int rc;
struct ndr n;
- rc = ksmbd_vfs_getxattr(dentry, XATTR_NAME_SD, &n.data);
+ rc = ksmbd_vfs_getxattr(user_ns, dentry, XATTR_NAME_SD, &n.data);
if (rc > 0) {
struct inode *inode = d_inode(dentry);
struct ndr acl_ndr = {0};
@@ -1566,27 +1511,29 @@ int ksmbd_vfs_get_sd_xattr(struct ksmbd_conn *conn, struct dentry *dentry,
if (rc)
return rc;
- smb_acl = ksmbd_vfs_make_xattr_posix_acl(inode,
+ smb_acl = ksmbd_vfs_make_xattr_posix_acl(user_ns, inode,
ACL_TYPE_ACCESS);
if (S_ISDIR(inode->i_mode))
- def_smb_acl = ksmbd_vfs_make_xattr_posix_acl(inode,
+ def_smb_acl = ksmbd_vfs_make_xattr_posix_acl(user_ns,
+ inode,
ACL_TYPE_DEFAULT);
- rc = ndr_encode_posix_acl(&acl_ndr, inode, smb_acl, def_smb_acl);
+ rc = ndr_encode_posix_acl(&acl_ndr, user_ns, inode,
+ smb_acl, def_smb_acl);
if (rc) {
- ksmbd_err("failed to encode ndr to posix acl\n");
+ pr_err("failed to encode ndr to posix acl\n");
goto out;
}
rc = ksmbd_gen_sd_hash(conn, acl_ndr.data, acl_ndr.offset,
cmp_hash);
if (rc) {
- ksmbd_err("failed to generate hash for ndr acl\n");
+ pr_err("failed to generate hash for ndr acl\n");
goto out;
}
if (memcmp(cmp_hash, acl.posix_acl_hash, XATTR_SD_HASH_SIZE)) {
- ksmbd_err("hash value diff\n");
+ pr_err("hash value diff\n");
rc = -EINVAL;
goto out;
}
@@ -1610,7 +1557,8 @@ out:
return rc;
}
-int ksmbd_vfs_set_dos_attrib_xattr(struct dentry *dentry,
+int ksmbd_vfs_set_dos_attrib_xattr(struct user_namespace *user_ns,
+ struct dentry *dentry,
struct xattr_dos_attrib *da)
{
struct ndr n;
@@ -1620,7 +1568,7 @@ int ksmbd_vfs_set_dos_attrib_xattr(struct dentry *dentry,
if (err)
return err;
- err = ksmbd_vfs_setxattr(dentry, XATTR_NAME_DOS_ATTRIBUTE,
+ err = ksmbd_vfs_setxattr(user_ns, dentry, XATTR_NAME_DOS_ATTRIBUTE,
(void *)n.data, n.offset, 0);
if (err)
ksmbd_debug(SMB, "failed to store dos attribute in xattr\n");
@@ -1629,13 +1577,14 @@ int ksmbd_vfs_set_dos_attrib_xattr(struct dentry *dentry,
return err;
}
-int ksmbd_vfs_get_dos_attrib_xattr(struct dentry *dentry,
+int ksmbd_vfs_get_dos_attrib_xattr(struct user_namespace *user_ns,
+ struct dentry *dentry,
struct xattr_dos_attrib *da)
{
struct ndr n;
int err;
- err = ksmbd_vfs_getxattr(dentry, XATTR_NAME_DOS_ATTRIBUTE,
+ err = ksmbd_vfs_getxattr(user_ns, dentry, XATTR_NAME_DOS_ATTRIBUTE,
(char **)&n.data);
if (err > 0) {
n.length = err;
@@ -1649,34 +1598,6 @@ int ksmbd_vfs_get_dos_attrib_xattr(struct dentry *dentry,
return err;
}
-struct posix_acl *ksmbd_vfs_posix_acl_alloc(int count, gfp_t flags)
-{
-#if IS_ENABLED(CONFIG_FS_POSIX_ACL)
- return posix_acl_alloc(count, flags);
-#else
- return NULL;
-#endif
-}
-
-struct posix_acl *ksmbd_vfs_get_acl(struct inode *inode, int type)
-{
-#if IS_ENABLED(CONFIG_FS_POSIX_ACL)
- return get_acl(inode, type);
-#else
- return NULL;
-#endif
-}
-
-int ksmbd_vfs_set_posix_acl(struct inode *inode, int type,
- struct posix_acl *acl)
-{
-#if IS_ENABLED(CONFIG_FS_POSIX_ACL)
- return set_posix_acl(&init_user_ns, inode, type, acl);
-#else
- return -EOPNOTSUPP;
-#endif
-}
-
/**
* ksmbd_vfs_init_kstat() - convert unix stat information to smb stat format
* @p: destination buffer
@@ -1709,13 +1630,15 @@ void *ksmbd_vfs_init_kstat(char **p, struct ksmbd_kstat *ksmbd_kstat)
return info;
}
-int ksmbd_vfs_fill_dentry_attrs(struct ksmbd_work *work, struct dentry *dentry,
+int ksmbd_vfs_fill_dentry_attrs(struct ksmbd_work *work,
+ struct user_namespace *user_ns,
+ struct dentry *dentry,
struct ksmbd_kstat *ksmbd_kstat)
{
u64 time;
int rc;
- generic_fillattr(&init_user_ns, d_inode(dentry), ksmbd_kstat->kstat);
+ generic_fillattr(user_ns, d_inode(dentry), ksmbd_kstat->kstat);
time = ksmbd_UnixTimeToNT(ksmbd_kstat->kstat->ctime);
ksmbd_kstat->create_time = time;
@@ -1733,7 +1656,7 @@ int ksmbd_vfs_fill_dentry_attrs(struct ksmbd_work *work, struct dentry *dentry,
KSMBD_SHARE_FLAG_STORE_DOS_ATTRS)) {
struct xattr_dos_attrib da;
- rc = ksmbd_vfs_get_dos_attrib_xattr(dentry, &da);
+ rc = ksmbd_vfs_get_dos_attrib_xattr(user_ns, dentry, &da);
if (rc > 0) {
ksmbd_kstat->file_attributes = cpu_to_le32(da.attr);
ksmbd_kstat->create_time = da.create_time;
@@ -1745,7 +1668,8 @@ int ksmbd_vfs_fill_dentry_attrs(struct ksmbd_work *work, struct dentry *dentry,
return 0;
}
-ssize_t ksmbd_vfs_casexattr_len(struct dentry *dentry, char *attr_name,
+ssize_t ksmbd_vfs_casexattr_len(struct user_namespace *user_ns,
+ struct dentry *dentry, char *attr_name,
int attr_name_len)
{
char *name, *xattr_list = NULL;
@@ -1761,7 +1685,7 @@ ssize_t ksmbd_vfs_casexattr_len(struct dentry *dentry, char *attr_name,
if (strncasecmp(attr_name, name, attr_name_len))
continue;
- value_len = ksmbd_vfs_xattr_len(dentry, name);
+ value_len = ksmbd_vfs_xattr_len(user_ns, dentry, name);
break;
}
@@ -1806,52 +1730,6 @@ int ksmbd_vfs_xattr_stream_name(char *stream_name, char **xattr_stream_name,
return 0;
}
-int ksmbd_vfs_copy_file_range(struct file *file_in, loff_t pos_in,
- struct file *file_out, loff_t pos_out, size_t len)
-{
- struct inode *inode_in = file_inode(file_in);
- struct inode *inode_out = file_inode(file_out);
- int ret;
-
- ret = vfs_copy_file_range(file_in, pos_in, file_out, pos_out, len, 0);
- /* do splice for the copy between different file systems */
- if (ret != -EXDEV)
- return ret;
-
- if (S_ISDIR(inode_in->i_mode) || S_ISDIR(inode_out->i_mode))
- return -EISDIR;
- if (!S_ISREG(inode_in->i_mode) || !S_ISREG(inode_out->i_mode))
- return -EINVAL;
-
- if (!(file_in->f_mode & FMODE_READ) ||
- !(file_out->f_mode & FMODE_WRITE))
- return -EBADF;
-
- if (len == 0)
- return 0;
-
- file_start_write(file_out);
-
- /*
- * skip the verification of the range of data. it will be done
- * in do_splice_direct
- */
- ret = do_splice_direct(file_in, &pos_in, file_out, &pos_out,
- len > MAX_RW_COUNT ? MAX_RW_COUNT : len, 0);
- if (ret > 0) {
- fsnotify_access(file_in);
- add_rchar(current, ret);
- fsnotify_modify(file_out);
- add_wchar(current, ret);
- }
-
- inc_syscr(current);
- inc_syscw(current);
-
- file_end_write(file_out);
- return ret;
-}
-
int ksmbd_vfs_copy_file_ranges(struct ksmbd_work *work,
struct ksmbd_file *src_fp,
struct ksmbd_file *dst_fp,
@@ -1871,11 +1749,11 @@ int ksmbd_vfs_copy_file_ranges(struct ksmbd_work *work,
*total_size_written = 0;
if (!(src_fp->daccess & (FILE_READ_DATA_LE | FILE_EXECUTE_LE))) {
- ksmbd_err("no right to read(%s)\n", FP_FILENAME(src_fp));
+ pr_err("no right to read(%pd)\n", src_fp->filp->f_path.dentry);
return -EACCES;
}
if (!(dst_fp->daccess & (FILE_WRITE_DATA_LE | FILE_APPEND_DATA_LE))) {
- ksmbd_err("no right to write(%s)\n", FP_FILENAME(dst_fp));
+ pr_err("no right to write(%pd)\n", dst_fp->filp->f_path.dentry);
return -EACCES;
}
@@ -1909,8 +1787,8 @@ int ksmbd_vfs_copy_file_ranges(struct ksmbd_work *work,
if (src_off + len > src_file_size)
return -E2BIG;
- ret = ksmbd_vfs_copy_file_range(src_fp->filp, src_off,
- dst_fp->filp, dst_off, len);
+ ret = vfs_copy_file_range(src_fp->filp, src_off,
+ dst_fp->filp, dst_off, len, 0);
if (ret < 0)
return ret;
@@ -1937,7 +1815,8 @@ void ksmbd_vfs_posix_lock_unblock(struct file_lock *flock)
locks_delete_block(flock);
}
-int ksmbd_vfs_set_init_posix_acl(struct inode *inode)
+int ksmbd_vfs_set_init_posix_acl(struct user_namespace *user_ns,
+ struct inode *inode)
{
struct posix_acl_state acl_state;
struct posix_acl *acls;
@@ -1960,19 +1839,20 @@ int ksmbd_vfs_set_init_posix_acl(struct inode *inode)
acl_state.group.allow;
acl_state.mask.allow = 0x07;
- acls = ksmbd_vfs_posix_acl_alloc(6, GFP_KERNEL);
+ acls = posix_acl_alloc(6, GFP_KERNEL);
if (!acls) {
free_acl_state(&acl_state);
return -ENOMEM;
}
posix_state_to_acl(&acl_state, acls->a_entries);
- rc = ksmbd_vfs_set_posix_acl(inode, ACL_TYPE_ACCESS, acls);
+ rc = set_posix_acl(user_ns, inode, ACL_TYPE_ACCESS, acls);
if (rc < 0)
ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_ACCESS) failed, rc : %d\n",
rc);
else if (S_ISDIR(inode->i_mode)) {
posix_state_to_acl(&acl_state, acls->a_entries);
- rc = ksmbd_vfs_set_posix_acl(inode, ACL_TYPE_DEFAULT, acls);
+ rc = set_posix_acl(user_ns, inode, ACL_TYPE_DEFAULT,
+ acls);
if (rc < 0)
ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_DEFAULT) failed, rc : %d\n",
rc);
@@ -1982,13 +1862,14 @@ int ksmbd_vfs_set_init_posix_acl(struct inode *inode)
return rc;
}
-int ksmbd_vfs_inherit_posix_acl(struct inode *inode, struct inode *parent_inode)
+int ksmbd_vfs_inherit_posix_acl(struct user_namespace *user_ns,
+ struct inode *inode, struct inode *parent_inode)
{
struct posix_acl *acls;
struct posix_acl_entry *pace;
int rc, i;
- acls = ksmbd_vfs_get_acl(parent_inode, ACL_TYPE_DEFAULT);
+ acls = get_acl(parent_inode, ACL_TYPE_DEFAULT);
if (!acls)
return -ENOENT;
pace = acls->a_entries;
@@ -2000,12 +1881,13 @@ int ksmbd_vfs_inherit_posix_acl(struct inode *inode, struct inode *parent_inode)
}
}
- rc = ksmbd_vfs_set_posix_acl(inode, ACL_TYPE_ACCESS, acls);
+ rc = set_posix_acl(user_ns, inode, ACL_TYPE_ACCESS, acls);
if (rc < 0)
ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_ACCESS) failed, rc : %d\n",
rc);
if (S_ISDIR(inode->i_mode)) {
- rc = ksmbd_vfs_set_posix_acl(inode, ACL_TYPE_DEFAULT, acls);
+ rc = set_posix_acl(user_ns, inode, ACL_TYPE_DEFAULT,
+ acls);
if (rc < 0)
ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_DEFAULT) failed, rc : %d\n",
rc);
diff --git a/fs/cifsd/vfs.h b/fs/ksmbd/vfs.h
index 5db1e9e2a754..b255f90acf8f 100644
--- a/fs/cifsd/vfs.h
+++ b/fs/ksmbd/vfs.h
@@ -14,93 +14,16 @@
#include <linux/posix_acl.h>
#include "smbacl.h"
+#include "xattr.h"
-/* STREAM XATTR PREFIX */
-#define STREAM_PREFIX "DosStream."
-#define STREAM_PREFIX_LEN (sizeof(STREAM_PREFIX) - 1)
-#define XATTR_NAME_STREAM (XATTR_USER_PREFIX STREAM_PREFIX)
-#define XATTR_NAME_STREAM_LEN (sizeof(XATTR_NAME_STREAM) - 1)
-
-enum {
- XATTR_DOSINFO_ATTRIB = 0x00000001,
- XATTR_DOSINFO_EA_SIZE = 0x00000002,
- XATTR_DOSINFO_SIZE = 0x00000004,
- XATTR_DOSINFO_ALLOC_SIZE = 0x00000008,
- XATTR_DOSINFO_CREATE_TIME = 0x00000010,
- XATTR_DOSINFO_CHANGE_TIME = 0x00000020,
- XATTR_DOSINFO_ITIME = 0x00000040
-};
-
-struct xattr_dos_attrib {
- __u16 version;
- __u32 flags;
- __u32 attr;
- __u32 ea_size;
- __u64 size;
- __u64 alloc_size;
- __u64 create_time;
- __u64 change_time;
- __u64 itime;
-};
-
-/* DOS ATTRIBUITE XATTR PREFIX */
-#define DOS_ATTRIBUTE_PREFIX "DOSATTRIB"
-#define DOS_ATTRIBUTE_PREFIX_LEN (sizeof(DOS_ATTRIBUTE_PREFIX) - 1)
-#define XATTR_NAME_DOS_ATTRIBUTE \
- (XATTR_USER_PREFIX DOS_ATTRIBUTE_PREFIX)
-#define XATTR_NAME_DOS_ATTRIBUTE_LEN \
- (sizeof(XATTR_USER_PREFIX DOS_ATTRIBUTE_PREFIX) - 1)
-
-#define XATTR_SD_HASH_TYPE_SHA256 0x1
-#define XATTR_SD_HASH_SIZE 64
-
-#define SMB_ACL_READ 4
-#define SMB_ACL_WRITE 2
-#define SMB_ACL_EXECUTE 1
-
+/*
+ * Enumeration for stream type.
+ */
enum {
- SMB_ACL_TAG_INVALID = 0,
- SMB_ACL_USER,
- SMB_ACL_USER_OBJ,
- SMB_ACL_GROUP,
- SMB_ACL_GROUP_OBJ,
- SMB_ACL_OTHER,
- SMB_ACL_MASK
-};
-
-struct xattr_acl_entry {
- int type;
- uid_t uid;
- gid_t gid;
- mode_t perm;
-};
-
-struct xattr_smb_acl {
- int count;
- int next;
- struct xattr_acl_entry entries[0];
+ DATA_STREAM = 1, /* type $DATA */
+ DIR_STREAM /* type $INDEX_ALLOCATION */
};
-struct xattr_ntacl {
- __u16 version;
- void *sd_buf;
- __u32 sd_size;
- __u16 hash_type;
- __u8 desc[10];
- __u16 desc_len;
- __u64 current_time;
- __u8 hash[XATTR_SD_HASH_SIZE];
- __u8 posix_acl_hash[XATTR_SD_HASH_SIZE];
-};
-
-/* SECURITY DESCRIPTOR XATTR PREFIX */
-#define SD_PREFIX "NTACL"
-#define SD_PREFIX_LEN (sizeof(SD_PREFIX) - 1)
-#define XATTR_NAME_SD \
- (XATTR_SECURITY_PREFIX SD_PREFIX)
-#define XATTR_NAME_SD_LEN \
- (sizeof(XATTR_SECURITY_PREFIX SD_PREFIX) - 1)
-
/* CreateOptions */
/* Flag is set, it must not be a file , valid for directory only */
#define FILE_DIRECTORY_FILE_LE cpu_to_le32(0x00000001)
@@ -184,15 +107,10 @@ struct ksmbd_kstat {
__le32 file_attributes;
};
-struct ksmbd_fs_sector_size {
- unsigned short logical_sector_size;
- unsigned int physical_sector_size;
- unsigned int optimal_io_size;
-};
-
-int ksmbd_vfs_inode_permission(struct dentry *dentry, int acc_mode,
- bool delete);
-int ksmbd_vfs_query_maximal_access(struct dentry *dentry, __le32 *daccess);
+int ksmbd_vfs_lock_parent(struct dentry *parent, struct dentry *child);
+int ksmbd_vfs_may_delete(struct user_namespace *user_ns, struct dentry *dentry);
+int ksmbd_vfs_query_maximal_access(struct user_namespace *user_ns,
+ struct dentry *dentry, __le32 *daccess);
int ksmbd_vfs_create(struct ksmbd_work *work, const char *name, umode_t mode);
int ksmbd_vfs_mkdir(struct ksmbd_work *work, const char *name, umode_t mode);
int ksmbd_vfs_read(struct ksmbd_work *work, struct ksmbd_file *fp,
@@ -218,58 +136,62 @@ int ksmbd_vfs_copy_file_ranges(struct ksmbd_work *work,
unsigned int *chunk_count_written,
unsigned int *chunk_size_written,
loff_t *total_size_written);
-int ksmbd_vfs_copy_file_range(struct file *file_in, loff_t pos_in,
- struct file *file_out, loff_t pos_out,
- size_t len);
ssize_t ksmbd_vfs_listxattr(struct dentry *dentry, char **list);
-ssize_t ksmbd_vfs_getxattr(struct dentry *dentry, char *xattr_name,
+ssize_t ksmbd_vfs_getxattr(struct user_namespace *user_ns,
+ struct dentry *dentry,
+ char *xattr_name,
char **xattr_buf);
-ssize_t ksmbd_vfs_casexattr_len(struct dentry *dentry, char *attr_name,
+ssize_t ksmbd_vfs_casexattr_len(struct user_namespace *user_ns,
+ struct dentry *dentry, char *attr_name,
int attr_name_len);
-int ksmbd_vfs_setxattr(struct dentry *dentry, const char *attr_name,
+int ksmbd_vfs_setxattr(struct user_namespace *user_ns,
+ struct dentry *dentry, const char *attr_name,
const void *attr_value, size_t attr_size, int flags);
int ksmbd_vfs_xattr_stream_name(char *stream_name, char **xattr_stream_name,
size_t *xattr_stream_name_size, int s_type);
-int ksmbd_vfs_remove_xattr(struct dentry *dentry, char *attr_name);
+int ksmbd_vfs_remove_xattr(struct user_namespace *user_ns,
+ struct dentry *dentry, char *attr_name);
int ksmbd_vfs_kern_path(char *name, unsigned int flags, struct path *path,
bool caseless);
int ksmbd_vfs_empty_dir(struct ksmbd_file *fp);
void ksmbd_vfs_set_fadvise(struct file *filp, __le32 option);
-int ksmbd_vfs_lock(struct file *filp, int cmd, struct file_lock *flock);
-int ksmbd_vfs_readdir(struct file *file, struct ksmbd_readdir_data *rdata);
-int ksmbd_vfs_alloc_size(struct ksmbd_work *work, struct ksmbd_file *fp,
- loff_t len);
int ksmbd_vfs_zero_data(struct ksmbd_work *work, struct ksmbd_file *fp,
loff_t off, loff_t len);
struct file_allocated_range_buffer;
int ksmbd_vfs_fqar_lseek(struct ksmbd_file *fp, loff_t start, loff_t length,
struct file_allocated_range_buffer *ranges,
int in_count, int *out_count);
-int ksmbd_vfs_unlink(struct dentry *dir, struct dentry *dentry);
-unsigned short ksmbd_vfs_logical_sector_size(struct inode *inode);
-void ksmbd_vfs_smb2_sector_size(struct inode *inode,
- struct ksmbd_fs_sector_size *fs_ss);
+int ksmbd_vfs_unlink(struct user_namespace *user_ns,
+ struct dentry *dir, struct dentry *dentry);
void *ksmbd_vfs_init_kstat(char **p, struct ksmbd_kstat *ksmbd_kstat);
-int ksmbd_vfs_fill_dentry_attrs(struct ksmbd_work *work, struct dentry *dentry,
+int ksmbd_vfs_fill_dentry_attrs(struct ksmbd_work *work,
+ struct user_namespace *user_ns,
+ struct dentry *dentry,
struct ksmbd_kstat *ksmbd_kstat);
int ksmbd_vfs_posix_lock_wait(struct file_lock *flock);
int ksmbd_vfs_posix_lock_wait_timeout(struct file_lock *flock, long timeout);
void ksmbd_vfs_posix_lock_unblock(struct file_lock *flock);
-int ksmbd_vfs_remove_acl_xattrs(struct dentry *dentry);
-int ksmbd_vfs_remove_sd_xattrs(struct dentry *dentry);
-int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn, struct dentry *dentry,
+int ksmbd_vfs_remove_acl_xattrs(struct user_namespace *user_ns,
+ struct dentry *dentry);
+int ksmbd_vfs_remove_sd_xattrs(struct user_namespace *user_ns,
+ struct dentry *dentry);
+int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn,
+ struct user_namespace *user_ns,
+ struct dentry *dentry,
struct smb_ntsd *pntsd, int len);
-int ksmbd_vfs_get_sd_xattr(struct ksmbd_conn *conn, struct dentry *dentry,
+int ksmbd_vfs_get_sd_xattr(struct ksmbd_conn *conn,
+ struct user_namespace *user_ns,
+ struct dentry *dentry,
struct smb_ntsd **pntsd);
-int ksmbd_vfs_set_dos_attrib_xattr(struct dentry *dentry,
+int ksmbd_vfs_set_dos_attrib_xattr(struct user_namespace *user_ns,
+ struct dentry *dentry,
struct xattr_dos_attrib *da);
-int ksmbd_vfs_get_dos_attrib_xattr(struct dentry *dentry,
+int ksmbd_vfs_get_dos_attrib_xattr(struct user_namespace *user_ns,
+ struct dentry *dentry,
struct xattr_dos_attrib *da);
-struct posix_acl *ksmbd_vfs_posix_acl_alloc(int count, gfp_t flags);
-struct posix_acl *ksmbd_vfs_get_acl(struct inode *inode, int type);
-int ksmbd_vfs_set_posix_acl(struct inode *inode, int type,
- struct posix_acl *acl);
-int ksmbd_vfs_set_init_posix_acl(struct inode *inode);
-int ksmbd_vfs_inherit_posix_acl(struct inode *inode,
+int ksmbd_vfs_set_init_posix_acl(struct user_namespace *user_ns,
+ struct inode *inode);
+int ksmbd_vfs_inherit_posix_acl(struct user_namespace *user_ns,
+ struct inode *inode,
struct inode *parent_inode);
#endif /* __KSMBD_VFS_H__ */
diff --git a/fs/cifsd/vfs_cache.c b/fs/ksmbd/vfs_cache.c
index 6ea09fe82814..1941ad3f5aa5 100644
--- a/fs/cifsd/vfs_cache.c
+++ b/fs/ksmbd/vfs_cache.c
@@ -10,7 +10,6 @@
#include "glob.h"
#include "vfs_cache.h"
-#include "buffer_pool.h"
#include "oplock.h"
#include "vfs.h"
#include "connection.h"
@@ -29,6 +28,7 @@ static DEFINE_RWLOCK(inode_hash_lock);
static struct ksmbd_file_table global_ft;
static atomic_long_t fd_limit;
+static struct kmem_cache *filp_cache;
void ksmbd_set_fd_limit(unsigned long limit)
{
@@ -83,7 +83,7 @@ static struct ksmbd_inode *__ksmbd_inode_lookup(struct inode *inode)
static struct ksmbd_inode *ksmbd_inode_lookup(struct ksmbd_file *fp)
{
- return __ksmbd_inode_lookup(FP_INODE(fp));
+ return __ksmbd_inode_lookup(file_inode(fp->filp));
}
static struct ksmbd_inode *ksmbd_inode_lookup_by_vfsinode(struct inode *inode)
@@ -156,7 +156,7 @@ static void ksmbd_inode_unhash(struct ksmbd_inode *ci)
static int ksmbd_inode_init(struct ksmbd_inode *ci, struct ksmbd_file *fp)
{
- ci->m_inode = FP_INODE(fp);
+ ci->m_inode = file_inode(fp->filp);
atomic_set(&ci->m_count, 1);
atomic_set(&ci->op_count, 0);
atomic_set(&ci->sop_count, 0);
@@ -185,7 +185,7 @@ static struct ksmbd_inode *ksmbd_inode_get(struct ksmbd_file *fp)
rc = ksmbd_inode_init(ci, fp);
if (rc) {
- ksmbd_err("inode initialized failed\n");
+ pr_err("inode initialized failed\n");
kfree(ci);
return NULL;
}
@@ -251,11 +251,12 @@ static void __ksmbd_inode_close(struct ksmbd_file *fp)
filp = fp->filp;
if (ksmbd_stream_fd(fp) && (ci->m_flags & S_DEL_ON_CLS_STREAM)) {
ci->m_flags &= ~S_DEL_ON_CLS_STREAM;
- err = ksmbd_vfs_remove_xattr(filp->f_path.dentry,
+ err = ksmbd_vfs_remove_xattr(file_mnt_user_ns(filp),
+ filp->f_path.dentry,
fp->stream.name);
if (err)
- ksmbd_err("remove xattr failed : %s\n",
- fp->stream.name);
+ pr_err("remove xattr failed : %s\n",
+ fp->stream.name);
}
if (atomic_dec_and_test(&ci->m_count)) {
@@ -265,7 +266,7 @@ static void __ksmbd_inode_close(struct ksmbd_file *fp)
dir = dentry->d_parent;
ci->m_flags &= ~(S_DEL_ON_CLS | S_DEL_PENDING);
write_unlock(&ci->m_lock);
- ksmbd_vfs_unlink(dir, dentry);
+ ksmbd_vfs_unlink(file_mnt_user_ns(filp), dir, dentry);
write_lock(&ci->m_lock);
}
write_unlock(&ci->m_lock);
@@ -315,7 +316,7 @@ static void __ksmbd_close_fd(struct ksmbd_file_table *ft, struct ksmbd_file *fp)
kfree(fp->filename);
if (ksmbd_stream_fd(fp))
kfree(fp->stream.name);
- ksmbd_free_file_struct(fp);
+ kmem_cache_free(filp_cache, fp);
}
static struct ksmbd_file *ksmbd_fp_get(struct ksmbd_file *fp)
@@ -472,16 +473,14 @@ struct ksmbd_file *ksmbd_lookup_fd_inode(struct inode *inode)
{
struct ksmbd_file *lfp;
struct ksmbd_inode *ci;
- struct list_head *cur;
ci = ksmbd_inode_lookup_by_vfsinode(inode);
if (!ci)
return NULL;
read_lock(&ci->m_lock);
- list_for_each(cur, &ci->m_fp_list) {
- lfp = list_entry(cur, struct ksmbd_file, node);
- if (inode == FP_INODE(lfp)) {
+ list_for_each_entry(lfp, &ci->m_fp_list, node) {
+ if (inode == file_inode(lfp->filp)) {
atomic_dec(&ci->m_count);
read_unlock(&ci->m_lock);
return lfp;
@@ -539,12 +538,12 @@ unsigned int ksmbd_open_durable_fd(struct ksmbd_file *fp)
struct ksmbd_file *ksmbd_open_fd(struct ksmbd_work *work, struct file *filp)
{
- struct ksmbd_file *fp;
+ struct ksmbd_file *fp;
int ret;
- fp = ksmbd_alloc_file_struct();
+ fp = kmem_cache_zalloc(filp_cache, GFP_KERNEL);
if (!fp) {
- ksmbd_err("Failed to allocate memory\n");
+ pr_err("Failed to allocate memory\n");
return ERR_PTR(-ENOMEM);
}
@@ -561,19 +560,22 @@ struct ksmbd_file *ksmbd_open_fd(struct ksmbd_work *work, struct file *filp)
fp->f_ci = ksmbd_inode_get(fp);
if (!fp->f_ci) {
- ksmbd_free_file_struct(fp);
- return ERR_PTR(-ENOMEM);
+ ret = -ENOMEM;
+ goto err_out;
}
ret = __open_id(&work->sess->file_table, fp, OPEN_ID_TYPE_VOLATILE_ID);
if (ret) {
ksmbd_inode_put(fp->f_ci);
- ksmbd_free_file_struct(fp);
- return ERR_PTR(ret);
+ goto err_out;
}
atomic_inc(&work->conn->stats.open_files_count);
return fp;
+
+err_out:
+ kmem_cache_free(filp_cache, fp);
+ return ERR_PTR(ret);
}
static int
@@ -600,12 +602,14 @@ __close_file_table_ids(struct ksmbd_file_table *ft,
return num;
}
-static bool tree_conn_fd_check(struct ksmbd_tree_connect *tcon, struct ksmbd_file *fp)
+static bool tree_conn_fd_check(struct ksmbd_tree_connect *tcon,
+ struct ksmbd_file *fp)
{
return fp->tcon != tcon;
}
-static bool session_fd_check(struct ksmbd_tree_connect *tcon, struct ksmbd_file *fp)
+static bool session_fd_check(struct ksmbd_tree_connect *tcon,
+ struct ksmbd_file *fp)
{
return false;
}
@@ -640,7 +644,7 @@ void ksmbd_free_global_file_table(void)
idr_for_each_entry(global_ft.idr, fp, id) {
__ksmbd_remove_durable_fd(fp);
- ksmbd_free_file_struct(fp);
+ kmem_cache_free(filp_cache, fp);
}
ksmbd_destroy_file_table(&global_ft);
@@ -683,3 +687,23 @@ void ksmbd_destroy_file_table(struct ksmbd_file_table *ft)
kfree(ft->idr);
ft->idr = NULL;
}
+
+int ksmbd_init_file_cache(void)
+{
+ filp_cache = kmem_cache_create("ksmbd_file_cache",
+ sizeof(struct ksmbd_file), 0,
+ SLAB_HWCACHE_ALIGN, NULL);
+ if (!filp_cache)
+ goto out;
+
+ return 0;
+
+out:
+ pr_err("failed to allocate file cache\n");
+ return -ENOMEM;
+}
+
+void ksmbd_exit_file_cache(void)
+{
+ kmem_cache_destroy(filp_cache);
+}
diff --git a/fs/cifsd/vfs_cache.h b/fs/ksmbd/vfs_cache.h
index 635eedbd497c..543494f664cb 100644
--- a/fs/cifsd/vfs_cache.h
+++ b/fs/ksmbd/vfs_cache.h
@@ -25,15 +25,6 @@
#define KSMBD_NO_FID (UINT_MAX)
#define SMB2_NO_FID (0xFFFFFFFFFFFFFFFFULL)
-#define FP_FILENAME(fp) ((fp)->filp->f_path.dentry->d_name.name)
-#define FP_INODE(fp) d_inode((fp)->filp->f_path.dentry)
-#define PARENT_INODE(fp) d_inode((fp)->filp->f_path.dentry->d_parent)
-
-#define ATTR_FP(fp) ((fp)->attrib_only && \
- ((fp)->cdoption != FILE_OVERWRITE_IF_LE && \
- (fp)->cdoption != FILE_OVERWRITE_LE && \
- (fp)->cdoption != FILE_SUPERSEDE_LE))
-
struct ksmbd_conn;
struct ksmbd_session;
@@ -182,4 +173,6 @@ void ksmbd_set_inode_pending_delete(struct ksmbd_file *fp);
void ksmbd_clear_inode_pending_delete(struct ksmbd_file *fp);
void ksmbd_fd_set_delete_on_close(struct ksmbd_file *fp,
int file_info);
+int ksmbd_init_file_cache(void);
+void ksmbd_exit_file_cache(void);
#endif /* __VFS_CACHE_H__ */
diff --git a/fs/ksmbd/xattr.h b/fs/ksmbd/xattr.h
new file mode 100644
index 000000000000..8857c01093d9
--- /dev/null
+++ b/fs/ksmbd/xattr.h
@@ -0,0 +1,122 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2021 Samsung Electronics Co., Ltd.
+ */
+
+#ifndef __XATTR_H__
+#define __XATTR_H__
+
+/*
+ * These are on-disk structures to store additional metadata into xattr to
+ * reproduce windows filesystem semantics. And they are encoded with NDR to
+ * compatible with samba's xattr meta format. The compatibility with samba
+ * is important because it can lose the information(file attribute,
+ * creation time, acls) about the existing files when switching between
+ * ksmbd and samba.
+ */
+
+/*
+ * Dos attribute flags used for what variable is valid.
+ */
+enum {
+ XATTR_DOSINFO_ATTRIB = 0x00000001,
+ XATTR_DOSINFO_EA_SIZE = 0x00000002,
+ XATTR_DOSINFO_SIZE = 0x00000004,
+ XATTR_DOSINFO_ALLOC_SIZE = 0x00000008,
+ XATTR_DOSINFO_CREATE_TIME = 0x00000010,
+ XATTR_DOSINFO_CHANGE_TIME = 0x00000020,
+ XATTR_DOSINFO_ITIME = 0x00000040
+};
+
+/*
+ * Dos attribute structure which is compatible with samba's one.
+ * Storing it into the xattr named "DOSATTRIB" separately from inode
+ * allows ksmbd to faithfully reproduce windows filesystem semantics
+ * on top of a POSIX filesystem.
+ */
+struct xattr_dos_attrib {
+ __u16 version; /* version 3 or version 4 */
+ __u32 flags; /* valid flags */
+ __u32 attr; /* Dos attribute */
+ __u32 ea_size; /* EA size */
+ __u64 size;
+ __u64 alloc_size;
+ __u64 create_time; /* File creation time */
+ __u64 change_time; /* File change time */
+ __u64 itime; /* Invented/Initial time */
+};
+
+/*
+ * Enumeration is used for computing posix acl hash.
+ */
+enum {
+ SMB_ACL_TAG_INVALID = 0,
+ SMB_ACL_USER,
+ SMB_ACL_USER_OBJ,
+ SMB_ACL_GROUP,
+ SMB_ACL_GROUP_OBJ,
+ SMB_ACL_OTHER,
+ SMB_ACL_MASK
+};
+
+#define SMB_ACL_READ 4
+#define SMB_ACL_WRITE 2
+#define SMB_ACL_EXECUTE 1
+
+struct xattr_acl_entry {
+ int type;
+ uid_t uid;
+ gid_t gid;
+ mode_t perm;
+};
+
+/*
+ * xattr_smb_acl structure is used for computing posix acl hash.
+ */
+struct xattr_smb_acl {
+ int count;
+ int next;
+ struct xattr_acl_entry entries[0];
+};
+
+/* 64bytes hash in xattr_ntacl is computed with sha256 */
+#define XATTR_SD_HASH_TYPE_SHA256 0x1
+#define XATTR_SD_HASH_SIZE 64
+
+/*
+ * xattr_ntacl is used for storing ntacl and hashes.
+ * Hash is used for checking valid posix acl and ntacl in xattr.
+ */
+struct xattr_ntacl {
+ __u16 version; /* version 4*/
+ void *sd_buf;
+ __u32 sd_size;
+ __u16 hash_type; /* hash type */
+ __u8 desc[10]; /* posix_acl description */
+ __u16 desc_len;
+ __u64 current_time;
+ __u8 hash[XATTR_SD_HASH_SIZE]; /* 64bytes hash for ntacl */
+ __u8 posix_acl_hash[XATTR_SD_HASH_SIZE]; /* 64bytes hash for posix acl */
+};
+
+/* DOS ATTRIBUITE XATTR PREFIX */
+#define DOS_ATTRIBUTE_PREFIX "DOSATTRIB"
+#define DOS_ATTRIBUTE_PREFIX_LEN (sizeof(DOS_ATTRIBUTE_PREFIX) - 1)
+#define XATTR_NAME_DOS_ATTRIBUTE (XATTR_USER_PREFIX DOS_ATTRIBUTE_PREFIX)
+#define XATTR_NAME_DOS_ATTRIBUTE_LEN \
+ (sizeof(XATTR_USER_PREFIX DOS_ATTRIBUTE_PREFIX) - 1)
+
+/* STREAM XATTR PREFIX */
+#define STREAM_PREFIX "DosStream."
+#define STREAM_PREFIX_LEN (sizeof(STREAM_PREFIX) - 1)
+#define XATTR_NAME_STREAM (XATTR_USER_PREFIX STREAM_PREFIX)
+#define XATTR_NAME_STREAM_LEN (sizeof(XATTR_NAME_STREAM) - 1)
+
+/* SECURITY DESCRIPTOR(NTACL) XATTR PREFIX */
+#define SD_PREFIX "NTACL"
+#define SD_PREFIX_LEN (sizeof(SD_PREFIX) - 1)
+#define XATTR_NAME_SD (XATTR_SECURITY_PREFIX SD_PREFIX)
+#define XATTR_NAME_SD_LEN \
+ (sizeof(XATTR_SECURITY_PREFIX SD_PREFIX) - 1)
+
+#endif /* __XATTR_H__ */