aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/pid_namespace.c
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2012-10-30 03:09:18 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2012-10-30 03:09:18 -0400
commit68fe0f0a6dcd2ac1ace5da3647a6d1cf0f4d2fea (patch)
tree69d855c2e46d42ef8f23680cf3a1e6ff38de9ef4 /kernel/pid_namespace.c
parent88fd449e734a4264347e12b8ff74ccb33a9b9a35 (diff)
parent8f0d8163b50e01f398b14bcd4dc039ac5ab18d64 (diff)
Merge tag 'v3.7-rc3' into for-linus to sync up with recent USB changes
Diffstat (limited to 'kernel/pid_namespace.c')
-rw-r--r--kernel/pid_namespace.c39
1 files changed, 31 insertions, 8 deletions
diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c
index b3c7fd554250..7b07cc0dfb75 100644
--- a/kernel/pid_namespace.c
+++ b/kernel/pid_namespace.c
@@ -16,6 +16,7 @@
16#include <linux/slab.h> 16#include <linux/slab.h>
17#include <linux/proc_fs.h> 17#include <linux/proc_fs.h>
18#include <linux/reboot.h> 18#include <linux/reboot.h>
19#include <linux/export.h>
19 20
20#define BITS_PER_PAGE (PAGE_SIZE*8) 21#define BITS_PER_PAGE (PAGE_SIZE*8)
21 22
@@ -70,12 +71,22 @@ err_alloc:
70 return NULL; 71 return NULL;
71} 72}
72 73
74/* MAX_PID_NS_LEVEL is needed for limiting size of 'struct pid' */
75#define MAX_PID_NS_LEVEL 32
76
73static struct pid_namespace *create_pid_namespace(struct pid_namespace *parent_pid_ns) 77static struct pid_namespace *create_pid_namespace(struct pid_namespace *parent_pid_ns)
74{ 78{
75 struct pid_namespace *ns; 79 struct pid_namespace *ns;
76 unsigned int level = parent_pid_ns->level + 1; 80 unsigned int level = parent_pid_ns->level + 1;
77 int i, err = -ENOMEM; 81 int i;
82 int err;
83
84 if (level > MAX_PID_NS_LEVEL) {
85 err = -EINVAL;
86 goto out;
87 }
78 88
89 err = -ENOMEM;
79 ns = kmem_cache_zalloc(pid_ns_cachep, GFP_KERNEL); 90 ns = kmem_cache_zalloc(pid_ns_cachep, GFP_KERNEL);
80 if (ns == NULL) 91 if (ns == NULL)
81 goto out; 92 goto out;
@@ -132,18 +143,26 @@ struct pid_namespace *copy_pid_ns(unsigned long flags, struct pid_namespace *old
132 return create_pid_namespace(old_ns); 143 return create_pid_namespace(old_ns);
133} 144}
134 145
135void free_pid_ns(struct kref *kref) 146static void free_pid_ns(struct kref *kref)
136{ 147{
137 struct pid_namespace *ns, *parent; 148 struct pid_namespace *ns;
138 149
139 ns = container_of(kref, struct pid_namespace, kref); 150 ns = container_of(kref, struct pid_namespace, kref);
140
141 parent = ns->parent;
142 destroy_pid_namespace(ns); 151 destroy_pid_namespace(ns);
152}
153
154void put_pid_ns(struct pid_namespace *ns)
155{
156 struct pid_namespace *parent;
143 157
144 if (parent != NULL) 158 while (ns != &init_pid_ns) {
145 put_pid_ns(parent); 159 parent = ns->parent;
160 if (!kref_put(&ns->kref, free_pid_ns))
161 break;
162 ns = parent;
163 }
146} 164}
165EXPORT_SYMBOL_GPL(put_pid_ns);
147 166
148void zap_pid_ns_processes(struct pid_namespace *pid_ns) 167void zap_pid_ns_processes(struct pid_namespace *pid_ns)
149{ 168{
@@ -232,15 +251,19 @@ static int pid_ns_ctl_handler(struct ctl_table *table, int write,
232 */ 251 */
233 252
234 tmp.data = &current->nsproxy->pid_ns->last_pid; 253 tmp.data = &current->nsproxy->pid_ns->last_pid;
235 return proc_dointvec(&tmp, write, buffer, lenp, ppos); 254 return proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
236} 255}
237 256
257extern int pid_max;
258static int zero = 0;
238static struct ctl_table pid_ns_ctl_table[] = { 259static struct ctl_table pid_ns_ctl_table[] = {
239 { 260 {
240 .procname = "ns_last_pid", 261 .procname = "ns_last_pid",
241 .maxlen = sizeof(int), 262 .maxlen = sizeof(int),
242 .mode = 0666, /* permissions are checked in the handler */ 263 .mode = 0666, /* permissions are checked in the handler */
243 .proc_handler = pid_ns_ctl_handler, 264 .proc_handler = pid_ns_ctl_handler,
265 .extra1 = &zero,
266 .extra2 = &pid_max,
244 }, 267 },
245 { } 268 { }
246}; 269};