Skip to content

Commit b956294

Browse files
namjaejeonSteve French
authored andcommitted
ksmbd: fix racy issue from session lookup and expire
Increment the session reference count within the lock for lookup to avoid racy issue with session expire. Cc: [email protected] Reported-by: [email protected] # ZDI-CAN-25737 Signed-off-by: Namjae Jeon <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent 2b904d6 commit b956294

File tree

4 files changed

+23
-16
lines changed

4 files changed

+23
-16
lines changed

fs/smb/server/auth.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,6 +1016,8 @@ static int ksmbd_get_encryption_key(struct ksmbd_work *work, __u64 ses_id,
10161016

10171017
ses_enc_key = enc ? sess->smb3encryptionkey :
10181018
sess->smb3decryptionkey;
1019+
if (enc)
1020+
ksmbd_user_session_get(sess);
10191021
memcpy(key, ses_enc_key, SMB3_ENC_DEC_KEY_SIZE);
10201022

10211023
return 0;

fs/smb/server/mgmt/user_session.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,8 +263,10 @@ struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn,
263263

264264
down_read(&conn->session_lock);
265265
sess = xa_load(&conn->sessions, id);
266-
if (sess)
266+
if (sess) {
267267
sess->last_active = jiffies;
268+
ksmbd_user_session_get(sess);
269+
}
268270
up_read(&conn->session_lock);
269271
return sess;
270272
}
@@ -275,6 +277,8 @@ struct ksmbd_session *ksmbd_session_lookup_slowpath(unsigned long long id)
275277

276278
down_read(&sessions_table_lock);
277279
sess = __session_lookup(id);
280+
if (sess)
281+
ksmbd_user_session_get(sess);
278282
up_read(&sessions_table_lock);
279283

280284
return sess;

fs/smb/server/server.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -241,14 +241,14 @@ static void __handle_ksmbd_work(struct ksmbd_work *work,
241241
if (work->tcon)
242242
ksmbd_tree_connect_put(work->tcon);
243243
smb3_preauth_hash_rsp(work);
244-
if (work->sess)
245-
ksmbd_user_session_put(work->sess);
246244
if (work->sess && work->sess->enc && work->encrypted &&
247245
conn->ops->encrypt_resp) {
248246
rc = conn->ops->encrypt_resp(work);
249247
if (rc < 0)
250248
conn->ops->set_rsp_status(work, STATUS_DATA_ERROR);
251249
}
250+
if (work->sess)
251+
ksmbd_user_session_put(work->sess);
252252

253253
ksmbd_conn_write(work);
254254
}

fs/smb/server/smb2pdu.c

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,10 @@ static inline bool check_session_id(struct ksmbd_conn *conn, u64 id)
6767
return false;
6868

6969
sess = ksmbd_session_lookup_all(conn, id);
70-
if (sess)
70+
if (sess) {
71+
ksmbd_user_session_put(sess);
7172
return true;
73+
}
7274
pr_err("Invalid user session id: %llu\n", id);
7375
return false;
7476
}
@@ -605,10 +607,8 @@ int smb2_check_user_session(struct ksmbd_work *work)
605607

606608
/* Check for validity of user session */
607609
work->sess = ksmbd_session_lookup_all(conn, sess_id);
608-
if (work->sess) {
609-
ksmbd_user_session_get(work->sess);
610+
if (work->sess)
610611
return 1;
611-
}
612612
ksmbd_debug(SMB, "Invalid user session, Uid %llu\n", sess_id);
613613
return -ENOENT;
614614
}
@@ -1701,37 +1701,44 @@ int smb2_sess_setup(struct ksmbd_work *work)
17011701

17021702
if (conn->dialect != sess->dialect) {
17031703
rc = -EINVAL;
1704+
ksmbd_user_session_put(sess);
17041705
goto out_err;
17051706
}
17061707

17071708
if (!(req->hdr.Flags & SMB2_FLAGS_SIGNED)) {
17081709
rc = -EINVAL;
1710+
ksmbd_user_session_put(sess);
17091711
goto out_err;
17101712
}
17111713

17121714
if (strncmp(conn->ClientGUID, sess->ClientGUID,
17131715
SMB2_CLIENT_GUID_SIZE)) {
17141716
rc = -ENOENT;
1717+
ksmbd_user_session_put(sess);
17151718
goto out_err;
17161719
}
17171720

17181721
if (sess->state == SMB2_SESSION_IN_PROGRESS) {
17191722
rc = -EACCES;
1723+
ksmbd_user_session_put(sess);
17201724
goto out_err;
17211725
}
17221726

17231727
if (sess->state == SMB2_SESSION_EXPIRED) {
17241728
rc = -EFAULT;
1729+
ksmbd_user_session_put(sess);
17251730
goto out_err;
17261731
}
1732+
ksmbd_user_session_put(sess);
17271733

17281734
if (ksmbd_conn_need_reconnect(conn)) {
17291735
rc = -EFAULT;
17301736
sess = NULL;
17311737
goto out_err;
17321738
}
17331739

1734-
if (ksmbd_session_lookup(conn, sess_id)) {
1740+
sess = ksmbd_session_lookup(conn, sess_id);
1741+
if (!sess) {
17351742
rc = -EACCES;
17361743
goto out_err;
17371744
}
@@ -1742,7 +1749,6 @@ int smb2_sess_setup(struct ksmbd_work *work)
17421749
}
17431750

17441751
conn->binding = true;
1745-
ksmbd_user_session_get(sess);
17461752
} else if ((conn->dialect < SMB30_PROT_ID ||
17471753
server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL) &&
17481754
(req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) {
@@ -1769,7 +1775,6 @@ int smb2_sess_setup(struct ksmbd_work *work)
17691775
}
17701776

17711777
conn->binding = false;
1772-
ksmbd_user_session_get(sess);
17731778
}
17741779
work->sess = sess;
17751780

@@ -2197,9 +2202,9 @@ int smb2_tree_disconnect(struct ksmbd_work *work)
21972202
int smb2_session_logoff(struct ksmbd_work *work)
21982203
{
21992204
struct ksmbd_conn *conn = work->conn;
2205+
struct ksmbd_session *sess = work->sess;
22002206
struct smb2_logoff_req *req;
22012207
struct smb2_logoff_rsp *rsp;
2202-
struct ksmbd_session *sess;
22032208
u64 sess_id;
22042209
int err;
22052210

@@ -2221,11 +2226,6 @@ int smb2_session_logoff(struct ksmbd_work *work)
22212226
ksmbd_close_session_fds(work);
22222227
ksmbd_conn_wait_idle(conn);
22232228

2224-
/*
2225-
* Re-lookup session to validate if session is deleted
2226-
* while waiting request complete
2227-
*/
2228-
sess = ksmbd_session_lookup_all(conn, sess_id);
22292229
if (ksmbd_tree_conn_session_logoff(sess)) {
22302230
ksmbd_debug(SMB, "Invalid tid %d\n", req->hdr.Id.SyncId.TreeId);
22312231
rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED;
@@ -8992,6 +8992,7 @@ int smb3_decrypt_req(struct ksmbd_work *work)
89928992
le64_to_cpu(tr_hdr->SessionId));
89938993
return -ECONNABORTED;
89948994
}
8995+
ksmbd_user_session_put(sess);
89958996

89968997
iov[0].iov_base = buf;
89978998
iov[0].iov_len = sizeof(struct smb2_transform_hdr) + 4;

0 commit comments

Comments
 (0)