Commit 49f4d8b93ccf9454284b6f524b96c66d8d7fbccc
1 parent
ae06c7c83f
Exists in
master
and in
20 other branches
pidns: Capture the user namespace and filter ns_last_pid
- Capture the the user namespace that creates the pid namespace - Use that user namespace to test if it is ok to write to /proc/sys/kernel/ns_last_pid. Zhao Hongjiang <zhaohongjiang@huawei.com> noticed I was missing a put_user_ns in when destroying a pid_ns. I have foloded his patch into this one so that bisects will work properly. Acked-by: Serge Hallyn <serge.hallyn@canonical.com> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Showing 4 changed files with 19 additions and 9 deletions Side-by-side Diff
include/linux/pid_namespace.h
... | ... | @@ -31,6 +31,7 @@ |
31 | 31 | #ifdef CONFIG_BSD_PROCESS_ACCT |
32 | 32 | struct bsd_acct_struct *bacct; |
33 | 33 | #endif |
34 | + struct user_namespace *user_ns; | |
34 | 35 | kgid_t pid_gid; |
35 | 36 | int hide_pid; |
36 | 37 | int reboot; /* group exit code if this pidns was rebooted */ |
... | ... | @@ -46,7 +47,8 @@ |
46 | 47 | return ns; |
47 | 48 | } |
48 | 49 | |
49 | -extern struct pid_namespace *copy_pid_ns(unsigned long flags, struct pid_namespace *ns); | |
50 | +extern struct pid_namespace *copy_pid_ns(unsigned long flags, | |
51 | + struct user_namespace *user_ns, struct pid_namespace *ns); | |
50 | 52 | extern void zap_pid_ns_processes(struct pid_namespace *pid_ns); |
51 | 53 | extern int reboot_pid_ns(struct pid_namespace *pid_ns, int cmd); |
52 | 54 | extern void put_pid_ns(struct pid_namespace *ns); |
... | ... | @@ -59,8 +61,8 @@ |
59 | 61 | return ns; |
60 | 62 | } |
61 | 63 | |
62 | -static inline struct pid_namespace * | |
63 | -copy_pid_ns(unsigned long flags, struct pid_namespace *ns) | |
64 | +static inline struct pid_namespace *copy_pid_ns(unsigned long flags, | |
65 | + struct user_namespace *user_ns, struct pid_namespace *ns) | |
64 | 66 | { |
65 | 67 | if (flags & CLONE_NEWPID) |
66 | 68 | ns = ERR_PTR(-EINVAL); |
kernel/nsproxy.c
... | ... | @@ -84,7 +84,7 @@ |
84 | 84 | goto out_ipc; |
85 | 85 | } |
86 | 86 | |
87 | - new_nsp->pid_ns = copy_pid_ns(flags, task_active_pid_ns(tsk)); | |
87 | + new_nsp->pid_ns = copy_pid_ns(flags, task_cred_xxx(tsk, user_ns), task_active_pid_ns(tsk)); | |
88 | 88 | if (IS_ERR(new_nsp->pid_ns)) { |
89 | 89 | err = PTR_ERR(new_nsp->pid_ns); |
90 | 90 | goto out_pid; |
kernel/pid.c
kernel/pid_namespace.c
... | ... | @@ -10,6 +10,7 @@ |
10 | 10 | |
11 | 11 | #include <linux/pid.h> |
12 | 12 | #include <linux/pid_namespace.h> |
13 | +#include <linux/user_namespace.h> | |
13 | 14 | #include <linux/syscalls.h> |
14 | 15 | #include <linux/err.h> |
15 | 16 | #include <linux/acct.h> |
... | ... | @@ -74,7 +75,8 @@ |
74 | 75 | /* MAX_PID_NS_LEVEL is needed for limiting size of 'struct pid' */ |
75 | 76 | #define MAX_PID_NS_LEVEL 32 |
76 | 77 | |
77 | -static struct pid_namespace *create_pid_namespace(struct pid_namespace *parent_pid_ns) | |
78 | +static struct pid_namespace *create_pid_namespace(struct user_namespace *user_ns, | |
79 | + struct pid_namespace *parent_pid_ns) | |
78 | 80 | { |
79 | 81 | struct pid_namespace *ns; |
80 | 82 | unsigned int level = parent_pid_ns->level + 1; |
... | ... | @@ -102,6 +104,7 @@ |
102 | 104 | kref_init(&ns->kref); |
103 | 105 | ns->level = level; |
104 | 106 | ns->parent = get_pid_ns(parent_pid_ns); |
107 | + ns->user_ns = get_user_ns(user_ns); | |
105 | 108 | |
106 | 109 | set_bit(0, ns->pidmap[0].page); |
107 | 110 | atomic_set(&ns->pidmap[0].nr_free, BITS_PER_PAGE - 1); |
... | ... | @@ -117,6 +120,7 @@ |
117 | 120 | |
118 | 121 | out_put_parent_pid_ns: |
119 | 122 | put_pid_ns(parent_pid_ns); |
123 | + put_user_ns(user_ns); | |
120 | 124 | out_free_map: |
121 | 125 | kfree(ns->pidmap[0].page); |
122 | 126 | out_free: |
123 | 127 | |
124 | 128 | |
... | ... | @@ -131,16 +135,18 @@ |
131 | 135 | |
132 | 136 | for (i = 0; i < PIDMAP_ENTRIES; i++) |
133 | 137 | kfree(ns->pidmap[i].page); |
138 | + put_user_ns(ns->user_ns); | |
134 | 139 | kmem_cache_free(pid_ns_cachep, ns); |
135 | 140 | } |
136 | 141 | |
137 | -struct pid_namespace *copy_pid_ns(unsigned long flags, struct pid_namespace *old_ns) | |
142 | +struct pid_namespace *copy_pid_ns(unsigned long flags, | |
143 | + struct user_namespace *user_ns, struct pid_namespace *old_ns) | |
138 | 144 | { |
139 | 145 | if (!(flags & CLONE_NEWPID)) |
140 | 146 | return get_pid_ns(old_ns); |
141 | 147 | if (flags & (CLONE_THREAD|CLONE_PARENT)) |
142 | 148 | return ERR_PTR(-EINVAL); |
143 | - return create_pid_namespace(old_ns); | |
149 | + return create_pid_namespace(user_ns, old_ns); | |
144 | 150 | } |
145 | 151 | |
146 | 152 | static void free_pid_ns(struct kref *kref) |
147 | 153 | |
... | ... | @@ -239,9 +245,10 @@ |
239 | 245 | static int pid_ns_ctl_handler(struct ctl_table *table, int write, |
240 | 246 | void __user *buffer, size_t *lenp, loff_t *ppos) |
241 | 247 | { |
248 | + struct pid_namespace *pid_ns = task_active_pid_ns(current); | |
242 | 249 | struct ctl_table tmp = *table; |
243 | 250 | |
244 | - if (write && !capable(CAP_SYS_ADMIN)) | |
251 | + if (write && !ns_capable(pid_ns->user_ns, CAP_SYS_ADMIN)) | |
245 | 252 | return -EPERM; |
246 | 253 | |
247 | 254 | /* |
... | ... | @@ -250,7 +257,7 @@ |
250 | 257 | * it should synchronize its usage with external means. |
251 | 258 | */ |
252 | 259 | |
253 | - tmp.data = ¤t->nsproxy->pid_ns->last_pid; | |
260 | + tmp.data = &pid_ns->last_pid; | |
254 | 261 | return proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos); |
255 | 262 | } |
256 | 263 |