diff options
author | Serge E. Hallyn <serue@us.ibm.com> | 2006-10-02 05:18:14 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-02 10:57:21 -0400 |
commit | 4865ecf1315b450ab3317a745a6678c04d311e40 (patch) | |
tree | 6cf5d3028f8642eba2a8094eb413db080cc9219c | |
parent | 96b644bdec977b97a45133e5b4466ba47a7a5e65 (diff) |
[PATCH] namespaces: utsname: implement utsname namespaces
This patch defines the uts namespace and some manipulators.
Adds the uts namespace to task_struct, and initializes a
system-wide init namespace.
It leaves a #define for system_utsname so sysctl will compile.
This define will be removed in a separate patch.
[akpm@osdl.org: build fix, cleanup]
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>
-rw-r--r-- | include/linux/init_task.h | 2 | ||||
-rw-r--r-- | include/linux/nsproxy.h | 2 | ||||
-rw-r--r-- | include/linux/sched.h | 1 | ||||
-rw-r--r-- | include/linux/utsname.h | 40 | ||||
-rw-r--r-- | init/Kconfig | 8 | ||||
-rw-r--r-- | init/version.c | 23 | ||||
-rw-r--r-- | kernel/Makefile | 1 | ||||
-rw-r--r-- | kernel/nsproxy.c | 14 | ||||
-rw-r--r-- | kernel/utsname.c | 42 |
9 files changed, 121 insertions, 12 deletions
diff --git a/include/linux/init_task.h b/include/linux/init_task.h index 4865348ca8bd..e08531ec32f0 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h | |||
@@ -4,6 +4,7 @@ | |||
4 | #include <linux/file.h> | 4 | #include <linux/file.h> |
5 | #include <linux/rcupdate.h> | 5 | #include <linux/rcupdate.h> |
6 | #include <linux/irqflags.h> | 6 | #include <linux/irqflags.h> |
7 | #include <linux/utsname.h> | ||
7 | #include <linux/lockdep.h> | 8 | #include <linux/lockdep.h> |
8 | 9 | ||
9 | #define INIT_FDTABLE \ | 10 | #define INIT_FDTABLE \ |
@@ -72,6 +73,7 @@ extern struct nsproxy init_nsproxy; | |||
72 | #define INIT_NSPROXY(nsproxy) { \ | 73 | #define INIT_NSPROXY(nsproxy) { \ |
73 | .count = ATOMIC_INIT(1), \ | 74 | .count = ATOMIC_INIT(1), \ |
74 | .nslock = SPIN_LOCK_UNLOCKED, \ | 75 | .nslock = SPIN_LOCK_UNLOCKED, \ |
76 | .uts_ns = &init_uts_ns, \ | ||
75 | .namespace = NULL, \ | 77 | .namespace = NULL, \ |
76 | } | 78 | } |
77 | 79 | ||
diff --git a/include/linux/nsproxy.h b/include/linux/nsproxy.h index 7ebe66670c59..9c2e0ad508db 100644 --- a/include/linux/nsproxy.h +++ b/include/linux/nsproxy.h | |||
@@ -5,6 +5,7 @@ | |||
5 | #include <linux/sched.h> | 5 | #include <linux/sched.h> |
6 | 6 | ||
7 | struct namespace; | 7 | struct namespace; |
8 | struct uts_namespace; | ||
8 | 9 | ||
9 | /* | 10 | /* |
10 | * A structure to contain pointers to all per-process | 11 | * A structure to contain pointers to all per-process |
@@ -21,6 +22,7 @@ struct namespace; | |||
21 | struct nsproxy { | 22 | struct nsproxy { |
22 | atomic_t count; | 23 | atomic_t count; |
23 | spinlock_t nslock; | 24 | spinlock_t nslock; |
25 | struct uts_namespace *uts_ns; | ||
24 | struct namespace *namespace; | 26 | struct namespace *namespace; |
25 | }; | 27 | }; |
26 | extern struct nsproxy init_nsproxy; | 28 | extern struct nsproxy init_nsproxy; |
diff --git a/include/linux/sched.h b/include/linux/sched.h index 670b89a20070..46d6f5be72f2 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -753,6 +753,7 @@ static inline void prefetch_stack(struct task_struct *t) { } | |||
753 | struct audit_context; /* See audit.c */ | 753 | struct audit_context; /* See audit.c */ |
754 | struct mempolicy; | 754 | struct mempolicy; |
755 | struct pipe_inode_info; | 755 | struct pipe_inode_info; |
756 | struct uts_namespace; | ||
756 | 757 | ||
757 | enum sleep_type { | 758 | enum sleep_type { |
758 | SLEEP_NORMAL, | 759 | SLEEP_NORMAL, |
diff --git a/include/linux/utsname.h b/include/linux/utsname.h index 77e97a5755d9..afa54e1542b3 100644 --- a/include/linux/utsname.h +++ b/include/linux/utsname.h | |||
@@ -1,6 +1,11 @@ | |||
1 | #ifndef _LINUX_UTSNAME_H | 1 | #ifndef _LINUX_UTSNAME_H |
2 | #define _LINUX_UTSNAME_H | 2 | #define _LINUX_UTSNAME_H |
3 | 3 | ||
4 | #include <linux/sched.h> | ||
5 | #include <linux/kref.h> | ||
6 | #include <linux/nsproxy.h> | ||
7 | #include <asm/atomic.h> | ||
8 | |||
4 | #define __OLD_UTS_LEN 8 | 9 | #define __OLD_UTS_LEN 8 |
5 | 10 | ||
6 | struct oldold_utsname { | 11 | struct oldold_utsname { |
@@ -30,17 +35,46 @@ struct new_utsname { | |||
30 | char domainname[65]; | 35 | char domainname[65]; |
31 | }; | 36 | }; |
32 | 37 | ||
33 | extern struct new_utsname system_utsname; | 38 | struct uts_namespace { |
39 | struct kref kref; | ||
40 | struct new_utsname name; | ||
41 | }; | ||
42 | extern struct uts_namespace init_uts_ns; | ||
43 | |||
44 | static inline void get_uts_ns(struct uts_namespace *ns) | ||
45 | { | ||
46 | kref_get(&ns->kref); | ||
47 | } | ||
48 | |||
49 | #ifdef CONFIG_UTS_NS | ||
50 | extern int copy_utsname(int flags, struct task_struct *tsk); | ||
51 | extern void free_uts_ns(struct kref *kref); | ||
52 | |||
53 | static inline void put_uts_ns(struct uts_namespace *ns) | ||
54 | { | ||
55 | kref_put(&ns->kref, free_uts_ns); | ||
56 | } | ||
57 | #else | ||
58 | static inline int copy_utsname(int flags, struct task_struct *tsk) | ||
59 | { | ||
60 | return 0; | ||
61 | } | ||
62 | static inline void put_uts_ns(struct uts_namespace *ns) | ||
63 | { | ||
64 | } | ||
65 | #endif | ||
34 | 66 | ||
35 | static inline struct new_utsname *utsname(void) | 67 | static inline struct new_utsname *utsname(void) |
36 | { | 68 | { |
37 | return &system_utsname; | 69 | return ¤t->nsproxy->uts_ns->name; |
38 | } | 70 | } |
39 | 71 | ||
40 | static inline struct new_utsname *init_utsname(void) | 72 | static inline struct new_utsname *init_utsname(void) |
41 | { | 73 | { |
42 | return &system_utsname; | 74 | return &init_uts_ns.name; |
43 | } | 75 | } |
44 | 76 | ||
77 | #define system_utsname init_uts_ns.name | ||
78 | |||
45 | extern struct rw_semaphore uts_sem; | 79 | extern struct rw_semaphore uts_sem; |
46 | #endif | 80 | #endif |
diff --git a/init/Kconfig b/init/Kconfig index f7a04d0daf07..b0ea97554473 100644 --- a/init/Kconfig +++ b/init/Kconfig | |||
@@ -182,6 +182,14 @@ config TASK_DELAY_ACCT | |||
182 | 182 | ||
183 | Say N if unsure. | 183 | Say N if unsure. |
184 | 184 | ||
185 | config UTS_NS | ||
186 | bool "UTS Namespaces" | ||
187 | default n | ||
188 | help | ||
189 | Support uts namespaces. This allows containers, i.e. | ||
190 | vservers, to use uts namespaces to provide different | ||
191 | uts info for different servers. If unsure, say N. | ||
192 | |||
185 | config AUDIT | 193 | config AUDIT |
186 | bool "Auditing support" | 194 | bool "Auditing support" |
187 | depends on NET | 195 | depends on NET |
diff --git a/init/version.c b/init/version.c index e290802c6bd2..8f28344d9c70 100644 --- a/init/version.c +++ b/init/version.c | |||
@@ -12,22 +12,27 @@ | |||
12 | #include <linux/utsname.h> | 12 | #include <linux/utsname.h> |
13 | #include <linux/utsrelease.h> | 13 | #include <linux/utsrelease.h> |
14 | #include <linux/version.h> | 14 | #include <linux/version.h> |
15 | #include <linux/sched.h> | ||
15 | 16 | ||
16 | #define version(a) Version_ ## a | 17 | #define version(a) Version_ ## a |
17 | #define version_string(a) version(a) | 18 | #define version_string(a) version(a) |
18 | 19 | ||
19 | int version_string(LINUX_VERSION_CODE); | 20 | int version_string(LINUX_VERSION_CODE); |
20 | 21 | ||
21 | struct new_utsname system_utsname = { | 22 | struct uts_namespace init_uts_ns = { |
22 | .sysname = UTS_SYSNAME, | 23 | .kref = { |
23 | .nodename = UTS_NODENAME, | 24 | .refcount = ATOMIC_INIT(2), |
24 | .release = UTS_RELEASE, | 25 | }, |
25 | .version = UTS_VERSION, | 26 | .name = { |
26 | .machine = UTS_MACHINE, | 27 | .sysname = UTS_SYSNAME, |
27 | .domainname = UTS_DOMAINNAME, | 28 | .nodename = UTS_NODENAME, |
29 | .release = UTS_RELEASE, | ||
30 | .version = UTS_VERSION, | ||
31 | .machine = UTS_MACHINE, | ||
32 | .domainname = UTS_DOMAINNAME, | ||
33 | }, | ||
28 | }; | 34 | }; |
29 | 35 | EXPORT_SYMBOL_GPL(init_uts_ns); | |
30 | EXPORT_SYMBOL(system_utsname); | ||
31 | 36 | ||
32 | const char linux_banner[] = | 37 | const char linux_banner[] = |
33 | "Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@" | 38 | "Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@" |
diff --git a/kernel/Makefile b/kernel/Makefile index 6ec53009b866..d948ca12acf0 100644 --- a/kernel/Makefile +++ b/kernel/Makefile | |||
@@ -48,6 +48,7 @@ obj-$(CONFIG_GENERIC_HARDIRQS) += irq/ | |||
48 | obj-$(CONFIG_SECCOMP) += seccomp.o | 48 | obj-$(CONFIG_SECCOMP) += seccomp.o |
49 | obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o | 49 | obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o |
50 | obj-$(CONFIG_RELAY) += relay.o | 50 | obj-$(CONFIG_RELAY) += relay.o |
51 | obj-$(CONFIG_UTS_NS) += utsname.o | ||
51 | obj-$(CONFIG_TASK_DELAY_ACCT) += delayacct.o | 52 | obj-$(CONFIG_TASK_DELAY_ACCT) += delayacct.o |
52 | obj-$(CONFIG_TASKSTATS) += taskstats.o tsacct.o | 53 | obj-$(CONFIG_TASKSTATS) += taskstats.o tsacct.o |
53 | 54 | ||
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c index e10385c17f73..47c19280c55b 100644 --- a/kernel/nsproxy.c +++ b/kernel/nsproxy.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/nsproxy.h> | 14 | #include <linux/nsproxy.h> |
15 | #include <linux/init_task.h> | 15 | #include <linux/init_task.h> |
16 | #include <linux/namespace.h> | 16 | #include <linux/namespace.h> |
17 | #include <linux/utsname.h> | ||
17 | 18 | ||
18 | struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy); | 19 | struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy); |
19 | 20 | ||
@@ -59,6 +60,8 @@ struct nsproxy *dup_namespaces(struct nsproxy *orig) | |||
59 | if (ns) { | 60 | if (ns) { |
60 | if (ns->namespace) | 61 | if (ns->namespace) |
61 | get_namespace(ns->namespace); | 62 | get_namespace(ns->namespace); |
63 | if (ns->uts_ns) | ||
64 | get_uts_ns(ns->uts_ns); | ||
62 | } | 65 | } |
63 | 66 | ||
64 | return ns; | 67 | return ns; |
@@ -97,6 +100,15 @@ int copy_namespaces(int flags, struct task_struct *tsk) | |||
97 | goto out; | 100 | goto out; |
98 | } | 101 | } |
99 | 102 | ||
103 | err = copy_utsname(flags, tsk); | ||
104 | if (err) { | ||
105 | if (new_ns->namespace) | ||
106 | put_namespace(new_ns->namespace); | ||
107 | tsk->nsproxy = old_ns; | ||
108 | put_nsproxy(new_ns); | ||
109 | goto out; | ||
110 | } | ||
111 | |||
100 | out: | 112 | out: |
101 | put_nsproxy(old_ns); | 113 | put_nsproxy(old_ns); |
102 | return err; | 114 | return err; |
@@ -106,5 +118,7 @@ void free_nsproxy(struct nsproxy *ns) | |||
106 | { | 118 | { |
107 | if (ns->namespace) | 119 | if (ns->namespace) |
108 | put_namespace(ns->namespace); | 120 | put_namespace(ns->namespace); |
121 | if (ns->uts_ns) | ||
122 | put_uts_ns(ns->uts_ns); | ||
109 | kfree(ns); | 123 | kfree(ns); |
110 | } | 124 | } |
diff --git a/kernel/utsname.c b/kernel/utsname.c new file mode 100644 index 000000000000..1824384ecfa3 --- /dev/null +++ b/kernel/utsname.c | |||
@@ -0,0 +1,42 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004 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/uts.h> | ||
14 | #include <linux/utsname.h> | ||
15 | #include <linux/version.h> | ||
16 | |||
17 | /* | ||
18 | * Copy task tsk's utsname namespace, or clone it if flags | ||
19 | * specifies CLONE_NEWUTS. In latter case, changes to the | ||
20 | * utsname of this process won't be seen by parent, and vice | ||
21 | * versa. | ||
22 | */ | ||
23 | int copy_utsname(int flags, struct task_struct *tsk) | ||
24 | { | ||
25 | struct uts_namespace *old_ns = tsk->nsproxy->uts_ns; | ||
26 | int err = 0; | ||
27 | |||
28 | if (!old_ns) | ||
29 | return 0; | ||
30 | |||
31 | get_uts_ns(old_ns); | ||
32 | |||
33 | return err; | ||
34 | } | ||
35 | |||
36 | void free_uts_ns(struct kref *kref) | ||
37 | { | ||
38 | struct uts_namespace *ns; | ||
39 | |||
40 | ns = container_of(kref, struct uts_namespace, kref); | ||
41 | kfree(ns); | ||
42 | } | ||