aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc
diff options
context:
space:
mode:
Diffstat (limited to 'fs/proc')
-rw-r--r--fs/proc/array.c15
-rw-r--r--fs/proc/base.c93
-rw-r--r--fs/proc/inode.c4
-rw-r--r--fs/proc/proc_sysctl.c4
-rw-r--r--fs/proc/root.c2
5 files changed, 102 insertions, 16 deletions
diff --git a/fs/proc/array.c b/fs/proc/array.c
index f9bd395b3473..dc4c5a7b9ece 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -81,6 +81,7 @@
81#include <linux/pid_namespace.h> 81#include <linux/pid_namespace.h>
82#include <linux/ptrace.h> 82#include <linux/ptrace.h>
83#include <linux/tracehook.h> 83#include <linux/tracehook.h>
84#include <linux/user_namespace.h>
84 85
85#include <asm/pgtable.h> 86#include <asm/pgtable.h>
86#include <asm/processor.h> 87#include <asm/processor.h>
@@ -161,6 +162,7 @@ static inline const char *get_task_state(struct task_struct *tsk)
161static inline void task_state(struct seq_file *m, struct pid_namespace *ns, 162static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
162 struct pid *pid, struct task_struct *p) 163 struct pid *pid, struct task_struct *p)
163{ 164{
165 struct user_namespace *user_ns = current_user_ns();
164 struct group_info *group_info; 166 struct group_info *group_info;
165 int g; 167 int g;
166 struct fdtable *fdt = NULL; 168 struct fdtable *fdt = NULL;
@@ -189,8 +191,14 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
189 task_tgid_nr_ns(p, ns), 191 task_tgid_nr_ns(p, ns),
190 pid_nr_ns(pid, ns), 192 pid_nr_ns(pid, ns),
191 ppid, tpid, 193 ppid, tpid,
192 cred->uid, cred->euid, cred->suid, cred->fsuid, 194 from_kuid_munged(user_ns, cred->uid),
193 cred->gid, cred->egid, cred->sgid, cred->fsgid); 195 from_kuid_munged(user_ns, cred->euid),
196 from_kuid_munged(user_ns, cred->suid),
197 from_kuid_munged(user_ns, cred->fsuid),
198 from_kgid_munged(user_ns, cred->gid),
199 from_kgid_munged(user_ns, cred->egid),
200 from_kgid_munged(user_ns, cred->sgid),
201 from_kgid_munged(user_ns, cred->fsgid));
194 202
195 task_lock(p); 203 task_lock(p);
196 if (p->files) 204 if (p->files)
@@ -205,7 +213,8 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
205 task_unlock(p); 213 task_unlock(p);
206 214
207 for (g = 0; g < min(group_info->ngroups, NGROUPS_SMALL); g++) 215 for (g = 0; g < min(group_info->ngroups, NGROUPS_SMALL); g++)
208 seq_printf(m, "%d ", GROUP_AT(group_info, g)); 216 seq_printf(m, "%d ",
217 from_kgid_munged(user_ns, GROUP_AT(group_info, g)));
209 put_cred(cred); 218 put_cred(cred);
210 219
211 seq_putc(m, '\n'); 220 seq_putc(m, '\n');
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 57b8159f26f3..d2d3108a611c 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -81,6 +81,7 @@
81#include <linux/oom.h> 81#include <linux/oom.h>
82#include <linux/elf.h> 82#include <linux/elf.h>
83#include <linux/pid_namespace.h> 83#include <linux/pid_namespace.h>
84#include <linux/user_namespace.h>
84#include <linux/fs_struct.h> 85#include <linux/fs_struct.h>
85#include <linux/slab.h> 86#include <linux/slab.h>
86#include <linux/flex_array.h> 87#include <linux/flex_array.h>
@@ -1561,8 +1562,8 @@ int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
1561 generic_fillattr(inode, stat); 1562 generic_fillattr(inode, stat);
1562 1563
1563 rcu_read_lock(); 1564 rcu_read_lock();
1564 stat->uid = 0; 1565 stat->uid = GLOBAL_ROOT_UID;
1565 stat->gid = 0; 1566 stat->gid = GLOBAL_ROOT_GID;
1566 task = pid_task(proc_pid(inode), PIDTYPE_PID); 1567 task = pid_task(proc_pid(inode), PIDTYPE_PID);
1567 if (task) { 1568 if (task) {
1568 if (!has_pid_permissions(pid, task, 2)) { 1569 if (!has_pid_permissions(pid, task, 2)) {
@@ -1622,8 +1623,8 @@ int pid_revalidate(struct dentry *dentry, struct nameidata *nd)
1622 inode->i_gid = cred->egid; 1623 inode->i_gid = cred->egid;
1623 rcu_read_unlock(); 1624 rcu_read_unlock();
1624 } else { 1625 } else {
1625 inode->i_uid = 0; 1626 inode->i_uid = GLOBAL_ROOT_UID;
1626 inode->i_gid = 0; 1627 inode->i_gid = GLOBAL_ROOT_GID;
1627 } 1628 }
1628 inode->i_mode &= ~(S_ISUID | S_ISGID); 1629 inode->i_mode &= ~(S_ISUID | S_ISGID);
1629 security_task_to_inode(task, inode); 1630 security_task_to_inode(task, inode);
@@ -1815,8 +1816,8 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
1815 inode->i_gid = cred->egid; 1816 inode->i_gid = cred->egid;
1816 rcu_read_unlock(); 1817 rcu_read_unlock();
1817 } else { 1818 } else {
1818 inode->i_uid = 0; 1819 inode->i_uid = GLOBAL_ROOT_UID;
1819 inode->i_gid = 0; 1820 inode->i_gid = GLOBAL_ROOT_GID;
1820 } 1821 }
1821 1822
1822 i_mode = S_IFLNK; 1823 i_mode = S_IFLNK;
@@ -2045,8 +2046,8 @@ static int map_files_d_revalidate(struct dentry *dentry, struct nameidata *nd)
2045 inode->i_gid = cred->egid; 2046 inode->i_gid = cred->egid;
2046 rcu_read_unlock(); 2047 rcu_read_unlock();
2047 } else { 2048 } else {
2048 inode->i_uid = 0; 2049 inode->i_uid = GLOBAL_ROOT_UID;
2049 inode->i_gid = 0; 2050 inode->i_gid = GLOBAL_ROOT_GID;
2050 } 2051 }
2051 security_task_to_inode(task, inode); 2052 security_task_to_inode(task, inode);
2052 status = 1; 2053 status = 1;
@@ -2924,6 +2925,74 @@ static int proc_tgid_io_accounting(struct task_struct *task, char *buffer)
2924} 2925}
2925#endif /* CONFIG_TASK_IO_ACCOUNTING */ 2926#endif /* CONFIG_TASK_IO_ACCOUNTING */
2926 2927
2928#ifdef CONFIG_USER_NS
2929static int proc_id_map_open(struct inode *inode, struct file *file,
2930 struct seq_operations *seq_ops)
2931{
2932 struct user_namespace *ns = NULL;
2933 struct task_struct *task;
2934 struct seq_file *seq;
2935 int ret = -EINVAL;
2936
2937 task = get_proc_task(inode);
2938 if (task) {
2939 rcu_read_lock();
2940 ns = get_user_ns(task_cred_xxx(task, user_ns));
2941 rcu_read_unlock();
2942 put_task_struct(task);
2943 }
2944 if (!ns)
2945 goto err;
2946
2947 ret = seq_open(file, seq_ops);
2948 if (ret)
2949 goto err_put_ns;
2950
2951 seq = file->private_data;
2952 seq->private = ns;
2953
2954 return 0;
2955err_put_ns:
2956 put_user_ns(ns);
2957err:
2958 return ret;
2959}
2960
2961static int proc_id_map_release(struct inode *inode, struct file *file)
2962{
2963 struct seq_file *seq = file->private_data;
2964 struct user_namespace *ns = seq->private;
2965 put_user_ns(ns);
2966 return seq_release(inode, file);
2967}
2968
2969static int proc_uid_map_open(struct inode *inode, struct file *file)
2970{
2971 return proc_id_map_open(inode, file, &proc_uid_seq_operations);
2972}
2973
2974static int proc_gid_map_open(struct inode *inode, struct file *file)
2975{
2976 return proc_id_map_open(inode, file, &proc_gid_seq_operations);
2977}
2978
2979static const struct file_operations proc_uid_map_operations = {
2980 .open = proc_uid_map_open,
2981 .write = proc_uid_map_write,
2982 .read = seq_read,
2983 .llseek = seq_lseek,
2984 .release = proc_id_map_release,
2985};
2986
2987static const struct file_operations proc_gid_map_operations = {
2988 .open = proc_gid_map_open,
2989 .write = proc_gid_map_write,
2990 .read = seq_read,
2991 .llseek = seq_lseek,
2992 .release = proc_id_map_release,
2993};
2994#endif /* CONFIG_USER_NS */
2995
2927static int proc_pid_personality(struct seq_file *m, struct pid_namespace *ns, 2996static int proc_pid_personality(struct seq_file *m, struct pid_namespace *ns,
2928 struct pid *pid, struct task_struct *task) 2997 struct pid *pid, struct task_struct *task)
2929{ 2998{
@@ -3026,6 +3095,10 @@ static const struct pid_entry tgid_base_stuff[] = {
3026#ifdef CONFIG_HARDWALL 3095#ifdef CONFIG_HARDWALL
3027 INF("hardwall", S_IRUGO, proc_pid_hardwall), 3096 INF("hardwall", S_IRUGO, proc_pid_hardwall),
3028#endif 3097#endif
3098#ifdef CONFIG_USER_NS
3099 REG("uid_map", S_IRUGO|S_IWUSR, proc_uid_map_operations),
3100 REG("gid_map", S_IRUGO|S_IWUSR, proc_gid_map_operations),
3101#endif
3029}; 3102};
3030 3103
3031static int proc_tgid_base_readdir(struct file * filp, 3104static int proc_tgid_base_readdir(struct file * filp,
@@ -3381,6 +3454,10 @@ static const struct pid_entry tid_base_stuff[] = {
3381#ifdef CONFIG_HARDWALL 3454#ifdef CONFIG_HARDWALL
3382 INF("hardwall", S_IRUGO, proc_pid_hardwall), 3455 INF("hardwall", S_IRUGO, proc_pid_hardwall),
3383#endif 3456#endif
3457#ifdef CONFIG_USER_NS
3458 REG("uid_map", S_IRUGO|S_IWUSR, proc_uid_map_operations),
3459 REG("gid_map", S_IRUGO|S_IWUSR, proc_gid_map_operations),
3460#endif
3384}; 3461};
3385 3462
3386static int proc_tid_base_readdir(struct file * filp, 3463static int proc_tid_base_readdir(struct file * filp,
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index 205c92280838..554ecc54799f 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -108,8 +108,8 @@ static int proc_show_options(struct seq_file *seq, struct dentry *root)
108 struct super_block *sb = root->d_sb; 108 struct super_block *sb = root->d_sb;
109 struct pid_namespace *pid = sb->s_fs_info; 109 struct pid_namespace *pid = sb->s_fs_info;
110 110
111 if (pid->pid_gid) 111 if (!gid_eq(pid->pid_gid, GLOBAL_ROOT_GID))
112 seq_printf(seq, ",gid=%lu", (unsigned long)pid->pid_gid); 112 seq_printf(seq, ",gid=%u", from_kgid_munged(&init_user_ns, pid->pid_gid));
113 if (pid->hide_pid != 0) 113 if (pid->hide_pid != 0)
114 seq_printf(seq, ",hidepid=%u", pid->hide_pid); 114 seq_printf(seq, ",hidepid=%u", pid->hide_pid);
115 115
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index 21d836f40292..3476bca8f7af 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -371,9 +371,9 @@ void register_sysctl_root(struct ctl_table_root *root)
371 371
372static int test_perm(int mode, int op) 372static int test_perm(int mode, int op)
373{ 373{
374 if (!current_euid()) 374 if (uid_eq(current_euid(), GLOBAL_ROOT_UID))
375 mode >>= 6; 375 mode >>= 6;
376 else if (in_egroup_p(0)) 376 else if (in_egroup_p(GLOBAL_ROOT_GID))
377 mode >>= 3; 377 mode >>= 3;
378 if ((op & ~mode & (MAY_READ|MAY_WRITE|MAY_EXEC)) == 0) 378 if ((op & ~mode & (MAY_READ|MAY_WRITE|MAY_EXEC)) == 0)
379 return 0; 379 return 0;
diff --git a/fs/proc/root.c b/fs/proc/root.c
index eed44bfc85db..7c30fce037c0 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -67,7 +67,7 @@ static int proc_parse_options(char *options, struct pid_namespace *pid)
67 case Opt_gid: 67 case Opt_gid:
68 if (match_int(&args[0], &option)) 68 if (match_int(&args[0], &option))
69 return 0; 69 return 0;
70 pid->pid_gid = option; 70 pid->pid_gid = make_kgid(current_user_ns(), option);
71 break; 71 break;
72 case Opt_hidepid: 72 case Opt_hidepid:
73 if (match_int(&args[0], &option)) 73 if (match_int(&args[0], &option))