CVE-2026-23220: Add .vulnerable file

The fix commit 010eb01ce23b ("ksmbd: fix infinite loop caused by
next_smb2_rcv_hdr_off reset in error paths") addresses an infinite loop
in ksmbd's SMB2 compound (chained) request processing. When a signed
SMB2 compound request fails signature verification (or hits two other
error conditions), the server loops forever processing the same failed
request, flooding kernel logs with "bad smb2 signature" messages and
consuming 100% CPU.

The root cause commit is be0f89d4419dc5413a1cf06db3671c9949be0d52
("ksmbd: fix wrong error response status by using
set_smb2_rsp_status()"), authored by Namjae Jeon on 2023-10-09.

The infinite loop involves three interacting code paths:

1. The do-while loop in __handle_ksmbd_work() (fs/smb/server/server.c)
   processes compound (chained) SMB2 requests. The loop only breaks on
   SERVER_HANDLER_ABORT. If __process_request() returns
SERVER_HANDLER_CONTINUE, it proceeds to call is_chained_smb2_message(),
which determines whether there are more commands in the chain.

2. Three error paths in __process_request() call
   conn->ops->set_rsp_status(work, ...) and then return
SERVER_HANDLER_CONTINUE:
  - command >= conn->max_cmds -> STATUS_INVALID_PARAMETER
  - !cmds->proc (unimplemented command) -> STATUS_NOT_IMPLEMENTED
  - check_sign_req() failure -> STATUS_ACCESS_DENIED
These have returned CONTINUE since the initial ksmbd commit
(0626e6641f6b4, 2021-03-16). This was intentionally safe -- the idea
was that a single bad command in a compound chain should generate an
error response but let processing continue to the next command in the
chain.

3. set_smb2_rsp_status() in fs/smb/server/smb2pdu.c was changed by the
   root cause commit. Before be0f89d4419dc, this function preserved
   work->next_smb2_rcv_hdr_off by checking its value:

    void set_smb2_rsp_status(struct ksmbd_work *work, __le32 err)
    {
        if (work->next_smb2_rcv_hdr_off)
            rsp_hdr = ksmbd_resp_buf_next(work);
        else
            rsp_hdr = smb2_get_msg(work->response_buf);
        rsp_hdr->Status = err;
        smb2_set_err_rsp(work);
    }

After be0f89d4419dc, it resets the offset to zero:

    void set_smb2_rsp_status(struct ksmbd_work *work, __le32 err)
    {
        rsp_hdr = smb2_get_msg(work->response_buf);
        rsp_hdr->Status = err;
        work->iov_idx = 0;
        work->iov_cnt = 0;
        work->next_smb2_rcv_hdr_off = 0;  // THIS CAUSES THE BUG
        smb2_set_err_rsp(work);
    }

The change was made to fix a different bug (wrong error response status
in compound requests after e2b76ab8b5c9 introduced iov-based compound
handling). The idea was to reset all iov vectors and set the error
status on a clean one.

4. The infinite loop occurs because when is_chained_smb2_message() is
   called, it uses ksmbd_req_buf_next(work), which returns
   work->request_buf + work->next_smb2_rcv_hdr_off + 4. Since
   next_smb2_rcv_hdr_off was reset to 0 by set_smb2_rsp_status(),
   ksmbd_req_buf_next() points back to the first request header in the
   buffer. If that first request's NextCommand field is non-zero (which
   it always is for the first command in a compound chain),
   is_chained_smb2_message() returns true, and the loop processes the
   exact same first request again -- which fails again, resets the
   offset to 0 again, and loops forever.

Before commit be0f89d4419dc, the three error paths in
__process_request() that return CONTINUE were safe:
set_smb2_rsp_status() preserved next_smb2_rcv_hdr_off, so
is_chained_smb2_message() could correctly advance to the next command,
and chained processing would continue normally after an error response.

After commit be0f89d4419dc, set_smb2_rsp_status() resets
next_smb2_rcv_hdr_off to 0, the chain position is lost,
is_chained_smb2_message() re-reads the first request header, and if
NextCommand != 0, the loop repeats forever.

The fix commit 010eb01ce23b addresses this by changing the three error
paths to return SERVER_HANDLER_ABORT instead of SERVER_HANDLER_CONTINUE,
ensuring the loop terminates immediately when an error occurs rather
than trying to continue from a now-corrupted chain offset.

Signed-off-by: Sasha Levin <sashal@kernel.org>
1 file changed