]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
fs: Provide function telling whether file_remove_privs() will do anything
authorJan Kara <jack@suse.cz>
Thu, 21 May 2015 14:05:54 +0000 (16:05 +0200)
committerChuck Anderson <chuck.anderson@oracle.com>
Mon, 29 May 2017 00:52:20 +0000 (17:52 -0700)
From dbfae0cdcd87602737101d4417811f4323156b54 Mon Sep 17 00:00:00 2001

Provide function telling whether file_remove_privs() will do anything.
Currently we only have should_remove_suid() and that does something
slightly different.

Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Orabug: 24803533
Signed-off-by: darrick.wong@oracle.com
fs/inode.c
include/linux/fs.h

index 48313a1444fbe90ac9df51c5f5411514861fa4b1..620cb7686242fd2e3182cc9f4e446b0b8088d351 100644 (file)
@@ -1660,7 +1660,32 @@ int should_remove_suid(struct dentry *dentry)
 }
 EXPORT_SYMBOL(should_remove_suid);
 
-static int __remove_suid(struct dentry *dentry, int kill)
+/*
+ * Return mask of changes for notify_change() that need to be done as a
+ * response to write or truncate. Return 0 if nothing has to be changed.
+ * Negative value on error (change should be denied).
+ */
+int file_needs_remove_privs(struct file *file)
+{
+       struct dentry *dentry = file->f_path.dentry;
+       struct inode *inode = d_inode(dentry);
+       int mask = 0;
+       int ret;
+
+       if (IS_NOSEC(inode))
+               return 0;
+
+       mask = should_remove_suid(dentry);
+       ret = security_inode_need_killpriv(dentry);
+       if (ret < 0)
+               return ret;
+       if (ret)
+               mask |= ATTR_KILL_PRIV;
+       return mask;
+}
+EXPORT_SYMBOL(file_needs_remove_privs);
+
+static int __remove_privs(struct dentry *dentry, int kill)
 {
        struct iattr newattrs;
 
@@ -1680,23 +1705,18 @@ int file_remove_privs(struct file *file)
 {
        struct dentry *dentry = file->f_path.dentry;
        struct inode *inode = d_inode(dentry);
-       int killsuid;
-       int killpriv;
+       int kill;
        int error = 0;
 
        /* Fast path for nothing security related */
        if (IS_NOSEC(inode))
                return 0;
 
-       killsuid = should_remove_suid(dentry);
-       killpriv = security_inode_need_killpriv(dentry);
-
-       if (killpriv < 0)
-               return killpriv;
-       if (killpriv)
-               error = security_inode_killpriv(dentry);
-       if (!error && killsuid)
-               error = __remove_suid(dentry, killsuid);
+       kill = file_needs_remove_privs(file);
+       if (kill < 0)
+               return kill;
+       if (kill)
+               error = __remove_privs(dentry, kill);
        if (!error)
                inode_has_no_xattr(inode);
 
index 1e2f50b7ff169a7c40ae50788a9bd9db26d0ef1f..99ff8cfcfb5b0db940a89466b2c8e7cb83a845f7 100644 (file)
@@ -2569,6 +2569,7 @@ extern struct inode *new_inode(struct super_block *sb);
 extern void free_inode_nonrcu(struct inode *inode);
 extern int should_remove_suid(struct dentry *);
 extern int file_remove_privs(struct file *);
+extern int file_needs_remove_privs(struct file *file);
 
 extern void __insert_inode_hash(struct inode *, unsigned long hashval);
 static inline void insert_inode_hash(struct inode *inode)