diff options
Diffstat (limited to 'fs/proc/base.c')
-rw-r--r-- | fs/proc/base.c | 102 |
1 files changed, 58 insertions, 44 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c index 8e7e61b28f31..ad98d883847a 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -1667,12 +1667,63 @@ const struct inode_operations proc_pid_link_inode_operations = { | |||
1667 | 1667 | ||
1668 | /* building an inode */ | 1668 | /* building an inode */ |
1669 | 1669 | ||
1670 | void task_dump_owner(struct task_struct *task, mode_t mode, | ||
1671 | kuid_t *ruid, kgid_t *rgid) | ||
1672 | { | ||
1673 | /* Depending on the state of dumpable compute who should own a | ||
1674 | * proc file for a task. | ||
1675 | */ | ||
1676 | const struct cred *cred; | ||
1677 | kuid_t uid; | ||
1678 | kgid_t gid; | ||
1679 | |||
1680 | /* Default to the tasks effective ownership */ | ||
1681 | rcu_read_lock(); | ||
1682 | cred = __task_cred(task); | ||
1683 | uid = cred->euid; | ||
1684 | gid = cred->egid; | ||
1685 | rcu_read_unlock(); | ||
1686 | |||
1687 | /* | ||
1688 | * Before the /proc/pid/status file was created the only way to read | ||
1689 | * the effective uid of a /process was to stat /proc/pid. Reading | ||
1690 | * /proc/pid/status is slow enough that procps and other packages | ||
1691 | * kept stating /proc/pid. To keep the rules in /proc simple I have | ||
1692 | * made this apply to all per process world readable and executable | ||
1693 | * directories. | ||
1694 | */ | ||
1695 | if (mode != (S_IFDIR|S_IRUGO|S_IXUGO)) { | ||
1696 | struct mm_struct *mm; | ||
1697 | task_lock(task); | ||
1698 | mm = task->mm; | ||
1699 | /* Make non-dumpable tasks owned by some root */ | ||
1700 | if (mm) { | ||
1701 | if (get_dumpable(mm) != SUID_DUMP_USER) { | ||
1702 | struct user_namespace *user_ns = mm->user_ns; | ||
1703 | |||
1704 | uid = make_kuid(user_ns, 0); | ||
1705 | if (!uid_valid(uid)) | ||
1706 | uid = GLOBAL_ROOT_UID; | ||
1707 | |||
1708 | gid = make_kgid(user_ns, 0); | ||
1709 | if (!gid_valid(gid)) | ||
1710 | gid = GLOBAL_ROOT_GID; | ||
1711 | } | ||
1712 | } else { | ||
1713 | uid = GLOBAL_ROOT_UID; | ||
1714 | gid = GLOBAL_ROOT_GID; | ||
1715 | } | ||
1716 | task_unlock(task); | ||
1717 | } | ||
1718 | *ruid = uid; | ||
1719 | *rgid = gid; | ||
1720 | } | ||
1721 | |||
1670 | struct inode *proc_pid_make_inode(struct super_block * sb, | 1722 | struct inode *proc_pid_make_inode(struct super_block * sb, |
1671 | struct task_struct *task, umode_t mode) | 1723 | struct task_struct *task, umode_t mode) |
1672 | { | 1724 | { |
1673 | struct inode * inode; | 1725 | struct inode * inode; |
1674 | struct proc_inode *ei; | 1726 | struct proc_inode *ei; |
1675 | const struct cred *cred; | ||
1676 | 1727 | ||
1677 | /* We need a new inode */ | 1728 | /* We need a new inode */ |
1678 | 1729 | ||
@@ -1694,13 +1745,7 @@ struct inode *proc_pid_make_inode(struct super_block * sb, | |||
1694 | if (!ei->pid) | 1745 | if (!ei->pid) |
1695 | goto out_unlock; | 1746 | goto out_unlock; |
1696 | 1747 | ||
1697 | if (task_dumpable(task)) { | 1748 | task_dump_owner(task, 0, &inode->i_uid, &inode->i_gid); |
1698 | rcu_read_lock(); | ||
1699 | cred = __task_cred(task); | ||
1700 | inode->i_uid = cred->euid; | ||
1701 | inode->i_gid = cred->egid; | ||
1702 | rcu_read_unlock(); | ||
1703 | } | ||
1704 | security_task_to_inode(task, inode); | 1749 | security_task_to_inode(task, inode); |
1705 | 1750 | ||
1706 | out: | 1751 | out: |
@@ -1715,7 +1760,6 @@ int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | |||
1715 | { | 1760 | { |
1716 | struct inode *inode = d_inode(dentry); | 1761 | struct inode *inode = d_inode(dentry); |
1717 | struct task_struct *task; | 1762 | struct task_struct *task; |
1718 | const struct cred *cred; | ||
1719 | struct pid_namespace *pid = dentry->d_sb->s_fs_info; | 1763 | struct pid_namespace *pid = dentry->d_sb->s_fs_info; |
1720 | 1764 | ||
1721 | generic_fillattr(inode, stat); | 1765 | generic_fillattr(inode, stat); |
@@ -1733,12 +1777,7 @@ int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | |||
1733 | */ | 1777 | */ |
1734 | return -ENOENT; | 1778 | return -ENOENT; |
1735 | } | 1779 | } |
1736 | if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) || | 1780 | task_dump_owner(task, inode->i_mode, &stat->uid, &stat->gid); |
1737 | task_dumpable(task)) { | ||
1738 | cred = __task_cred(task); | ||
1739 | stat->uid = cred->euid; | ||
1740 | stat->gid = cred->egid; | ||
1741 | } | ||
1742 | } | 1781 | } |
1743 | rcu_read_unlock(); | 1782 | rcu_read_unlock(); |
1744 | return 0; | 1783 | return 0; |
@@ -1754,18 +1793,11 @@ int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | |||
1754 | * Rewrite the inode's ownerships here because the owning task may have | 1793 | * Rewrite the inode's ownerships here because the owning task may have |
1755 | * performed a setuid(), etc. | 1794 | * performed a setuid(), etc. |
1756 | * | 1795 | * |
1757 | * Before the /proc/pid/status file was created the only way to read | ||
1758 | * the effective uid of a /process was to stat /proc/pid. Reading | ||
1759 | * /proc/pid/status is slow enough that procps and other packages | ||
1760 | * kept stating /proc/pid. To keep the rules in /proc simple I have | ||
1761 | * made this apply to all per process world readable and executable | ||
1762 | * directories. | ||
1763 | */ | 1796 | */ |
1764 | int pid_revalidate(struct dentry *dentry, unsigned int flags) | 1797 | int pid_revalidate(struct dentry *dentry, unsigned int flags) |
1765 | { | 1798 | { |
1766 | struct inode *inode; | 1799 | struct inode *inode; |
1767 | struct task_struct *task; | 1800 | struct task_struct *task; |
1768 | const struct cred *cred; | ||
1769 | 1801 | ||
1770 | if (flags & LOOKUP_RCU) | 1802 | if (flags & LOOKUP_RCU) |
1771 | return -ECHILD; | 1803 | return -ECHILD; |
@@ -1774,17 +1806,8 @@ int pid_revalidate(struct dentry *dentry, unsigned int flags) | |||
1774 | task = get_proc_task(inode); | 1806 | task = get_proc_task(inode); |
1775 | 1807 | ||
1776 | if (task) { | 1808 | if (task) { |
1777 | if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) || | 1809 | task_dump_owner(task, inode->i_mode, &inode->i_uid, &inode->i_gid); |
1778 | task_dumpable(task)) { | 1810 | |
1779 | rcu_read_lock(); | ||
1780 | cred = __task_cred(task); | ||
1781 | inode->i_uid = cred->euid; | ||
1782 | inode->i_gid = cred->egid; | ||
1783 | rcu_read_unlock(); | ||
1784 | } else { | ||
1785 | inode->i_uid = GLOBAL_ROOT_UID; | ||
1786 | inode->i_gid = GLOBAL_ROOT_GID; | ||
1787 | } | ||
1788 | inode->i_mode &= ~(S_ISUID | S_ISGID); | 1811 | inode->i_mode &= ~(S_ISUID | S_ISGID); |
1789 | security_task_to_inode(task, inode); | 1812 | security_task_to_inode(task, inode); |
1790 | put_task_struct(task); | 1813 | put_task_struct(task); |
@@ -1881,7 +1904,6 @@ static int map_files_d_revalidate(struct dentry *dentry, unsigned int flags) | |||
1881 | bool exact_vma_exists = false; | 1904 | bool exact_vma_exists = false; |
1882 | struct mm_struct *mm = NULL; | 1905 | struct mm_struct *mm = NULL; |
1883 | struct task_struct *task; | 1906 | struct task_struct *task; |
1884 | const struct cred *cred; | ||
1885 | struct inode *inode; | 1907 | struct inode *inode; |
1886 | int status = 0; | 1908 | int status = 0; |
1887 | 1909 | ||
@@ -1906,16 +1928,8 @@ static int map_files_d_revalidate(struct dentry *dentry, unsigned int flags) | |||
1906 | mmput(mm); | 1928 | mmput(mm); |
1907 | 1929 | ||
1908 | if (exact_vma_exists) { | 1930 | if (exact_vma_exists) { |
1909 | if (task_dumpable(task)) { | 1931 | task_dump_owner(task, 0, &inode->i_uid, &inode->i_gid); |
1910 | rcu_read_lock(); | 1932 | |
1911 | cred = __task_cred(task); | ||
1912 | inode->i_uid = cred->euid; | ||
1913 | inode->i_gid = cred->egid; | ||
1914 | rcu_read_unlock(); | ||
1915 | } else { | ||
1916 | inode->i_uid = GLOBAL_ROOT_UID; | ||
1917 | inode->i_gid = GLOBAL_ROOT_GID; | ||
1918 | } | ||
1919 | security_task_to_inode(task, inode); | 1933 | security_task_to_inode(task, inode); |
1920 | status = 1; | 1934 | status = 1; |
1921 | } | 1935 | } |