summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNamjae Jeon <linkinjeon@kernel.org>2026-08-16 13:46:36 +0900
committerNamjae Jeon <linkinjeon@kernel.org>2026-08-17 22:38:25 +0900
commitd8fc4fc7e57fc2bfd45699a10ee0df8ab9dccfa5 (patch)
treebf1e39d08362cfe8b78418e008c6f6b9d9f325ea
parent12a6680ce59bcd431730c9f049caddb017964c64 (diff)
downloadlinux-d8fc4fc7e57fc2bfd45699a10ee0df8ab9dccfa5.tar.gz
linux-d8fc4fc7e57fc2bfd45699a10ee0df8ab9dccfa5.zip
ksmbd: decrypt requests from expired encrypted sessions
Previous-session replacement marks the old session expired but retains its SMB3 encryption key. An in-flight encrypted request can still arrive on that connection. Rejecting the expired session before decryption made ksmbd treat the request as a key failure and abort the transport, causing reconnect failures. Allow key lookup for expired sessions that have encryption enabled. Keep the session reference during validation so the normal STATUS_USER_SESSION_DELETED response is encrypted with the old key. The session remains expired and no command is executed. Fixes: fa9415d4024f ("ksmbd: mark SMB2_SESSION_EXPIRED to session when destroying previous session") Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
-rw-r--r--fs/smb/server/auth.c12
-rw-r--r--fs/smb/server/smb2pdu.c8
2 files changed, 14 insertions, 6 deletions
diff --git a/fs/smb/server/auth.c b/fs/smb/server/auth.c
index bcd371f5550d..78491b20897e 100644
--- a/fs/smb/server/auth.c
+++ b/fs/smb/server/auth.c
@@ -724,15 +724,15 @@ static int ksmbd_get_encryption_key(struct ksmbd_work *work, __u64 ses_id,
sess = work->sess;
else {
/*
- * An encrypted SESSION_SETUP request may reauthenticate an expired
- * Kerberos session. Keep using the established decryption key so
- * that the command can reach the session setup handler. Other
- * commands are rejected there with STATUS_NETWORK_SESSION_EXPIRED.
+ * A previous-session replacement leaves the old encryption key in
+ * place. Use it to authenticate an encrypted request, then let
+ * session validation reject the expired session. This preserves the
+ * encrypted STATUS_USER_SESSION_DELETED response without reviving
+ * the session.
*/
sess = ksmbd_session_lookup_all_states(work->conn, ses_id);
if (sess && sess->state != SMB2_SESSION_VALID &&
- (sess->state != SMB2_SESSION_EXPIRED ||
- !sess->kerberos_expiry)) {
+ (sess->state != SMB2_SESSION_EXPIRED || !sess->enc)) {
ksmbd_user_session_put(sess);
sess = NULL;
}
diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
index ade16532a8c1..8d06c934f24f 100644
--- a/fs/smb/server/smb2pdu.c
+++ b/fs/smb/server/smb2pdu.c
@@ -1012,6 +1012,14 @@ int smb2_check_user_session(struct ksmbd_work *work)
1 : -EKEYEXPIRED;
}
if (work->sess->state != SMB2_SESSION_VALID) {
+ /*
+ * Keep the reference for an encrypted request so the caller can
+ * return STATUS_USER_SESSION_DELETED encrypted with the old key.
+ */
+ if (work->encrypted &&
+ work->sess->state == SMB2_SESSION_EXPIRED &&
+ work->sess->enc)
+ return -ENOENT;
ksmbd_user_session_put(work->sess);
work->sess = NULL;
return -ENOENT;