diff options
Diffstat (limited to 'kernel/capability.c')
-rw-r--r-- | kernel/capability.c | 112 |
1 files changed, 103 insertions, 9 deletions
diff --git a/kernel/capability.c b/kernel/capability.c index 2f05303715a5..283c529f8b1c 100644 --- a/kernel/capability.c +++ b/kernel/capability.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/security.h> | 14 | #include <linux/security.h> |
15 | #include <linux/syscalls.h> | 15 | #include <linux/syscalls.h> |
16 | #include <linux/pid_namespace.h> | 16 | #include <linux/pid_namespace.h> |
17 | #include <linux/user_namespace.h> | ||
17 | #include <asm/uaccess.h> | 18 | #include <asm/uaccess.h> |
18 | 19 | ||
19 | /* | 20 | /* |
@@ -21,12 +22,8 @@ | |||
21 | */ | 22 | */ |
22 | 23 | ||
23 | const kernel_cap_t __cap_empty_set = CAP_EMPTY_SET; | 24 | const kernel_cap_t __cap_empty_set = CAP_EMPTY_SET; |
24 | const kernel_cap_t __cap_full_set = CAP_FULL_SET; | ||
25 | const kernel_cap_t __cap_init_eff_set = CAP_INIT_EFF_SET; | ||
26 | 25 | ||
27 | EXPORT_SYMBOL(__cap_empty_set); | 26 | EXPORT_SYMBOL(__cap_empty_set); |
28 | EXPORT_SYMBOL(__cap_full_set); | ||
29 | EXPORT_SYMBOL(__cap_init_eff_set); | ||
30 | 27 | ||
31 | int file_caps_enabled = 1; | 28 | int file_caps_enabled = 1; |
32 | 29 | ||
@@ -290,6 +287,60 @@ error: | |||
290 | } | 287 | } |
291 | 288 | ||
292 | /** | 289 | /** |
290 | * has_capability - Does a task have a capability in init_user_ns | ||
291 | * @t: The task in question | ||
292 | * @cap: The capability to be tested for | ||
293 | * | ||
294 | * Return true if the specified task has the given superior capability | ||
295 | * currently in effect to the initial user namespace, false if not. | ||
296 | * | ||
297 | * Note that this does not set PF_SUPERPRIV on the task. | ||
298 | */ | ||
299 | bool has_capability(struct task_struct *t, int cap) | ||
300 | { | ||
301 | int ret = security_real_capable(t, &init_user_ns, cap); | ||
302 | |||
303 | return (ret == 0); | ||
304 | } | ||
305 | |||
306 | /** | ||
307 | * has_capability - Does a task have a capability in a specific user ns | ||
308 | * @t: The task in question | ||
309 | * @ns: target user namespace | ||
310 | * @cap: The capability to be tested for | ||
311 | * | ||
312 | * Return true if the specified task has the given superior capability | ||
313 | * currently in effect to the specified user namespace, false if not. | ||
314 | * | ||
315 | * Note that this does not set PF_SUPERPRIV on the task. | ||
316 | */ | ||
317 | bool has_ns_capability(struct task_struct *t, | ||
318 | struct user_namespace *ns, int cap) | ||
319 | { | ||
320 | int ret = security_real_capable(t, ns, cap); | ||
321 | |||
322 | return (ret == 0); | ||
323 | } | ||
324 | |||
325 | /** | ||
326 | * has_capability_noaudit - Does a task have a capability (unaudited) | ||
327 | * @t: The task in question | ||
328 | * @cap: The capability to be tested for | ||
329 | * | ||
330 | * Return true if the specified task has the given superior capability | ||
331 | * currently in effect to init_user_ns, false if not. Don't write an | ||
332 | * audit message for the check. | ||
333 | * | ||
334 | * Note that this does not set PF_SUPERPRIV on the task. | ||
335 | */ | ||
336 | bool has_capability_noaudit(struct task_struct *t, int cap) | ||
337 | { | ||
338 | int ret = security_real_capable_noaudit(t, &init_user_ns, cap); | ||
339 | |||
340 | return (ret == 0); | ||
341 | } | ||
342 | |||
343 | /** | ||
293 | * capable - Determine if the current task has a superior capability in effect | 344 | * capable - Determine if the current task has a superior capability in effect |
294 | * @cap: The capability to be tested for | 345 | * @cap: The capability to be tested for |
295 | * | 346 | * |
@@ -299,17 +350,60 @@ error: | |||
299 | * This sets PF_SUPERPRIV on the task if the capability is available on the | 350 | * This sets PF_SUPERPRIV on the task if the capability is available on the |
300 | * assumption that it's about to be used. | 351 | * assumption that it's about to be used. |
301 | */ | 352 | */ |
302 | int capable(int cap) | 353 | bool capable(int cap) |
354 | { | ||
355 | return ns_capable(&init_user_ns, cap); | ||
356 | } | ||
357 | EXPORT_SYMBOL(capable); | ||
358 | |||
359 | /** | ||
360 | * ns_capable - Determine if the current task has a superior capability in effect | ||
361 | * @ns: The usernamespace we want the capability in | ||
362 | * @cap: The capability to be tested for | ||
363 | * | ||
364 | * Return true if the current task has the given superior capability currently | ||
365 | * available for use, false if not. | ||
366 | * | ||
367 | * This sets PF_SUPERPRIV on the task if the capability is available on the | ||
368 | * assumption that it's about to be used. | ||
369 | */ | ||
370 | bool ns_capable(struct user_namespace *ns, int cap) | ||
303 | { | 371 | { |
304 | if (unlikely(!cap_valid(cap))) { | 372 | if (unlikely(!cap_valid(cap))) { |
305 | printk(KERN_CRIT "capable() called with invalid cap=%u\n", cap); | 373 | printk(KERN_CRIT "capable() called with invalid cap=%u\n", cap); |
306 | BUG(); | 374 | BUG(); |
307 | } | 375 | } |
308 | 376 | ||
309 | if (security_capable(cap) == 0) { | 377 | if (security_capable(ns, current_cred(), cap) == 0) { |
310 | current->flags |= PF_SUPERPRIV; | 378 | current->flags |= PF_SUPERPRIV; |
311 | return 1; | 379 | return true; |
312 | } | 380 | } |
313 | return 0; | 381 | return false; |
382 | } | ||
383 | EXPORT_SYMBOL(ns_capable); | ||
384 | |||
385 | /** | ||
386 | * task_ns_capable - Determine whether current task has a superior | ||
387 | * capability targeted at a specific task's user namespace. | ||
388 | * @t: The task whose user namespace is targeted. | ||
389 | * @cap: The capability in question. | ||
390 | * | ||
391 | * Return true if it does, false otherwise. | ||
392 | */ | ||
393 | bool task_ns_capable(struct task_struct *t, int cap) | ||
394 | { | ||
395 | return ns_capable(task_cred_xxx(t, user)->user_ns, cap); | ||
396 | } | ||
397 | EXPORT_SYMBOL(task_ns_capable); | ||
398 | |||
399 | /** | ||
400 | * nsown_capable - Check superior capability to one's own user_ns | ||
401 | * @cap: The capability in question | ||
402 | * | ||
403 | * Return true if the current task has the given superior capability | ||
404 | * targeted at its own user namespace. | ||
405 | */ | ||
406 | bool nsown_capable(int cap) | ||
407 | { | ||
408 | return ns_capable(current_user_ns(), cap); | ||
314 | } | 409 | } |
315 | EXPORT_SYMBOL(capable); | ||