mirror of
https://github.com/torvalds/linux.git
synced 2026-10-06 18:46:02 +02:00
ksmbd: deny renaming directory with open children
Windows denies renaming a directory while a file below that directory is still open. smb2.rename.rename_dir_openfile checks this by keeping a file handle open under the directory and then attempting to rename the directory handle. ksmbd did not check open children before calling vfs_rename(), so the rename incorrectly succeeded. For non-POSIX clients, scan the global open file table for active handles whose dentries are below the directory being renamed. If any child is open, fail the rename with -EACCES so the client receives STATUS_ACCESS_DENIED. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
9a5784f4d5
commit
c841bd3d8d
|
|
@ -700,6 +700,12 @@ int ksmbd_vfs_rename(struct ksmbd_work *work, const struct path *old_path,
|
||||||
if (err)
|
if (err)
|
||||||
goto out_drop_write;
|
goto out_drop_write;
|
||||||
|
|
||||||
|
if (!work->tcon->posix_extensions && d_is_dir(old_child) &&
|
||||||
|
ksmbd_has_open_files(old_child)) {
|
||||||
|
err = -EACCES;
|
||||||
|
goto out3;
|
||||||
|
}
|
||||||
|
|
||||||
parent_fp = ksmbd_lookup_fd_inode(old_child->d_parent);
|
parent_fp = ksmbd_lookup_fd_inode(old_child->d_parent);
|
||||||
if (parent_fp) {
|
if (parent_fp) {
|
||||||
if ((parent_fp->daccess & FILE_DELETE_LE) ||
|
if ((parent_fp->daccess & FILE_DELETE_LE) ||
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
#include <linux/vmalloc.h>
|
#include <linux/vmalloc.h>
|
||||||
#include <linux/kthread.h>
|
#include <linux/kthread.h>
|
||||||
#include <linux/freezer.h>
|
#include <linux/freezer.h>
|
||||||
|
#include <linux/dcache.h>
|
||||||
|
|
||||||
#include "glob.h"
|
#include "glob.h"
|
||||||
#include "vfs_cache.h"
|
#include "vfs_cache.h"
|
||||||
|
|
@ -914,6 +915,30 @@ struct ksmbd_file *ksmbd_lookup_fd_inode(struct dentry *dentry)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ksmbd_has_open_files(struct dentry *dentry)
|
||||||
|
{
|
||||||
|
struct ksmbd_file *fp;
|
||||||
|
unsigned int id;
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
|
read_lock(&global_ft.lock);
|
||||||
|
idr_for_each_entry(global_ft.idr, fp, id) {
|
||||||
|
struct dentry *fp_dentry = fp->filp->f_path.dentry;
|
||||||
|
|
||||||
|
if (fp->f_state != FP_INITED)
|
||||||
|
continue;
|
||||||
|
if (fp_dentry == dentry)
|
||||||
|
continue;
|
||||||
|
if (is_subdir(fp_dentry, dentry)) {
|
||||||
|
ret = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
read_unlock(&global_ft.lock);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
#define OPEN_ID_TYPE_VOLATILE_ID (0)
|
#define OPEN_ID_TYPE_VOLATILE_ID (0)
|
||||||
#define OPEN_ID_TYPE_PERSISTENT_ID (1)
|
#define OPEN_ID_TYPE_PERSISTENT_ID (1)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -172,6 +172,7 @@ bool ksmbd_has_other_active_fd(struct ksmbd_file *fp);
|
||||||
int ksmbd_close_fd_app_instance_id(char *app_instance_id);
|
int ksmbd_close_fd_app_instance_id(char *app_instance_id);
|
||||||
struct ksmbd_file *ksmbd_lookup_fd_cguid(char *cguid);
|
struct ksmbd_file *ksmbd_lookup_fd_cguid(char *cguid);
|
||||||
struct ksmbd_file *ksmbd_lookup_fd_inode(struct dentry *dentry);
|
struct ksmbd_file *ksmbd_lookup_fd_inode(struct dentry *dentry);
|
||||||
|
bool ksmbd_has_open_files(struct dentry *dentry);
|
||||||
unsigned int ksmbd_open_durable_fd(struct ksmbd_file *fp);
|
unsigned int ksmbd_open_durable_fd(struct ksmbd_file *fp);
|
||||||
struct ksmbd_file *ksmbd_open_fd(struct ksmbd_work *work, struct file *filp);
|
struct ksmbd_file *ksmbd_open_fd(struct ksmbd_work *work, struct file *filp);
|
||||||
void ksmbd_launch_ksmbd_durable_scavenger(void);
|
void ksmbd_launch_ksmbd_durable_scavenger(void);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user