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;