ksmbd: fix multichannel connection failure

ksmbd check that the session of second channel is in the session list of
first connection. If it is in session list, multichannel connection
should not be allowed.

Fixes: b95629435b ("ksmbd: fix racy issue from session lookup and expire")
Reported-by: Sean Heelan <seanheelan@gmail.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
Namjae Jeon 2025-03-24 20:19:20 +09:00 committed by Steve French
parent 15a9605f8d
commit c1883049aa
3 changed files with 22 additions and 8 deletions

View File

@ -259,6 +259,22 @@ void ksmbd_sessions_deregister(struct ksmbd_conn *conn)
up_write(&sessions_table_lock);
}
bool is_ksmbd_session_in_connection(struct ksmbd_conn *conn,
unsigned long long id)
{
struct ksmbd_session *sess;
down_read(&conn->session_lock);
sess = xa_load(&conn->sessions, id);
if (sess) {
up_read(&conn->session_lock);
return true;
}
up_read(&conn->session_lock);
return false;
}
struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn,
unsigned long long id)
{

View File

@ -87,6 +87,8 @@ void ksmbd_session_destroy(struct ksmbd_session *sess);
struct ksmbd_session *ksmbd_session_lookup_slowpath(unsigned long long id);
struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn,
unsigned long long id);
bool is_ksmbd_session_in_connection(struct ksmbd_conn *conn,
unsigned long long id);
int ksmbd_session_register(struct ksmbd_conn *conn,
struct ksmbd_session *sess);
void ksmbd_sessions_deregister(struct ksmbd_conn *conn);

View File

@ -1707,44 +1707,38 @@ 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;
ksmbd_user_session_put(sess);
sess = NULL;
goto out_err;
}
sess = ksmbd_session_lookup(conn, sess_id);
if (!sess) {
if (is_ksmbd_session_in_connection(conn, sess_id)) {
rc = -EACCES;
goto out_err;
}
@ -1910,6 +1904,8 @@ int smb2_sess_setup(struct ksmbd_work *work)
sess->last_active = jiffies;
sess->state = SMB2_SESSION_EXPIRED;
ksmbd_user_session_put(sess);
work->sess = NULL;
if (try_delay) {
ksmbd_conn_set_need_reconnect(conn);
ssleep(5);