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) | |
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 ab429fe0fa0..150784e936e 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) | |||
| 453 | if (root->fs_info->sb->s_flags & MS_RDONLY) | 453 | if (root->fs_info->sb->s_flags & MS_RDONLY) |
| 454 | return -EROFS; | 454 | return -EROFS; |
| 455 | 455 | ||
| 456 | if (!capable(CAP_SYS_ADMIN)) | ||
| 457 | return -EPERM; | ||
| 458 | |||
| 456 | vol_args = kmalloc(sizeof(*vol_args), GFP_NOFS); | 459 | vol_args = kmalloc(sizeof(*vol_args), GFP_NOFS); |
| 457 | 460 | ||
| 458 | if (!vol_args) | 461 | if (!vol_args) |
| @@ -638,16 +641,24 @@ static int btrfs_ioctl_defrag(struct file *file) | |||
| 638 | 641 | ||
| 639 | switch (inode->i_mode & S_IFMT) { | 642 | switch (inode->i_mode & S_IFMT) { |
| 640 | case S_IFDIR: | 643 | case S_IFDIR: |
| 644 | if (!capable(CAP_SYS_ADMIN)) { | ||
| 645 | ret = -EPERM; | ||
| 646 | goto out; | ||
| 647 | } | ||
| 641 | btrfs_defrag_root(root, 0); | 648 | btrfs_defrag_root(root, 0); |
| 642 | btrfs_defrag_root(root->fs_info->extent_root, 0); | 649 | btrfs_defrag_root(root->fs_info->extent_root, 0); |
| 643 | break; | 650 | break; |
| 644 | case S_IFREG: | 651 | case S_IFREG: |
| 652 | if (!(file->f_mode & FMODE_WRITE)) { | ||
| 653 | ret = -EINVAL; | ||
| 654 | goto out; | ||
| 655 | } | ||
| 645 | btrfs_defrag_file(file); | 656 | btrfs_defrag_file(file); |
| 646 | break; | 657 | break; |
| 647 | } | 658 | } |
| 648 | 659 | out: | |
| 649 | mnt_drop_write(file->f_path.mnt); | 660 | mnt_drop_write(file->f_path.mnt); |
| 650 | return 0; | 661 | return ret; |
| 651 | } | 662 | } |
| 652 | 663 | ||
| 653 | static long btrfs_ioctl_add_dev(struct btrfs_root *root, void __user *arg) | 664 | 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) | |||
| 655 | struct btrfs_ioctl_vol_args *vol_args; | 666 | struct btrfs_ioctl_vol_args *vol_args; |
| 656 | int ret; | 667 | int ret; |
| 657 | 668 | ||
| 669 | if (!capable(CAP_SYS_ADMIN)) | ||
| 670 | return -EPERM; | ||
| 671 | |||
| 658 | vol_args = kmalloc(sizeof(*vol_args), GFP_NOFS); | 672 | vol_args = kmalloc(sizeof(*vol_args), GFP_NOFS); |
| 659 | 673 | ||
| 660 | if (!vol_args) | 674 | if (!vol_args) |
| @@ -677,6 +691,9 @@ static long btrfs_ioctl_rm_dev(struct btrfs_root *root, void __user *arg) | |||
| 677 | struct btrfs_ioctl_vol_args *vol_args; | 691 | struct btrfs_ioctl_vol_args *vol_args; |
| 678 | int ret; | 692 | int ret; |
| 679 | 693 | ||
| 694 | if (!capable(CAP_SYS_ADMIN)) | ||
| 695 | return -EPERM; | ||
| 696 | |||
| 680 | if (root->fs_info->sb->s_flags & MS_RDONLY) | 697 | if (root->fs_info->sb->s_flags & MS_RDONLY) |
| 681 | return -EROFS; | 698 | return -EROFS; |
| 682 | 699 | ||
| @@ -726,6 +743,10 @@ static long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
| 726 | * they don't overlap)? | 743 | * they don't overlap)? |
| 727 | */ | 744 | */ |
| 728 | 745 | ||
| 746 | /* the destination must be opened for writing */ | ||
| 747 | if (!(file->f_mode & FMODE_WRITE)) | ||
| 748 | return -EINVAL; | ||
| 749 | |||
| 729 | ret = mnt_want_write(file->f_path.mnt); | 750 | ret = mnt_want_write(file->f_path.mnt); |
| 730 | if (ret) | 751 | if (ret) |
| 731 | return ret; | 752 | return ret; |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 84c3b66564d..3814238d6eb 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, | |||
| 589 | int ret = 0; | 589 | int ret = 0; |
| 590 | int len; | 590 | int len; |
| 591 | 591 | ||
| 592 | if (!capable(CAP_SYS_ADMIN)) | ||
| 593 | return -EPERM; | ||
| 594 | |||
| 592 | vol = kmalloc(sizeof(*vol), GFP_KERNEL); | 595 | vol = kmalloc(sizeof(*vol), GFP_KERNEL); |
| 593 | if (copy_from_user(vol, (void __user *)arg, sizeof(*vol))) { | 596 | if (copy_from_user(vol, (void __user *)arg, sizeof(*vol))) { |
| 594 | ret = -EFAULT; | 597 | ret = -EFAULT; |
