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

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

* tag 'v6.15rc-part2-ksmbd-server-fixes' of git://git.samba.org/ksmbd:
ksmbd: fix null pointer dereference in alloc_preauth_hash()
ksmbd: validate zero num_subauth before sub_auth is accessed
ksmbd: fix overflow in dacloffset bounds check
ksmbd: fix session use-after-free in multichannel connection

+55 -20
+2 -2
fs/smb/server/auth.c
··· 1016 1016 1017 1017 ses_enc_key = enc ? sess->smb3encryptionkey : 1018 1018 sess->smb3decryptionkey; 1019 - if (enc) 1020 - ksmbd_user_session_get(sess); 1021 1019 memcpy(key, ses_enc_key, SMB3_ENC_DEC_KEY_SIZE); 1020 + if (!enc) 1021 + ksmbd_user_session_put(sess); 1022 1022 1023 1023 return 0; 1024 1024 }
+11
fs/smb/server/connection.h
··· 27 27 KSMBD_SESS_EXITING, 28 28 KSMBD_SESS_NEED_RECONNECT, 29 29 KSMBD_SESS_NEED_NEGOTIATE, 30 + KSMBD_SESS_NEED_SETUP, 30 31 KSMBD_SESS_RELEASING 31 32 }; 32 33 ··· 188 187 return READ_ONCE(conn->status) == KSMBD_SESS_NEED_NEGOTIATE; 189 188 } 190 189 190 + static inline bool ksmbd_conn_need_setup(struct ksmbd_conn *conn) 191 + { 192 + return READ_ONCE(conn->status) == KSMBD_SESS_NEED_SETUP; 193 + } 194 + 191 195 static inline bool ksmbd_conn_need_reconnect(struct ksmbd_conn *conn) 192 196 { 193 197 return READ_ONCE(conn->status) == KSMBD_SESS_NEED_RECONNECT; ··· 221 215 static inline void ksmbd_conn_set_need_negotiate(struct ksmbd_conn *conn) 222 216 { 223 217 WRITE_ONCE(conn->status, KSMBD_SESS_NEED_NEGOTIATE); 218 + } 219 + 220 + static inline void ksmbd_conn_set_need_setup(struct ksmbd_conn *conn) 221 + { 222 + WRITE_ONCE(conn->status, KSMBD_SESS_NEED_SETUP); 224 223 } 225 224 226 225 static inline void ksmbd_conn_set_need_reconnect(struct ksmbd_conn *conn)
+10 -8
fs/smb/server/mgmt/user_session.c
··· 181 181 down_write(&sessions_table_lock); 182 182 down_write(&conn->session_lock); 183 183 xa_for_each(&conn->sessions, id, sess) { 184 - if (atomic_read(&sess->refcnt) == 0 && 184 + if (atomic_read(&sess->refcnt) <= 1 && 185 185 (sess->state != SMB2_SESSION_VALID || 186 186 time_after(jiffies, 187 187 sess->last_active + SMB2_SESSION_TIMEOUT))) { ··· 233 233 down_write(&conn->session_lock); 234 234 xa_erase(&conn->sessions, sess->id); 235 235 up_write(&conn->session_lock); 236 - ksmbd_session_destroy(sess); 236 + if (atomic_dec_and_test(&sess->refcnt)) 237 + ksmbd_session_destroy(sess); 237 238 } 238 239 } 239 240 } ··· 253 252 if (xa_empty(&sess->ksmbd_chann_list)) { 254 253 xa_erase(&conn->sessions, sess->id); 255 254 hash_del(&sess->hlist); 256 - ksmbd_session_destroy(sess); 255 + if (atomic_dec_and_test(&sess->refcnt)) 256 + ksmbd_session_destroy(sess); 257 257 } 258 258 } 259 259 up_write(&conn->session_lock); ··· 330 328 331 329 if (atomic_read(&sess->refcnt) <= 0) 332 330 WARN_ON(1); 333 - else 334 - atomic_dec(&sess->refcnt); 331 + else if (atomic_dec_and_test(&sess->refcnt)) 332 + ksmbd_session_destroy(sess); 335 333 } 336 334 337 335 struct preauth_session *ksmbd_preauth_session_alloc(struct ksmbd_conn *conn, ··· 374 372 ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_RECONNECT); 375 373 err = ksmbd_conn_wait_idle_sess_id(conn, id); 376 374 if (err) { 377 - ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_NEGOTIATE); 375 + ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_SETUP); 378 376 goto out; 379 377 } 380 378 381 379 ksmbd_destroy_file_table(&prev_sess->file_table); 382 380 prev_sess->state = SMB2_SESSION_EXPIRED; 383 - ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_NEGOTIATE); 381 + ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_SETUP); 384 382 ksmbd_launch_ksmbd_durable_scavenger(); 385 383 out: 386 384 up_write(&conn->session_lock); ··· 438 436 xa_init(&sess->rpc_handle_list); 439 437 sess->sequence_number = 1; 440 438 rwlock_init(&sess->tree_conns_lock); 441 - atomic_set(&sess->refcnt, 1); 439 + atomic_set(&sess->refcnt, 2); 442 440 443 441 ret = __init_smb2_session(sess); 444 442 if (ret)
+15 -6
fs/smb/server/smb2pdu.c
··· 1249 1249 } 1250 1250 1251 1251 conn->srv_sec_mode = le16_to_cpu(rsp->SecurityMode); 1252 - ksmbd_conn_set_need_negotiate(conn); 1252 + ksmbd_conn_set_need_setup(conn); 1253 1253 1254 1254 err_out: 1255 1255 ksmbd_conn_unlock(conn); ··· 1270 1270 { 1271 1271 if (sess->Preauth_HashValue) 1272 1272 return 0; 1273 + 1274 + if (!conn->preauth_info) 1275 + return -ENOMEM; 1273 1276 1274 1277 sess->Preauth_HashValue = kmemdup(conn->preauth_info->Preauth_HashValue, 1275 1278 PREAUTH_HASHVALUE_SIZE, KSMBD_DEFAULT_GFP); ··· 1677 1674 1678 1675 ksmbd_debug(SMB, "Received smb2 session setup request\n"); 1679 1676 1677 + if (!ksmbd_conn_need_setup(conn) && !ksmbd_conn_good(conn)) { 1678 + work->send_no_response = 1; 1679 + return rc; 1680 + } 1681 + 1680 1682 WORK_BUFFERS(work, req, rsp); 1681 1683 1682 1684 rsp->StructureSize = cpu_to_le16(9); ··· 1917 1909 if (try_delay) { 1918 1910 ksmbd_conn_set_need_reconnect(conn); 1919 1911 ssleep(5); 1920 - ksmbd_conn_set_need_negotiate(conn); 1912 + ksmbd_conn_set_need_setup(conn); 1921 1913 } 1922 1914 } 1923 1915 smb2_set_err_rsp(work); ··· 2243 2235 return -ENOENT; 2244 2236 } 2245 2237 2246 - ksmbd_destroy_file_table(&sess->file_table); 2247 2238 down_write(&conn->session_lock); 2248 2239 sess->state = SMB2_SESSION_EXPIRED; 2249 2240 up_write(&conn->session_lock); 2250 2241 2251 - ksmbd_free_user(sess->user); 2252 - sess->user = NULL; 2253 - ksmbd_all_conn_set_status(sess_id, KSMBD_SESS_NEED_NEGOTIATE); 2242 + if (sess->user) { 2243 + ksmbd_free_user(sess->user); 2244 + sess->user = NULL; 2245 + } 2246 + ksmbd_all_conn_set_status(sess_id, KSMBD_SESS_NEED_SETUP); 2254 2247 2255 2248 rsp->StructureSize = cpu_to_le16(4); 2256 2249 err = ksmbd_iov_pin_rsp(work, rsp, sizeof(struct smb2_logoff_rsp));
+17 -4
fs/smb/server/smbacl.c
··· 270 270 return -EIO; 271 271 } 272 272 273 + if (psid->num_subauth == 0) { 274 + pr_err("%s: zero subauthorities!\n", __func__); 275 + return -EIO; 276 + } 277 + 273 278 if (sidtype == SIDOWNER) { 274 279 kuid_t uid; 275 280 uid_t id; ··· 1031 1026 struct dentry *parent = path->dentry->d_parent; 1032 1027 struct mnt_idmap *idmap = mnt_idmap(path->mnt); 1033 1028 int inherited_flags = 0, flags = 0, i, nt_size = 0, pdacl_size; 1034 - int rc = 0, dacloffset, pntsd_type, pntsd_size, acl_len, aces_size; 1029 + int rc = 0, pntsd_type, pntsd_size, acl_len, aces_size; 1030 + unsigned int dacloffset; 1031 + size_t dacl_struct_end; 1035 1032 u16 num_aces, ace_cnt = 0; 1036 1033 char *aces_base; 1037 1034 bool is_dir = S_ISDIR(d_inode(path->dentry)->i_mode); ··· 1042 1035 parent, &parent_pntsd); 1043 1036 if (pntsd_size <= 0) 1044 1037 return -ENOENT; 1038 + 1045 1039 dacloffset = le32_to_cpu(parent_pntsd->dacloffset); 1046 - if (!dacloffset || (dacloffset + sizeof(struct smb_acl) > pntsd_size)) { 1040 + if (!dacloffset || 1041 + check_add_overflow(dacloffset, sizeof(struct smb_acl), &dacl_struct_end) || 1042 + dacl_struct_end > (size_t)pntsd_size) { 1047 1043 rc = -EINVAL; 1048 1044 goto free_parent_pntsd; 1049 1045 } ··· 1250 1240 struct smb_ntsd *pntsd = NULL; 1251 1241 struct smb_acl *pdacl; 1252 1242 struct posix_acl *posix_acls; 1253 - int rc = 0, pntsd_size, acl_size, aces_size, pdacl_size, dacl_offset; 1243 + int rc = 0, pntsd_size, acl_size, aces_size, pdacl_size; 1244 + unsigned int dacl_offset; 1245 + size_t dacl_struct_end; 1254 1246 struct smb_sid sid; 1255 1247 int granted = le32_to_cpu(*pdaccess & ~FILE_MAXIMAL_ACCESS_LE); 1256 1248 struct smb_ace *ace; ··· 1271 1259 1272 1260 dacl_offset = le32_to_cpu(pntsd->dacloffset); 1273 1261 if (!dacl_offset || 1274 - (dacl_offset + sizeof(struct smb_acl) > pntsd_size)) 1262 + check_add_overflow(dacl_offset, sizeof(struct smb_acl), &dacl_struct_end) || 1263 + dacl_struct_end > (size_t)pntsd_size) 1275 1264 goto err_out; 1276 1265 1277 1266 pdacl = (struct smb_acl *)((char *)pntsd + le32_to_cpu(pntsd->dacloffset));