mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 09:36:22 +02:00
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:
parent
388e4139db
commit
be6d26bf27
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user