summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGael Blivet <gael.blivet@gmail.com>2026-07-17 09:37:20 +0200
committerNamjae Jeon <linkinjeon@kernel.org>2026-08-17 15:00:50 +0900
commit7b461610882c8baa64d56dade57cdbfb686739fa (patch)
tree8e34809adc7d9a5fd926495fe6d0bf5524d68df4
parent08f41323f549b1ad9ad2e67e7b5c5ac312c1cb1a (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.c15
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);