diff options
author | Cong Wang <xiyou.wangcong@gmail.com> | 2012-05-15 02:57:33 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-05-30 21:04:52 -0400 |
commit | 3ed37648e1cbf1bbebc200c6ea8fd8daf8325843 (patch) | |
tree | 60f27fc77a1e5c9c48790243266367318a3267dc /fs | |
parent | 8bdc81c5069e43755d6e59e5e990e21ca200e8e2 (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.c | 65 |
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 | } |
1531 | EXPORT_SYMBOL(touch_atime); | 1531 | EXPORT_SYMBOL(touch_atime); |
1532 | 1532 | ||
1533 | /* | ||
1534 | * The logic we want is | ||
1535 | * | ||
1536 | * if suid or (sgid and xgrp) | ||
1537 | * remove privs | ||
1538 | */ | ||
1539 | int 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 | } | ||
1560 | EXPORT_SYMBOL(should_remove_suid); | ||
1561 | |||
1562 | static 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 | |||
1570 | int 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 | } | ||
1596 | EXPORT_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 |