diff options
Diffstat (limited to 'kernel/utsname.c')
-rw-r--r-- | kernel/utsname.c | 40 |
1 files changed, 35 insertions, 5 deletions
diff --git a/kernel/utsname.c b/kernel/utsname.c index 831ea7108232..6976cd47dcf6 100644 --- a/kernel/utsname.c +++ b/kernel/utsname.c | |||
@@ -17,6 +17,16 @@ | |||
17 | #include <linux/user_namespace.h> | 17 | #include <linux/user_namespace.h> |
18 | #include <linux/proc_ns.h> | 18 | #include <linux/proc_ns.h> |
19 | 19 | ||
20 | static struct ucounts *inc_uts_namespaces(struct user_namespace *ns) | ||
21 | { | ||
22 | return inc_ucount(ns, current_euid(), UCOUNT_UTS_NAMESPACES); | ||
23 | } | ||
24 | |||
25 | static void dec_uts_namespaces(struct ucounts *ucounts) | ||
26 | { | ||
27 | dec_ucount(ucounts, UCOUNT_UTS_NAMESPACES); | ||
28 | } | ||
29 | |||
20 | static struct uts_namespace *create_uts_ns(void) | 30 | static struct uts_namespace *create_uts_ns(void) |
21 | { | 31 | { |
22 | struct uts_namespace *uts_ns; | 32 | struct uts_namespace *uts_ns; |
@@ -36,18 +46,24 @@ static struct uts_namespace *clone_uts_ns(struct user_namespace *user_ns, | |||
36 | struct uts_namespace *old_ns) | 46 | struct uts_namespace *old_ns) |
37 | { | 47 | { |
38 | struct uts_namespace *ns; | 48 | struct uts_namespace *ns; |
49 | struct ucounts *ucounts; | ||
39 | int err; | 50 | int err; |
40 | 51 | ||
52 | err = -ENOSPC; | ||
53 | ucounts = inc_uts_namespaces(user_ns); | ||
54 | if (!ucounts) | ||
55 | goto fail; | ||
56 | |||
57 | err = -ENOMEM; | ||
41 | ns = create_uts_ns(); | 58 | ns = create_uts_ns(); |
42 | if (!ns) | 59 | if (!ns) |
43 | return ERR_PTR(-ENOMEM); | 60 | goto fail_dec; |
44 | 61 | ||
45 | err = ns_alloc_inum(&ns->ns); | 62 | err = ns_alloc_inum(&ns->ns); |
46 | if (err) { | 63 | if (err) |
47 | kfree(ns); | 64 | goto fail_free; |
48 | return ERR_PTR(err); | ||
49 | } | ||
50 | 65 | ||
66 | ns->ucounts = ucounts; | ||
51 | ns->ns.ops = &utsns_operations; | 67 | ns->ns.ops = &utsns_operations; |
52 | 68 | ||
53 | down_read(&uts_sem); | 69 | down_read(&uts_sem); |
@@ -55,6 +71,13 @@ static struct uts_namespace *clone_uts_ns(struct user_namespace *user_ns, | |||
55 | ns->user_ns = get_user_ns(user_ns); | 71 | ns->user_ns = get_user_ns(user_ns); |
56 | up_read(&uts_sem); | 72 | up_read(&uts_sem); |
57 | return ns; | 73 | return ns; |
74 | |||
75 | fail_free: | ||
76 | kfree(ns); | ||
77 | fail_dec: | ||
78 | dec_uts_namespaces(ucounts); | ||
79 | fail: | ||
80 | return ERR_PTR(err); | ||
58 | } | 81 | } |
59 | 82 | ||
60 | /* | 83 | /* |
@@ -85,6 +108,7 @@ void free_uts_ns(struct kref *kref) | |||
85 | struct uts_namespace *ns; | 108 | struct uts_namespace *ns; |
86 | 109 | ||
87 | ns = container_of(kref, struct uts_namespace, kref); | 110 | ns = container_of(kref, struct uts_namespace, kref); |
111 | dec_uts_namespaces(ns->ucounts); | ||
88 | put_user_ns(ns->user_ns); | 112 | put_user_ns(ns->user_ns); |
89 | ns_free_inum(&ns->ns); | 113 | ns_free_inum(&ns->ns); |
90 | kfree(ns); | 114 | kfree(ns); |
@@ -130,10 +154,16 @@ static int utsns_install(struct nsproxy *nsproxy, struct ns_common *new) | |||
130 | return 0; | 154 | return 0; |
131 | } | 155 | } |
132 | 156 | ||
157 | static struct user_namespace *utsns_owner(struct ns_common *ns) | ||
158 | { | ||
159 | return to_uts_ns(ns)->user_ns; | ||
160 | } | ||
161 | |||
133 | const struct proc_ns_operations utsns_operations = { | 162 | const struct proc_ns_operations utsns_operations = { |
134 | .name = "uts", | 163 | .name = "uts", |
135 | .type = CLONE_NEWUTS, | 164 | .type = CLONE_NEWUTS, |
136 | .get = utsns_get, | 165 | .get = utsns_get, |
137 | .put = utsns_put, | 166 | .put = utsns_put, |
138 | .install = utsns_install, | 167 | .install = utsns_install, |
168 | .owner = utsns_owner, | ||
139 | }; | 169 | }; |