aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2015-05-21 10:05:54 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2015-06-23 18:01:09 -0400
commitdbfae0cdcd87602737101d4417811f4323156b54 (patch)
treebe947840a5adb296619ebd75898740de16ded617
parent5fa8e0a1c6a762857ae67d1628c58b9a02362003 (diff)
fs: Provide function telling whether file_remove_privs() will do anything
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>
-rw-r--r--fs/inode.c44
-rw-r--r--include/linux/fs.h1
2 files changed, 33 insertions, 12 deletions
diff --git a/fs/inode.c b/fs/inode.c
index 849210c155dc..8c2dd74455c9 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -1673,7 +1673,32 @@ int should_remove_suid(struct dentry *dentry)
1673} 1673}
1674EXPORT_SYMBOL(should_remove_suid); 1674EXPORT_SYMBOL(should_remove_suid);
1675 1675
1676static int __remove_suid(struct dentry *dentry, int kill) 1676/*
1677 * Return mask of changes for notify_change() that need to be done as a
1678 * response to write or truncate. Return 0 if nothing has to be changed.
1679 * Negative value on error (change should be denied).
1680 */
1681int file_needs_remove_privs(struct file *file)
1682{
1683 struct dentry *dentry = file->f_path.dentry;
1684 struct inode *inode = d_inode(dentry);
1685 int mask = 0;
1686 int ret;
1687
1688 if (IS_NOSEC(inode))
1689 return 0;
1690
1691 mask = should_remove_suid(dentry);
1692 ret = security_inode_need_killpriv(dentry);
1693 if (ret < 0)
1694 return ret;
1695 if (ret)
1696 mask |= ATTR_KILL_PRIV;
1697 return mask;
1698}
1699EXPORT_SYMBOL(file_needs_remove_privs);
1700
1701static int __remove_privs(struct dentry *dentry, int kill)
1677{ 1702{
1678 struct iattr newattrs; 1703 struct iattr newattrs;
1679 1704
@@ -1693,23 +1718,18 @@ int file_remove_privs(struct file *file)
1693{ 1718{
1694 struct dentry *dentry = file->f_path.dentry; 1719 struct dentry *dentry = file->f_path.dentry;
1695 struct inode *inode = d_inode(dentry); 1720 struct inode *inode = d_inode(dentry);
1696 int killsuid; 1721 int kill;
1697 int killpriv;
1698 int error = 0; 1722 int error = 0;
1699 1723
1700 /* Fast path for nothing security related */ 1724 /* Fast path for nothing security related */
1701 if (IS_NOSEC(inode)) 1725 if (IS_NOSEC(inode))
1702 return 0; 1726 return 0;
1703 1727
1704 killsuid = should_remove_suid(dentry); 1728 kill = file_needs_remove_privs(file);
1705 killpriv = security_inode_need_killpriv(dentry); 1729 if (kill < 0)
1706 1730 return kill;
1707 if (killpriv < 0) 1731 if (kill)
1708 return killpriv; 1732 error = __remove_privs(dentry, kill);
1709 if (killpriv)
1710 error = security_inode_killpriv(dentry);
1711 if (!error && killsuid)
1712 error = __remove_suid(dentry, killsuid);
1713 if (!error) 1733 if (!error)
1714 inode_has_no_xattr(inode); 1734 inode_has_no_xattr(inode);
1715 1735
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 641e68d850cf..ee60e8ab210f 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2554,6 +2554,7 @@ extern struct inode *new_inode(struct super_block *sb);
2554extern void free_inode_nonrcu(struct inode *inode); 2554extern void free_inode_nonrcu(struct inode *inode);
2555extern int should_remove_suid(struct dentry *); 2555extern int should_remove_suid(struct dentry *);
2556extern int file_remove_privs(struct file *); 2556extern int file_remove_privs(struct file *);
2557extern int file_needs_remove_privs(struct file *file);
2557 2558
2558extern void __insert_inode_hash(struct inode *, unsigned long hashval); 2559extern void __insert_inode_hash(struct inode *, unsigned long hashval);
2559static inline void insert_inode_hash(struct inode *inode) 2560static inline void insert_inode_hash(struct inode *inode)