Merge branch 'for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/paulmck...
[linux-2.6-microblaze.git] / fs / inode.c
index 2bf21e2..0f1e3b5 100644 (file)
@@ -1899,6 +1899,26 @@ int file_update_time(struct file *file)
 }
 EXPORT_SYMBOL(file_update_time);
 
+/* Caller must hold the file's inode lock */
+int file_modified(struct file *file)
+{
+       int err;
+
+       /*
+        * Clear the security bits if the process is not being run by root.
+        * This keeps people from modifying setuid and setgid binaries.
+        */
+       err = file_remove_privs(file);
+       if (err)
+               return err;
+
+       if (unlikely(file->f_mode & FMODE_NOCMTIME))
+               return 0;
+
+       return file_update_time(file);
+}
+EXPORT_SYMBOL(file_modified);
+
 int inode_needs_sync(struct inode *inode)
 {
        if (IS_SYNC(inode))
@@ -2170,3 +2190,89 @@ struct timespec64 current_time(struct inode *inode)
        return timespec64_trunc(now, inode->i_sb->s_time_gran);
 }
 EXPORT_SYMBOL(current_time);
+
+/*
+ * Generic function to check FS_IOC_SETFLAGS values and reject any invalid
+ * configurations.
+ *
+ * Note: the caller should be holding i_mutex, or else be sure that they have
+ * exclusive access to the inode structure.
+ */
+int vfs_ioc_setflags_prepare(struct inode *inode, unsigned int oldflags,
+                            unsigned int flags)
+{
+       /*
+        * 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) & (FS_APPEND_FL | FS_IMMUTABLE_FL) &&
+           !capable(CAP_LINUX_IMMUTABLE))
+               return -EPERM;
+
+       return 0;
+}
+EXPORT_SYMBOL(vfs_ioc_setflags_prepare);
+
+/*
+ * Generic function to check FS_IOC_FSSETXATTR values and reject any invalid
+ * configurations.
+ *
+ * Note: the caller should be holding i_mutex, or else be sure that they have
+ * exclusive access to the inode structure.
+ */
+int vfs_ioc_fssetxattr_check(struct inode *inode, const struct fsxattr *old_fa,
+                            struct fsxattr *fa)
+{
+       /*
+        * Can't modify an immutable/append-only file unless we have
+        * appropriate permission.
+        */
+       if ((old_fa->fsx_xflags ^ fa->fsx_xflags) &
+                       (FS_XFLAG_IMMUTABLE | FS_XFLAG_APPEND) &&
+           !capable(CAP_LINUX_IMMUTABLE))
+               return -EPERM;
+
+       /*
+        * 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) {
+               if (old_fa->fsx_projid != fa->fsx_projid)
+                       return -EINVAL;
+               if ((old_fa->fsx_xflags ^ fa->fsx_xflags) &
+                               FS_XFLAG_PROJINHERIT)
+                       return -EINVAL;
+       }
+
+       /* Check extent size hints. */
+       if ((fa->fsx_xflags & FS_XFLAG_EXTSIZE) && !S_ISREG(inode->i_mode))
+               return -EINVAL;
+
+       if ((fa->fsx_xflags & FS_XFLAG_EXTSZINHERIT) &&
+                       !S_ISDIR(inode->i_mode))
+               return -EINVAL;
+
+       if ((fa->fsx_xflags & FS_XFLAG_COWEXTSIZE) &&
+           !S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode))
+               return -EINVAL;
+
+       /*
+        * It is only valid to set the DAX flag on regular files and
+        * directories on filesystems.
+        */
+       if ((fa->fsx_xflags & FS_XFLAG_DAX) &&
+           !(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)))
+               return -EINVAL;
+
+       /* Extent size hints of zero turn off the flags. */
+       if (fa->fsx_extsize == 0)
+               fa->fsx_xflags &= ~(FS_XFLAG_EXTSIZE | FS_XFLAG_EXTSZINHERIT);
+       if (fa->fsx_cowextsize == 0)
+               fa->fsx_xflags &= ~FS_XFLAG_COWEXTSIZE;
+
+       return 0;
+}
+EXPORT_SYMBOL(vfs_ioc_fssetxattr_check);