diff options
Diffstat (limited to 'kernel/capability.c')
-rw-r--r-- | kernel/capability.c | 103 |
1 files changed, 35 insertions, 68 deletions
diff --git a/kernel/capability.c b/kernel/capability.c index 493d9725948..283c529f8b1 100644 --- a/kernel/capability.c +++ b/kernel/capability.c | |||
@@ -10,7 +10,7 @@ | |||
10 | #include <linux/audit.h> | 10 | #include <linux/audit.h> |
11 | #include <linux/capability.h> | 11 | #include <linux/capability.h> |
12 | #include <linux/mm.h> | 12 | #include <linux/mm.h> |
13 | #include <linux/export.h> | 13 | #include <linux/module.h> |
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> |
@@ -287,84 +287,74 @@ error: | |||
287 | } | 287 | } |
288 | 288 | ||
289 | /** | 289 | /** |
290 | * has_ns_capability - Does a task have a capability in a specific user ns | 290 | * has_capability - Does a task have a capability in init_user_ns |
291 | * @t: The task in question | 291 | * @t: The task in question |
292 | * @ns: target user namespace | ||
293 | * @cap: The capability to be tested for | 292 | * @cap: The capability to be tested for |
294 | * | 293 | * |
295 | * Return true if the specified task has the given superior capability | 294 | * Return true if the specified task has the given superior capability |
296 | * currently in effect to the specified user namespace, false if not. | 295 | * currently in effect to the initial user namespace, false if not. |
297 | * | 296 | * |
298 | * Note that this does not set PF_SUPERPRIV on the task. | 297 | * Note that this does not set PF_SUPERPRIV on the task. |
299 | */ | 298 | */ |
300 | bool has_ns_capability(struct task_struct *t, | 299 | bool has_capability(struct task_struct *t, int cap) |
301 | struct user_namespace *ns, int cap) | ||
302 | { | 300 | { |
303 | int ret; | 301 | int ret = security_real_capable(t, &init_user_ns, cap); |
304 | |||
305 | rcu_read_lock(); | ||
306 | ret = security_capable(__task_cred(t), ns, cap); | ||
307 | rcu_read_unlock(); | ||
308 | 302 | ||
309 | return (ret == 0); | 303 | return (ret == 0); |
310 | } | 304 | } |
311 | 305 | ||
312 | /** | 306 | /** |
313 | * has_capability - Does a task have a capability in init_user_ns | 307 | * has_capability - Does a task have a capability in a specific user ns |
314 | * @t: The task in question | 308 | * @t: The task in question |
309 | * @ns: target user namespace | ||
315 | * @cap: The capability to be tested for | 310 | * @cap: The capability to be tested for |
316 | * | 311 | * |
317 | * Return true if the specified task has the given superior capability | 312 | * Return true if the specified task has the given superior capability |
318 | * currently in effect to the initial user namespace, false if not. | 313 | * currently in effect to the specified user namespace, false if not. |
319 | * | 314 | * |
320 | * Note that this does not set PF_SUPERPRIV on the task. | 315 | * Note that this does not set PF_SUPERPRIV on the task. |
321 | */ | 316 | */ |
322 | bool has_capability(struct task_struct *t, int cap) | 317 | bool has_ns_capability(struct task_struct *t, |
318 | struct user_namespace *ns, int cap) | ||
323 | { | 319 | { |
324 | return has_ns_capability(t, &init_user_ns, cap); | 320 | int ret = security_real_capable(t, ns, cap); |
321 | |||
322 | return (ret == 0); | ||
325 | } | 323 | } |
326 | 324 | ||
327 | /** | 325 | /** |
328 | * has_ns_capability_noaudit - Does a task have a capability (unaudited) | 326 | * has_capability_noaudit - Does a task have a capability (unaudited) |
329 | * in a specific user ns. | ||
330 | * @t: The task in question | 327 | * @t: The task in question |
331 | * @ns: target user namespace | ||
332 | * @cap: The capability to be tested for | 328 | * @cap: The capability to be tested for |
333 | * | 329 | * |
334 | * Return true if the specified task has the given superior capability | 330 | * Return true if the specified task has the given superior capability |
335 | * currently in effect to the specified user namespace, false if not. | 331 | * currently in effect to init_user_ns, false if not. Don't write an |
336 | * Do not write an audit message for the check. | 332 | * audit message for the check. |
337 | * | 333 | * |
338 | * Note that this does not set PF_SUPERPRIV on the task. | 334 | * Note that this does not set PF_SUPERPRIV on the task. |
339 | */ | 335 | */ |
340 | bool has_ns_capability_noaudit(struct task_struct *t, | 336 | bool has_capability_noaudit(struct task_struct *t, int cap) |
341 | struct user_namespace *ns, int cap) | ||
342 | { | 337 | { |
343 | int ret; | 338 | int ret = security_real_capable_noaudit(t, &init_user_ns, cap); |
344 | |||
345 | rcu_read_lock(); | ||
346 | ret = security_capable_noaudit(__task_cred(t), ns, cap); | ||
347 | rcu_read_unlock(); | ||
348 | 339 | ||
349 | return (ret == 0); | 340 | return (ret == 0); |
350 | } | 341 | } |
351 | 342 | ||
352 | /** | 343 | /** |
353 | * has_capability_noaudit - Does a task have a capability (unaudited) in the | 344 | * capable - Determine if the current task has a superior capability in effect |
354 | * initial user ns | ||
355 | * @t: The task in question | ||
356 | * @cap: The capability to be tested for | 345 | * @cap: The capability to be tested for |
357 | * | 346 | * |
358 | * Return true if the specified task has the given superior capability | 347 | * Return true if the current task has the given superior capability currently |
359 | * currently in effect to init_user_ns, false if not. Don't write an | 348 | * available for use, false if not. |
360 | * audit message for the check. | ||
361 | * | 349 | * |
362 | * Note that this does not set PF_SUPERPRIV on the task. | 350 | * This sets PF_SUPERPRIV on the task if the capability is available on the |
351 | * assumption that it's about to be used. | ||
363 | */ | 352 | */ |
364 | bool has_capability_noaudit(struct task_struct *t, int cap) | 353 | bool capable(int cap) |
365 | { | 354 | { |
366 | return has_ns_capability_noaudit(t, &init_user_ns, cap); | 355 | return ns_capable(&init_user_ns, cap); |
367 | } | 356 | } |
357 | EXPORT_SYMBOL(capable); | ||
368 | 358 | ||
369 | /** | 359 | /** |
370 | * ns_capable - Determine if the current task has a superior capability in effect | 360 | * ns_capable - Determine if the current task has a superior capability in effect |
@@ -384,7 +374,7 @@ bool ns_capable(struct user_namespace *ns, int cap) | |||
384 | BUG(); | 374 | BUG(); |
385 | } | 375 | } |
386 | 376 | ||
387 | if (security_capable(current_cred(), ns, cap) == 0) { | 377 | if (security_capable(ns, current_cred(), cap) == 0) { |
388 | current->flags |= PF_SUPERPRIV; | 378 | current->flags |= PF_SUPERPRIV; |
389 | return true; | 379 | return true; |
390 | } | 380 | } |
@@ -393,20 +383,18 @@ bool ns_capable(struct user_namespace *ns, int cap) | |||
393 | EXPORT_SYMBOL(ns_capable); | 383 | EXPORT_SYMBOL(ns_capable); |
394 | 384 | ||
395 | /** | 385 | /** |
396 | * capable - Determine if the current task has a superior capability in effect | 386 | * task_ns_capable - Determine whether current task has a superior |
397 | * @cap: The capability to be tested for | 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. | ||
398 | * | 390 | * |
399 | * Return true if the current task has the given superior capability currently | 391 | * Return true if it does, false otherwise. |
400 | * available for use, false if not. | ||
401 | * | ||
402 | * This sets PF_SUPERPRIV on the task if the capability is available on the | ||
403 | * assumption that it's about to be used. | ||
404 | */ | 392 | */ |
405 | bool capable(int cap) | 393 | bool task_ns_capable(struct task_struct *t, int cap) |
406 | { | 394 | { |
407 | return ns_capable(&init_user_ns, cap); | 395 | return ns_capable(task_cred_xxx(t, user)->user_ns, cap); |
408 | } | 396 | } |
409 | EXPORT_SYMBOL(capable); | 397 | EXPORT_SYMBOL(task_ns_capable); |
410 | 398 | ||
411 | /** | 399 | /** |
412 | * nsown_capable - Check superior capability to one's own user_ns | 400 | * nsown_capable - Check superior capability to one's own user_ns |
@@ -419,24 +407,3 @@ bool nsown_capable(int cap) | |||
419 | { | 407 | { |
420 | return ns_capable(current_user_ns(), cap); | 408 | return ns_capable(current_user_ns(), cap); |
421 | } | 409 | } |
422 | |||
423 | /** | ||
424 | * inode_capable - Check superior capability over inode | ||
425 | * @inode: The inode in question | ||
426 | * @cap: The capability in question | ||
427 | * | ||
428 | * Return true if the current task has the given superior capability | ||
429 | * targeted at it's own user namespace and that the given inode is owned | ||
430 | * by the current user namespace or a child namespace. | ||
431 | * | ||
432 | * Currently we check to see if an inode is owned by the current | ||
433 | * user namespace by seeing if the inode's owner maps into the | ||
434 | * current user namespace. | ||
435 | * | ||
436 | */ | ||
437 | bool inode_capable(const struct inode *inode, int cap) | ||
438 | { | ||
439 | struct user_namespace *ns = current_user_ns(); | ||
440 | |||
441 | return ns_capable(ns, cap) && kuid_has_mapping(ns, inode->i_uid); | ||
442 | } | ||