aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/capability.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/capability.c')
-rw-r--r--kernel/capability.c103
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 */
300bool has_ns_capability(struct task_struct *t, 299bool 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 */
322bool has_capability(struct task_struct *t, int cap) 317bool 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 */
340bool has_ns_capability_noaudit(struct task_struct *t, 336bool 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 */
364bool has_capability_noaudit(struct task_struct *t, int cap) 353bool 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}
357EXPORT_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)
393EXPORT_SYMBOL(ns_capable); 383EXPORT_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 */
405bool capable(int cap) 393bool 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}
409EXPORT_SYMBOL(capable); 397EXPORT_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 */
437bool 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}