aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/avc.c
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2012-04-03 12:37:02 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-04-03 12:48:40 -0400
commit3b3b0e4fc15efa507b902d90cea39e496a523c3b (patch)
treed7b91c21ad6c6f4ac21dd51297b74eec47c61684 /security/selinux/avc.c
parent95694129b43165911dc4e8a972f0d39ad98d86be (diff)
LSM: shrink sizeof LSM specific portion of common_audit_data
Linus found that the gigantic size of the common audit data caused a big perf hit on something as simple as running stat() in a loop. This patch requires LSMs to declare the LSM specific portion separately rather than doing it in a union. Thus each LSM can be responsible for shrinking their portion and don't have to pay a penalty just because other LSMs have a bigger space requirement. Signed-off-by: Eric Paris <eparis@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'security/selinux/avc.c')
-rw-r--r--security/selinux/avc.c34
1 files changed, 18 insertions, 16 deletions
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index 1a70fa26da72..00f3860c2370 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -436,9 +436,9 @@ static void avc_audit_pre_callback(struct audit_buffer *ab, void *a)
436{ 436{
437 struct common_audit_data *ad = a; 437 struct common_audit_data *ad = a;
438 audit_log_format(ab, "avc: %s ", 438 audit_log_format(ab, "avc: %s ",
439 ad->selinux_audit_data.denied ? "denied" : "granted"); 439 ad->selinux_audit_data->denied ? "denied" : "granted");
440 avc_dump_av(ab, ad->selinux_audit_data.tclass, 440 avc_dump_av(ab, ad->selinux_audit_data->tclass,
441 ad->selinux_audit_data.audited); 441 ad->selinux_audit_data->audited);
442 audit_log_format(ab, " for "); 442 audit_log_format(ab, " for ");
443} 443}
444 444
@@ -452,9 +452,9 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a)
452{ 452{
453 struct common_audit_data *ad = a; 453 struct common_audit_data *ad = a;
454 audit_log_format(ab, " "); 454 audit_log_format(ab, " ");
455 avc_dump_query(ab, ad->selinux_audit_data.ssid, 455 avc_dump_query(ab, ad->selinux_audit_data->ssid,
456 ad->selinux_audit_data.tsid, 456 ad->selinux_audit_data->tsid,
457 ad->selinux_audit_data.tclass); 457 ad->selinux_audit_data->tclass);
458} 458}
459 459
460/* This is the slow part of avc audit with big stack footprint */ 460/* This is the slow part of avc audit with big stack footprint */
@@ -464,10 +464,12 @@ static noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass,
464 unsigned flags) 464 unsigned flags)
465{ 465{
466 struct common_audit_data stack_data; 466 struct common_audit_data stack_data;
467 struct selinux_audit_data sad = {0,};
467 468
468 if (!a) { 469 if (!a) {
469 a = &stack_data; 470 a = &stack_data;
470 COMMON_AUDIT_DATA_INIT(a, NONE); 471 COMMON_AUDIT_DATA_INIT(a, NONE);
472 a->selinux_audit_data = &sad;
471 } 473 }
472 474
473 /* 475 /*
@@ -481,12 +483,12 @@ static noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass,
481 (flags & MAY_NOT_BLOCK)) 483 (flags & MAY_NOT_BLOCK))
482 return -ECHILD; 484 return -ECHILD;
483 485
484 a->selinux_audit_data.tclass = tclass; 486 a->selinux_audit_data->tclass = tclass;
485 a->selinux_audit_data.requested = requested; 487 a->selinux_audit_data->requested = requested;
486 a->selinux_audit_data.ssid = ssid; 488 a->selinux_audit_data->ssid = ssid;
487 a->selinux_audit_data.tsid = tsid; 489 a->selinux_audit_data->tsid = tsid;
488 a->selinux_audit_data.audited = audited; 490 a->selinux_audit_data->audited = audited;
489 a->selinux_audit_data.denied = denied; 491 a->selinux_audit_data->denied = denied;
490 a->lsm_pre_audit = avc_audit_pre_callback; 492 a->lsm_pre_audit = avc_audit_pre_callback;
491 a->lsm_post_audit = avc_audit_post_callback; 493 a->lsm_post_audit = avc_audit_post_callback;
492 common_lsm_audit(a); 494 common_lsm_audit(a);
@@ -523,7 +525,7 @@ inline int avc_audit(u32 ssid, u32 tsid,
523 if (unlikely(denied)) { 525 if (unlikely(denied)) {
524 audited = denied & avd->auditdeny; 526 audited = denied & avd->auditdeny;
525 /* 527 /*
526 * a->selinux_audit_data.auditdeny is TRICKY! Setting a bit in 528 * a->selinux_audit_data->auditdeny is TRICKY! Setting a bit in
527 * this field means that ANY denials should NOT be audited if 529 * this field means that ANY denials should NOT be audited if
528 * the policy contains an explicit dontaudit rule for that 530 * the policy contains an explicit dontaudit rule for that
529 * permission. Take notice that this is unrelated to the 531 * permission. Take notice that this is unrelated to the
@@ -532,15 +534,15 @@ inline int avc_audit(u32 ssid, u32 tsid,
532 * 534 *
533 * denied == READ 535 * denied == READ
534 * avd.auditdeny & ACCESS == 0 (not set means explicit rule) 536 * avd.auditdeny & ACCESS == 0 (not set means explicit rule)
535 * selinux_audit_data.auditdeny & ACCESS == 1 537 * selinux_audit_data->auditdeny & ACCESS == 1
536 * 538 *
537 * We will NOT audit the denial even though the denied 539 * We will NOT audit the denial even though the denied
538 * permission was READ and the auditdeny checks were for 540 * permission was READ and the auditdeny checks were for
539 * ACCESS 541 * ACCESS
540 */ 542 */
541 if (a && 543 if (a &&
542 a->selinux_audit_data.auditdeny && 544 a->selinux_audit_data->auditdeny &&
543 !(a->selinux_audit_data.auditdeny & avd->auditdeny)) 545 !(a->selinux_audit_data->auditdeny & avd->auditdeny))
544 audited = 0; 546 audited = 0;
545 } else if (result) 547 } else if (result)
546 audited = denied = requested; 548 audited = denied = requested;