diff options
-rw-r--r-- | fs/inode.c | 65 | ||||
-rw-r--r-- | mm/filemap.c | 65 |
2 files changed, 65 insertions, 65 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 |
diff --git a/mm/filemap.c b/mm/filemap.c index 79c4b2b0b14e..21e5abfbcdf6 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
@@ -1938,71 +1938,6 @@ struct page *read_cache_page(struct address_space *mapping, | |||
1938 | } | 1938 | } |
1939 | EXPORT_SYMBOL(read_cache_page); | 1939 | EXPORT_SYMBOL(read_cache_page); |
1940 | 1940 | ||
1941 | /* | ||
1942 | * The logic we want is | ||
1943 | * | ||
1944 | * if suid or (sgid and xgrp) | ||
1945 | * remove privs | ||
1946 | */ | ||
1947 | int should_remove_suid(struct dentry *dentry) | ||
1948 | { | ||
1949 | umode_t mode = dentry->d_inode->i_mode; | ||
1950 | int kill = 0; | ||
1951 | |||
1952 | /* suid always must be killed */ | ||
1953 | if (unlikely(mode & S_ISUID)) | ||
1954 | kill = ATTR_KILL_SUID; | ||
1955 | |||
1956 | /* | ||
1957 | * sgid without any exec bits is just a mandatory locking mark; leave | ||
1958 | * it alone. If some exec bits are set, it's a real sgid; kill it. | ||
1959 | */ | ||
1960 | if (unlikely((mode & S_ISGID) && (mode & S_IXGRP))) | ||
1961 | kill |= ATTR_KILL_SGID; | ||
1962 | |||
1963 | if (unlikely(kill && !capable(CAP_FSETID) && S_ISREG(mode))) | ||
1964 | return kill; | ||
1965 | |||
1966 | return 0; | ||
1967 | } | ||
1968 | EXPORT_SYMBOL(should_remove_suid); | ||
1969 | |||
1970 | static int __remove_suid(struct dentry *dentry, int kill) | ||
1971 | { | ||
1972 | struct iattr newattrs; | ||
1973 | |||
1974 | newattrs.ia_valid = ATTR_FORCE | kill; | ||
1975 | return notify_change(dentry, &newattrs); | ||
1976 | } | ||
1977 | |||
1978 | int file_remove_suid(struct file *file) | ||
1979 | { | ||
1980 | struct dentry *dentry = file->f_path.dentry; | ||
1981 | struct inode *inode = dentry->d_inode; | ||
1982 | int killsuid; | ||
1983 | int killpriv; | ||
1984 | int error = 0; | ||
1985 | |||
1986 | /* Fast path for nothing security related */ | ||
1987 | if (IS_NOSEC(inode)) | ||
1988 | return 0; | ||
1989 | |||
1990 | killsuid = should_remove_suid(dentry); | ||
1991 | killpriv = security_inode_need_killpriv(dentry); | ||
1992 | |||
1993 | if (killpriv < 0) | ||
1994 | return killpriv; | ||
1995 | if (killpriv) | ||
1996 | error = security_inode_killpriv(dentry); | ||
1997 | if (!error && killsuid) | ||
1998 | error = __remove_suid(dentry, killsuid); | ||
1999 | if (!error && (inode->i_sb->s_flags & MS_NOSEC)) | ||
2000 | inode->i_flags |= S_NOSEC; | ||
2001 | |||
2002 | return error; | ||
2003 | } | ||
2004 | EXPORT_SYMBOL(file_remove_suid); | ||
2005 | |||
2006 | static size_t __iovec_copy_from_user_inatomic(char *vaddr, | 1941 | static size_t __iovec_copy_from_user_inatomic(char *vaddr, |
2007 | const struct iovec *iov, size_t base, size_t bytes) | 1942 | const struct iovec *iov, size_t base, size_t bytes) |
2008 | { | 1943 | { |