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.15-rc4-ksmbd-server-fixes' of git://git.samba.org/ksmbd

Pull smb server fixes from Steve French:

- Fix three potential use after frees: in session logoff, in krb5 auth,
and in RPC open

- Fix missing rc check in session setup authentication

* tag 'v6.15-rc4-ksmbd-server-fixes' of git://git.samba.org/ksmbd:
ksmbd: fix use-after-free in session logoff
ksmbd: fix use-after-free in kerberos authentication
ksmbd: fix use-after-free in ksmbd_session_rpc_open
smb: server: smb2pdu: check return value of xa_store()

+35 -18
+13 -1
fs/smb/server/auth.c
··· 550 550 retval = -ENOMEM; 551 551 goto out; 552 552 } 553 - sess->user = user; 553 + 554 + if (!sess->user) { 555 + /* First successful authentication */ 556 + sess->user = user; 557 + } else { 558 + if (!ksmbd_compare_user(sess->user, user)) { 559 + ksmbd_debug(AUTH, "different user tried to reuse session\n"); 560 + retval = -EPERM; 561 + ksmbd_free_user(user); 562 + goto out; 563 + } 564 + ksmbd_free_user(user); 565 + } 554 566 555 567 memcpy(sess->sess_key, resp->payload, resp->session_key_len); 556 568 memcpy(out_blob, resp->payload + resp->session_key_len,
+14 -6
fs/smb/server/mgmt/user_session.c
··· 59 59 struct ksmbd_session_rpc *entry; 60 60 long index; 61 61 62 + down_write(&sess->rpc_lock); 62 63 xa_for_each(&sess->rpc_handle_list, index, entry) { 63 64 xa_erase(&sess->rpc_handle_list, index); 64 65 __session_rpc_close(sess, entry); 65 66 } 67 + up_write(&sess->rpc_lock); 66 68 67 69 xa_destroy(&sess->rpc_handle_list); 68 70 } ··· 94 92 { 95 93 struct ksmbd_session_rpc *entry, *old; 96 94 struct ksmbd_rpc_command *resp; 97 - int method; 95 + int method, id; 98 96 99 97 method = __rpc_method(rpc_name); 100 98 if (!method) ··· 104 102 if (!entry) 105 103 return -ENOMEM; 106 104 105 + down_read(&sess->rpc_lock); 107 106 entry->method = method; 108 - entry->id = ksmbd_ipc_id_alloc(); 109 - if (entry->id < 0) 107 + entry->id = id = ksmbd_ipc_id_alloc(); 108 + if (id < 0) 110 109 goto free_entry; 111 - old = xa_store(&sess->rpc_handle_list, entry->id, entry, KSMBD_DEFAULT_GFP); 110 + old = xa_store(&sess->rpc_handle_list, id, entry, KSMBD_DEFAULT_GFP); 112 111 if (xa_is_err(old)) 113 112 goto free_id; 114 113 115 - resp = ksmbd_rpc_open(sess, entry->id); 114 + resp = ksmbd_rpc_open(sess, id); 116 115 if (!resp) 117 116 goto erase_xa; 118 117 118 + up_read(&sess->rpc_lock); 119 119 kvfree(resp); 120 - return entry->id; 120 + return id; 121 121 erase_xa: 122 122 xa_erase(&sess->rpc_handle_list, entry->id); 123 123 free_id: 124 124 ksmbd_rpc_id_free(entry->id); 125 125 free_entry: 126 126 kfree(entry); 127 + up_read(&sess->rpc_lock); 127 128 return -EINVAL; 128 129 } 129 130 ··· 134 129 { 135 130 struct ksmbd_session_rpc *entry; 136 131 132 + down_write(&sess->rpc_lock); 137 133 entry = xa_erase(&sess->rpc_handle_list, id); 138 134 if (entry) 139 135 __session_rpc_close(sess, entry); 136 + up_write(&sess->rpc_lock); 140 137 } 141 138 142 139 int ksmbd_session_rpc_method(struct ksmbd_session *sess, int id) ··· 446 439 sess->sequence_number = 1; 447 440 rwlock_init(&sess->tree_conns_lock); 448 441 atomic_set(&sess->refcnt, 2); 442 + init_rwsem(&sess->rpc_lock); 449 443 450 444 ret = __init_smb2_session(sess); 451 445 if (ret)
+1
fs/smb/server/mgmt/user_session.h
··· 63 63 rwlock_t tree_conns_lock; 64 64 65 65 atomic_t refcnt; 66 + struct rw_semaphore rpc_lock; 66 67 }; 67 68 68 69 static inline int test_session_flag(struct ksmbd_session *sess, int bit)
+7 -11
fs/smb/server/smb2pdu.c
··· 1445 1445 { 1446 1446 struct ksmbd_conn *conn = work->conn; 1447 1447 struct ksmbd_session *sess = work->sess; 1448 - struct channel *chann = NULL; 1448 + struct channel *chann = NULL, *old; 1449 1449 struct ksmbd_user *user; 1450 1450 u64 prev_id; 1451 1451 int sz, rc; ··· 1557 1557 return -ENOMEM; 1558 1558 1559 1559 chann->conn = conn; 1560 - xa_store(&sess->ksmbd_chann_list, (long)conn, chann, KSMBD_DEFAULT_GFP); 1560 + old = xa_store(&sess->ksmbd_chann_list, (long)conn, chann, 1561 + KSMBD_DEFAULT_GFP); 1562 + if (xa_is_err(old)) { 1563 + kfree(chann); 1564 + return xa_err(old); 1565 + } 1561 1566 } 1562 1567 } 1563 1568 ··· 1606 1601 prev_sess_id = le64_to_cpu(req->PreviousSessionId); 1607 1602 if (prev_sess_id && prev_sess_id != sess->id) 1608 1603 destroy_previous_session(conn, sess->user, prev_sess_id); 1609 - 1610 - if (sess->state == SMB2_SESSION_VALID) { 1611 - ksmbd_free_user(sess->user); 1612 - sess->user = NULL; 1613 - } 1614 1604 1615 1605 retval = ksmbd_krb5_authenticate(sess, in_blob, in_len, 1616 1606 out_blob, &out_len); ··· 2249 2249 sess->state = SMB2_SESSION_EXPIRED; 2250 2250 up_write(&conn->session_lock); 2251 2251 2252 - if (sess->user) { 2253 - ksmbd_free_user(sess->user); 2254 - sess->user = NULL; 2255 - } 2256 2252 ksmbd_all_conn_set_status(sess_id, KSMBD_SESS_NEED_SETUP); 2257 2253 2258 2254 rsp->StructureSize = cpu_to_le16(4);