Skip to content

Commit bbe6a7c

Browse files
author
Al Viro
committed
bch2_ioctl_subvolume_destroy(): fix locking
make it use user_path_locked_at() to get the normal directory protection for modifications, as well as stable ->d_parent and ->d_name in victim Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
1 parent 74d016e commit bbe6a7c

File tree

1 file changed

+17
-14
lines changed

1 file changed

+17
-14
lines changed

fs/bcachefs/fs-ioctl.c

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -453,33 +453,36 @@ static long bch2_ioctl_subvolume_create(struct bch_fs *c, struct file *filp,
453453
static long bch2_ioctl_subvolume_destroy(struct bch_fs *c, struct file *filp,
454454
struct bch_ioctl_subvolume arg)
455455
{
456+
const char __user *name = (void __user *)(unsigned long)arg.dst_ptr;
456457
struct path path;
457458
struct inode *dir;
459+
struct dentry *victim;
458460
int ret = 0;
459461

460462
if (arg.flags)
461463
return -EINVAL;
462464

463-
ret = user_path_at(arg.dirfd,
464-
(const char __user *)(unsigned long)arg.dst_ptr,
465-
LOOKUP_FOLLOW, &path);
466-
if (ret)
467-
return ret;
465+
victim = user_path_locked_at(arg.dirfd, name, &path);
466+
if (IS_ERR(victim))
467+
return PTR_ERR(victim);
468468

469-
if (path.dentry->d_sb->s_fs_info != c) {
469+
if (victim->d_sb->s_fs_info != c) {
470470
ret = -EXDEV;
471471
goto err;
472472
}
473-
474-
dir = path.dentry->d_parent->d_inode;
475-
476-
ret = __bch2_unlink(dir, path.dentry, true);
477-
if (ret)
473+
if (!d_is_positive(victim)) {
474+
ret = -ENOENT;
478475
goto err;
479-
480-
fsnotify_rmdir(dir, path.dentry);
481-
d_delete(path.dentry);
476+
}
477+
dir = d_inode(path.dentry);
478+
ret = __bch2_unlink(dir, victim, true);
479+
if (!ret) {
480+
fsnotify_rmdir(dir, victim);
481+
d_delete(victim);
482+
}
483+
inode_unlock(dir);
482484
err:
485+
dput(victim);
483486
path_put(&path);
484487
return ret;
485488
}

0 commit comments

Comments
 (0)