Commit ab516013ad9ca47f1d3a936fa81303bfbf734d52

Authored by Serge E. Hallyn
Committed by Linus Torvalds
1 parent b1ba4ddde0

[PATCH] namespaces: add nsproxy

This patch adds a nsproxy structure to the task struct.  Later patches will
move the fs namespace pointer into this structure, and introduce a new utsname
namespace into the nsproxy.

The vserver and openvz functionality, then, would be implemented in large part
by virtualizing/isolating more and more resources into namespaces, each
contained in the nsproxy.

[akpm@osdl.org: build fix]
Signed-off-by: Serge Hallyn <serue@us.ibm.com>
Cc: Kirill Korotaev <dev@openvz.org>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Cc: Herbert Poetzl <herbert@13thfloor.at>
Cc: Andrey Savochkin <saw@sw.ru>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

Showing 27 changed files with 196 additions and 2 deletions Side-by-side Diff

arch/alpha/kernel/init_task.c
... ... @@ -5,6 +5,7 @@
5 5 #include <linux/init_task.h>
6 6 #include <linux/fs.h>
7 7 #include <linux/mqueue.h>
  8 +#include <linux/nsproxy.h>
8 9 #include <asm/uaccess.h>
9 10  
10 11  
... ... @@ -13,6 +14,7 @@
13 14 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
14 15 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
15 16 struct mm_struct init_mm = INIT_MM(init_mm);
  17 +struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);
16 18 struct task_struct init_task = INIT_TASK(init_task);
17 19  
18 20 EXPORT_SYMBOL(init_mm);
arch/arm/kernel/init_task.c
... ... @@ -8,6 +8,7 @@
8 8 #include <linux/init.h>
9 9 #include <linux/init_task.h>
10 10 #include <linux/mqueue.h>
  11 +#include <linux/nsproxy.h>
11 12  
12 13 #include <asm/uaccess.h>
13 14 #include <asm/pgtable.h>
... ... @@ -17,6 +18,7 @@
17 18 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
18 19 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
19 20 struct mm_struct init_mm = INIT_MM(init_mm);
  21 +struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);
20 22  
21 23 EXPORT_SYMBOL(init_mm);
22 24  
arch/arm26/kernel/init_task.c
... ... @@ -11,6 +11,7 @@
11 11 #include <linux/init.h>
12 12 #include <linux/init_task.h>
13 13 #include <linux/mqueue.h>
  14 +#include <linux/nsproxy.h>
14 15  
15 16 #include <asm/uaccess.h>
16 17 #include <asm/pgtable.h>
... ... @@ -20,6 +21,7 @@
20 21 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
21 22 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
22 23 struct mm_struct init_mm = INIT_MM(init_mm);
  24 +struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);
23 25  
24 26 EXPORT_SYMBOL(init_mm);
25 27  
arch/frv/kernel/init_task.c
... ... @@ -5,6 +5,7 @@
5 5 #include <linux/init_task.h>
6 6 #include <linux/fs.h>
7 7 #include <linux/mqueue.h>
  8 +#include <linux/nsproxy.h>
8 9  
9 10 #include <asm/uaccess.h>
10 11 #include <asm/pgtable.h>
... ... @@ -15,6 +16,7 @@
15 16 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
16 17 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
17 18 struct mm_struct init_mm = INIT_MM(init_mm);
  19 +struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);
18 20  
19 21 EXPORT_SYMBOL(init_mm);
20 22  
arch/h8300/kernel/init_task.c
... ... @@ -8,6 +8,7 @@
8 8 #include <linux/init_task.h>
9 9 #include <linux/fs.h>
10 10 #include <linux/mqueue.h>
  11 +#include <linux/nsproxy.h>
11 12  
12 13 #include <asm/uaccess.h>
13 14 #include <asm/pgtable.h>
... ... @@ -17,6 +18,7 @@
17 18 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
18 19 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
19 20 struct mm_struct init_mm = INIT_MM(init_mm);
  21 +struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);
20 22  
21 23 EXPORT_SYMBOL(init_mm);
22 24  
arch/i386/kernel/init_task.c
... ... @@ -5,6 +5,7 @@
5 5 #include <linux/init_task.h>
6 6 #include <linux/fs.h>
7 7 #include <linux/mqueue.h>
  8 +#include <linux/nsproxy.h>
8 9  
9 10 #include <asm/uaccess.h>
10 11 #include <asm/pgtable.h>
... ... @@ -15,6 +16,7 @@
15 16 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
16 17 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
17 18 struct mm_struct init_mm = INIT_MM(init_mm);
  19 +struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);
18 20  
19 21 EXPORT_SYMBOL(init_mm);
20 22  
arch/ia64/kernel/init_task.c
... ... @@ -12,6 +12,7 @@
12 12 #include <linux/sched.h>
13 13 #include <linux/init_task.h>
14 14 #include <linux/mqueue.h>
  15 +#include <linux/nsproxy.h>
15 16  
16 17 #include <asm/uaccess.h>
17 18 #include <asm/pgtable.h>
... ... @@ -21,6 +22,7 @@
21 22 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
22 23 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
23 24 struct mm_struct init_mm = INIT_MM(init_mm);
  25 +struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);
24 26  
25 27 EXPORT_SYMBOL(init_mm);
26 28  
arch/m32r/kernel/init_task.c
... ... @@ -7,6 +7,7 @@
7 7 #include <linux/init_task.h>
8 8 #include <linux/fs.h>
9 9 #include <linux/mqueue.h>
  10 +#include <linux/nsproxy.h>
10 11  
11 12 #include <asm/uaccess.h>
12 13 #include <asm/pgtable.h>
... ... @@ -16,6 +17,7 @@
16 17 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
17 18 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
18 19 struct mm_struct init_mm = INIT_MM(init_mm);
  20 +struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);
19 21  
20 22 EXPORT_SYMBOL(init_mm);
21 23  
arch/m68knommu/kernel/init_task.c
... ... @@ -8,6 +8,7 @@
8 8 #include <linux/init_task.h>
9 9 #include <linux/fs.h>
10 10 #include <linux/mqueue.h>
  11 +#include <linux/nsproxy.h>
11 12  
12 13 #include <asm/uaccess.h>
13 14 #include <asm/pgtable.h>
... ... @@ -17,6 +18,7 @@
17 18 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
18 19 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
19 20 struct mm_struct init_mm = INIT_MM(init_mm);
  21 +struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);
20 22  
21 23 EXPORT_SYMBOL(init_mm);
22 24  
arch/mips/kernel/init_task.c
... ... @@ -4,6 +4,7 @@
4 4 #include <linux/init_task.h>
5 5 #include <linux/fs.h>
6 6 #include <linux/mqueue.h>
  7 +#include <linux/nsproxy.h>
7 8  
8 9 #include <asm/thread_info.h>
9 10 #include <asm/uaccess.h>
... ... @@ -14,6 +15,7 @@
14 15 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
15 16 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
16 17 struct mm_struct init_mm = INIT_MM(init_mm);
  18 +struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);
17 19  
18 20 EXPORT_SYMBOL(init_mm);
19 21  
arch/parisc/kernel/init_task.c
... ... @@ -28,6 +28,7 @@
28 28 #include <linux/init.h>
29 29 #include <linux/init_task.h>
30 30 #include <linux/mqueue.h>
  31 +#include <linux/nsproxy.h>
31 32  
32 33 #include <asm/uaccess.h>
33 34 #include <asm/pgtable.h>
... ... @@ -38,6 +39,7 @@
38 39 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
39 40 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
40 41 struct mm_struct init_mm = INIT_MM(init_mm);
  42 +struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);
41 43  
42 44 EXPORT_SYMBOL(init_mm);
43 45  
arch/powerpc/kernel/init_task.c
... ... @@ -5,6 +5,7 @@
5 5 #include <linux/init_task.h>
6 6 #include <linux/fs.h>
7 7 #include <linux/mqueue.h>
  8 +#include <linux/nsproxy.h>
8 9 #include <asm/uaccess.h>
9 10  
10 11 static struct fs_struct init_fs = INIT_FS;
... ... @@ -12,6 +13,7 @@
12 13 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
13 14 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
14 15 struct mm_struct init_mm = INIT_MM(init_mm);
  16 +struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);
15 17  
16 18 EXPORT_SYMBOL(init_mm);
17 19  
arch/s390/kernel/init_task.c
... ... @@ -11,6 +11,7 @@
11 11 #include <linux/sched.h>
12 12 #include <linux/init_task.h>
13 13 #include <linux/mqueue.h>
  14 +#include <linux/nsproxy.h>
14 15  
15 16 #include <asm/uaccess.h>
16 17 #include <asm/pgtable.h>
... ... @@ -20,6 +21,7 @@
20 21 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
21 22 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
22 23 struct mm_struct init_mm = INIT_MM(init_mm);
  24 +struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);
23 25  
24 26 EXPORT_SYMBOL(init_mm);
25 27  
arch/sh/kernel/init_task.c
... ... @@ -3,6 +3,7 @@
3 3 #include <linux/sched.h>
4 4 #include <linux/init_task.h>
5 5 #include <linux/mqueue.h>
  6 +#include <linux/nsproxy.h>
6 7  
7 8 #include <asm/uaccess.h>
8 9 #include <asm/pgtable.h>
... ... @@ -12,6 +13,7 @@
12 13 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
13 14 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
14 15 struct mm_struct init_mm = INIT_MM(init_mm);
  16 +struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);
15 17  
16 18 EXPORT_SYMBOL(init_mm);
17 19  
arch/sh64/kernel/init_task.c
... ... @@ -14,6 +14,7 @@
14 14 #include <linux/sched.h>
15 15 #include <linux/init_task.h>
16 16 #include <linux/mqueue.h>
  17 +#include <linux/nsproxy.h>
17 18  
18 19 #include <asm/uaccess.h>
19 20 #include <asm/pgtable.h>
... ... @@ -23,6 +24,7 @@
23 24 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
24 25 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
25 26 struct mm_struct init_mm = INIT_MM(init_mm);
  27 +struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);
26 28  
27 29 struct pt_regs fake_swapper_regs;
28 30  
arch/sparc/kernel/init_task.c
... ... @@ -3,6 +3,7 @@
3 3 #include <linux/sched.h>
4 4 #include <linux/init_task.h>
5 5 #include <linux/mqueue.h>
  6 +#include <linux/nsproxy.h>
6 7  
7 8 #include <asm/pgtable.h>
8 9 #include <asm/uaccess.h>
... ... @@ -12,6 +13,7 @@
12 13 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
13 14 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
14 15 struct mm_struct init_mm = INIT_MM(init_mm);
  16 +struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);
15 17 struct task_struct init_task = INIT_TASK(init_task);
16 18  
17 19 EXPORT_SYMBOL(init_mm);
arch/sparc64/kernel/init_task.c
... ... @@ -3,6 +3,7 @@
3 3 #include <linux/sched.h>
4 4 #include <linux/init_task.h>
5 5 #include <linux/mqueue.h>
  6 +#include <linux/nsproxy.h>
6 7  
7 8 #include <asm/pgtable.h>
8 9 #include <asm/uaccess.h>
... ... @@ -13,6 +14,7 @@
13 14 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
14 15 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
15 16 struct mm_struct init_mm = INIT_MM(init_mm);
  17 +struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);
16 18  
17 19 EXPORT_SYMBOL(init_mm);
18 20  
arch/um/kernel/init_task.c
... ... @@ -9,6 +9,7 @@
9 9 #include "linux/sched.h"
10 10 #include "linux/init_task.h"
11 11 #include "linux/mqueue.h"
  12 +#include "linux/nsproxy.h"
12 13 #include "asm/uaccess.h"
13 14 #include "asm/pgtable.h"
14 15 #include "user_util.h"
... ... @@ -17,6 +18,7 @@
17 18  
18 19 static struct fs_struct init_fs = INIT_FS;
19 20 struct mm_struct init_mm = INIT_MM(init_mm);
  21 +struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);
20 22 static struct files_struct init_files = INIT_FILES;
21 23 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
22 24 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
arch/v850/kernel/init_task.c
... ... @@ -16,6 +16,7 @@
16 16 #include <linux/init_task.h>
17 17 #include <linux/fs.h>
18 18 #include <linux/mqueue.h>
  19 +#include <linux/nsproxy.h>
19 20  
20 21 #include <asm/uaccess.h>
21 22 #include <asm/pgtable.h>
... ... @@ -25,6 +26,7 @@
25 26 static struct signal_struct init_signals = INIT_SIGNALS (init_signals);
26 27 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
27 28 struct mm_struct init_mm = INIT_MM (init_mm);
  29 +struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);
28 30  
29 31 EXPORT_SYMBOL(init_mm);
30 32  
arch/x86_64/kernel/init_task.c
... ... @@ -5,6 +5,7 @@
5 5 #include <linux/init_task.h>
6 6 #include <linux/fs.h>
7 7 #include <linux/mqueue.h>
  8 +#include <linux/nsproxy.h>
8 9  
9 10 #include <asm/uaccess.h>
10 11 #include <asm/pgtable.h>
... ... @@ -15,6 +16,7 @@
15 16 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
16 17 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
17 18 struct mm_struct init_mm = INIT_MM(init_mm);
  19 +struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);
18 20  
19 21 EXPORT_SYMBOL(init_mm);
20 22  
include/linux/init_task.h
... ... @@ -68,6 +68,12 @@
68 68 .session = 1, \
69 69 }
70 70  
  71 +extern struct nsproxy init_nsproxy;
  72 +#define INIT_NSPROXY(nsproxy) { \
  73 + .count = ATOMIC_INIT(1), \
  74 + .nslock = SPIN_LOCK_UNLOCKED, \
  75 +}
  76 +
71 77 #define INIT_SIGHAND(sighand) { \
72 78 .count = ATOMIC_INIT(1), \
73 79 .action = { { { .sa_handler = NULL, } }, }, \
... ... @@ -117,6 +123,7 @@
117 123 .files = &init_files, \
118 124 .signal = &init_signals, \
119 125 .sighand = &init_sighand, \
  126 + .nsproxy = &init_nsproxy, \
120 127 .pending = { \
121 128 .list = LIST_HEAD_INIT(tsk.pending.list), \
122 129 .signal = {{0}}}, \
include/linux/nsproxy.h
  1 +#ifndef _LINUX_NSPROXY_H
  2 +#define _LINUX_NSPROXY_H
  3 +
  4 +#include <linux/spinlock.h>
  5 +#include <linux/sched.h>
  6 +
  7 +/*
  8 + * A structure to contain pointers to all per-process
  9 + * namespaces - fs (mount), uts, network, sysvipc, etc.
  10 + *
  11 + * 'count' is the number of tasks holding a reference.
  12 + * The count for each namespace, then, will be the number
  13 + * of nsproxies pointing to it, not the number of tasks.
  14 + *
  15 + * The nsproxy is shared by tasks which share all namespaces.
  16 + * As soon as a single namespace is cloned or unshared, the
  17 + * nsproxy is copied.
  18 + */
  19 +struct nsproxy {
  20 + atomic_t count;
  21 + spinlock_t nslock;
  22 +};
  23 +extern struct nsproxy init_nsproxy;
  24 +
  25 +struct nsproxy *dup_namespaces(struct nsproxy *orig);
  26 +int copy_namespaces(int flags, struct task_struct *tsk);
  27 +void get_task_namespaces(struct task_struct *tsk);
  28 +void free_nsproxy(struct nsproxy *ns);
  29 +
  30 +static inline void put_nsproxy(struct nsproxy *ns)
  31 +{
  32 + if (atomic_dec_and_test(&ns->count)) {
  33 + free_nsproxy(ns);
  34 + }
  35 +}
  36 +
  37 +static inline void exit_task_namespaces(struct task_struct *p)
  38 +{
  39 + struct nsproxy *ns = p->nsproxy;
  40 + if (ns) {
  41 + put_nsproxy(ns);
  42 + p->nsproxy = NULL;
  43 + }
  44 +}
  45 +#endif
include/linux/sched.h
... ... @@ -239,6 +239,7 @@
239 239 asmlinkage void schedule(void);
240 240  
241 241 struct namespace;
  242 +struct nsproxy;
242 243  
243 244 /* Maximum number of active map areas.. This is a random (large) number */
244 245 #define DEFAULT_MAX_MAP_COUNT 65536
... ... @@ -898,6 +899,7 @@
898 899 struct files_struct *files;
899 900 /* namespace */
900 901 struct namespace *namespace;
  902 + struct nsproxy *nsproxy;
901 903 /* signal handlers */
902 904 struct signal_struct *signal;
903 905 struct sighand_struct *sighand;
... ... @@ -8,7 +8,7 @@
8 8 signal.o sys.o kmod.o workqueue.o pid.o \
9 9 rcupdate.o extable.o params.o posix-timers.o \
10 10 kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \
11   - hrtimer.o rwsem.o latency.o
  11 + hrtimer.o rwsem.o latency.o nsproxy.o
12 12  
13 13 obj-$(CONFIG_STACKTRACE) += stacktrace.o
14 14 obj-y += time/
... ... @@ -21,6 +21,7 @@
21 21 #include <linux/tsacct_kern.h>
22 22 #include <linux/file.h>
23 23 #include <linux/binfmts.h>
  24 +#include <linux/nsproxy.h>
24 25 #include <linux/ptrace.h>
25 26 #include <linux/profile.h>
26 27 #include <linux/mount.h>
27 28  
28 29  
29 30  
... ... @@ -397,9 +398,14 @@
397 398 fs = init_task.fs;
398 399 current->fs = fs;
399 400 atomic_inc(&fs->count);
  401 +
400 402 exit_namespace(current);
  403 + exit_task_namespaces(current);
401 404 current->namespace = init_task.namespace;
  405 + current->nsproxy = init_task.nsproxy;
402 406 get_namespace(current->namespace);
  407 + get_task_namespaces(current);
  408 +
403 409 exit_files(current);
404 410 current->files = init_task.files;
405 411 atomic_inc(&current->files->count);
... ... @@ -918,6 +924,7 @@
918 924 __exit_files(tsk);
919 925 __exit_fs(tsk);
920 926 exit_namespace(tsk);
  927 + exit_task_namespaces(tsk);
921 928 exit_thread();
922 929 cpuset_exit(tsk);
923 930 exit_keys(tsk);
... ... @@ -27,6 +27,7 @@
27 27 #include <linux/binfmts.h>
28 28 #include <linux/mman.h>
29 29 #include <linux/fs.h>
  30 +#include <linux/nsproxy.h>
30 31 #include <linux/capability.h>
31 32 #include <linux/cpu.h>
32 33 #include <linux/cpuset.h>
33 34  
... ... @@ -1116,8 +1117,10 @@
1116 1117 goto bad_fork_cleanup_signal;
1117 1118 if ((retval = copy_keys(clone_flags, p)))
1118 1119 goto bad_fork_cleanup_mm;
1119   - if ((retval = copy_namespace(clone_flags, p)))
  1120 + if ((retval = copy_namespaces(clone_flags, p)))
1120 1121 goto bad_fork_cleanup_keys;
  1122 + if ((retval = copy_namespace(clone_flags, p)))
  1123 + goto bad_fork_cleanup_namespaces;
1121 1124 retval = copy_thread(0, clone_flags, stack_start, stack_size, p, regs);
1122 1125 if (retval)
1123 1126 goto bad_fork_cleanup_namespace;
... ... @@ -1262,6 +1265,8 @@
1262 1265  
1263 1266 bad_fork_cleanup_namespace:
1264 1267 exit_namespace(p);
  1268 +bad_fork_cleanup_namespaces:
  1269 + exit_task_namespaces(p);
1265 1270 bad_fork_cleanup_keys:
1266 1271 exit_keys(p);
1267 1272 bad_fork_cleanup_mm:
... ... @@ -1606,6 +1611,7 @@
1606 1611 struct mm_struct *mm, *new_mm = NULL, *active_mm = NULL;
1607 1612 struct files_struct *fd, *new_fd = NULL;
1608 1613 struct sem_undo_list *new_ulist = NULL;
  1614 + struct nsproxy *new_nsproxy, *old_nsproxy;
1609 1615  
1610 1616 check_unshare_flags(&unshare_flags);
1611 1617  
1612 1618  
... ... @@ -1632,7 +1638,15 @@
1632 1638  
1633 1639 if (new_fs || new_ns || new_sigh || new_mm || new_fd || new_ulist) {
1634 1640  
  1641 + old_nsproxy = current->nsproxy;
  1642 + new_nsproxy = dup_namespaces(old_nsproxy);
  1643 + if (!new_nsproxy) {
  1644 + err = -ENOMEM;
  1645 + goto bad_unshare_cleanup_semundo;
  1646 + }
  1647 +
1635 1648 task_lock(current);
  1649 + current->nsproxy = new_nsproxy;
1636 1650  
1637 1651 if (new_fs) {
1638 1652 fs = current->fs;
1639 1653  
... ... @@ -1668,8 +1682,10 @@
1668 1682 }
1669 1683  
1670 1684 task_unlock(current);
  1685 + put_nsproxy(old_nsproxy);
1671 1686 }
1672 1687  
  1688 +bad_unshare_cleanup_semundo:
1673 1689 bad_unshare_cleanup_fd:
1674 1690 if (new_fd)
1675 1691 put_files_struct(new_fd);
  1 +/*
  2 + * Copyright (C) 2006 IBM Corporation
  3 + *
  4 + * Author: Serge Hallyn <serue@us.ibm.com>
  5 + *
  6 + * This program is free software; you can redistribute it and/or
  7 + * modify it under the terms of the GNU General Public License as
  8 + * published by the Free Software Foundation, version 2 of the
  9 + * License.
  10 + */
  11 +
  12 +#include <linux/module.h>
  13 +#include <linux/version.h>
  14 +#include <linux/nsproxy.h>
  15 +
  16 +static inline void get_nsproxy(struct nsproxy *ns)
  17 +{
  18 + atomic_inc(&ns->count);
  19 +}
  20 +
  21 +void get_task_namespaces(struct task_struct *tsk)
  22 +{
  23 + struct nsproxy *ns = tsk->nsproxy;
  24 + if (ns) {
  25 + get_nsproxy(ns);
  26 + }
  27 +}
  28 +
  29 +/*
  30 + * creates a copy of "orig" with refcount 1.
  31 + * This does not grab references to the contained namespaces,
  32 + * so that needs to be done by dup_namespaces.
  33 + */
  34 +static inline struct nsproxy *clone_namespaces(struct nsproxy *orig)
  35 +{
  36 + struct nsproxy *ns;
  37 +
  38 + ns = kmalloc(sizeof(struct nsproxy), GFP_KERNEL);
  39 + if (ns) {
  40 + memcpy(ns, orig, sizeof(struct nsproxy));
  41 + atomic_set(&ns->count, 1);
  42 + }
  43 + return ns;
  44 +}
  45 +
  46 +/*
  47 + * copies the nsproxy, setting refcount to 1, and grabbing a
  48 + * reference to all contained namespaces. Called from
  49 + * sys_unshare()
  50 + */
  51 +struct nsproxy *dup_namespaces(struct nsproxy *orig)
  52 +{
  53 + struct nsproxy *ns = clone_namespaces(orig);
  54 +
  55 + return ns;
  56 +}
  57 +
  58 +/*
  59 + * called from clone. This now handles copy for nsproxy and all
  60 + * namespaces therein.
  61 + */
  62 +int copy_namespaces(int flags, struct task_struct *tsk)
  63 +{
  64 + struct nsproxy *old_ns = tsk->nsproxy;
  65 +
  66 + if (!old_ns)
  67 + return 0;
  68 +
  69 + get_nsproxy(old_ns);
  70 +
  71 + return 0;
  72 +}
  73 +
  74 +void free_nsproxy(struct nsproxy *ns)
  75 +{
  76 + kfree(ns);
  77 +}