summaryrefslogtreecommitdiffstats
path: root/kernel/capability.c
diff options
context:
space:
mode:
authorMicah Morton <mortonm@chromium.org>2019-01-07 19:10:53 -0500
committerJames Morris <james.morris@microsoft.com>2019-01-10 17:16:06 -0500
commitc1a85a00ea66cb6f0bd0f14e47c28c2b0999799f (patch)
tree310c082e0b41d2d3ff8b619553ed5e45ad244862 /kernel/capability.c
parent2233975cd7927672525361c4c6eebc0b8d018a74 (diff)
LSM: generalize flag passing to security_capable
This patch provides a general mechanism for passing flags to the security_capable LSM hook. It replaces the specific 'audit' flag that is used to tell security_capable whether it should log an audit message for the given capability check. The reason for generalizing this flag passing is so we can add an additional flag that signifies whether security_capable is being called by a setid syscall (which is needed by the proposed SafeSetID LSM). Signed-off-by: Micah Morton <mortonm@chromium.org> Reviewed-by: Kees Cook <keescook@chromium.org> Signed-off-by: James Morris <james.morris@microsoft.com>
Diffstat (limited to 'kernel/capability.c')
-rw-r--r--kernel/capability.c22
1 files changed, 13 insertions, 9 deletions
diff --git a/kernel/capability.c b/kernel/capability.c
index 1e1c0236f55b..7718d7dcadc7 100644
--- a/kernel/capability.c
+++ b/kernel/capability.c
@@ -299,7 +299,7 @@ bool has_ns_capability(struct task_struct *t,
299 int ret; 299 int ret;
300 300
301 rcu_read_lock(); 301 rcu_read_lock();
302 ret = security_capable(__task_cred(t), ns, cap); 302 ret = security_capable(__task_cred(t), ns, cap, CAP_OPT_NONE);
303 rcu_read_unlock(); 303 rcu_read_unlock();
304 304
305 return (ret == 0); 305 return (ret == 0);
@@ -340,7 +340,7 @@ bool has_ns_capability_noaudit(struct task_struct *t,
340 int ret; 340 int ret;
341 341
342 rcu_read_lock(); 342 rcu_read_lock();
343 ret = security_capable_noaudit(__task_cred(t), ns, cap); 343 ret = security_capable(__task_cred(t), ns, cap, CAP_OPT_NOAUDIT);
344 rcu_read_unlock(); 344 rcu_read_unlock();
345 345
346 return (ret == 0); 346 return (ret == 0);
@@ -363,7 +363,9 @@ bool has_capability_noaudit(struct task_struct *t, int cap)
363 return has_ns_capability_noaudit(t, &init_user_ns, cap); 363 return has_ns_capability_noaudit(t, &init_user_ns, cap);
364} 364}
365 365
366static bool ns_capable_common(struct user_namespace *ns, int cap, bool audit) 366static bool ns_capable_common(struct user_namespace *ns,
367 int cap,
368 unsigned int opts)
367{ 369{
368 int capable; 370 int capable;
369 371
@@ -372,8 +374,7 @@ static bool ns_capable_common(struct user_namespace *ns, int cap, bool audit)
372 BUG(); 374 BUG();
373 } 375 }
374 376
375 capable = audit ? security_capable(current_cred(), ns, cap) : 377 capable = security_capable(current_cred(), ns, cap, opts);
376 security_capable_noaudit(current_cred(), ns, cap);
377 if (capable == 0) { 378 if (capable == 0) {
378 current->flags |= PF_SUPERPRIV; 379 current->flags |= PF_SUPERPRIV;
379 return true; 380 return true;
@@ -394,7 +395,7 @@ static bool ns_capable_common(struct user_namespace *ns, int cap, bool audit)
394 */ 395 */
395bool ns_capable(struct user_namespace *ns, int cap) 396bool ns_capable(struct user_namespace *ns, int cap)
396{ 397{
397 return ns_capable_common(ns, cap, true); 398 return ns_capable_common(ns, cap, CAP_OPT_NONE);
398} 399}
399EXPORT_SYMBOL(ns_capable); 400EXPORT_SYMBOL(ns_capable);
400 401
@@ -412,7 +413,7 @@ EXPORT_SYMBOL(ns_capable);
412 */ 413 */
413bool ns_capable_noaudit(struct user_namespace *ns, int cap) 414bool ns_capable_noaudit(struct user_namespace *ns, int cap)
414{ 415{
415 return ns_capable_common(ns, cap, false); 416 return ns_capable_common(ns, cap, CAP_OPT_NOAUDIT);
416} 417}
417EXPORT_SYMBOL(ns_capable_noaudit); 418EXPORT_SYMBOL(ns_capable_noaudit);
418 419
@@ -448,10 +449,11 @@ EXPORT_SYMBOL(capable);
448bool file_ns_capable(const struct file *file, struct user_namespace *ns, 449bool file_ns_capable(const struct file *file, struct user_namespace *ns,
449 int cap) 450 int cap)
450{ 451{
452
451 if (WARN_ON_ONCE(!cap_valid(cap))) 453 if (WARN_ON_ONCE(!cap_valid(cap)))
452 return false; 454 return false;
453 455
454 if (security_capable(file->f_cred, ns, cap) == 0) 456 if (security_capable(file->f_cred, ns, cap, CAP_OPT_NONE) == 0)
455 return true; 457 return true;
456 458
457 return false; 459 return false;
@@ -500,10 +502,12 @@ bool ptracer_capable(struct task_struct *tsk, struct user_namespace *ns)
500{ 502{
501 int ret = 0; /* An absent tracer adds no restrictions */ 503 int ret = 0; /* An absent tracer adds no restrictions */
502 const struct cred *cred; 504 const struct cred *cred;
505
503 rcu_read_lock(); 506 rcu_read_lock();
504 cred = rcu_dereference(tsk->ptracer_cred); 507 cred = rcu_dereference(tsk->ptracer_cred);
505 if (cred) 508 if (cred)
506 ret = security_capable_noaudit(cred, ns, CAP_SYS_PTRACE); 509 ret = security_capable(cred, ns, CAP_SYS_PTRACE,
510 CAP_OPT_NOAUDIT);
507 rcu_read_unlock(); 511 rcu_read_unlock();
508 return (ret == 0); 512 return (ret == 0);
509} 513}