diff options
author | Chris Mason <chris.mason@oracle.com> | 2009-01-05 16:57:23 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2009-01-05 16:57:23 -0500 |
commit | e441d54de4fd97dd381f3e73636f5ba51ff4c7d9 (patch) | |
tree | b0d664ffaa89cec80e6aaac11977c7f6aa92ff63 | |
parent | b34b086c1c1d934c5314d46ba25ccfa9acc471ae (diff) | |
download | linux-stable-e441d54de4fd97dd381f3e73636f5ba51ff4c7d9.tar.gz linux-stable-e441d54de4fd97dd381f3e73636f5ba51ff4c7d9.tar.bz2 linux-stable-e441d54de4fd97dd381f3e73636f5ba51ff4c7d9.zip |
Btrfs: add permission checks to the ioctls
Only root can add/remove devices
Only root can defrag subtrees
Only files open for writing can be defragged
Only files open for writing can be the destination for a clone
Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r-- | fs/btrfs/ioctl.c | 25 | ||||
-rw-r--r-- | fs/btrfs/super.c | 3 |
2 files changed, 26 insertions, 2 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index ab429fe0fa0f..150784e936e6 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 84c3b66564d0..3814238d6eba 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; |