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