Commit b311c1b4 authored by Linus Torvalds's avatar Linus Torvalds

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
parents 0108b7be 7c525ddd
...@@ -13,7 +13,7 @@ KSMBD architecture ...@@ -13,7 +13,7 @@ KSMBD architecture
The subset of performance related operations belong in kernelspace and The subset of performance related operations belong in kernelspace and
the other subset which belong to operations which are not really related with the other subset which belong to operations which are not really related with
performance in userspace. So, DCE/RPC management that has historically resulted 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. account management are implemented in user space as ksmbd.mountd.
File operations that are related with performance (open/read/write/close etc.) File operations that are related with performance (open/read/write/close etc.)
in kernel space (ksmbd). This also allows for easier integration with VFS in kernel space (ksmbd). This also allows for easier integration with VFS
...@@ -24,8 +24,8 @@ ksmbd (kernel daemon) ...@@ -24,8 +24,8 @@ ksmbd (kernel daemon)
When the server daemon is started, It starts up a forker thread When the server daemon is started, It starts up a forker thread
(ksmbd/interface name) at initialization time and open a dedicated port 445 (ksmbd/interface name) at initialization time and open a dedicated port 445
for listening to SMB requests. Whenever new clients make request, Forker 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 dedicated 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 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 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) 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), ...@@ -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. 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 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. 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 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 decreased it destroys the extra worker threads. So, after the connection is
established with client. Dedicated ksmbd/1..n(port number) takes complete established with the client. Dedicated ksmbd/1..n(port number) takes complete
ownership of receiving/parsing of SMB commands. Each received command is worked 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 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. 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 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. ...@@ -49,9 +49,9 @@ performance by handling client commands in parallel.
ksmbd.mountd (user space daemon) 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 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 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 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 requests (dcerpc and share/user info). It handles RPC calls (at a minimum few
...@@ -124,7 +124,7 @@ How to run ...@@ -124,7 +124,7 @@ How to run
1. Download ksmbd-tools(https://github.com/cifsd-team/ksmbd-tools/releases) and 1. Download ksmbd-tools(https://github.com/cifsd-team/ksmbd-tools/releases) and
compile them. 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 to know how to use ksmbd.mountd/adduser/addshare/control utils
$ ./autogen.sh $ ./autogen.sh
...@@ -133,7 +133,7 @@ How to run ...@@ -133,7 +133,7 @@ How to run
2. Create /usr/local/etc/ksmbd/ksmbd.conf file, add SMB share in ksmbd.conf file. 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. for details to configure shares.
$ man ksmbd.conf $ man ksmbd.conf
...@@ -145,7 +145,7 @@ How to run ...@@ -145,7 +145,7 @@ How to run
$ man ksmbd.adduser $ man ksmbd.adduser
$ sudo ksmbd.adduser -a <Enter USERNAME for SMB share access> $ 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. if ksmbd is built into the kernel.
- Set ksmbd in menuconfig(e.g. $ make menuconfig) - Set ksmbd in menuconfig(e.g. $ make menuconfig)
...@@ -175,7 +175,7 @@ Each layer ...@@ -175,7 +175,7 @@ Each layer
1. Enable all component prints 1. Enable all component prints
# sudo ksmbd.control -d "all" # 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" # sudo ksmbd.control -d "smb"
3. Show what prints are enabled. 3. Show what prints are enabled.
......
...@@ -165,11 +165,43 @@ void ksmbd_all_conn_set_status(u64 sess_id, u32 status) ...@@ -165,11 +165,43 @@ void ksmbd_all_conn_set_status(u64 sess_id, u32 status)
up_read(&conn_list_lock); 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); 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) int ksmbd_conn_write(struct ksmbd_work *work)
{ {
struct ksmbd_conn *conn = work->conn; struct ksmbd_conn *conn = work->conn;
......
...@@ -145,7 +145,8 @@ extern struct list_head conn_list; ...@@ -145,7 +145,8 @@ extern struct list_head conn_list;
extern struct rw_semaphore conn_list_lock; extern struct rw_semaphore conn_list_lock;
bool ksmbd_conn_alive(struct ksmbd_conn *conn); 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); struct ksmbd_conn *ksmbd_conn_alloc(void);
void ksmbd_conn_free(struct ksmbd_conn *conn); void ksmbd_conn_free(struct ksmbd_conn *conn);
bool ksmbd_conn_lookup_dialect(struct ksmbd_conn *c); bool ksmbd_conn_lookup_dialect(struct ksmbd_conn *c);
......
...@@ -311,6 +311,7 @@ void destroy_previous_session(struct ksmbd_conn *conn, ...@@ -311,6 +311,7 @@ void destroy_previous_session(struct ksmbd_conn *conn,
{ {
struct ksmbd_session *prev_sess; struct ksmbd_session *prev_sess;
struct ksmbd_user *prev_user; struct ksmbd_user *prev_user;
int err;
down_write(&sessions_table_lock); down_write(&sessions_table_lock);
down_write(&conn->session_lock); down_write(&conn->session_lock);
...@@ -325,8 +326,16 @@ void destroy_previous_session(struct ksmbd_conn *conn, ...@@ -325,8 +326,16 @@ void destroy_previous_session(struct ksmbd_conn *conn,
memcmp(user->passkey, prev_user->passkey, user->passkey_sz)) memcmp(user->passkey, prev_user->passkey, user->passkey_sz))
goto out; 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); ksmbd_destroy_file_table(&prev_sess->file_table);
prev_sess->state = SMB2_SESSION_EXPIRED; prev_sess->state = SMB2_SESSION_EXPIRED;
ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_NEGOTIATE);
ksmbd_launch_ksmbd_durable_scavenger(); ksmbd_launch_ksmbd_durable_scavenger();
out: out:
up_write(&conn->session_lock); up_write(&conn->session_lock);
......
...@@ -1370,7 +1370,8 @@ static int ntlm_negotiate(struct ksmbd_work *work, ...@@ -1370,7 +1370,8 @@ static int ntlm_negotiate(struct ksmbd_work *work,
} }
sz = le16_to_cpu(rsp->SecurityBufferOffset); 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); rsp->SecurityBufferLength = cpu_to_le16(spnego_blob_len);
out: out:
...@@ -1453,7 +1454,9 @@ static int ntlm_authenticate(struct ksmbd_work *work, ...@@ -1453,7 +1454,9 @@ static int ntlm_authenticate(struct ksmbd_work *work,
return -ENOMEM; return -ENOMEM;
sz = le16_to_cpu(rsp->SecurityBufferOffset); 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); rsp->SecurityBufferLength = cpu_to_le16(spnego_blob_len);
kfree(spnego_blob); kfree(spnego_blob);
} }
...@@ -2210,7 +2213,7 @@ int smb2_session_logoff(struct ksmbd_work *work) ...@@ -2210,7 +2213,7 @@ int smb2_session_logoff(struct ksmbd_work *work)
ksmbd_conn_unlock(conn); ksmbd_conn_unlock(conn);
ksmbd_close_session_fds(work); 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 * Re-lookup session to validate if session is deleted
...@@ -5357,7 +5360,7 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work, ...@@ -5357,7 +5360,7 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
"NTFS", PATH_MAX, conn->local_nls, 0); "NTFS", PATH_MAX, conn->local_nls, 0);
len = len * 2; len = len * 2;
info->FileSystemNameLen = cpu_to_le32(len); 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); rsp->OutputBufferLength = cpu_to_le32(sz);
break; break;
} }
...@@ -5383,7 +5386,7 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work, ...@@ -5383,7 +5386,7 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
len = len * 2; len = len * 2;
info->VolumeLabelSize = cpu_to_le32(len); info->VolumeLabelSize = cpu_to_le32(len);
info->Reserved = 0; info->Reserved = 0;
sz = sizeof(struct filesystem_vol_info) - 2 + len; sz = sizeof(struct filesystem_vol_info) + len;
rsp->OutputBufferLength = cpu_to_le32(sz); rsp->OutputBufferLength = cpu_to_le32(sz);
break; break;
} }
......
...@@ -213,7 +213,7 @@ struct filesystem_attribute_info { ...@@ -213,7 +213,7 @@ struct filesystem_attribute_info {
__le32 Attributes; __le32 Attributes;
__le32 MaxPathNameComponentLength; __le32 MaxPathNameComponentLength;
__le32 FileSystemNameLen; __le32 FileSystemNameLen;
__le16 FileSystemName[1]; /* do not have to save this - get subset? */ __le16 FileSystemName[]; /* do not have to save this - get subset? */
} __packed; } __packed;
struct filesystem_device_info { struct filesystem_device_info {
...@@ -226,7 +226,7 @@ struct filesystem_vol_info { ...@@ -226,7 +226,7 @@ struct filesystem_vol_info {
__le32 SerialNumber; __le32 SerialNumber;
__le32 VolumeLabelSize; __le32 VolumeLabelSize;
__le16 Reserved; __le16 Reserved;
__le16 VolumeLabel[1]; __le16 VolumeLabel[];
} __packed; } __packed;
struct filesystem_info { struct filesystem_info {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment