Skip to content

Commit 68eb94f

Browse files
committed
proc: Better ownership of files for non-dumpable tasks in user namespaces
Instead of making the files owned by the GLOBAL_ROOT_USER. Make non-dumpable files whose mm has always lived in a user namespace owned by the user namespace root. This allows the container root to have things work as expected in a container. Signed-off-by: "Eric W. Biederman" <[email protected]>
1 parent 9227dd2 commit 68eb94f

File tree

3 files changed

+61
-69
lines changed

3 files changed

+61
-69
lines changed

fs/proc/base.c

Lines changed: 58 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1667,12 +1667,63 @@ const struct inode_operations proc_pid_link_inode_operations = {
16671667

16681668
/* building an inode */
16691669

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+
16701722
struct inode *proc_pid_make_inode(struct super_block * sb,
16711723
struct task_struct *task, umode_t mode)
16721724
{
16731725
struct inode * inode;
16741726
struct proc_inode *ei;
1675-
const struct cred *cred;
16761727

16771728
/* We need a new inode */
16781729

@@ -1694,13 +1745,7 @@ struct inode *proc_pid_make_inode(struct super_block * sb,
16941745
if (!ei->pid)
16951746
goto out_unlock;
16961747

1697-
if (task_dumpable(task)) {
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-
}
1748+
task_dump_owner(task, 0, &inode->i_uid, &inode->i_gid);
17041749
security_task_to_inode(task, inode);
17051750

17061751
out:
@@ -1715,7 +1760,6 @@ int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
17151760
{
17161761
struct inode *inode = d_inode(dentry);
17171762
struct task_struct *task;
1718-
const struct cred *cred;
17191763
struct pid_namespace *pid = dentry->d_sb->s_fs_info;
17201764

17211765
generic_fillattr(inode, stat);
@@ -1733,12 +1777,7 @@ int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
17331777
*/
17341778
return -ENOENT;
17351779
}
1736-
if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) ||
1737-
task_dumpable(task)) {
1738-
cred = __task_cred(task);
1739-
stat->uid = cred->euid;
1740-
stat->gid = cred->egid;
1741-
}
1780+
task_dump_owner(task, inode->i_mode, &stat->uid, &stat->gid);
17421781
}
17431782
rcu_read_unlock();
17441783
return 0;
@@ -1754,18 +1793,11 @@ int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
17541793
* Rewrite the inode's ownerships here because the owning task may have
17551794
* performed a setuid(), etc.
17561795
*
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.
17631796
*/
17641797
int pid_revalidate(struct dentry *dentry, unsigned int flags)
17651798
{
17661799
struct inode *inode;
17671800
struct task_struct *task;
1768-
const struct cred *cred;
17691801

17701802
if (flags & LOOKUP_RCU)
17711803
return -ECHILD;
@@ -1774,17 +1806,8 @@ int pid_revalidate(struct dentry *dentry, unsigned int flags)
17741806
task = get_proc_task(inode);
17751807

17761808
if (task) {
1777-
if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) ||
1778-
task_dumpable(task)) {
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-
}
1809+
task_dump_owner(task, inode->i_mode, &inode->i_uid, &inode->i_gid);
1810+
17881811
inode->i_mode &= ~(S_ISUID | S_ISGID);
17891812
security_task_to_inode(task, inode);
17901813
put_task_struct(task);
@@ -1881,7 +1904,6 @@ static int map_files_d_revalidate(struct dentry *dentry, unsigned int flags)
18811904
bool exact_vma_exists = false;
18821905
struct mm_struct *mm = NULL;
18831906
struct task_struct *task;
1884-
const struct cred *cred;
18851907
struct inode *inode;
18861908
int status = 0;
18871909

@@ -1906,16 +1928,8 @@ static int map_files_d_revalidate(struct dentry *dentry, unsigned int flags)
19061928
mmput(mm);
19071929

19081930
if (exact_vma_exists) {
1909-
if (task_dumpable(task)) {
1910-
rcu_read_lock();
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-
}
1931+
task_dump_owner(task, 0, &inode->i_uid, &inode->i_gid);
1932+
19191933
security_task_to_inode(task, inode);
19201934
status = 1;
19211935
}

fs/proc/fd.c

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@ static int tid_fd_revalidate(struct dentry *dentry, unsigned int flags)
8484
{
8585
struct files_struct *files;
8686
struct task_struct *task;
87-
const struct cred *cred;
8887
struct inode *inode;
8988
unsigned int fd;
9089

@@ -108,16 +107,7 @@ static int tid_fd_revalidate(struct dentry *dentry, unsigned int flags)
108107
rcu_read_unlock();
109108
put_files_struct(files);
110109

111-
if (task_dumpable(task)) {
112-
rcu_read_lock();
113-
cred = __task_cred(task);
114-
inode->i_uid = cred->euid;
115-
inode->i_gid = cred->egid;
116-
rcu_read_unlock();
117-
} else {
118-
inode->i_uid = GLOBAL_ROOT_UID;
119-
inode->i_gid = GLOBAL_ROOT_GID;
120-
}
110+
task_dump_owner(task, 0, &inode->i_uid, &inode->i_gid);
121111

122112
if (S_ISLNK(inode->i_mode)) {
123113
unsigned i_mode = S_IFLNK;

fs/proc/internal.h

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -97,20 +97,8 @@ static inline struct task_struct *get_proc_task(struct inode *inode)
9797
return get_pid_task(proc_pid(inode), PIDTYPE_PID);
9898
}
9999

100-
static inline int task_dumpable(struct task_struct *task)
101-
{
102-
int dumpable = 0;
103-
struct mm_struct *mm;
104-
105-
task_lock(task);
106-
mm = task->mm;
107-
if (mm)
108-
dumpable = get_dumpable(mm);
109-
task_unlock(task);
110-
if (dumpable == SUID_DUMP_USER)
111-
return 1;
112-
return 0;
113-
}
100+
void task_dump_owner(struct task_struct *task, mode_t mode,
101+
kuid_t *ruid, kgid_t *rgid);
114102

115103
static inline unsigned name_to_int(const struct qstr *qstr)
116104
{

0 commit comments

Comments
 (0)