diff options
Diffstat (limited to 'kernel/utsname.c')
-rw-r--r-- | kernel/utsname.c | 51 |
1 files changed, 48 insertions, 3 deletions
diff --git a/kernel/utsname.c b/kernel/utsname.c index 8a82b4b8ea52..bff131b9510a 100644 --- a/kernel/utsname.c +++ b/kernel/utsname.c | |||
@@ -14,6 +14,8 @@ | |||
14 | #include <linux/utsname.h> | 14 | #include <linux/utsname.h> |
15 | #include <linux/err.h> | 15 | #include <linux/err.h> |
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include <linux/user_namespace.h> | ||
18 | #include <linux/proc_fs.h> | ||
17 | 19 | ||
18 | static struct uts_namespace *create_uts_ns(void) | 20 | static struct uts_namespace *create_uts_ns(void) |
19 | { | 21 | { |
@@ -30,7 +32,8 @@ static struct uts_namespace *create_uts_ns(void) | |||
30 | * @old_ns: namespace to clone | 32 | * @old_ns: namespace to clone |
31 | * Return NULL on error (failure to kmalloc), new ns otherwise | 33 | * Return NULL on error (failure to kmalloc), new ns otherwise |
32 | */ | 34 | */ |
33 | static struct uts_namespace *clone_uts_ns(struct uts_namespace *old_ns) | 35 | static struct uts_namespace *clone_uts_ns(struct task_struct *tsk, |
36 | struct uts_namespace *old_ns) | ||
34 | { | 37 | { |
35 | struct uts_namespace *ns; | 38 | struct uts_namespace *ns; |
36 | 39 | ||
@@ -40,6 +43,7 @@ static struct uts_namespace *clone_uts_ns(struct uts_namespace *old_ns) | |||
40 | 43 | ||
41 | down_read(&uts_sem); | 44 | down_read(&uts_sem); |
42 | memcpy(&ns->name, &old_ns->name, sizeof(ns->name)); | 45 | memcpy(&ns->name, &old_ns->name, sizeof(ns->name)); |
46 | ns->user_ns = get_user_ns(task_cred_xxx(tsk, user)->user_ns); | ||
43 | up_read(&uts_sem); | 47 | up_read(&uts_sem); |
44 | return ns; | 48 | return ns; |
45 | } | 49 | } |
@@ -50,8 +54,10 @@ static struct uts_namespace *clone_uts_ns(struct uts_namespace *old_ns) | |||
50 | * utsname of this process won't be seen by parent, and vice | 54 | * utsname of this process won't be seen by parent, and vice |
51 | * versa. | 55 | * versa. |
52 | */ | 56 | */ |
53 | struct uts_namespace *copy_utsname(unsigned long flags, struct uts_namespace *old_ns) | 57 | struct uts_namespace *copy_utsname(unsigned long flags, |
58 | struct task_struct *tsk) | ||
54 | { | 59 | { |
60 | struct uts_namespace *old_ns = tsk->nsproxy->uts_ns; | ||
55 | struct uts_namespace *new_ns; | 61 | struct uts_namespace *new_ns; |
56 | 62 | ||
57 | BUG_ON(!old_ns); | 63 | BUG_ON(!old_ns); |
@@ -60,7 +66,7 @@ struct uts_namespace *copy_utsname(unsigned long flags, struct uts_namespace *ol | |||
60 | if (!(flags & CLONE_NEWUTS)) | 66 | if (!(flags & CLONE_NEWUTS)) |
61 | return old_ns; | 67 | return old_ns; |
62 | 68 | ||
63 | new_ns = clone_uts_ns(old_ns); | 69 | new_ns = clone_uts_ns(tsk, old_ns); |
64 | 70 | ||
65 | put_uts_ns(old_ns); | 71 | put_uts_ns(old_ns); |
66 | return new_ns; | 72 | return new_ns; |
@@ -71,5 +77,44 @@ void free_uts_ns(struct kref *kref) | |||
71 | struct uts_namespace *ns; | 77 | struct uts_namespace *ns; |
72 | 78 | ||
73 | ns = container_of(kref, struct uts_namespace, kref); | 79 | ns = container_of(kref, struct uts_namespace, kref); |
80 | put_user_ns(ns->user_ns); | ||
74 | kfree(ns); | 81 | kfree(ns); |
75 | } | 82 | } |
83 | |||
84 | static void *utsns_get(struct task_struct *task) | ||
85 | { | ||
86 | struct uts_namespace *ns = NULL; | ||
87 | struct nsproxy *nsproxy; | ||
88 | |||
89 | rcu_read_lock(); | ||
90 | nsproxy = task_nsproxy(task); | ||
91 | if (nsproxy) { | ||
92 | ns = nsproxy->uts_ns; | ||
93 | get_uts_ns(ns); | ||
94 | } | ||
95 | rcu_read_unlock(); | ||
96 | |||
97 | return ns; | ||
98 | } | ||
99 | |||
100 | static void utsns_put(void *ns) | ||
101 | { | ||
102 | put_uts_ns(ns); | ||
103 | } | ||
104 | |||
105 | static int utsns_install(struct nsproxy *nsproxy, void *ns) | ||
106 | { | ||
107 | get_uts_ns(ns); | ||
108 | put_uts_ns(nsproxy->uts_ns); | ||
109 | nsproxy->uts_ns = ns; | ||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | const struct proc_ns_operations utsns_operations = { | ||
114 | .name = "uts", | ||
115 | .type = CLONE_NEWUTS, | ||
116 | .get = utsns_get, | ||
117 | .put = utsns_put, | ||
118 | .install = utsns_install, | ||
119 | }; | ||
120 | |||