Skip to content

Commit

Permalink
ksmbd: fix multichannel connection failure
Browse files Browse the repository at this point in the history
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: b956294 ("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>
  • Loading branch information
Namjae Jeon authored and Steve French committed Mar 28, 2025
1 parent 15a9605 commit c188304
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 8 deletions.
16 changes: 16 additions & 0 deletions fs/smb/server/mgmt/user_session.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
2 changes: 2 additions & 0 deletions fs/smb/server/mgmt/user_session.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
12 changes: 4 additions & 8 deletions fs/smb/server/smb2pdu.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit c188304

Please sign in to comment.