1
2
3
4
5
6
7
8
9
10#include <linux/audit.h>
11#include <linux/capability.h>
12#include <linux/mm.h>
13#include <linux/module.h>
14#include <linux/security.h>
15#include <linux/syscalls.h>
16#include <linux/pid_namespace.h>
17#include <asm/uaccess.h>
18
19
20
21
22
23const kernel_cap_t __cap_empty_set = CAP_EMPTY_SET;
24const kernel_cap_t __cap_full_set = CAP_FULL_SET;
25const kernel_cap_t __cap_init_eff_set = CAP_INIT_EFF_SET;
26
27EXPORT_SYMBOL(__cap_empty_set);
28EXPORT_SYMBOL(__cap_full_set);
29EXPORT_SYMBOL(__cap_init_eff_set);
30
31int file_caps_enabled = 1;
32
33static int __init file_caps_disable(char *str)
34{
35 file_caps_enabled = 0;
36 return 1;
37}
38__setup("no_file_caps", file_caps_disable);
39
40
41
42
43
44
45
46static void warn_legacy_capability_use(void)
47{
48 static int warned;
49 if (!warned) {
50 char name[sizeof(current->comm)];
51
52 printk(KERN_INFO "warning: `%s' uses 32-bit capabilities"
53 " (legacy support in use)\n",
54 get_task_comm(name, current));
55 warned = 1;
56 }
57}
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75static void warn_deprecated_v2(void)
76{
77 static int warned;
78
79 if (!warned) {
80 char name[sizeof(current->comm)];
81
82 printk(KERN_INFO "warning: `%s' uses deprecated v2"
83 " capabilities in a way that may be insecure.\n",
84 get_task_comm(name, current));
85 warned = 1;
86 }
87}
88
89
90
91
92
93static int cap_validate_magic(cap_user_header_t header, unsigned *tocopy)
94{
95 __u32 version;
96
97 if (get_user(version, &header->version))
98 return -EFAULT;
99
100 switch (version) {
101 case _LINUX_CAPABILITY_VERSION_1:
102 warn_legacy_capability_use();
103 *tocopy = _LINUX_CAPABILITY_U32S_1;
104 break;
105 case _LINUX_CAPABILITY_VERSION_2:
106 warn_deprecated_v2();
107
108
109
110 case _LINUX_CAPABILITY_VERSION_3:
111 *tocopy = _LINUX_CAPABILITY_U32S_3;
112 break;
113 default:
114 if (put_user((u32)_KERNEL_CAPABILITY_VERSION, &header->version))
115 return -EFAULT;
116 return -EINVAL;
117 }
118
119 return 0;
120}
121
122
123
124
125
126
127
128
129static inline int cap_get_target_pid(pid_t pid, kernel_cap_t *pEp,
130 kernel_cap_t *pIp, kernel_cap_t *pPp)
131{
132 int ret;
133
134 if (pid && (pid != task_pid_vnr(current))) {
135 struct task_struct *target;
136
137 rcu_read_lock();
138
139 target = find_task_by_vpid(pid);
140 if (!target)
141 ret = -ESRCH;
142 else
143 ret = security_capget(target, pEp, pIp, pPp);
144
145 rcu_read_unlock();
146 } else
147 ret = security_capget(current, pEp, pIp, pPp);
148
149 return ret;
150}
151
152
153
154
155
156
157
158
159
160
161SYSCALL_DEFINE2(capget, cap_user_header_t, header, cap_user_data_t, dataptr)
162{
163 int ret = 0;
164 pid_t pid;
165 unsigned tocopy;
166 kernel_cap_t pE, pI, pP;
167
168 ret = cap_validate_magic(header, &tocopy);
169 if ((dataptr == NULL) || (ret != 0))
170 return ((dataptr == NULL) && (ret == -EINVAL)) ? 0 : ret;
171
172 if (get_user(pid, &header->pid))
173 return -EFAULT;
174
175 if (pid < 0)
176 return -EINVAL;
177
178 ret = cap_get_target_pid(pid, &pE, &pI, &pP);
179 if (!ret) {
180 struct __user_cap_data_struct kdata[_KERNEL_CAPABILITY_U32S];
181 unsigned i;
182
183 for (i = 0; i < tocopy; i++) {
184 kdata[i].effective = pE.cap[i];
185 kdata[i].permitted = pP.cap[i];
186 kdata[i].inheritable = pI.cap[i];
187 }
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208 if (copy_to_user(dataptr, kdata, tocopy
209 * sizeof(struct __user_cap_data_struct))) {
210 return -EFAULT;
211 }
212 }
213
214 return ret;
215}
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235SYSCALL_DEFINE2(capset, cap_user_header_t, header, const cap_user_data_t, data)
236{
237 struct __user_cap_data_struct kdata[_KERNEL_CAPABILITY_U32S];
238 unsigned i, tocopy, copybytes;
239 kernel_cap_t inheritable, permitted, effective;
240 struct cred *new;
241 int ret;
242 pid_t pid;
243
244 ret = cap_validate_magic(header, &tocopy);
245 if (ret != 0)
246 return ret;
247
248 if (get_user(pid, &header->pid))
249 return -EFAULT;
250
251
252 if (pid != 0 && pid != task_pid_vnr(current))
253 return -EPERM;
254
255 copybytes = tocopy * sizeof(struct __user_cap_data_struct);
256 if (copybytes > sizeof(kdata))
257 return -EFAULT;
258
259 if (copy_from_user(&kdata, data, copybytes))
260 return -EFAULT;
261
262 for (i = 0; i < tocopy; i++) {
263 effective.cap[i] = kdata[i].effective;
264 permitted.cap[i] = kdata[i].permitted;
265 inheritable.cap[i] = kdata[i].inheritable;
266 }
267 while (i < _KERNEL_CAPABILITY_U32S) {
268 effective.cap[i] = 0;
269 permitted.cap[i] = 0;
270 inheritable.cap[i] = 0;
271 i++;
272 }
273
274 new = prepare_creds();
275 if (!new)
276 return -ENOMEM;
277
278 ret = security_capset(new, current_cred(),
279 &effective, &inheritable, &permitted);
280 if (ret < 0)
281 goto error;
282
283 audit_log_capset(pid, new, current_cred());
284
285 return commit_creds(new);
286
287error:
288 abort_creds(new);
289 return ret;
290}
291
292
293
294
295
296
297
298
299
300
301
302int capable(int cap)
303{
304 if (unlikely(!cap_valid(cap))) {
305 printk(KERN_CRIT "capable() called with invalid cap=%u\n", cap);
306 BUG();
307 }
308
309 if (security_capable(current_cred(), cap) == 0) {
310 current->flags |= PF_SUPERPRIV;
311 return 1;
312 }
313 return 0;
314}
315EXPORT_SYMBOL(capable);
316