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

+67 -22
+13 -13
Documentation/filesystems/smb/ksmbd.rst
··· 13 The subset of performance related operations belong in kernelspace and 14 the other subset which belong to operations which are not really related with 15 performance in userspace. So, DCE/RPC management that has historically resulted 16 - into number of buffer overflow issues and dangerous security bugs and user 17 account management are implemented in user space as ksmbd.mountd. 18 File operations that are related with performance (open/read/write/close etc.) 19 in kernel space (ksmbd). This also allows for easier integration with VFS ··· 24 25 When the server daemon is started, It starts up a forker thread 26 (ksmbd/interface name) at initialization time and open a dedicated port 445 27 - for listening to SMB requests. Whenever new clients make request, Forker 28 - thread will accept the client connection and fork a new thread for dedicated 29 communication channel between the client and the server. It allows for parallel 30 processing of SMB requests(commands) from clients as well as allowing for new 31 clients to make new connections. Each instance is named ksmbd/1~n(port number) ··· 34 currently DCE/RPC commands are identified to be handled through the user space. 35 To further utilize the linux kernel, it has been chosen to process the commands 36 as workitems and to be executed in the handlers of the ksmbd-io kworker threads. 37 - It allows for multiplexing of the handlers as the kernel take care of initiating 38 extra worker threads if the load is increased and vice versa, if the load is 39 - decreased it destroys the extra worker threads. So, after connection is 40 - established with client. Dedicated ksmbd/1..n(port number) takes complete 41 ownership of receiving/parsing of SMB commands. Each received command is worked 42 - in parallel i.e., There can be multiple clients commands which are worked in 43 parallel. After receiving each command a separated kernel workitem is prepared 44 for each command which is further queued to be handled by ksmbd-io kworkers. 45 So, each SMB workitem is queued to the kworkers. This allows the benefit of load ··· 49 ksmbd.mountd (user space daemon) 50 -------------------------------- 51 52 - ksmbd.mountd is userspace process to, transfer user account and password that 53 are registered using ksmbd.adduser (part of utils for user space). Further it 54 - allows sharing information parameters that parsed from smb.conf to ksmbd in 55 kernel. For the execution part it has a daemon which is continuously running 56 and connected to the kernel interface using netlink socket, it waits for the 57 requests (dcerpc and share/user info). It handles RPC calls (at a minimum few ··· 124 1. Download ksmbd-tools(https://github.com/cifsd-team/ksmbd-tools/releases) and 125 compile them. 126 127 - - Refer README(https://github.com/cifsd-team/ksmbd-tools/blob/master/README.md) 128 to know how to use ksmbd.mountd/adduser/addshare/control utils 129 130 $ ./autogen.sh ··· 133 134 2. Create /usr/local/etc/ksmbd/ksmbd.conf file, add SMB share in ksmbd.conf file. 135 136 - - Refer ksmbd.conf.example in ksmbd-utils, See ksmbd.conf manpage 137 for details to configure shares. 138 139 $ man ksmbd.conf ··· 145 $ man ksmbd.adduser 146 $ sudo ksmbd.adduser -a <Enter USERNAME for SMB share access> 147 148 - 4. Insert ksmbd.ko module after build your kernel. No need to load module 149 if ksmbd is built into the kernel. 150 151 - Set ksmbd in menuconfig(e.g. $ make menuconfig) ··· 175 1. Enable all component prints 176 # sudo ksmbd.control -d "all" 177 178 - 2. Enable one of components (smb, auth, vfs, oplock, ipc, conn, rdma) 179 # sudo ksmbd.control -d "smb" 180 181 3. Show what prints are enabled.
··· 13 The subset of performance related operations belong in kernelspace and 14 the other subset which belong to operations which are not really related with 15 performance in userspace. So, DCE/RPC management that has historically resulted 16 + into a number of buffer overflow issues and dangerous security bugs and user 17 account management are implemented in user space as ksmbd.mountd. 18 File operations that are related with performance (open/read/write/close etc.) 19 in kernel space (ksmbd). This also allows for easier integration with VFS ··· 24 25 When the server daemon is started, It starts up a forker thread 26 (ksmbd/interface name) at initialization time and open a dedicated port 445 27 + for listening to SMB requests. Whenever new clients make a request, the Forker 28 + thread will accept the client connection and fork a new thread for a dedicated 29 communication channel between the client and the server. It allows for parallel 30 processing of SMB requests(commands) from clients as well as allowing for new 31 clients to make new connections. Each instance is named ksmbd/1~n(port number) ··· 34 currently DCE/RPC commands are identified to be handled through the user space. 35 To further utilize the linux kernel, it has been chosen to process the commands 36 as workitems and to be executed in the handlers of the ksmbd-io kworker threads. 37 + It allows for multiplexing of the handlers as the kernel takes care of initiating 38 extra worker threads if the load is increased and vice versa, if the load is 39 + decreased it destroys the extra worker threads. So, after the connection is 40 + established with the client. Dedicated ksmbd/1..n(port number) takes complete 41 ownership of receiving/parsing of SMB commands. Each received command is worked 42 + in parallel i.e., there can be multiple client commands which are worked in 43 parallel. After receiving each command a separated kernel workitem is prepared 44 for each command which is further queued to be handled by ksmbd-io kworkers. 45 So, each SMB workitem is queued to the kworkers. This allows the benefit of load ··· 49 ksmbd.mountd (user space daemon) 50 -------------------------------- 51 52 + ksmbd.mountd is a userspace process to, transfer the user account and password that 53 are registered using ksmbd.adduser (part of utils for user space). Further it 54 + allows sharing information parameters that are parsed from smb.conf to ksmbd in 55 kernel. For the execution part it has a daemon which is continuously running 56 and connected to the kernel interface using netlink socket, it waits for the 57 requests (dcerpc and share/user info). It handles RPC calls (at a minimum few ··· 124 1. Download ksmbd-tools(https://github.com/cifsd-team/ksmbd-tools/releases) and 125 compile them. 126 127 + - Refer to README(https://github.com/cifsd-team/ksmbd-tools/blob/master/README.md) 128 to know how to use ksmbd.mountd/adduser/addshare/control utils 129 130 $ ./autogen.sh ··· 133 134 2. Create /usr/local/etc/ksmbd/ksmbd.conf file, add SMB share in ksmbd.conf file. 135 136 + - Refer to ksmbd.conf.example in ksmbd-utils, See ksmbd.conf manpage 137 for details to configure shares. 138 139 $ man ksmbd.conf ··· 145 $ man ksmbd.adduser 146 $ sudo ksmbd.adduser -a <Enter USERNAME for SMB share access> 147 148 + 4. Insert the ksmbd.ko module after you build your kernel. No need to load the module 149 if ksmbd is built into the kernel. 150 151 - Set ksmbd in menuconfig(e.g. $ make menuconfig) ··· 175 1. Enable all component prints 176 # sudo ksmbd.control -d "all" 177 178 + 2. Enable one of the components (smb, auth, vfs, oplock, ipc, conn, rdma) 179 # sudo ksmbd.control -d "smb" 180 181 3. Show what prints are enabled.
+33 -1
fs/smb/server/connection.c
··· 165 up_read(&conn_list_lock); 166 } 167 168 - void ksmbd_conn_wait_idle(struct ksmbd_conn *conn, u64 sess_id) 169 { 170 wait_event(conn->req_running_q, atomic_read(&conn->req_running) < 2); 171 } 172 173 int ksmbd_conn_write(struct ksmbd_work *work)
··· 165 up_read(&conn_list_lock); 166 } 167 168 + void ksmbd_conn_wait_idle(struct ksmbd_conn *conn) 169 { 170 wait_event(conn->req_running_q, atomic_read(&conn->req_running) < 2); 171 + } 172 + 173 + int ksmbd_conn_wait_idle_sess_id(struct ksmbd_conn *curr_conn, u64 sess_id) 174 + { 175 + struct ksmbd_conn *conn; 176 + int rc, retry_count = 0, max_timeout = 120; 177 + int rcount = 1; 178 + 179 + retry_idle: 180 + if (retry_count >= max_timeout) 181 + return -EIO; 182 + 183 + down_read(&conn_list_lock); 184 + list_for_each_entry(conn, &conn_list, conns_list) { 185 + if (conn->binding || xa_load(&conn->sessions, sess_id)) { 186 + if (conn == curr_conn) 187 + rcount = 2; 188 + if (atomic_read(&conn->req_running) >= rcount) { 189 + rc = wait_event_timeout(conn->req_running_q, 190 + atomic_read(&conn->req_running) < rcount, 191 + HZ); 192 + if (!rc) { 193 + up_read(&conn_list_lock); 194 + retry_count++; 195 + goto retry_idle; 196 + } 197 + } 198 + } 199 + } 200 + up_read(&conn_list_lock); 201 + 202 + return 0; 203 } 204 205 int ksmbd_conn_write(struct ksmbd_work *work)
+2 -1
fs/smb/server/connection.h
··· 145 extern struct rw_semaphore conn_list_lock; 146 147 bool ksmbd_conn_alive(struct ksmbd_conn *conn); 148 - void ksmbd_conn_wait_idle(struct ksmbd_conn *conn, u64 sess_id); 149 struct ksmbd_conn *ksmbd_conn_alloc(void); 150 void ksmbd_conn_free(struct ksmbd_conn *conn); 151 bool ksmbd_conn_lookup_dialect(struct ksmbd_conn *c);
··· 145 extern struct rw_semaphore conn_list_lock; 146 147 bool ksmbd_conn_alive(struct ksmbd_conn *conn); 148 + void ksmbd_conn_wait_idle(struct ksmbd_conn *conn); 149 + int ksmbd_conn_wait_idle_sess_id(struct ksmbd_conn *curr_conn, u64 sess_id); 150 struct ksmbd_conn *ksmbd_conn_alloc(void); 151 void ksmbd_conn_free(struct ksmbd_conn *conn); 152 bool ksmbd_conn_lookup_dialect(struct ksmbd_conn *c);
+9
fs/smb/server/mgmt/user_session.c
··· 311 { 312 struct ksmbd_session *prev_sess; 313 struct ksmbd_user *prev_user; 314 315 down_write(&sessions_table_lock); 316 down_write(&conn->session_lock); ··· 326 memcmp(user->passkey, prev_user->passkey, user->passkey_sz)) 327 goto out; 328 329 ksmbd_destroy_file_table(&prev_sess->file_table); 330 prev_sess->state = SMB2_SESSION_EXPIRED; 331 ksmbd_launch_ksmbd_durable_scavenger(); 332 out: 333 up_write(&conn->session_lock);
··· 311 { 312 struct ksmbd_session *prev_sess; 313 struct ksmbd_user *prev_user; 314 + int err; 315 316 down_write(&sessions_table_lock); 317 down_write(&conn->session_lock); ··· 325 memcmp(user->passkey, prev_user->passkey, user->passkey_sz)) 326 goto out; 327 328 + ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_RECONNECT); 329 + err = ksmbd_conn_wait_idle_sess_id(conn, id); 330 + if (err) { 331 + ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_NEGOTIATE); 332 + goto out; 333 + } 334 + 335 ksmbd_destroy_file_table(&prev_sess->file_table); 336 prev_sess->state = SMB2_SESSION_EXPIRED; 337 + ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_NEGOTIATE); 338 ksmbd_launch_ksmbd_durable_scavenger(); 339 out: 340 up_write(&conn->session_lock);
+8 -5
fs/smb/server/smb2pdu.c
··· 1370 } 1371 1372 sz = le16_to_cpu(rsp->SecurityBufferOffset); 1373 - memcpy((char *)&rsp->hdr.ProtocolId + sz, spnego_blob, spnego_blob_len); 1374 rsp->SecurityBufferLength = cpu_to_le16(spnego_blob_len); 1375 1376 out: ··· 1454 return -ENOMEM; 1455 1456 sz = le16_to_cpu(rsp->SecurityBufferOffset); 1457 - memcpy((char *)&rsp->hdr.ProtocolId + sz, spnego_blob, spnego_blob_len); 1458 rsp->SecurityBufferLength = cpu_to_le16(spnego_blob_len); 1459 kfree(spnego_blob); 1460 } ··· 2213 ksmbd_conn_unlock(conn); 2214 2215 ksmbd_close_session_fds(work); 2216 - ksmbd_conn_wait_idle(conn, sess_id); 2217 2218 /* 2219 * Re-lookup session to validate if session is deleted ··· 5360 "NTFS", PATH_MAX, conn->local_nls, 0); 5361 len = len * 2; 5362 info->FileSystemNameLen = cpu_to_le32(len); 5363 - sz = sizeof(struct filesystem_attribute_info) - 2 + len; 5364 rsp->OutputBufferLength = cpu_to_le32(sz); 5365 break; 5366 } ··· 5386 len = len * 2; 5387 info->VolumeLabelSize = cpu_to_le32(len); 5388 info->Reserved = 0; 5389 - sz = sizeof(struct filesystem_vol_info) - 2 + len; 5390 rsp->OutputBufferLength = cpu_to_le32(sz); 5391 break; 5392 }
··· 1370 } 1371 1372 sz = le16_to_cpu(rsp->SecurityBufferOffset); 1373 + unsafe_memcpy((char *)&rsp->hdr.ProtocolId + sz, spnego_blob, spnego_blob_len, 1374 + /* alloc is larger than blob, see smb2_allocate_rsp_buf() */); 1375 rsp->SecurityBufferLength = cpu_to_le16(spnego_blob_len); 1376 1377 out: ··· 1453 return -ENOMEM; 1454 1455 sz = le16_to_cpu(rsp->SecurityBufferOffset); 1456 + unsafe_memcpy((char *)&rsp->hdr.ProtocolId + sz, spnego_blob, 1457 + spnego_blob_len, 1458 + /* alloc is larger than blob, see smb2_allocate_rsp_buf() */); 1459 rsp->SecurityBufferLength = cpu_to_le16(spnego_blob_len); 1460 kfree(spnego_blob); 1461 } ··· 2210 ksmbd_conn_unlock(conn); 2211 2212 ksmbd_close_session_fds(work); 2213 + ksmbd_conn_wait_idle(conn); 2214 2215 /* 2216 * Re-lookup session to validate if session is deleted ··· 5357 "NTFS", PATH_MAX, conn->local_nls, 0); 5358 len = len * 2; 5359 info->FileSystemNameLen = cpu_to_le32(len); 5360 + sz = sizeof(struct filesystem_attribute_info) + len; 5361 rsp->OutputBufferLength = cpu_to_le32(sz); 5362 break; 5363 } ··· 5383 len = len * 2; 5384 info->VolumeLabelSize = cpu_to_le32(len); 5385 info->Reserved = 0; 5386 + sz = sizeof(struct filesystem_vol_info) + len; 5387 rsp->OutputBufferLength = cpu_to_le32(sz); 5388 break; 5389 }
+2 -2
fs/smb/server/smb_common.h
··· 213 __le32 Attributes; 214 __le32 MaxPathNameComponentLength; 215 __le32 FileSystemNameLen; 216 - __le16 FileSystemName[1]; /* do not have to save this - get subset? */ 217 } __packed; 218 219 struct filesystem_device_info { ··· 226 __le32 SerialNumber; 227 __le32 VolumeLabelSize; 228 __le16 Reserved; 229 - __le16 VolumeLabel[1]; 230 } __packed; 231 232 struct filesystem_info {
··· 213 __le32 Attributes; 214 __le32 MaxPathNameComponentLength; 215 __le32 FileSystemNameLen; 216 + __le16 FileSystemName[]; /* do not have to save this - get subset? */ 217 } __packed; 218 219 struct filesystem_device_info { ··· 226 __le32 SerialNumber; 227 __le32 VolumeLabelSize; 228 __le16 Reserved; 229 + __le16 VolumeLabel[]; 230 } __packed; 231 232 struct filesystem_info {