]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
fs: Call security_ops->inode_killpriv on truncate
authorJan Kara <jack@suse.cz>
Thu, 21 May 2015 14:05:55 +0000 (16:05 +0200)
committerChuck Anderson <chuck.anderson@oracle.com>
Mon, 29 May 2017 00:52:37 +0000 (17:52 -0700)
From 45f147a1bc97c743c6101a8d2741c69a51f583e4 Mon Sep 17 00:00:00 2001

Comment in include/linux/security.h says that ->inode_killpriv() should
be called when setuid bit is being removed and that similar security
labels (in fact this applies only to file capabilities) should be
removed at this time as well. However we don't call ->inode_killpriv()
when we remove suid bit on truncate.

We fix the problem by calling ->inode_need_killpriv() and subsequently
->inode_killpriv() on truncate the same way as we do it on file write.

After this patch there's only one user of should_remove_suid() - ocfs2 -
and indeed it's buggy because it doesn't call ->inode_killpriv() on
write. However fixing it is difficult because of special locking
constraints.

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
fs/open.c
include/linux/fs.h

index 620cb7686242fd2e3182cc9f4e446b0b8088d351..36982d74e967d8c943be10f82ac89c51500b0a6e 100644 (file)
@@ -1665,9 +1665,8 @@ EXPORT_SYMBOL(should_remove_suid);
  * 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)
+int dentry_needs_remove_privs(struct dentry *dentry)
 {
-       struct dentry *dentry = file->f_path.dentry;
        struct inode *inode = d_inode(dentry);
        int mask = 0;
        int ret;
@@ -1683,7 +1682,7 @@ int file_needs_remove_privs(struct file *file)
                mask |= ATTR_KILL_PRIV;
        return mask;
 }
-EXPORT_SYMBOL(file_needs_remove_privs);
+EXPORT_SYMBOL(dentry_needs_remove_privs);
 
 static int __remove_privs(struct dentry *dentry, int kill)
 {
index 301c4a24c43fb0bc25252e48a2ad96358bc28568..7bab5a4bb7b01dc395c7fe8d2f675469f648a317 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -51,8 +51,10 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
                newattrs.ia_valid |= ATTR_FILE;
        }
 
-       /* Remove suid/sgid on truncate too */
-       ret = should_remove_suid(dentry);
+       /* Remove suid, sgid, and file capabilities on truncate too */
+       ret = dentry_needs_remove_privs(dentry);
+       if (ret < 0)
+               return ret;
        if (ret)
                newattrs.ia_valid |= ret | ATTR_FORCE;
 
index 99ff8cfcfb5b0db940a89466b2c8e7cb83a845f7..85dc463cc8a4cc8368ed8d650043c2919d013d32 100644 (file)
@@ -2569,7 +2569,11 @@ 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 int dentry_needs_remove_privs(struct dentry *dentry);
+static inline int file_needs_remove_privs(struct file *file)
+{
+       return dentry_needs_remove_privs(file->f_path.dentry);
+}
 
 extern void __insert_inode_hash(struct inode *, unsigned long hashval);
 static inline void insert_inode_hash(struct inode *inode)