diff options
Diffstat (limited to 'fs/inode.c')
-rw-r--r-- | fs/inode.c | 66 |
1 files changed, 46 insertions, 20 deletions
diff --git a/fs/inode.c b/fs/inode.c index 069721f0cc0e..d30640f7a193 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
@@ -841,7 +841,11 @@ unsigned int get_next_ino(void) | |||
841 | } | 841 | } |
842 | #endif | 842 | #endif |
843 | 843 | ||
844 | *p = ++res; | 844 | res++; |
845 | /* get_next_ino should not provide a 0 inode number */ | ||
846 | if (unlikely(!res)) | ||
847 | res++; | ||
848 | *p = res; | ||
845 | put_cpu_var(last_ino); | 849 | put_cpu_var(last_ino); |
846 | return res; | 850 | return res; |
847 | } | 851 | } |
@@ -1674,7 +1678,31 @@ int should_remove_suid(struct dentry *dentry) | |||
1674 | } | 1678 | } |
1675 | EXPORT_SYMBOL(should_remove_suid); | 1679 | EXPORT_SYMBOL(should_remove_suid); |
1676 | 1680 | ||
1677 | static int __remove_suid(struct dentry *dentry, int kill) | 1681 | /* |
1682 | * Return mask of changes for notify_change() that need to be done as a | ||
1683 | * response to write or truncate. Return 0 if nothing has to be changed. | ||
1684 | * Negative value on error (change should be denied). | ||
1685 | */ | ||
1686 | int dentry_needs_remove_privs(struct dentry *dentry) | ||
1687 | { | ||
1688 | struct inode *inode = d_inode(dentry); | ||
1689 | int mask = 0; | ||
1690 | int ret; | ||
1691 | |||
1692 | if (IS_NOSEC(inode)) | ||
1693 | return 0; | ||
1694 | |||
1695 | mask = should_remove_suid(dentry); | ||
1696 | ret = security_inode_need_killpriv(dentry); | ||
1697 | if (ret < 0) | ||
1698 | return ret; | ||
1699 | if (ret) | ||
1700 | mask |= ATTR_KILL_PRIV; | ||
1701 | return mask; | ||
1702 | } | ||
1703 | EXPORT_SYMBOL(dentry_needs_remove_privs); | ||
1704 | |||
1705 | static int __remove_privs(struct dentry *dentry, int kill) | ||
1678 | { | 1706 | { |
1679 | struct iattr newattrs; | 1707 | struct iattr newattrs; |
1680 | 1708 | ||
@@ -1686,33 +1714,32 @@ static int __remove_suid(struct dentry *dentry, int kill) | |||
1686 | return notify_change(dentry, &newattrs, NULL); | 1714 | return notify_change(dentry, &newattrs, NULL); |
1687 | } | 1715 | } |
1688 | 1716 | ||
1689 | int file_remove_suid(struct file *file) | 1717 | /* |
1718 | * Remove special file priviledges (suid, capabilities) when file is written | ||
1719 | * to or truncated. | ||
1720 | */ | ||
1721 | int file_remove_privs(struct file *file) | ||
1690 | { | 1722 | { |
1691 | struct dentry *dentry = file->f_path.dentry; | 1723 | struct dentry *dentry = file->f_path.dentry; |
1692 | struct inode *inode = d_inode(dentry); | 1724 | struct inode *inode = d_inode(dentry); |
1693 | int killsuid; | 1725 | int kill; |
1694 | int killpriv; | ||
1695 | int error = 0; | 1726 | int error = 0; |
1696 | 1727 | ||
1697 | /* Fast path for nothing security related */ | 1728 | /* Fast path for nothing security related */ |
1698 | if (IS_NOSEC(inode)) | 1729 | if (IS_NOSEC(inode)) |
1699 | return 0; | 1730 | return 0; |
1700 | 1731 | ||
1701 | killsuid = should_remove_suid(dentry); | 1732 | kill = file_needs_remove_privs(file); |
1702 | killpriv = security_inode_need_killpriv(dentry); | 1733 | if (kill < 0) |
1703 | 1734 | return kill; | |
1704 | if (killpriv < 0) | 1735 | if (kill) |
1705 | return killpriv; | 1736 | error = __remove_privs(dentry, kill); |
1706 | if (killpriv) | 1737 | if (!error) |
1707 | error = security_inode_killpriv(dentry); | 1738 | inode_has_no_xattr(inode); |
1708 | if (!error && killsuid) | ||
1709 | error = __remove_suid(dentry, killsuid); | ||
1710 | if (!error && (inode->i_sb->s_flags & MS_NOSEC)) | ||
1711 | inode->i_flags |= S_NOSEC; | ||
1712 | 1739 | ||
1713 | return error; | 1740 | return error; |
1714 | } | 1741 | } |
1715 | EXPORT_SYMBOL(file_remove_suid); | 1742 | EXPORT_SYMBOL(file_remove_privs); |
1716 | 1743 | ||
1717 | /** | 1744 | /** |
1718 | * file_update_time - update mtime and ctime time | 1745 | * file_update_time - update mtime and ctime time |
@@ -1967,9 +1994,8 @@ EXPORT_SYMBOL(inode_dio_wait); | |||
1967 | * inode is being instantiated). The reason for the cmpxchg() loop | 1994 | * inode is being instantiated). The reason for the cmpxchg() loop |
1968 | * --- which wouldn't be necessary if all code paths which modify | 1995 | * --- which wouldn't be necessary if all code paths which modify |
1969 | * i_flags actually followed this rule, is that there is at least one | 1996 | * i_flags actually followed this rule, is that there is at least one |
1970 | * code path which doesn't today --- for example, | 1997 | * code path which doesn't today so we use cmpxchg() out of an abundance |
1971 | * __generic_file_aio_write() calls file_remove_suid() without holding | 1998 | * of caution. |
1972 | * i_mutex --- so we use cmpxchg() out of an abundance of caution. | ||
1973 | * | 1999 | * |
1974 | * In the long run, i_mutex is overkill, and we should probably look | 2000 | * In the long run, i_mutex is overkill, and we should probably look |
1975 | * at using the i_lock spinlock to protect i_flags, and then make sure | 2001 | * at using the i_lock spinlock to protect i_flags, and then make sure |