]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - fs/ext4/ioctl.c
Merge tag 'for-5.4/block-2019-09-16' of git://git.kernel.dk/linux-block
[linux.git] / fs / ext4 / ioctl.c
index 74648d42c69b3ee2b2bf0397a2fc85c9d6dd3a6f..442f7ef873fc368a3b33e867a90e65319e8b13a0 100644 (file)
@@ -312,16 +312,9 @@ static int ext4_ioctl_setflags(struct inode *inode,
        /* The JOURNAL_DATA flag is modifiable only by root */
        jflag = flags & EXT4_JOURNAL_DATA_FL;
 
-       /*
-        * The IMMUTABLE and APPEND_ONLY flags can only be changed by
-        * the relevant capability.
-        *
-        * This test looks nicer. Thanks to Pauline Middelink
-        */
-       if ((flags ^ oldflags) & (EXT4_APPEND_FL | EXT4_IMMUTABLE_FL)) {
-               if (!capable(CAP_LINUX_IMMUTABLE))
-                       goto flags_out;
-       }
+       err = vfs_ioc_setflags_prepare(inode, oldflags, flags);
+       if (err)
+               goto flags_out;
 
        /*
         * The JOURNAL_DATA flag can only be changed by
@@ -741,28 +734,15 @@ static long ext4_ioctl_group_add(struct file *file,
        return err;
 }
 
-static int ext4_ioctl_check_project(struct inode *inode, struct fsxattr *fa)
+static void ext4_fill_fsxattr(struct inode *inode, struct fsxattr *fa)
 {
-       /*
-        * Project Quota ID state is only allowed to change from within the init
-        * namespace. Enforce that restriction only if we are trying to change
-        * the quota ID state. Everything else is allowed in user namespaces.
-        */
-       if (current_user_ns() == &init_user_ns)
-               return 0;
-
-       if (__kprojid_val(EXT4_I(inode)->i_projid) != fa->fsx_projid)
-               return -EINVAL;
+       struct ext4_inode_info *ei = EXT4_I(inode);
 
-       if (ext4_test_inode_flag(inode, EXT4_INODE_PROJINHERIT)) {
-               if (!(fa->fsx_xflags & FS_XFLAG_PROJINHERIT))
-                       return -EINVAL;
-       } else {
-               if (fa->fsx_xflags & FS_XFLAG_PROJINHERIT)
-                       return -EINVAL;
-       }
+       simple_fill_fsxattr(fa, ext4_iflags_to_xflags(ei->i_flags &
+                                                     EXT4_FL_USER_VISIBLE));
 
-       return 0;
+       if (ext4_has_feature_project(inode->i_sb))
+               fa->fsx_projid = from_kprojid(&init_user_ns, ei->i_projid);
 }
 
 long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
@@ -1139,13 +1119,7 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
        {
                struct fsxattr fa;
 
-               memset(&fa, 0, sizeof(struct fsxattr));
-               fa.fsx_xflags = ext4_iflags_to_xflags(ei->i_flags & EXT4_FL_USER_VISIBLE);
-
-               if (ext4_has_feature_project(inode->i_sb)) {
-                       fa.fsx_projid = (__u32)from_kprojid(&init_user_ns,
-                               EXT4_I(inode)->i_projid);
-               }
+               ext4_fill_fsxattr(inode, &fa);
 
                if (copy_to_user((struct fsxattr __user *)arg,
                                 &fa, sizeof(fa)))
@@ -1154,7 +1128,7 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
        }
        case EXT4_IOC_FSSETXATTR:
        {
-               struct fsxattr fa;
+               struct fsxattr fa, old_fa;
                int err;
 
                if (copy_from_user(&fa, (struct fsxattr __user *)arg,
@@ -1177,7 +1151,8 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                        return err;
 
                inode_lock(inode);
-               err = ext4_ioctl_check_project(inode, &fa);
+               ext4_fill_fsxattr(inode, &old_fa);
+               err = vfs_ioc_fssetxattr_check(inode, &old_fa, &fa);
                if (err)
                        goto out;
                flags = (ei->i_flags & ~EXT4_FL_XFLAG_VISIBLE) |