aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorCong Wang <xiyou.wangcong@gmail.com>2012-05-15 02:57:33 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2012-05-30 21:04:52 -0400
commit3ed37648e1cbf1bbebc200c6ea8fd8daf8325843 (patch)
tree60f27fc77a1e5c9c48790243266367318a3267dc /fs
parent8bdc81c5069e43755d6e59e5e990e21ca200e8e2 (diff)
fs: move file_remove_suid() to fs/inode.c
file_remove_suid() is a generic function operates on struct file, it almost has no relations with file mapping, so move it to fs/inode.c. Cc: Alexander Viro <viro@zeniv.linux.org.uk> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs')
-rw-r--r--fs/inode.c65
1 files changed, 65 insertions, 0 deletions
diff --git a/fs/inode.c b/fs/inode.c
index 183ddd6cda71..a79555e492e0 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -1530,6 +1530,71 @@ void touch_atime(struct path *path)
1530} 1530}
1531EXPORT_SYMBOL(touch_atime); 1531EXPORT_SYMBOL(touch_atime);
1532 1532
1533/*
1534 * The logic we want is
1535 *
1536 * if suid or (sgid and xgrp)
1537 * remove privs
1538 */
1539int should_remove_suid(struct dentry *dentry)
1540{
1541 umode_t mode = dentry->d_inode->i_mode;
1542 int kill = 0;
1543
1544 /* suid always must be killed */
1545 if (unlikely(mode & S_ISUID))
1546 kill = ATTR_KILL_SUID;
1547
1548 /*
1549 * sgid without any exec bits is just a mandatory locking mark; leave
1550 * it alone. If some exec bits are set, it's a real sgid; kill it.
1551 */
1552 if (unlikely((mode & S_ISGID) && (mode & S_IXGRP)))
1553 kill |= ATTR_KILL_SGID;
1554
1555 if (unlikely(kill && !capable(CAP_FSETID) && S_ISREG(mode)))
1556 return kill;
1557
1558 return 0;
1559}
1560EXPORT_SYMBOL(should_remove_suid);
1561
1562static int __remove_suid(struct dentry *dentry, int kill)
1563{
1564 struct iattr newattrs;
1565
1566 newattrs.ia_valid = ATTR_FORCE | kill;
1567 return notify_change(dentry, &newattrs);
1568}
1569
1570int file_remove_suid(struct file *file)
1571{
1572 struct dentry *dentry = file->f_path.dentry;
1573 struct inode *inode = dentry->d_inode;
1574 int killsuid;
1575 int killpriv;
1576 int error = 0;
1577
1578 /* Fast path for nothing security related */
1579 if (IS_NOSEC(inode))
1580 return 0;
1581
1582 killsuid = should_remove_suid(dentry);
1583 killpriv = security_inode_need_killpriv(dentry);
1584
1585 if (killpriv < 0)
1586 return killpriv;
1587 if (killpriv)
1588 error = security_inode_killpriv(dentry);
1589 if (!error && killsuid)
1590 error = __remove_suid(dentry, killsuid);
1591 if (!error && (inode->i_sb->s_flags & MS_NOSEC))
1592 inode->i_flags |= S_NOSEC;
1593
1594 return error;
1595}
1596EXPORT_SYMBOL(file_remove_suid);
1597
1533/** 1598/**
1534 * file_update_time - update mtime and ctime time 1599 * file_update_time - update mtime and ctime time
1535 * @file: file accessed 1600 * @file: file accessed