From: Namjae Jeon <linkinjeon@kernel.org>
To: linux-cifs@vger.kernel.org
Cc: smfrench@gmail.com, senozhatsky@chromium.org, tom@talpey.com,
atteh.mailbox@gmail.com, Namjae Jeon <linkinjeon@kernel.org>
Subject: [PATCH] ksmbd: scope session state changes to bound connections
Date: Mon, 17 Aug 2026 21:15:18 +0900 [thread overview]
Message-ID: <20260817121524.8812-6-linkinjeon@kernel.org> (raw)
In-Reply-To: <20260817121524.8812-1-linkinjeon@kernel.org>
ksmbd_all_conn_set_status() treats every connection whose transient
binding flag is set as belonging to the target SessionId. A logoff or
session replacement can consequently move an unrelated connection to
NEED_RECONNECT or NEED_SETUP.
Pass the target session itself and select connections using either the
connection-local session xarray or the session's permanent channel list.
Use the same association test while waiting for requests to drain.
Serialize session-wide status changes under request_lock and do not
overwrite EXITING or RELEASING. Protect the shutdown transition with the
same lock so a concurrent session update cannot revive a closing
connection.
Fixes: f5a544e3bab7 ("ksmbd: add support for SMB3 multichannel")
Fixes: abcc506a9a71 ("ksmbd: fix racy issue from smb2 close and logoff with multichannel")
Fixes: c444139cb747 ("ksmbd: rewrite stop_sessions() with restartable iteration")
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
---
fs/smb/server/connection.c | 37 ++++++++++++++++++++++++++-----
fs/smb/server/connection.h | 6 +++--
fs/smb/server/mgmt/user_session.c | 8 +++----
fs/smb/server/smb2pdu.c | 6 ++---
4 files changed, 41 insertions(+), 16 deletions(-)
diff --git a/fs/smb/server/connection.c b/fs/smb/server/connection.c
index e225aca67686..71d55d903f6f 100644
--- a/fs/smb/server/connection.c
+++ b/fs/smb/server/connection.c
@@ -404,15 +404,37 @@ void ksmbd_conn_unlock(struct ksmbd_conn *conn)
mutex_unlock(&conn->srv_mutex);
}
-void ksmbd_all_conn_set_status(u64 sess_id, u32 status)
+static bool ksmbd_session_is_bound_to_conn(struct ksmbd_session *sess,
+ struct ksmbd_conn *conn)
+{
+ bool found;
+
+ rcu_read_lock();
+ found = xa_load(&conn->sessions, sess->id) == sess;
+ rcu_read_unlock();
+ if (found)
+ return true;
+
+ down_read(&sess->chann_lock);
+ found = xa_load(&sess->ksmbd_chann_list, (long)conn);
+ up_read(&sess->chann_lock);
+ return found;
+}
+
+void ksmbd_all_conn_set_status(struct ksmbd_session *sess, u32 status)
{
struct ksmbd_conn *conn;
int bkt;
down_read(&conn_list_lock);
hash_for_each(conn_list, bkt, conn, hlist) {
- if (conn->binding || xa_load(&conn->sessions, sess_id))
- WRITE_ONCE(conn->status, status);
+ if (ksmbd_session_is_bound_to_conn(sess, conn)) {
+ spin_lock(&conn->request_lock);
+ if (!ksmbd_conn_exiting(conn) &&
+ !ksmbd_conn_releasing(conn))
+ WRITE_ONCE(conn->status, status);
+ spin_unlock(&conn->request_lock);
+ }
}
up_read(&conn_list_lock);
}
@@ -422,7 +444,8 @@ void ksmbd_conn_wait_idle(struct ksmbd_conn *conn)
wait_event(conn->req_running_q, atomic_read(&conn->req_running) < 2);
}
-int ksmbd_conn_wait_idle_sess_id(struct ksmbd_conn *curr_conn, u64 sess_id)
+int ksmbd_conn_wait_idle_sess(struct ksmbd_conn *curr_conn,
+ struct ksmbd_session *sess)
{
struct ksmbd_conn *conn;
int rc, retry_count = 0, max_timeout = 120;
@@ -434,7 +457,7 @@ int ksmbd_conn_wait_idle_sess_id(struct ksmbd_conn *curr_conn, u64 sess_id)
down_read(&conn_list_lock);
hash_for_each(conn_list, bkt, conn, hlist) {
- if (conn->binding || xa_load(&conn->sessions, sess_id)) {
+ if (ksmbd_session_is_bound_to_conn(sess, conn)) {
rcount = (conn == curr_conn) ? 2 : 1;
if (atomic_read(&conn->req_running) >= rcount) {
rc = wait_event_timeout(conn->req_running_q,
@@ -780,8 +803,10 @@ static void stop_sessions(void)
* handler exited its receive loop for an unrelated
* reason).
*/
- if (READ_ONCE(conn->status) != KSMBD_SESS_RELEASING)
+ spin_lock(&conn->request_lock);
+ if (!ksmbd_conn_releasing(conn))
ksmbd_conn_set_exiting(conn);
+ spin_unlock(&conn->request_lock);
target = conn;
break;
}
diff --git a/fs/smb/server/connection.h b/fs/smb/server/connection.h
index 9ca03f9774d3..c01ccbe8b97c 100644
--- a/fs/smb/server/connection.h
+++ b/fs/smb/server/connection.h
@@ -23,6 +23,7 @@
#include "ksmbd_work.h"
struct smbdirect_buffer_descriptor_v1;
+struct ksmbd_session;
#define KSMBD_SOCKET_BACKLOG 16
@@ -196,7 +197,8 @@ extern struct rw_semaphore conn_list_lock;
bool ksmbd_conn_alive(struct ksmbd_conn *conn);
void ksmbd_conn_wait_idle(struct ksmbd_conn *conn);
-int ksmbd_conn_wait_idle_sess_id(struct ksmbd_conn *curr_conn, u64 sess_id);
+int ksmbd_conn_wait_idle_sess(struct ksmbd_conn *curr_conn,
+ struct ksmbd_session *sess);
struct ksmbd_conn *ksmbd_conn_alloc(void);
void ksmbd_conn_free(struct ksmbd_conn *conn);
struct ksmbd_conn *ksmbd_conn_get(struct ksmbd_conn *conn);
@@ -310,5 +312,5 @@ static inline void ksmbd_conn_set_releasing(struct ksmbd_conn *conn)
WRITE_ONCE(conn->status, KSMBD_SESS_RELEASING);
}
-void ksmbd_all_conn_set_status(u64 sess_id, u32 status);
+void ksmbd_all_conn_set_status(struct ksmbd_session *sess, u32 status);
#endif /* __CONNECTION_H__ */
diff --git a/fs/smb/server/mgmt/user_session.c b/fs/smb/server/mgmt/user_session.c
index 31eccad5d732..7e187d20828b 100644
--- a/fs/smb/server/mgmt/user_session.c
+++ b/fs/smb/server/mgmt/user_session.c
@@ -647,17 +647,17 @@ void destroy_previous_session(struct ksmbd_conn *conn,
memcmp(user->passkey, prev_user->passkey, user->passkey_sz))
goto out;
- ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_RECONNECT);
- err = ksmbd_conn_wait_idle_sess_id(conn, id);
+ ksmbd_all_conn_set_status(prev_sess, KSMBD_SESS_NEED_RECONNECT);
+ err = ksmbd_conn_wait_idle_sess(conn, prev_sess);
if (err) {
- ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_SETUP);
+ ksmbd_all_conn_set_status(prev_sess, KSMBD_SESS_NEED_SETUP);
goto out;
}
ksmbd_destroy_file_table(prev_sess);
prev_sess->kerberos_expiry = 0;
prev_sess->state = SMB2_SESSION_EXPIRED;
- ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_SETUP);
+ ksmbd_all_conn_set_status(prev_sess, KSMBD_SESS_NEED_SETUP);
ksmbd_launch_ksmbd_durable_scavenger();
out:
up_write(&conn->session_lock);
diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
index aa662adaf63d..6581c79635fa 100644
--- a/fs/smb/server/smb2pdu.c
+++ b/fs/smb/server/smb2pdu.c
@@ -2899,7 +2899,6 @@ int smb2_session_logoff(struct ksmbd_work *work)
struct ksmbd_session *sess = work->sess;
struct smb2_logoff_req *req;
struct smb2_logoff_rsp *rsp;
- u64 sess_id;
int err;
WORK_BUFFERS(work, req, rsp);
@@ -2913,8 +2912,7 @@ int smb2_session_logoff(struct ksmbd_work *work)
smb2_set_err_rsp(work);
return -ENOENT;
}
- sess_id = le64_to_cpu(req->hdr.SessionId);
- ksmbd_all_conn_set_status(sess_id, KSMBD_SESS_NEED_RECONNECT);
+ ksmbd_all_conn_set_status(sess, KSMBD_SESS_NEED_RECONNECT);
ksmbd_conn_unlock(conn);
ksmbd_close_session_fds(work);
@@ -2932,7 +2930,7 @@ int smb2_session_logoff(struct ksmbd_work *work)
sess->state = SMB2_SESSION_EXPIRED;
up_write(&conn->session_lock);
- ksmbd_all_conn_set_status(sess_id, KSMBD_SESS_NEED_SETUP);
+ ksmbd_all_conn_set_status(sess, KSMBD_SESS_NEED_SETUP);
rsp->StructureSize = cpu_to_le16(4);
err = ksmbd_iov_pin_rsp(work, rsp, sizeof(struct smb2_logoff_rsp));
--
2.25.1
next prev parent reply other threads:[~2026-08-17 12:15 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-17 12:15 [PATCH] ksmbd: accept unspecified volatile ID on durable reconnect Namjae Jeon
2026-08-17 12:15 ` [PATCH] ksmbd: implement SMB2 AppInstanceVersion takeover Namjae Jeon
2026-08-17 12:15 ` [PATCH] ksmbd: notify parent directory leases on child create Namjae Jeon
2026-08-17 12:15 ` [PATCH] ksmbd: add per-share SMB3 encryption enforcement Namjae Jeon
2026-08-17 12:15 ` [PATCH] ksmbd: fix encrypted request lookup on bound channels Namjae Jeon
2026-08-17 12:15 ` Namjae Jeon [this message]
2026-08-17 12:15 ` [PATCH] ksmbd: encrypt interim responses to encrypted requests Namjae Jeon
2026-08-17 12:15 ` [PATCH] ksmbd: disconnect on SMB3 decryption failure Namjae Jeon
2026-08-17 12:15 ` [PATCH] ksmbd: decrypt requests from expired encrypted sessions Namjae Jeon
2026-08-17 12:15 ` [PATCH] ksmbd: handle encrypted compressed requests Namjae Jeon
2026-08-17 12:15 ` [PATCH] ksmbd: add SMB Direct RDMA encryption transform Namjae Jeon
2026-08-17 12:15 ` [PATCH] ksmbd: make RDMA encryption diagnostics conditional Namjae Jeon
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260817121524.8812-6-linkinjeon@kernel.org \
--to=linkinjeon@kernel.org \
--cc=atteh.mailbox@gmail.com \
--cc=linux-cifs@vger.kernel.org \
--cc=senozhatsky@chromium.org \
--cc=smfrench@gmail.com \
--cc=tom@talpey.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).