mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-04-29 01:09:33 -04:00
Merge tag '6.11-rc4-server-fixes' of git://git.samba.org/ksmbd
Pull smb server fixes from Steve French: - important reconnect fix - fix for memcpy issues on mount - two minor cleanup patches * tag '6.11-rc4-server-fixes' of git://git.samba.org/ksmbd: ksmbd: Replace one-element arrays with flexible-array members ksmbd: fix spelling mistakes in documentation ksmbd: fix race condition between destroy_previous_session() and smb2 operations() ksmbd: Use unsafe_memcpy() for ntlm_negotiate
This commit is contained in:
@@ -13,7 +13,7 @@ KSMBD architecture
|
||||
The subset of performance related operations belong in kernelspace and
|
||||
the other subset which belong to operations which are not really related with
|
||||
performance in userspace. So, DCE/RPC management that has historically resulted
|
||||
into number of buffer overflow issues and dangerous security bugs and user
|
||||
into a number of buffer overflow issues and dangerous security bugs and user
|
||||
account management are implemented in user space as ksmbd.mountd.
|
||||
File operations that are related with performance (open/read/write/close etc.)
|
||||
in kernel space (ksmbd). This also allows for easier integration with VFS
|
||||
@@ -24,8 +24,8 @@ ksmbd (kernel daemon)
|
||||
|
||||
When the server daemon is started, It starts up a forker thread
|
||||
(ksmbd/interface name) at initialization time and open a dedicated port 445
|
||||
for listening to SMB requests. Whenever new clients make request, Forker
|
||||
thread will accept the client connection and fork a new thread for dedicated
|
||||
for listening to SMB requests. Whenever new clients make a request, the Forker
|
||||
thread will accept the client connection and fork a new thread for a dedicated
|
||||
communication channel between the client and the server. It allows for parallel
|
||||
processing of SMB requests(commands) from clients as well as allowing for new
|
||||
clients to make new connections. Each instance is named ksmbd/1~n(port number)
|
||||
@@ -34,12 +34,12 @@ thread can decide to pass through the commands to the user space (ksmbd.mountd),
|
||||
currently DCE/RPC commands are identified to be handled through the user space.
|
||||
To further utilize the linux kernel, it has been chosen to process the commands
|
||||
as workitems and to be executed in the handlers of the ksmbd-io kworker threads.
|
||||
It allows for multiplexing of the handlers as the kernel take care of initiating
|
||||
It allows for multiplexing of the handlers as the kernel takes care of initiating
|
||||
extra worker threads if the load is increased and vice versa, if the load is
|
||||
decreased it destroys the extra worker threads. So, after connection is
|
||||
established with client. Dedicated ksmbd/1..n(port number) takes complete
|
||||
decreased it destroys the extra worker threads. So, after the connection is
|
||||
established with the client. Dedicated ksmbd/1..n(port number) takes complete
|
||||
ownership of receiving/parsing of SMB commands. Each received command is worked
|
||||
in parallel i.e., There can be multiple clients commands which are worked in
|
||||
in parallel i.e., there can be multiple client commands which are worked in
|
||||
parallel. After receiving each command a separated kernel workitem is prepared
|
||||
for each command which is further queued to be handled by ksmbd-io kworkers.
|
||||
So, each SMB workitem is queued to the kworkers. This allows the benefit of load
|
||||
@@ -49,9 +49,9 @@ performance by handling client commands in parallel.
|
||||
ksmbd.mountd (user space daemon)
|
||||
--------------------------------
|
||||
|
||||
ksmbd.mountd is userspace process to, transfer user account and password that
|
||||
ksmbd.mountd is a userspace process to, transfer the user account and password that
|
||||
are registered using ksmbd.adduser (part of utils for user space). Further it
|
||||
allows sharing information parameters that parsed from smb.conf to ksmbd in
|
||||
allows sharing information parameters that are parsed from smb.conf to ksmbd in
|
||||
kernel. For the execution part it has a daemon which is continuously running
|
||||
and connected to the kernel interface using netlink socket, it waits for the
|
||||
requests (dcerpc and share/user info). It handles RPC calls (at a minimum few
|
||||
@@ -124,7 +124,7 @@ How to run
|
||||
1. Download ksmbd-tools(https://github.com/cifsd-team/ksmbd-tools/releases) and
|
||||
compile them.
|
||||
|
||||
- Refer README(https://github.com/cifsd-team/ksmbd-tools/blob/master/README.md)
|
||||
- Refer to README(https://github.com/cifsd-team/ksmbd-tools/blob/master/README.md)
|
||||
to know how to use ksmbd.mountd/adduser/addshare/control utils
|
||||
|
||||
$ ./autogen.sh
|
||||
@@ -133,7 +133,7 @@ How to run
|
||||
|
||||
2. Create /usr/local/etc/ksmbd/ksmbd.conf file, add SMB share in ksmbd.conf file.
|
||||
|
||||
- Refer ksmbd.conf.example in ksmbd-utils, See ksmbd.conf manpage
|
||||
- Refer to ksmbd.conf.example in ksmbd-utils, See ksmbd.conf manpage
|
||||
for details to configure shares.
|
||||
|
||||
$ man ksmbd.conf
|
||||
@@ -145,7 +145,7 @@ How to run
|
||||
$ man ksmbd.adduser
|
||||
$ sudo ksmbd.adduser -a <Enter USERNAME for SMB share access>
|
||||
|
||||
4. Insert ksmbd.ko module after build your kernel. No need to load module
|
||||
4. Insert the ksmbd.ko module after you build your kernel. No need to load the module
|
||||
if ksmbd is built into the kernel.
|
||||
|
||||
- Set ksmbd in menuconfig(e.g. $ make menuconfig)
|
||||
@@ -175,7 +175,7 @@ Each layer
|
||||
1. Enable all component prints
|
||||
# sudo ksmbd.control -d "all"
|
||||
|
||||
2. Enable one of components (smb, auth, vfs, oplock, ipc, conn, rdma)
|
||||
2. Enable one of the components (smb, auth, vfs, oplock, ipc, conn, rdma)
|
||||
# sudo ksmbd.control -d "smb"
|
||||
|
||||
3. Show what prints are enabled.
|
||||
|
||||
@@ -165,11 +165,43 @@ void ksmbd_all_conn_set_status(u64 sess_id, u32 status)
|
||||
up_read(&conn_list_lock);
|
||||
}
|
||||
|
||||
void ksmbd_conn_wait_idle(struct ksmbd_conn *conn, u64 sess_id)
|
||||
void ksmbd_conn_wait_idle(struct ksmbd_conn *conn)
|
||||
{
|
||||
wait_event(conn->req_running_q, atomic_read(&conn->req_running) < 2);
|
||||
}
|
||||
|
||||
int ksmbd_conn_wait_idle_sess_id(struct ksmbd_conn *curr_conn, u64 sess_id)
|
||||
{
|
||||
struct ksmbd_conn *conn;
|
||||
int rc, retry_count = 0, max_timeout = 120;
|
||||
int rcount = 1;
|
||||
|
||||
retry_idle:
|
||||
if (retry_count >= max_timeout)
|
||||
return -EIO;
|
||||
|
||||
down_read(&conn_list_lock);
|
||||
list_for_each_entry(conn, &conn_list, conns_list) {
|
||||
if (conn->binding || xa_load(&conn->sessions, sess_id)) {
|
||||
if (conn == curr_conn)
|
||||
rcount = 2;
|
||||
if (atomic_read(&conn->req_running) >= rcount) {
|
||||
rc = wait_event_timeout(conn->req_running_q,
|
||||
atomic_read(&conn->req_running) < rcount,
|
||||
HZ);
|
||||
if (!rc) {
|
||||
up_read(&conn_list_lock);
|
||||
retry_count++;
|
||||
goto retry_idle;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
up_read(&conn_list_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ksmbd_conn_write(struct ksmbd_work *work)
|
||||
{
|
||||
struct ksmbd_conn *conn = work->conn;
|
||||
|
||||
@@ -145,7 +145,8 @@ extern struct list_head conn_list;
|
||||
extern struct rw_semaphore conn_list_lock;
|
||||
|
||||
bool ksmbd_conn_alive(struct ksmbd_conn *conn);
|
||||
void ksmbd_conn_wait_idle(struct ksmbd_conn *conn, u64 sess_id);
|
||||
void ksmbd_conn_wait_idle(struct ksmbd_conn *conn);
|
||||
int ksmbd_conn_wait_idle_sess_id(struct ksmbd_conn *curr_conn, u64 sess_id);
|
||||
struct ksmbd_conn *ksmbd_conn_alloc(void);
|
||||
void ksmbd_conn_free(struct ksmbd_conn *conn);
|
||||
bool ksmbd_conn_lookup_dialect(struct ksmbd_conn *c);
|
||||
|
||||
@@ -311,6 +311,7 @@ void destroy_previous_session(struct ksmbd_conn *conn,
|
||||
{
|
||||
struct ksmbd_session *prev_sess;
|
||||
struct ksmbd_user *prev_user;
|
||||
int err;
|
||||
|
||||
down_write(&sessions_table_lock);
|
||||
down_write(&conn->session_lock);
|
||||
@@ -325,8 +326,16 @@ void destroy_previous_session(struct ksmbd_conn *conn,
|
||||
memcmp(user->passkey, prev_user->passkey, user->passkey_sz))
|
||||
goto out;
|
||||
|
||||
ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_RECONNECT);
|
||||
err = ksmbd_conn_wait_idle_sess_id(conn, id);
|
||||
if (err) {
|
||||
ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_NEGOTIATE);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ksmbd_destroy_file_table(&prev_sess->file_table);
|
||||
prev_sess->state = SMB2_SESSION_EXPIRED;
|
||||
ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_NEGOTIATE);
|
||||
ksmbd_launch_ksmbd_durable_scavenger();
|
||||
out:
|
||||
up_write(&conn->session_lock);
|
||||
|
||||
@@ -1370,7 +1370,8 @@ static int ntlm_negotiate(struct ksmbd_work *work,
|
||||
}
|
||||
|
||||
sz = le16_to_cpu(rsp->SecurityBufferOffset);
|
||||
memcpy((char *)&rsp->hdr.ProtocolId + sz, spnego_blob, spnego_blob_len);
|
||||
unsafe_memcpy((char *)&rsp->hdr.ProtocolId + sz, spnego_blob, spnego_blob_len,
|
||||
/* alloc is larger than blob, see smb2_allocate_rsp_buf() */);
|
||||
rsp->SecurityBufferLength = cpu_to_le16(spnego_blob_len);
|
||||
|
||||
out:
|
||||
@@ -1453,7 +1454,9 @@ static int ntlm_authenticate(struct ksmbd_work *work,
|
||||
return -ENOMEM;
|
||||
|
||||
sz = le16_to_cpu(rsp->SecurityBufferOffset);
|
||||
memcpy((char *)&rsp->hdr.ProtocolId + sz, spnego_blob, spnego_blob_len);
|
||||
unsafe_memcpy((char *)&rsp->hdr.ProtocolId + sz, spnego_blob,
|
||||
spnego_blob_len,
|
||||
/* alloc is larger than blob, see smb2_allocate_rsp_buf() */);
|
||||
rsp->SecurityBufferLength = cpu_to_le16(spnego_blob_len);
|
||||
kfree(spnego_blob);
|
||||
}
|
||||
@@ -2210,7 +2213,7 @@ int smb2_session_logoff(struct ksmbd_work *work)
|
||||
ksmbd_conn_unlock(conn);
|
||||
|
||||
ksmbd_close_session_fds(work);
|
||||
ksmbd_conn_wait_idle(conn, sess_id);
|
||||
ksmbd_conn_wait_idle(conn);
|
||||
|
||||
/*
|
||||
* Re-lookup session to validate if session is deleted
|
||||
@@ -5357,7 +5360,7 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
|
||||
"NTFS", PATH_MAX, conn->local_nls, 0);
|
||||
len = len * 2;
|
||||
info->FileSystemNameLen = cpu_to_le32(len);
|
||||
sz = sizeof(struct filesystem_attribute_info) - 2 + len;
|
||||
sz = sizeof(struct filesystem_attribute_info) + len;
|
||||
rsp->OutputBufferLength = cpu_to_le32(sz);
|
||||
break;
|
||||
}
|
||||
@@ -5383,7 +5386,7 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
|
||||
len = len * 2;
|
||||
info->VolumeLabelSize = cpu_to_le32(len);
|
||||
info->Reserved = 0;
|
||||
sz = sizeof(struct filesystem_vol_info) - 2 + len;
|
||||
sz = sizeof(struct filesystem_vol_info) + len;
|
||||
rsp->OutputBufferLength = cpu_to_le32(sz);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -213,7 +213,7 @@ struct filesystem_attribute_info {
|
||||
__le32 Attributes;
|
||||
__le32 MaxPathNameComponentLength;
|
||||
__le32 FileSystemNameLen;
|
||||
__le16 FileSystemName[1]; /* do not have to save this - get subset? */
|
||||
__le16 FileSystemName[]; /* do not have to save this - get subset? */
|
||||
} __packed;
|
||||
|
||||
struct filesystem_device_info {
|
||||
@@ -226,7 +226,7 @@ struct filesystem_vol_info {
|
||||
__le32 SerialNumber;
|
||||
__le32 VolumeLabelSize;
|
||||
__le16 Reserved;
|
||||
__le16 VolumeLabel[1];
|
||||
__le16 VolumeLabel[];
|
||||
} __packed;
|
||||
|
||||
struct filesystem_info {
|
||||
|
||||
Reference in New Issue
Block a user