[PATCH] ksmbd: fix use-after-free in __ksmbd_close_fd() lock cleanup
From: munan Huang
Date: Thu Apr 02 2026 - 04:39:58 EST
In __ksmbd_close_fd(), when cleaning up byte-range locks on a durable
file handle closed by the scavenger, the lock cleanup loop
unconditionally dereferences fp->conn->llist_lock to remove each lock
from the connection's list:
list_for_each_entry_safe(smb_lock, tmp_lock, &fp->lock_list, flist) {
spin_lock(&fp->conn->llist_lock);
list_del(&smb_lock->clist);
spin_unlock(&fp->conn->llist_lock);
}
However, when a client disconnects without SMB2 LOGOFF, ksmbd preserves
durable file handles via session_fd_check(), which sets fp->conn to
NULL and arms the durable scavenger timeout, but does not detach the
byte-range locks from the dying connection's lock list.
When the scavenger timeout expires, ksmbd_durable_scavenger() calls
__ksmbd_close_fd(NULL, fp). At this point fp->conn is NULL and the
original connection object has already been freed by ksmbd_conn_free(),
so it would cause a use-after-free or NULL pointer dereference.
Fix by checking fp->conn for NULL before accessing fp->conn->llist_lock
in the lock cleanup loop.
Fixes: c8efcc786146 ("ksmbd: add support for durable handles v1/v2")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: munan Huang <munanevil@xxxxxxxxx>
---
fs/smb/server/vfs_cache.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/fs/smb/server/vfs_cache.c b/fs/smb/server/vfs_cache.c
index 168f2dd7e200..772a84d95fe3 100644
--- a/fs/smb/server/vfs_cache.c
+++ b/fs/smb/server/vfs_cache.c
@@ -463,9 +463,11 @@ static void __ksmbd_close_fd(struct ksmbd_file_table *ft, struct ksmbd_file *fp)
* there are not accesses to fp->lock_list.
*/
list_for_each_entry_safe(smb_lock, tmp_lock, &fp->lock_list, flist) {
- spin_lock(&fp->conn->llist_lock);
- list_del(&smb_lock->clist);
- spin_unlock(&fp->conn->llist_lock);
+ if (fp->conn) {
+ spin_lock(&fp->conn->llist_lock);
+ list_del(&smb_lock->clist);
+ spin_unlock(&fp->conn->llist_lock);
+ }
list_del(&smb_lock->flist);
locks_free_lock(smb_lock->fl);
--
2.34.1