diff options
| author | Gael Blivet <gael.blivet@gmail.com> | 2026-07-17 09:37:20 +0200 |
|---|---|---|
| committer | Namjae Jeon <linkinjeon@kernel.org> | 2026-08-17 15:00:50 +0900 |
| commit | 7b461610882c8baa64d56dade57cdbfb686739fa (patch) | |
| tree | 8e34809adc7d9a5fd926495fe6d0bf5524d68df4 | |
| parent | 08f41323f549b1ad9ad2e67e7b5c5ac312c1cb1a (diff) | |
ksmbd: fix AsyncId zeroed before use in smb2_lock() cancel response
release_async_work() zeroes work->async_id before the CANCELLED path
calls smb2_send_interim_resp(work, STATUS_CANCELLED), which reads
work->async_id to build the response's AsyncId field. The cancellation
response for a cancelled blocked-lock request is sent with AsyncId=0
instead of the id the client received in the original STATUS_PENDING
response for this request.
Checked against every other release_async_work() call site in this
file: smb2_read()/smb2_write() don't send a further async response
afterward (their status goes out on the synchronous path instead), and
smb2_notify()'s two async paths already transfer the id to a separate
struct before releasing, so this reordering is scoped to smb2_lock()
only.
Send the STATUS_CANCELLED response while work->async_id is still valid,
then release the async work afterward.
Signed-off-by: Gael Blivet <gael.blivet@gmail.com>
Assisted-by: Claude:claude-sonnet-5
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
| -rw-r--r-- | fs/smb/server/smb2pdu.c | 15 |
1 files changed, 9 insertions, 6 deletions
diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c index 8d8567b73c43..18d1369b41f0 100644 --- a/fs/smb/server/smb2pdu.c +++ b/fs/smb/server/smb2pdu.c @@ -9319,22 +9319,25 @@ skip: spin_unlock(&fp->f_lock); list_del(&smb_lock->llist); - release_async_work(work); - - if (work->state == KSMBD_WORK_ACTIVE) - goto retry; - - locks_free_lock(flock); if (work->state == KSMBD_WORK_CANCELLED) { rsp->hdr.Status = STATUS_CANCELLED; kfree(smb_lock); smb2_send_interim_resp(work, STATUS_CANCELLED); + release_async_work(work); + locks_free_lock(flock); work->send_no_response = 1; goto out; } + release_async_work(work); + + if (work->state == KSMBD_WORK_ACTIVE) + goto retry; + + locks_free_lock(flock); + rsp->hdr.Status = STATUS_RANGE_NOT_LOCKED; kfree(smb_lock); |
