diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index ab429fe0fa0f5fbe6fef0f586dc9b7bc18e09c1d..150784e936e6cb1da1e7f63200a5e9ebe069d6f0 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -453,6 +453,9 @@ static int btrfs_ioctl_resize(struct btrfs_root *root, void __user *arg) if (root->fs_info->sb->s_flags & MS_RDONLY) return -EROFS; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + vol_args = kmalloc(sizeof(*vol_args), GFP_NOFS); if (!vol_args) @@ -638,16 +641,24 @@ static int btrfs_ioctl_defrag(struct file *file) switch (inode->i_mode & S_IFMT) { case S_IFDIR: + if (!capable(CAP_SYS_ADMIN)) { + ret = -EPERM; + goto out; + } btrfs_defrag_root(root, 0); btrfs_defrag_root(root->fs_info->extent_root, 0); break; case S_IFREG: + if (!(file->f_mode & FMODE_WRITE)) { + ret = -EINVAL; + goto out; + } btrfs_defrag_file(file); break; } - +out: mnt_drop_write(file->f_path.mnt); - return 0; + return ret; } static long btrfs_ioctl_add_dev(struct btrfs_root *root, void __user *arg) @@ -655,6 +666,9 @@ static long btrfs_ioctl_add_dev(struct btrfs_root *root, void __user *arg) struct btrfs_ioctl_vol_args *vol_args; int ret; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + vol_args = kmalloc(sizeof(*vol_args), GFP_NOFS); if (!vol_args) @@ -677,6 +691,9 @@ static long btrfs_ioctl_rm_dev(struct btrfs_root *root, void __user *arg) struct btrfs_ioctl_vol_args *vol_args; int ret; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (root->fs_info->sb->s_flags & MS_RDONLY) return -EROFS; @@ -726,6 +743,10 @@ static long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, * they don't overlap)? */ + /* the destination must be opened for writing */ + if (!(file->f_mode & FMODE_WRITE)) + return -EINVAL; + ret = mnt_want_write(file->f_path.mnt); if (ret) return ret; diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 84c3b66564d0f16a34712fc4c0803771904ac362..3814238d6eba473199bc5d597b6c51edaa9a4861 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -589,6 +589,9 @@ static long btrfs_control_ioctl(struct file *file, unsigned int cmd, int ret = 0; int len; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + vol = kmalloc(sizeof(*vol), GFP_KERNEL); if (copy_from_user(vol, (void __user *)arg, sizeof(*vol))) { ret = -EFAULT;