Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'v6.12-rc6-ksmbd-fixes' of git://git.samba.org/ksmbd

Pull smb server fixes from Steve French:
"Four fixes, all also marked for stable:

- fix two potential use after free issues

- fix OOM issue with many simultaneous requests

- fix missing error check in RPC pipe handling"

* tag 'v6.12-rc6-ksmbd-fixes' of git://git.samba.org/ksmbd:
ksmbd: check outstanding simultaneous SMB operations
ksmbd: fix slab-use-after-free in smb3_preauth_hash_rsp
ksmbd: fix slab-use-after-free in ksmbd_smb2_session_create
ksmbd: Fix the missing xa_store error check

+32 -17
+1
fs/smb/server/connection.c
··· 70 70 atomic_set(&conn->req_running, 0); 71 71 atomic_set(&conn->r_count, 0); 72 72 atomic_set(&conn->refcnt, 1); 73 + atomic_set(&conn->mux_smb_requests, 0); 73 74 conn->total_credits = 1; 74 75 conn->outstanding_credits = 0; 75 76
+1
fs/smb/server/connection.h
··· 107 107 __le16 signing_algorithm; 108 108 bool binding; 109 109 atomic_t refcnt; 110 + atomic_t mux_smb_requests; 110 111 }; 111 112 112 113 struct ksmbd_conn_ops {
+10 -5
fs/smb/server/mgmt/user_session.c
··· 90 90 91 91 int ksmbd_session_rpc_open(struct ksmbd_session *sess, char *rpc_name) 92 92 { 93 - struct ksmbd_session_rpc *entry; 93 + struct ksmbd_session_rpc *entry, *old; 94 94 struct ksmbd_rpc_command *resp; 95 95 int method; 96 96 ··· 106 106 entry->id = ksmbd_ipc_id_alloc(); 107 107 if (entry->id < 0) 108 108 goto free_entry; 109 - xa_store(&sess->rpc_handle_list, entry->id, entry, GFP_KERNEL); 109 + old = xa_store(&sess->rpc_handle_list, entry->id, entry, GFP_KERNEL); 110 + if (xa_is_err(old)) 111 + goto free_id; 110 112 111 113 resp = ksmbd_rpc_open(sess, entry->id); 112 114 if (!resp) 113 - goto free_id; 115 + goto erase_xa; 114 116 115 117 kvfree(resp); 116 118 return entry->id; 117 - free_id: 119 + erase_xa: 118 120 xa_erase(&sess->rpc_handle_list, entry->id); 121 + free_id: 119 122 ksmbd_rpc_id_free(entry->id); 120 123 free_entry: 121 124 kfree(entry); ··· 178 175 unsigned long id; 179 176 struct ksmbd_session *sess; 180 177 178 + down_write(&sessions_table_lock); 181 179 down_write(&conn->session_lock); 182 180 xa_for_each(&conn->sessions, id, sess) { 183 181 if (atomic_read(&sess->refcnt) == 0 && ··· 192 188 } 193 189 } 194 190 up_write(&conn->session_lock); 191 + up_write(&sessions_table_lock); 195 192 } 196 193 197 194 int ksmbd_session_register(struct ksmbd_conn *conn, ··· 234 229 } 235 230 } 236 231 } 237 - up_write(&sessions_table_lock); 238 232 239 233 down_write(&conn->session_lock); 240 234 xa_for_each(&conn->sessions, id, sess) { ··· 253 249 } 254 250 } 255 251 up_write(&conn->session_lock); 252 + up_write(&sessions_table_lock); 256 253 } 257 254 258 255 struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn,
+12 -8
fs/smb/server/server.c
··· 238 238 } while (is_chained == true); 239 239 240 240 send: 241 - if (work->sess) 242 - ksmbd_user_session_put(work->sess); 243 241 if (work->tcon) 244 242 ksmbd_tree_connect_put(work->tcon); 245 243 smb3_preauth_hash_rsp(work); 244 + if (work->sess) 245 + ksmbd_user_session_put(work->sess); 246 246 if (work->sess && work->sess->enc && work->encrypted && 247 247 conn->ops->encrypt_resp) { 248 248 rc = conn->ops->encrypt_resp(work); ··· 270 270 271 271 ksmbd_conn_try_dequeue_request(work); 272 272 ksmbd_free_work_struct(work); 273 + atomic_dec(&conn->mux_smb_requests); 273 274 /* 274 275 * Checking waitqueue to dropping pending requests on 275 276 * disconnection. waitqueue_active is safe because it ··· 292 291 struct ksmbd_work *work; 293 292 int err; 294 293 294 + err = ksmbd_init_smb_server(conn); 295 + if (err) 296 + return 0; 297 + 298 + if (atomic_inc_return(&conn->mux_smb_requests) >= conn->vals->max_credits) { 299 + atomic_dec_return(&conn->mux_smb_requests); 300 + return -ENOSPC; 301 + } 302 + 295 303 work = ksmbd_alloc_work_struct(); 296 304 if (!work) { 297 305 pr_err("allocation for work failed\n"); ··· 310 300 work->conn = conn; 311 301 work->request_buf = conn->request_buf; 312 302 conn->request_buf = NULL; 313 - 314 - err = ksmbd_init_smb_server(work); 315 - if (err) { 316 - ksmbd_free_work_struct(work); 317 - return 0; 318 - } 319 303 320 304 ksmbd_conn_enqueue_request(work); 321 305 atomic_inc(&conn->r_count);
+7 -3
fs/smb/server/smb_common.c
··· 388 388 .set_rsp_status = set_smb1_rsp_status, 389 389 }; 390 390 391 + static struct smb_version_values smb1_server_values = { 392 + .max_credits = SMB2_MAX_CREDITS, 393 + }; 394 + 391 395 static int smb1_negotiate(struct ksmbd_work *work) 392 396 { 393 397 return ksmbd_smb_negotiate_common(work, SMB_COM_NEGOTIATE); ··· 403 399 404 400 static int init_smb1_server(struct ksmbd_conn *conn) 405 401 { 402 + conn->vals = &smb1_server_values; 406 403 conn->ops = &smb1_server_ops; 407 404 conn->cmds = smb1_server_cmds; 408 405 conn->max_cmds = ARRAY_SIZE(smb1_server_cmds); 409 406 return 0; 410 407 } 411 408 412 - int ksmbd_init_smb_server(struct ksmbd_work *work) 409 + int ksmbd_init_smb_server(struct ksmbd_conn *conn) 413 410 { 414 - struct ksmbd_conn *conn = work->conn; 415 411 __le32 proto; 416 412 417 - proto = *(__le32 *)((struct smb_hdr *)work->request_buf)->Protocol; 413 + proto = *(__le32 *)((struct smb_hdr *)conn->request_buf)->Protocol; 418 414 if (conn->need_neg == false) { 419 415 if (proto == SMB1_PROTO_NUMBER) 420 416 return -EINVAL;
+1 -1
fs/smb/server/smb_common.h
··· 427 427 428 428 int ksmbd_lookup_dialect_by_id(__le16 *cli_dialects, __le16 dialects_count); 429 429 430 - int ksmbd_init_smb_server(struct ksmbd_work *work); 430 + int ksmbd_init_smb_server(struct ksmbd_conn *conn); 431 431 432 432 struct ksmbd_kstat; 433 433 int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work,