mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
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: stable@vger.kernel.org Reported-by: zdi-disclosures@trendmicro.com # ZDI-CAN-25737 Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
2b904d61a9
commit
b95629435b
4 changed files with 23 additions and 16 deletions
|
@ -1016,6 +1016,8 @@ static int ksmbd_get_encryption_key(struct ksmbd_work *work, __u64 ses_id,
|
||||||
|
|
||||||
ses_enc_key = enc ? sess->smb3encryptionkey :
|
ses_enc_key = enc ? sess->smb3encryptionkey :
|
||||||
sess->smb3decryptionkey;
|
sess->smb3decryptionkey;
|
||||||
|
if (enc)
|
||||||
|
ksmbd_user_session_get(sess);
|
||||||
memcpy(key, ses_enc_key, SMB3_ENC_DEC_KEY_SIZE);
|
memcpy(key, ses_enc_key, SMB3_ENC_DEC_KEY_SIZE);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -263,8 +263,10 @@ struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn,
|
||||||
|
|
||||||
down_read(&conn->session_lock);
|
down_read(&conn->session_lock);
|
||||||
sess = xa_load(&conn->sessions, id);
|
sess = xa_load(&conn->sessions, id);
|
||||||
if (sess)
|
if (sess) {
|
||||||
sess->last_active = jiffies;
|
sess->last_active = jiffies;
|
||||||
|
ksmbd_user_session_get(sess);
|
||||||
|
}
|
||||||
up_read(&conn->session_lock);
|
up_read(&conn->session_lock);
|
||||||
return sess;
|
return sess;
|
||||||
}
|
}
|
||||||
|
@ -275,6 +277,8 @@ struct ksmbd_session *ksmbd_session_lookup_slowpath(unsigned long long id)
|
||||||
|
|
||||||
down_read(&sessions_table_lock);
|
down_read(&sessions_table_lock);
|
||||||
sess = __session_lookup(id);
|
sess = __session_lookup(id);
|
||||||
|
if (sess)
|
||||||
|
ksmbd_user_session_get(sess);
|
||||||
up_read(&sessions_table_lock);
|
up_read(&sessions_table_lock);
|
||||||
|
|
||||||
return sess;
|
return sess;
|
||||||
|
|
|
@ -241,14 +241,14 @@ send:
|
||||||
if (work->tcon)
|
if (work->tcon)
|
||||||
ksmbd_tree_connect_put(work->tcon);
|
ksmbd_tree_connect_put(work->tcon);
|
||||||
smb3_preauth_hash_rsp(work);
|
smb3_preauth_hash_rsp(work);
|
||||||
if (work->sess)
|
|
||||||
ksmbd_user_session_put(work->sess);
|
|
||||||
if (work->sess && work->sess->enc && work->encrypted &&
|
if (work->sess && work->sess->enc && work->encrypted &&
|
||||||
conn->ops->encrypt_resp) {
|
conn->ops->encrypt_resp) {
|
||||||
rc = conn->ops->encrypt_resp(work);
|
rc = conn->ops->encrypt_resp(work);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
conn->ops->set_rsp_status(work, STATUS_DATA_ERROR);
|
conn->ops->set_rsp_status(work, STATUS_DATA_ERROR);
|
||||||
}
|
}
|
||||||
|
if (work->sess)
|
||||||
|
ksmbd_user_session_put(work->sess);
|
||||||
|
|
||||||
ksmbd_conn_write(work);
|
ksmbd_conn_write(work);
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,8 +67,10 @@ static inline bool check_session_id(struct ksmbd_conn *conn, u64 id)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
sess = ksmbd_session_lookup_all(conn, id);
|
sess = ksmbd_session_lookup_all(conn, id);
|
||||||
if (sess)
|
if (sess) {
|
||||||
|
ksmbd_user_session_put(sess);
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
pr_err("Invalid user session id: %llu\n", id);
|
pr_err("Invalid user session id: %llu\n", id);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -605,10 +607,8 @@ int smb2_check_user_session(struct ksmbd_work *work)
|
||||||
|
|
||||||
/* Check for validity of user session */
|
/* Check for validity of user session */
|
||||||
work->sess = ksmbd_session_lookup_all(conn, sess_id);
|
work->sess = ksmbd_session_lookup_all(conn, sess_id);
|
||||||
if (work->sess) {
|
if (work->sess)
|
||||||
ksmbd_user_session_get(work->sess);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
|
||||||
ksmbd_debug(SMB, "Invalid user session, Uid %llu\n", sess_id);
|
ksmbd_debug(SMB, "Invalid user session, Uid %llu\n", sess_id);
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
@ -1701,29 +1701,35 @@ int smb2_sess_setup(struct ksmbd_work *work)
|
||||||
|
|
||||||
if (conn->dialect != sess->dialect) {
|
if (conn->dialect != sess->dialect) {
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
|
ksmbd_user_session_put(sess);
|
||||||
goto out_err;
|
goto out_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(req->hdr.Flags & SMB2_FLAGS_SIGNED)) {
|
if (!(req->hdr.Flags & SMB2_FLAGS_SIGNED)) {
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
|
ksmbd_user_session_put(sess);
|
||||||
goto out_err;
|
goto out_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strncmp(conn->ClientGUID, sess->ClientGUID,
|
if (strncmp(conn->ClientGUID, sess->ClientGUID,
|
||||||
SMB2_CLIENT_GUID_SIZE)) {
|
SMB2_CLIENT_GUID_SIZE)) {
|
||||||
rc = -ENOENT;
|
rc = -ENOENT;
|
||||||
|
ksmbd_user_session_put(sess);
|
||||||
goto out_err;
|
goto out_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sess->state == SMB2_SESSION_IN_PROGRESS) {
|
if (sess->state == SMB2_SESSION_IN_PROGRESS) {
|
||||||
rc = -EACCES;
|
rc = -EACCES;
|
||||||
|
ksmbd_user_session_put(sess);
|
||||||
goto out_err;
|
goto out_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sess->state == SMB2_SESSION_EXPIRED) {
|
if (sess->state == SMB2_SESSION_EXPIRED) {
|
||||||
rc = -EFAULT;
|
rc = -EFAULT;
|
||||||
|
ksmbd_user_session_put(sess);
|
||||||
goto out_err;
|
goto out_err;
|
||||||
}
|
}
|
||||||
|
ksmbd_user_session_put(sess);
|
||||||
|
|
||||||
if (ksmbd_conn_need_reconnect(conn)) {
|
if (ksmbd_conn_need_reconnect(conn)) {
|
||||||
rc = -EFAULT;
|
rc = -EFAULT;
|
||||||
|
@ -1731,7 +1737,8 @@ int smb2_sess_setup(struct ksmbd_work *work)
|
||||||
goto out_err;
|
goto out_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ksmbd_session_lookup(conn, sess_id)) {
|
sess = ksmbd_session_lookup(conn, sess_id);
|
||||||
|
if (!sess) {
|
||||||
rc = -EACCES;
|
rc = -EACCES;
|
||||||
goto out_err;
|
goto out_err;
|
||||||
}
|
}
|
||||||
|
@ -1742,7 +1749,6 @@ int smb2_sess_setup(struct ksmbd_work *work)
|
||||||
}
|
}
|
||||||
|
|
||||||
conn->binding = true;
|
conn->binding = true;
|
||||||
ksmbd_user_session_get(sess);
|
|
||||||
} else if ((conn->dialect < SMB30_PROT_ID ||
|
} else if ((conn->dialect < SMB30_PROT_ID ||
|
||||||
server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL) &&
|
server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL) &&
|
||||||
(req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) {
|
(req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) {
|
||||||
|
@ -1769,7 +1775,6 @@ int smb2_sess_setup(struct ksmbd_work *work)
|
||||||
}
|
}
|
||||||
|
|
||||||
conn->binding = false;
|
conn->binding = false;
|
||||||
ksmbd_user_session_get(sess);
|
|
||||||
}
|
}
|
||||||
work->sess = sess;
|
work->sess = sess;
|
||||||
|
|
||||||
|
@ -2197,9 +2202,9 @@ err_out:
|
||||||
int smb2_session_logoff(struct ksmbd_work *work)
|
int smb2_session_logoff(struct ksmbd_work *work)
|
||||||
{
|
{
|
||||||
struct ksmbd_conn *conn = work->conn;
|
struct ksmbd_conn *conn = work->conn;
|
||||||
|
struct ksmbd_session *sess = work->sess;
|
||||||
struct smb2_logoff_req *req;
|
struct smb2_logoff_req *req;
|
||||||
struct smb2_logoff_rsp *rsp;
|
struct smb2_logoff_rsp *rsp;
|
||||||
struct ksmbd_session *sess;
|
|
||||||
u64 sess_id;
|
u64 sess_id;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
@ -2221,11 +2226,6 @@ int smb2_session_logoff(struct ksmbd_work *work)
|
||||||
ksmbd_close_session_fds(work);
|
ksmbd_close_session_fds(work);
|
||||||
ksmbd_conn_wait_idle(conn);
|
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)) {
|
if (ksmbd_tree_conn_session_logoff(sess)) {
|
||||||
ksmbd_debug(SMB, "Invalid tid %d\n", req->hdr.Id.SyncId.TreeId);
|
ksmbd_debug(SMB, "Invalid tid %d\n", req->hdr.Id.SyncId.TreeId);
|
||||||
rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED;
|
rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED;
|
||||||
|
@ -8992,6 +8992,7 @@ int smb3_decrypt_req(struct ksmbd_work *work)
|
||||||
le64_to_cpu(tr_hdr->SessionId));
|
le64_to_cpu(tr_hdr->SessionId));
|
||||||
return -ECONNABORTED;
|
return -ECONNABORTED;
|
||||||
}
|
}
|
||||||
|
ksmbd_user_session_put(sess);
|
||||||
|
|
||||||
iov[0].iov_base = buf;
|
iov[0].iov_base = buf;
|
||||||
iov[0].iov_len = sizeof(struct smb2_transform_hdr) + 4;
|
iov[0].iov_len = sizeof(struct smb2_transform_hdr) + 4;
|
||||||
|
|
Loading…
Add table
Reference in a new issue