aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/avc.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-05-21 23:27:36 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-05-21 23:27:36 -0400
commitcb60e3e65c1b96a4d6444a7a13dc7dd48bc15a2b (patch)
tree4322be35db678f6299348a76ad60a2023954af7d /security/selinux/avc.c
parent99262a3dafa3290866512ddfb32609198f8973e9 (diff)
parentff2bb047c4bce9742e94911eeb44b4d6ff4734ab (diff)
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security subsystem updates from James Morris: "New notable features: - The seccomp work from Will Drewry - PR_{GET,SET}_NO_NEW_PRIVS from Andy Lutomirski - Longer security labels for Smack from Casey Schaufler - Additional ptrace restriction modes for Yama by Kees Cook" Fix up trivial context conflicts in arch/x86/Kconfig and include/linux/filter.h * 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (65 commits) apparmor: fix long path failure due to disconnected path apparmor: fix profile lookup for unconfined ima: fix filename hint to reflect script interpreter name KEYS: Don't check for NULL key pointer in key_validate() Smack: allow for significantly longer Smack labels v4 gfp flags for security_inode_alloc()? Smack: recursive tramsmute Yama: replace capable() with ns_capable() TOMOYO: Accept manager programs which do not start with / . KEYS: Add invalidation support KEYS: Do LRU discard in full keyrings KEYS: Permit in-place link replacement in keyring list KEYS: Perform RCU synchronisation on keys prior to key destruction KEYS: Announce key type (un)registration KEYS: Reorganise keys Makefile KEYS: Move the key config into security/keys/Kconfig KEYS: Use the compat keyctl() syscall wrapper on Sparc64 for Sparc32 compat Yama: remove an unused variable samples/seccomp: fix dependencies on arch macros Yama: add additional ptrace scopes ...
Diffstat (limited to 'security/selinux/avc.c')
-rw-r--r--security/selinux/avc.c130
1 files changed, 24 insertions, 106 deletions
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index 8ee42b2a5f19..68d82daed257 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -65,14 +65,8 @@ struct avc_cache {
65}; 65};
66 66
67struct avc_callback_node { 67struct avc_callback_node {
68 int (*callback) (u32 event, u32 ssid, u32 tsid, 68 int (*callback) (u32 event);
69 u16 tclass, u32 perms,
70 u32 *out_retained);
71 u32 events; 69 u32 events;
72 u32 ssid;
73 u32 tsid;
74 u16 tclass;
75 u32 perms;
76 struct avc_callback_node *next; 70 struct avc_callback_node *next;
77}; 71};
78 72
@@ -436,9 +430,9 @@ static void avc_audit_pre_callback(struct audit_buffer *ab, void *a)
436{ 430{
437 struct common_audit_data *ad = a; 431 struct common_audit_data *ad = a;
438 audit_log_format(ab, "avc: %s ", 432 audit_log_format(ab, "avc: %s ",
439 ad->selinux_audit_data->slad->denied ? "denied" : "granted"); 433 ad->selinux_audit_data->denied ? "denied" : "granted");
440 avc_dump_av(ab, ad->selinux_audit_data->slad->tclass, 434 avc_dump_av(ab, ad->selinux_audit_data->tclass,
441 ad->selinux_audit_data->slad->audited); 435 ad->selinux_audit_data->audited);
442 audit_log_format(ab, " for "); 436 audit_log_format(ab, " for ");
443} 437}
444 438
@@ -452,25 +446,23 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a)
452{ 446{
453 struct common_audit_data *ad = a; 447 struct common_audit_data *ad = a;
454 audit_log_format(ab, " "); 448 audit_log_format(ab, " ");
455 avc_dump_query(ab, ad->selinux_audit_data->slad->ssid, 449 avc_dump_query(ab, ad->selinux_audit_data->ssid,
456 ad->selinux_audit_data->slad->tsid, 450 ad->selinux_audit_data->tsid,
457 ad->selinux_audit_data->slad->tclass); 451 ad->selinux_audit_data->tclass);
458} 452}
459 453
460/* This is the slow part of avc audit with big stack footprint */ 454/* This is the slow part of avc audit with big stack footprint */
461static noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass, 455noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass,
462 u32 requested, u32 audited, u32 denied, 456 u32 requested, u32 audited, u32 denied,
463 struct common_audit_data *a, 457 struct common_audit_data *a,
464 unsigned flags) 458 unsigned flags)
465{ 459{
466 struct common_audit_data stack_data; 460 struct common_audit_data stack_data;
467 struct selinux_audit_data sad = {0,}; 461 struct selinux_audit_data sad;
468 struct selinux_late_audit_data slad;
469 462
470 if (!a) { 463 if (!a) {
471 a = &stack_data; 464 a = &stack_data;
472 COMMON_AUDIT_DATA_INIT(a, NONE); 465 a->type = LSM_AUDIT_DATA_NONE;
473 a->selinux_audit_data = &sad;
474 } 466 }
475 467
476 /* 468 /*
@@ -484,104 +476,34 @@ static noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass,
484 (flags & MAY_NOT_BLOCK)) 476 (flags & MAY_NOT_BLOCK))
485 return -ECHILD; 477 return -ECHILD;
486 478
487 slad.tclass = tclass; 479 sad.tclass = tclass;
488 slad.requested = requested; 480 sad.requested = requested;
489 slad.ssid = ssid; 481 sad.ssid = ssid;
490 slad.tsid = tsid; 482 sad.tsid = tsid;
491 slad.audited = audited; 483 sad.audited = audited;
492 slad.denied = denied; 484 sad.denied = denied;
485
486 a->selinux_audit_data = &sad;
493 487
494 a->selinux_audit_data->slad = &slad;
495 common_lsm_audit(a, avc_audit_pre_callback, avc_audit_post_callback); 488 common_lsm_audit(a, avc_audit_pre_callback, avc_audit_post_callback);
496 return 0; 489 return 0;
497} 490}
498 491
499/** 492/**
500 * avc_audit - Audit the granting or denial of permissions.
501 * @ssid: source security identifier
502 * @tsid: target security identifier
503 * @tclass: target security class
504 * @requested: requested permissions
505 * @avd: access vector decisions
506 * @result: result from avc_has_perm_noaudit
507 * @a: auxiliary audit data
508 * @flags: VFS walk flags
509 *
510 * Audit the granting or denial of permissions in accordance
511 * with the policy. This function is typically called by
512 * avc_has_perm() after a permission check, but can also be
513 * called directly by callers who use avc_has_perm_noaudit()
514 * in order to separate the permission check from the auditing.
515 * For example, this separation is useful when the permission check must
516 * be performed under a lock, to allow the lock to be released
517 * before calling the auditing code.
518 */
519inline int avc_audit(u32 ssid, u32 tsid,
520 u16 tclass, u32 requested,
521 struct av_decision *avd, int result, struct common_audit_data *a,
522 unsigned flags)
523{
524 u32 denied, audited;
525 denied = requested & ~avd->allowed;
526 if (unlikely(denied)) {
527 audited = denied & avd->auditdeny;
528 /*
529 * a->selinux_audit_data->auditdeny is TRICKY! Setting a bit in
530 * this field means that ANY denials should NOT be audited if
531 * the policy contains an explicit dontaudit rule for that
532 * permission. Take notice that this is unrelated to the
533 * actual permissions that were denied. As an example lets
534 * assume:
535 *
536 * denied == READ
537 * avd.auditdeny & ACCESS == 0 (not set means explicit rule)
538 * selinux_audit_data->auditdeny & ACCESS == 1
539 *
540 * We will NOT audit the denial even though the denied
541 * permission was READ and the auditdeny checks were for
542 * ACCESS
543 */
544 if (a &&
545 a->selinux_audit_data->auditdeny &&
546 !(a->selinux_audit_data->auditdeny & avd->auditdeny))
547 audited = 0;
548 } else if (result)
549 audited = denied = requested;
550 else
551 audited = requested & avd->auditallow;
552 if (likely(!audited))
553 return 0;
554
555 return slow_avc_audit(ssid, tsid, tclass,
556 requested, audited, denied,
557 a, flags);
558}
559
560/**
561 * avc_add_callback - Register a callback for security events. 493 * avc_add_callback - Register a callback for security events.
562 * @callback: callback function 494 * @callback: callback function
563 * @events: security events 495 * @events: security events
564 * @ssid: source security identifier or %SECSID_WILD
565 * @tsid: target security identifier or %SECSID_WILD
566 * @tclass: target security class
567 * @perms: permissions
568 * 496 *
569 * Register a callback function for events in the set @events 497 * Register a callback function for events in the set @events.
570 * related to the SID pair (@ssid, @tsid) 498 * Returns %0 on success or -%ENOMEM if insufficient memory
571 * and the permissions @perms, interpreting 499 * exists to add the callback.
572 * @perms based on @tclass. Returns %0 on success or
573 * -%ENOMEM if insufficient memory exists to add the callback.
574 */ 500 */
575int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid, 501int __init avc_add_callback(int (*callback)(u32 event), u32 events)
576 u16 tclass, u32 perms,
577 u32 *out_retained),
578 u32 events, u32 ssid, u32 tsid,
579 u16 tclass, u32 perms)
580{ 502{
581 struct avc_callback_node *c; 503 struct avc_callback_node *c;
582 int rc = 0; 504 int rc = 0;
583 505
584 c = kmalloc(sizeof(*c), GFP_ATOMIC); 506 c = kmalloc(sizeof(*c), GFP_KERNEL);
585 if (!c) { 507 if (!c) {
586 rc = -ENOMEM; 508 rc = -ENOMEM;
587 goto out; 509 goto out;
@@ -589,9 +511,6 @@ int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid,
589 511
590 c->callback = callback; 512 c->callback = callback;
591 c->events = events; 513 c->events = events;
592 c->ssid = ssid;
593 c->tsid = tsid;
594 c->perms = perms;
595 c->next = avc_callbacks; 514 c->next = avc_callbacks;
596 avc_callbacks = c; 515 avc_callbacks = c;
597out: 516out:
@@ -731,8 +650,7 @@ int avc_ss_reset(u32 seqno)
731 650
732 for (c = avc_callbacks; c; c = c->next) { 651 for (c = avc_callbacks; c; c = c->next) {
733 if (c->events & AVC_CALLBACK_RESET) { 652 if (c->events & AVC_CALLBACK_RESET) {
734 tmprc = c->callback(AVC_CALLBACK_RESET, 653 tmprc = c->callback(AVC_CALLBACK_RESET);
735 0, 0, 0, 0, NULL);
736 /* save the first error encountered for the return 654 /* save the first error encountered for the return
737 value and continue processing the callbacks */ 655 value and continue processing the callbacks */
738 if (!rc) 656 if (!rc)