Commit 9a575a92db3312a40cdf0b0406d88de88ad9741e

Authored by Cedric Le Goater
Committed by Linus Torvalds
1 parent 61a58c6c23

[PATCH] to nsproxy

Add the pid namespace framework to the nsproxy object.  The copy of the pid
namespace only increases the refcount on the global pid namespace,
init_pid_ns, and unshare is not implemented.

There is no configuration option to activate or deactivate this feature
because this not relevant for the moment.

Signed-off-by: Cedric Le Goater <clg@fr.ibm.com>
Cc: Kirill Korotaev <dev@openvz.org>
Cc: Eric W. Biederman <ebiederm@xmission.com>
Cc: Herbert Poetzl <herbert@13thfloor.at>
Cc: Sukadev Bhattiprolu <sukadev@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

Showing 5 changed files with 64 additions and 9 deletions Side-by-side Diff

include/linux/init_task.h
... ... @@ -7,6 +7,7 @@
7 7 #include <linux/utsname.h>
8 8 #include <linux/lockdep.h>
9 9 #include <linux/ipc.h>
  10 +#include <linux/pid_namespace.h>
10 11  
11 12 #define INIT_FDTABLE \
12 13 { \
... ... @@ -73,6 +74,7 @@
73 74  
74 75 extern struct nsproxy init_nsproxy;
75 76 #define INIT_NSPROXY(nsproxy) { \
  77 + .pid_ns = &init_pid_ns, \
76 78 .count = ATOMIC_INIT(1), \
77 79 .nslock = __SPIN_LOCK_UNLOCKED(nsproxy.nslock), \
78 80 .id = 0, \
include/linux/nsproxy.h
... ... @@ -7,6 +7,7 @@
7 7 struct mnt_namespace;
8 8 struct uts_namespace;
9 9 struct ipc_namespace;
  10 +struct pid_namespace;
10 11  
11 12 /*
12 13 * A structure to contain pointers to all per-process
... ... @@ -27,6 +28,7 @@
27 28 struct uts_namespace *uts_ns;
28 29 struct ipc_namespace *ipc_ns;
29 30 struct mnt_namespace *mnt_ns;
  31 + struct pid_namespace *pid_ns;
30 32 };
31 33 extern struct nsproxy init_nsproxy;
32 34  
include/linux/pid_namespace.h
... ... @@ -5,6 +5,8 @@
5 5 #include <linux/mm.h>
6 6 #include <linux/threads.h>
7 7 #include <linux/pid.h>
  8 +#include <linux/nsproxy.h>
  9 +#include <linux/kref.h>
8 10  
9 11 struct pidmap {
10 12 atomic_t nr_free;
11 13  
... ... @@ -14,11 +16,25 @@
14 16 #define PIDMAP_ENTRIES ((PID_MAX_LIMIT + 8*PAGE_SIZE - 1)/PAGE_SIZE/8)
15 17  
16 18 struct pid_namespace {
17   - struct pidmap pidmap[PIDMAP_ENTRIES];
18   - int last_pid;
  19 + struct kref kref;
  20 + struct pidmap pidmap[PIDMAP_ENTRIES];
  21 + int last_pid;
19 22 };
20 23  
21 24 extern struct pid_namespace init_pid_ns;
  25 +
  26 +static inline void get_pid_ns(struct pid_namespace *ns)
  27 +{
  28 + kref_get(&ns->kref);
  29 +}
  30 +
  31 +extern int copy_pid_ns(int flags, struct task_struct *tsk);
  32 +extern void free_pid_ns(struct kref *kref);
  33 +
  34 +static inline void put_pid_ns(struct pid_namespace *ns)
  35 +{
  36 + kref_put(&ns->kref, free_pid_ns);
  37 +}
22 38  
23 39 #endif /* _LINUX_PID_NS_H */
... ... @@ -19,6 +19,7 @@
19 19 #include <linux/init_task.h>
20 20 #include <linux/mnt_namespace.h>
21 21 #include <linux/utsname.h>
  22 +#include <linux/pid_namespace.h>
22 23  
23 24 struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);
24 25  
... ... @@ -68,6 +69,8 @@
68 69 get_uts_ns(ns->uts_ns);
69 70 if (ns->ipc_ns)
70 71 get_ipc_ns(ns->ipc_ns);
  72 + if (ns->pid_ns)
  73 + get_pid_ns(ns->pid_ns);
71 74 }
72 75  
73 76 return ns;
74 77  
... ... @@ -111,10 +114,17 @@
111 114 if (err)
112 115 goto out_ipc;
113 116  
  117 + err = copy_pid_ns(flags, tsk);
  118 + if (err)
  119 + goto out_pid;
  120 +
114 121 out:
115 122 put_nsproxy(old_ns);
116 123 return err;
117 124  
  125 +out_pid:
  126 + if (new_ns->ipc_ns)
  127 + put_ipc_ns(new_ns->ipc_ns);
118 128 out_ipc:
119 129 if (new_ns->uts_ns)
120 130 put_uts_ns(new_ns->uts_ns);
... ... @@ -129,12 +139,14 @@
129 139  
130 140 void free_nsproxy(struct nsproxy *ns)
131 141 {
132   - if (ns->mnt_ns)
133   - put_mnt_ns(ns->mnt_ns);
134   - if (ns->uts_ns)
135   - put_uts_ns(ns->uts_ns);
136   - if (ns->ipc_ns)
137   - put_ipc_ns(ns->ipc_ns);
138   - kfree(ns);
  142 + if (ns->mnt_ns)
  143 + put_mnt_ns(ns->mnt_ns);
  144 + if (ns->uts_ns)
  145 + put_uts_ns(ns->uts_ns);
  146 + if (ns->ipc_ns)
  147 + put_ipc_ns(ns->ipc_ns);
  148 + if (ns->pid_ns)
  149 + put_pid_ns(ns->pid_ns);
  150 + kfree(ns);
139 151 }
... ... @@ -59,6 +59,9 @@
59 59 * the scheme scales to up to 4 million PIDs, runtime.
60 60 */
61 61 struct pid_namespace init_pid_ns = {
  62 + .kref = {
  63 + .refcount = ATOMIC_INIT(2),
  64 + },
62 65 .pidmap = {
63 66 [ 0 ... PIDMAP_ENTRIES-1] = { ATOMIC_INIT(BITS_PER_PAGE), NULL }
64 67 },
... ... @@ -355,6 +358,26 @@
355 358 return pid;
356 359 }
357 360 EXPORT_SYMBOL_GPL(find_get_pid);
  361 +
  362 +int copy_pid_ns(int flags, struct task_struct *tsk)
  363 +{
  364 + struct pid_namespace *old_ns = tsk->nsproxy->pid_ns;
  365 + int err = 0;
  366 +
  367 + if (!old_ns)
  368 + return 0;
  369 +
  370 + get_pid_ns(old_ns);
  371 + return err;
  372 +}
  373 +
  374 +void free_pid_ns(struct kref *kref)
  375 +{
  376 + struct pid_namespace *ns;
  377 +
  378 + ns = container_of(kref, struct pid_namespace, kref);
  379 + kfree(ns);
  380 +}
358 381  
359 382 /*
360 383 * The pid hash table is scaled according to the amount of memory in the