1
2
3
4
5
6
7
8
9
10
11
12#include <linux/export.h>
13#include <linux/uts.h>
14#include <linux/utsname.h>
15#include <linux/err.h>
16#include <linux/slab.h>
17#include <linux/user_namespace.h>
18#include <linux/proc_ns.h>
19
20static struct ucounts *inc_uts_namespaces(struct user_namespace *ns)
21{
22 return inc_ucount(ns, current_euid(), UCOUNT_UTS_NAMESPACES);
23}
24
25static void dec_uts_namespaces(struct ucounts *ucounts)
26{
27 dec_ucount(ucounts, UCOUNT_UTS_NAMESPACES);
28}
29
30static struct uts_namespace *create_uts_ns(void)
31{
32 struct uts_namespace *uts_ns;
33
34 uts_ns = kmalloc(sizeof(struct uts_namespace), GFP_KERNEL);
35 if (uts_ns)
36 kref_init(&uts_ns->kref);
37 return uts_ns;
38}
39
40
41
42
43
44
45static struct uts_namespace *clone_uts_ns(struct user_namespace *user_ns,
46 struct uts_namespace *old_ns)
47{
48 struct uts_namespace *ns;
49 struct ucounts *ucounts;
50 int err;
51
52 err = -ENOSPC;
53 ucounts = inc_uts_namespaces(user_ns);
54 if (!ucounts)
55 goto fail;
56
57 err = -ENOMEM;
58 ns = create_uts_ns();
59 if (!ns)
60 goto fail_dec;
61
62 err = proc_alloc_inum(&ns->proc_inum);
63 if (err)
64 goto fail_free;
65
66 ns->ucounts = ucounts;
67
68 down_read(&uts_sem);
69 memcpy(&ns->name, &old_ns->name, sizeof(ns->name));
70 ns->user_ns = get_user_ns(user_ns);
71 up_read(&uts_sem);
72 return ns;
73
74fail_free:
75 kfree(ns);
76fail_dec:
77 dec_uts_namespaces(ucounts);
78fail:
79 return ERR_PTR(err);
80}
81
82
83
84
85
86
87
88struct uts_namespace *copy_utsname(unsigned long flags,
89 struct user_namespace *user_ns, struct uts_namespace *old_ns)
90{
91 struct uts_namespace *new_ns;
92
93 BUG_ON(!old_ns);
94 get_uts_ns(old_ns);
95
96 if (!(flags & CLONE_NEWUTS))
97 return old_ns;
98
99 new_ns = clone_uts_ns(user_ns, old_ns);
100
101 put_uts_ns(old_ns);
102 return new_ns;
103}
104
105void free_uts_ns(struct kref *kref)
106{
107 struct uts_namespace *ns;
108
109 ns = container_of(kref, struct uts_namespace, kref);
110 dec_uts_namespaces(ns->ucounts);
111 put_user_ns(ns->user_ns);
112 proc_free_inum(ns->proc_inum);
113 kfree(ns);
114}
115
116static void *utsns_get(struct task_struct *task)
117{
118 struct uts_namespace *ns = NULL;
119 struct nsproxy *nsproxy;
120
121 task_lock(task);
122 nsproxy = task->nsproxy;
123 if (nsproxy) {
124 ns = nsproxy->uts_ns;
125 get_uts_ns(ns);
126 }
127 task_unlock(task);
128
129 return ns;
130}
131
132static void utsns_put(void *ns)
133{
134 put_uts_ns(ns);
135}
136
137static int utsns_install(struct nsproxy *nsproxy, void *new)
138{
139 struct uts_namespace *ns = new;
140
141 if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN) ||
142 !ns_capable(current_user_ns(), CAP_SYS_ADMIN))
143 return -EPERM;
144
145 get_uts_ns(ns);
146 put_uts_ns(nsproxy->uts_ns);
147 nsproxy->uts_ns = ns;
148 return 0;
149}
150
151static unsigned int utsns_inum(void *vp)
152{
153 struct uts_namespace *ns = vp;
154
155 return ns->proc_inum;
156}
157
158const struct proc_ns_operations utsns_operations = {
159 .name = "uts",
160 .type = CLONE_NEWUTS,
161 .get = utsns_get,
162 .put = utsns_put,
163 .install = utsns_install,
164 .inum = utsns_inum,
165};
166