]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
ksmbd: fix infinite loop caused by next_smb2_rcv_hdr_off reset in error paths
authorNamjae Jeon <linkinjeon@kernel.org>
Sat, 24 Jan 2026 01:55:46 +0000 (10:55 +0900)
committerSteve French <stfrench@microsoft.com>
Mon, 9 Feb 2026 02:24:11 +0000 (20:24 -0600)
The problem occurs when a signed request fails smb2 signature verification
check. In __process_request(), if check_sign_req() returns an error,
set_smb2_rsp_status(work, STATUS_ACCESS_DENIED) is called.
set_smb2_rsp_status() set work->next_smb2_rcv_hdr_off as zero. By resetting
next_smb2_rcv_hdr_off to zero, the pointer to the next command in the chain
is lost. Consequently, is_chained_smb2_message() continues to point to
the same request header instead of advancing. If the header's NextCommand
field is non-zero, the function returns true, causing __handle_ksmbd_work()
to repeatedly process the same failed request in an infinite loop.
This results in the kernel log being flooded with "bad smb2 signature"
messages and high CPU usage.

This patch fixes the issue by changing the return value from
SERVER_HANDLER_CONTINUE to SERVER_HANDLER_ABORT. This ensures that
the processing loop terminates immediately rather than attempting to
continue from an invalidated offset.

Reported-by: tianshuo han <hantianshuo233@gmail.com>
Cc: stable@vger.kernel.org
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/smb/server/server.c

index 554ae90df906dbf11d53c5baa62711b2e1c4afaa..d2410a3f163aec875b316e0602143c35d6a262a0 100644 (file)
@@ -126,21 +126,21 @@ static int __process_request(struct ksmbd_work *work, struct ksmbd_conn *conn,
 andx_again:
        if (command >= conn->max_cmds) {
                conn->ops->set_rsp_status(work, STATUS_INVALID_PARAMETER);
-               return SERVER_HANDLER_CONTINUE;
+               return SERVER_HANDLER_ABORT;
        }
 
        cmds = &conn->cmds[command];
        if (!cmds->proc) {
                ksmbd_debug(SMB, "*** not implemented yet cmd = %x\n", command);
                conn->ops->set_rsp_status(work, STATUS_NOT_IMPLEMENTED);
-               return SERVER_HANDLER_CONTINUE;
+               return SERVER_HANDLER_ABORT;
        }
 
        if (work->sess && conn->ops->is_sign_req(work, command)) {
                ret = conn->ops->check_sign_req(work);
                if (!ret) {
                        conn->ops->set_rsp_status(work, STATUS_ACCESS_DENIED);
-                       return SERVER_HANDLER_CONTINUE;
+                       return SERVER_HANDLER_ABORT;
                }
        }