Skip to content

Commit

Permalink
ksmbd: fix racy issue from session lookup and expire
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
namjaejeon committed Dec 3, 2024
1 parent 31fe923 commit 2fc566b
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 20 deletions.
2 changes: 2 additions & 0 deletions auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -1358,6 +1358,8 @@ static int ksmbd_get_encryption_key(struct ksmbd_work *work, __u64 ses_id,

ses_enc_key = enc ? sess->smb3encryptionkey :
sess->smb3decryptionkey;
if (enc)
ksmbd_user_session_get(sess);
memcpy(key, ses_enc_key, SMB3_ENC_DEC_KEY_SIZE);

return 0;
Expand Down
6 changes: 5 additions & 1 deletion mgmt/user_session.c
Original file line number Diff line number Diff line change
Expand Up @@ -278,8 +278,10 @@ struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn,

down_read(&conn->session_lock);
sess = xa_load(&conn->sessions, id);
if (sess)
if (sess) {
sess->last_active = jiffies;
ksmbd_user_session_get(sess);
}
up_read(&conn->session_lock);
return sess;
}
Expand All @@ -290,6 +292,8 @@ struct ksmbd_session *ksmbd_session_lookup_slowpath(unsigned long long id)

down_read(&sessions_table_lock);
sess = __session_lookup(id);
if (sess)
ksmbd_user_session_get(sess);
up_read(&sessions_table_lock);

return sess;
Expand Down
4 changes: 2 additions & 2 deletions server.c
Original file line number Diff line number Diff line change
Expand Up @@ -241,14 +241,14 @@ static void __handle_ksmbd_work(struct ksmbd_work *work,
if (work->tcon)
ksmbd_tree_connect_put(work->tcon);
smb3_preauth_hash_rsp(work);
if (work->sess)
ksmbd_user_session_put(work->sess);
if (work->sess && work->sess->enc && work->encrypted &&
conn->ops->encrypt_resp) {
rc = conn->ops->encrypt_resp(work);
if (rc < 0)
conn->ops->set_rsp_status(work, STATUS_DATA_ERROR);
}
if (work->sess)
ksmbd_user_session_put(work->sess);

ksmbd_conn_write(work);
}
Expand Down
5 changes: 1 addition & 4 deletions smb1pdu.c
Original file line number Diff line number Diff line change
Expand Up @@ -336,10 +336,8 @@ int smb_check_user_session(struct ksmbd_work *work)
}

work->sess = ksmbd_session_lookup(conn, le16_to_cpu(req_hdr->Uid));
if (work->sess) {
ksmbd_user_session_get(work->sess);
if (work->sess)
return 1;
}
ksmbd_debug(SMB, "Invalid user session, Uid %u\n",
le16_to_cpu(req_hdr->Uid));
return -EINVAL;
Expand Down Expand Up @@ -1335,7 +1333,6 @@ int smb_session_setup_andx(struct ksmbd_work *work)
rc = -ENOENT;
goto out_err;
}
ksmbd_user_session_get(sess);
ksmbd_debug(SMB, "Reuse session ID: %llu, Uid: %u\n",
sess->id, uid);
} else {
Expand Down
28 changes: 15 additions & 13 deletions smb2pdu.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,10 @@ static inline bool check_session_id(struct ksmbd_conn *conn, u64 id)
return false;

sess = ksmbd_session_lookup_all(conn, id);
if (sess)
if (sess) {
ksmbd_user_session_put(sess);
return true;
}
pr_err("Invalid user session id: %llu\n", id);
return false;
}
Expand Down Expand Up @@ -611,10 +613,8 @@ int smb2_check_user_session(struct ksmbd_work *work)

/* Check for validity of user session */
work->sess = ksmbd_session_lookup_all(conn, sess_id);
if (work->sess) {
ksmbd_user_session_get(work->sess);
if (work->sess)
return 1;
}
ksmbd_debug(SMB, "Invalid user session, Uid %llu\n", sess_id);
return -ENOENT;
}
Expand Down Expand Up @@ -1719,37 +1719,44 @@ int smb2_sess_setup(struct ksmbd_work *work)

if (conn->dialect != sess->dialect) {
rc = -EINVAL;
ksmbd_user_session_put(sess);
goto out_err;
}

if (!(req->hdr.Flags & SMB2_FLAGS_SIGNED)) {
rc = -EINVAL;
ksmbd_user_session_put(sess);
goto out_err;
}

if (strncmp(conn->ClientGUID, sess->ClientGUID,
SMB2_CLIENT_GUID_SIZE)) {
rc = -ENOENT;
ksmbd_user_session_put(sess);
goto out_err;
}

if (sess->state == SMB2_SESSION_IN_PROGRESS) {
rc = -EACCES;
ksmbd_user_session_put(sess);
goto out_err;
}

if (sess->state == SMB2_SESSION_EXPIRED) {
rc = -EFAULT;
ksmbd_user_session_put(sess);
goto out_err;
}
ksmbd_user_session_put(sess);

if (ksmbd_conn_need_reconnect(conn)) {
rc = -EFAULT;
sess = NULL;
goto out_err;
}

if (ksmbd_session_lookup(conn, sess_id)) {
sess = ksmbd_session_lookup(conn, sess_id);
if (!sess) {
rc = -EACCES;
goto out_err;
}
Expand All @@ -1760,7 +1767,6 @@ int smb2_sess_setup(struct ksmbd_work *work)
}

conn->binding = true;
ksmbd_user_session_get(sess);
} else if ((conn->dialect < SMB30_PROT_ID ||
server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL) &&
(req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) {
Expand All @@ -1787,7 +1793,6 @@ int smb2_sess_setup(struct ksmbd_work *work)
}

conn->binding = false;
ksmbd_user_session_get(sess);
}
work->sess = sess;

Expand Down Expand Up @@ -2214,9 +2219,9 @@ int smb2_tree_disconnect(struct ksmbd_work *work)
int smb2_session_logoff(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
struct ksmbd_session *sess = work->sess;
struct smb2_logoff_req *req;
struct smb2_logoff_rsp *rsp;
struct ksmbd_session *sess;
u64 sess_id;
int err;

Expand All @@ -2238,14 +2243,10 @@ int smb2_session_logoff(struct ksmbd_work *work)
ksmbd_close_session_fds(work);
ksmbd_conn_wait_idle(conn);

/*
* Re-lookup session to validate if session is deleted
* while waiting request complete
*/
sess = ksmbd_session_lookup_all(conn, sess_id);
if (ksmbd_tree_conn_session_logoff(sess)) {
ksmbd_debug(SMB, "Invalid tid %d\n", req->hdr.Id.SyncId.TreeId);
rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED;
ksmbd_user_session_put(sess);
smb2_set_err_rsp(work);
return -ENOENT;
}
Expand Down Expand Up @@ -9589,6 +9590,7 @@ int smb3_decrypt_req(struct ksmbd_work *work)
le64_to_cpu(tr_hdr->SessionId));
return -ECONNABORTED;
}
ksmbd_user_session_put(sess);

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

0 comments on commit 2fc566b

Please sign in to comment.