diff options
author | Serge E. Hallyn <serue@us.ibm.com> | 2006-10-02 05:18:06 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-02 10:57:20 -0400 |
commit | ab516013ad9ca47f1d3a936fa81303bfbf734d52 (patch) | |
tree | 643ea9c4c3d28958cb42dd87b1856f74edd22b11 /kernel | |
parent | b1ba4ddde0cf67991d89f039365eaaeda61aa027 (diff) |
[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>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/Makefile | 2 | ||||
-rw-r--r-- | kernel/exit.c | 7 | ||||
-rw-r--r-- | kernel/fork.c | 18 | ||||
-rw-r--r-- | kernel/nsproxy.c | 77 |
4 files changed, 102 insertions, 2 deletions
diff --git a/kernel/Makefile b/kernel/Makefile index aacaafb28b9d..6ec53009b866 100644 --- a/kernel/Makefile +++ b/kernel/Makefile | |||
@@ -8,7 +8,7 @@ obj-y = sched.o fork.o exec_domain.o panic.o printk.o profile.o \ | |||
8 | signal.o sys.o kmod.o workqueue.o pid.o \ | 8 | signal.o sys.o kmod.o workqueue.o pid.o \ |
9 | rcupdate.o extable.o params.o posix-timers.o \ | 9 | rcupdate.o extable.o params.o posix-timers.o \ |
10 | kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \ | 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 | obj-$(CONFIG_STACKTRACE) += stacktrace.o | 13 | obj-$(CONFIG_STACKTRACE) += stacktrace.o |
14 | obj-y += time/ | 14 | obj-y += time/ |
diff --git a/kernel/exit.c b/kernel/exit.c index 3b47f26985f2..1d0e9ea1fa05 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/tsacct_kern.h> | 21 | #include <linux/tsacct_kern.h> |
22 | #include <linux/file.h> | 22 | #include <linux/file.h> |
23 | #include <linux/binfmts.h> | 23 | #include <linux/binfmts.h> |
24 | #include <linux/nsproxy.h> | ||
24 | #include <linux/ptrace.h> | 25 | #include <linux/ptrace.h> |
25 | #include <linux/profile.h> | 26 | #include <linux/profile.h> |
26 | #include <linux/mount.h> | 27 | #include <linux/mount.h> |
@@ -397,9 +398,14 @@ void daemonize(const char *name, ...) | |||
397 | fs = init_task.fs; | 398 | fs = init_task.fs; |
398 | current->fs = fs; | 399 | current->fs = fs; |
399 | atomic_inc(&fs->count); | 400 | atomic_inc(&fs->count); |
401 | |||
400 | exit_namespace(current); | 402 | exit_namespace(current); |
403 | exit_task_namespaces(current); | ||
401 | current->namespace = init_task.namespace; | 404 | current->namespace = init_task.namespace; |
405 | current->nsproxy = init_task.nsproxy; | ||
402 | get_namespace(current->namespace); | 406 | get_namespace(current->namespace); |
407 | get_task_namespaces(current); | ||
408 | |||
403 | exit_files(current); | 409 | exit_files(current); |
404 | current->files = init_task.files; | 410 | current->files = init_task.files; |
405 | atomic_inc(¤t->files->count); | 411 | atomic_inc(¤t->files->count); |
@@ -918,6 +924,7 @@ fastcall NORET_TYPE void do_exit(long code) | |||
918 | __exit_files(tsk); | 924 | __exit_files(tsk); |
919 | __exit_fs(tsk); | 925 | __exit_fs(tsk); |
920 | exit_namespace(tsk); | 926 | exit_namespace(tsk); |
927 | exit_task_namespaces(tsk); | ||
921 | exit_thread(); | 928 | exit_thread(); |
922 | cpuset_exit(tsk); | 929 | cpuset_exit(tsk); |
923 | exit_keys(tsk); | 930 | exit_keys(tsk); |
diff --git a/kernel/fork.c b/kernel/fork.c index 89f666491d1f..c9e660ae47aa 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/binfmts.h> | 27 | #include <linux/binfmts.h> |
28 | #include <linux/mman.h> | 28 | #include <linux/mman.h> |
29 | #include <linux/fs.h> | 29 | #include <linux/fs.h> |
30 | #include <linux/nsproxy.h> | ||
30 | #include <linux/capability.h> | 31 | #include <linux/capability.h> |
31 | #include <linux/cpu.h> | 32 | #include <linux/cpu.h> |
32 | #include <linux/cpuset.h> | 33 | #include <linux/cpuset.h> |
@@ -1116,8 +1117,10 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1116 | goto bad_fork_cleanup_signal; | 1117 | goto bad_fork_cleanup_signal; |
1117 | if ((retval = copy_keys(clone_flags, p))) | 1118 | if ((retval = copy_keys(clone_flags, p))) |
1118 | goto bad_fork_cleanup_mm; | 1119 | goto bad_fork_cleanup_mm; |
1119 | if ((retval = copy_namespace(clone_flags, p))) | 1120 | if ((retval = copy_namespaces(clone_flags, p))) |
1120 | goto bad_fork_cleanup_keys; | 1121 | goto bad_fork_cleanup_keys; |
1122 | if ((retval = copy_namespace(clone_flags, p))) | ||
1123 | goto bad_fork_cleanup_namespaces; | ||
1121 | retval = copy_thread(0, clone_flags, stack_start, stack_size, p, regs); | 1124 | retval = copy_thread(0, clone_flags, stack_start, stack_size, p, regs); |
1122 | if (retval) | 1125 | if (retval) |
1123 | goto bad_fork_cleanup_namespace; | 1126 | goto bad_fork_cleanup_namespace; |
@@ -1262,6 +1265,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1262 | 1265 | ||
1263 | bad_fork_cleanup_namespace: | 1266 | bad_fork_cleanup_namespace: |
1264 | exit_namespace(p); | 1267 | exit_namespace(p); |
1268 | bad_fork_cleanup_namespaces: | ||
1269 | exit_task_namespaces(p); | ||
1265 | bad_fork_cleanup_keys: | 1270 | bad_fork_cleanup_keys: |
1266 | exit_keys(p); | 1271 | exit_keys(p); |
1267 | bad_fork_cleanup_mm: | 1272 | bad_fork_cleanup_mm: |
@@ -1606,6 +1611,7 @@ asmlinkage long sys_unshare(unsigned long unshare_flags) | |||
1606 | struct mm_struct *mm, *new_mm = NULL, *active_mm = NULL; | 1611 | struct mm_struct *mm, *new_mm = NULL, *active_mm = NULL; |
1607 | struct files_struct *fd, *new_fd = NULL; | 1612 | struct files_struct *fd, *new_fd = NULL; |
1608 | struct sem_undo_list *new_ulist = NULL; | 1613 | struct sem_undo_list *new_ulist = NULL; |
1614 | struct nsproxy *new_nsproxy, *old_nsproxy; | ||
1609 | 1615 | ||
1610 | check_unshare_flags(&unshare_flags); | 1616 | check_unshare_flags(&unshare_flags); |
1611 | 1617 | ||
@@ -1632,7 +1638,15 @@ asmlinkage long sys_unshare(unsigned long unshare_flags) | |||
1632 | 1638 | ||
1633 | if (new_fs || new_ns || new_sigh || new_mm || new_fd || new_ulist) { | 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 | task_lock(current); | 1648 | task_lock(current); |
1649 | current->nsproxy = new_nsproxy; | ||
1636 | 1650 | ||
1637 | if (new_fs) { | 1651 | if (new_fs) { |
1638 | fs = current->fs; | 1652 | fs = current->fs; |
@@ -1668,8 +1682,10 @@ asmlinkage long sys_unshare(unsigned long unshare_flags) | |||
1668 | } | 1682 | } |
1669 | 1683 | ||
1670 | task_unlock(current); | 1684 | task_unlock(current); |
1685 | put_nsproxy(old_nsproxy); | ||
1671 | } | 1686 | } |
1672 | 1687 | ||
1688 | bad_unshare_cleanup_semundo: | ||
1673 | bad_unshare_cleanup_fd: | 1689 | bad_unshare_cleanup_fd: |
1674 | if (new_fd) | 1690 | if (new_fd) |
1675 | put_files_struct(new_fd); | 1691 | put_files_struct(new_fd); |
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c new file mode 100644 index 000000000000..ad9508865473 --- /dev/null +++ b/kernel/nsproxy.c | |||
@@ -0,0 +1,77 @@ | |||
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 | } | ||