linux/fs/smb
Gil Portnoy f580d27e89 ksmbd: fix use-after-free of a deferred file_lock on double SMB2_CANCEL
A deferred byte-range lock (an SMB2_LOCK that blocks) registers an async work on
conn->async_requests via setup_async_work(), with cancel_fn =
smb2_remove_blocked_lock and cancel_argv[0] pointing at the struct file_lock.

When the request is cancelled, the worker frees the file_lock with
locks_free_lock() and takes the cancelled early-exit, which "goto out"s and never
reaches release_async_work() -- the only site that unlinks the work from
conn->async_requests and clears cancel_fn/cancel_argv. The work therefore stays
matchable on async_requests with a live cancel_fn pointing at the freed file_lock,
until connection teardown finally runs release_async_work().

smb2_cancel() fires cancel_fn unconditionally with no state guard, so a second
SMB2_CANCEL for the same AsyncId, arriving in that window, re-runs
smb2_remove_blocked_lock() on the freed file_lock -- a slab use-after-free:

  BUG: KASAN: slab-use-after-free in __locks_delete_block
    __locks_delete_block
    locks_delete_block
    ksmbd_vfs_posix_lock_unblock
    smb2_remove_blocked_lock
    smb2_cancel                 <- 2nd SMB2_CANCEL fires cancel_fn
    handle_ksmbd_work
  Allocated by ...: locks_alloc_lock <- smb2_lock
  Freed by ...:     locks_free_lock  <- smb2_lock (cancelled branch)
  ... cache file_lock_cache of size 192

Reproduced on mainline with KASAN by an authenticated SMB client.

Skip a work whose state is already KSMBD_WORK_CANCELLED so its cancel callback
cannot be fired a second time.

Cc: stable@vger.kernel.org
Signed-off-by: Gil Portnoy <dddhkts1@gmail.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
2026-05-31 19:13:48 -05:00
..
client smb: client: fix uninitialized variable in smb2_writev_callback 2026-05-27 17:15:43 -05:00
common SMB3.1.1: add missing QUERY_DIR info levels 2026-05-12 10:13:24 -05:00
server ksmbd: fix use-after-free of a deferred file_lock on double SMB2_CANCEL 2026-05-31 19:13:48 -05:00
smbdirect smb: smbdirect: divide, not multiply, milliseconds by 1000 2026-05-21 09:29:49 -05:00
Kconfig smb: smbdirect: move fs/smb/common/smbdirect/ to fs/smb/smbdirect/ 2026-04-22 19:00:41 -05:00
Makefile smb: smbdirect: move fs/smb/common/smbdirect/ to fs/smb/smbdirect/ 2026-04-22 19:00:41 -05:00