ksmbd: serialize QUERY_DIRECTORY requests per file

smb2_query_dir() stores a pointer to its stack-allocated private data in
the ksmbd_file readdir_data. Concurrent QUERY_DIRECTORY requests using the
same file handle can overwrite this pointer while an iterate_dir() callback
is still using it, resulting in a stack use-after-free.

Add a per-file mutex and hold it while accessing the shared directory
enumeration state. The lock covers scan restart, dot entry state,
readdir_data setup and iteration, and response construction. This prevents
another request from replacing readdir_data.private before the current
request has finished using it and also serializes the shared file position.

Cc: stable@vger.kernel.org
Reported-by: zdi-disclosures@trendmicro.com # ZDI-CAN-30527
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
Namjae Jeon 2026-06-12 08:00:00 +09:00 committed by Steve French
parent 388e4139db
commit be6d26bf27
3 changed files with 7 additions and 0 deletions

View File

@ -4569,6 +4569,8 @@ int smb2_query_dir(struct ksmbd_work *work)
ksmbd_debug(SMB, "Search pattern is %s\n", srch_ptr);
}
mutex_lock(&dir_fp->readdir_lock);
if (srch_flag & SMB2_REOPEN || srch_flag & SMB2_RESTART_SCANS) {
ksmbd_debug(SMB, "Restart directory scan\n");
generic_file_llseek(dir_fp->filp, 0, SEEK_SET);
@ -4673,6 +4675,7 @@ int smb2_query_dir(struct ksmbd_work *work)
goto err_out;
}
mutex_unlock(&dir_fp->readdir_lock);
kfree(srch_ptr);
ksmbd_fd_put(work, dir_fp);
ksmbd_revert_fsids(work);
@ -4680,6 +4683,7 @@ int smb2_query_dir(struct ksmbd_work *work)
err_out:
pr_err("error while processing smb2 query dir rc = %d\n", rc);
mutex_unlock(&dir_fp->readdir_lock);
kfree(srch_ptr);
err_out2:

View File

@ -790,6 +790,7 @@ struct ksmbd_file *ksmbd_open_fd(struct ksmbd_work *work, struct file *filp)
INIT_LIST_HEAD(&fp->node);
INIT_LIST_HEAD(&fp->lock_list);
spin_lock_init(&fp->f_lock);
mutex_init(&fp->readdir_lock);
atomic_set(&fp->refcount, 1);
fp->filp = filp;

View File

@ -8,6 +8,7 @@
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/mutex.h>
#include <linux/rwsem.h>
#include <linux/spinlock.h>
#include <linux/idr.h>
@ -113,6 +114,7 @@ struct ksmbd_file {
/* if ls is happening on directory, below is valid*/
struct ksmbd_readdir_data readdir_data;
struct mutex readdir_lock;
int dot_dotdot[2];
unsigned int f_state;
bool reserve_lease_break;