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>
This commit is contained in:
Eric Paris
2012-04-03 09:37:02 -07:00
committed by Linus Torvalds
parent 95694129b4
commit 3b3b0e4fc1
16 changed files with 241 additions and 146 deletions

View File

@@ -436,9 +436,9 @@ static void avc_audit_pre_callback(struct audit_buffer *ab, void *a)
{
struct common_audit_data *ad = a;
audit_log_format(ab, "avc: %s ",
ad->selinux_audit_data.denied ? "denied" : "granted");
avc_dump_av(ab, ad->selinux_audit_data.tclass,
ad->selinux_audit_data.audited);
ad->selinux_audit_data->denied ? "denied" : "granted");
avc_dump_av(ab, ad->selinux_audit_data->tclass,
ad->selinux_audit_data->audited);
audit_log_format(ab, " for ");
}
@@ -452,9 +452,9 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a)
{
struct common_audit_data *ad = a;
audit_log_format(ab, " ");
avc_dump_query(ab, ad->selinux_audit_data.ssid,
ad->selinux_audit_data.tsid,
ad->selinux_audit_data.tclass);
avc_dump_query(ab, ad->selinux_audit_data->ssid,
ad->selinux_audit_data->tsid,
ad->selinux_audit_data->tclass);
}
/* 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,
unsigned flags)
{
struct common_audit_data stack_data;
struct selinux_audit_data sad = {0,};
if (!a) {
a = &stack_data;
COMMON_AUDIT_DATA_INIT(a, NONE);
a->selinux_audit_data = &sad;
}
/*
@@ -481,12 +483,12 @@ static noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass,
(flags & MAY_NOT_BLOCK))
return -ECHILD;
a->selinux_audit_data.tclass = tclass;
a->selinux_audit_data.requested = requested;
a->selinux_audit_data.ssid = ssid;
a->selinux_audit_data.tsid = tsid;
a->selinux_audit_data.audited = audited;
a->selinux_audit_data.denied = denied;
a->selinux_audit_data->tclass = tclass;
a->selinux_audit_data->requested = requested;
a->selinux_audit_data->ssid = ssid;
a->selinux_audit_data->tsid = tsid;
a->selinux_audit_data->audited = audited;
a->selinux_audit_data->denied = denied;
a->lsm_pre_audit = avc_audit_pre_callback;
a->lsm_post_audit = avc_audit_post_callback;
common_lsm_audit(a);
@@ -523,7 +525,7 @@ inline int avc_audit(u32 ssid, u32 tsid,
if (unlikely(denied)) {
audited = denied & avd->auditdeny;
/*
* a->selinux_audit_data.auditdeny is TRICKY! Setting a bit in
* a->selinux_audit_data->auditdeny is TRICKY! Setting a bit in
* this field means that ANY denials should NOT be audited if
* the policy contains an explicit dontaudit rule for that
* permission. Take notice that this is unrelated to the
@@ -532,15 +534,15 @@ inline int avc_audit(u32 ssid, u32 tsid,
*
* denied == READ
* avd.auditdeny & ACCESS == 0 (not set means explicit rule)
* selinux_audit_data.auditdeny & ACCESS == 1
* selinux_audit_data->auditdeny & ACCESS == 1
*
* We will NOT audit the denial even though the denied
* permission was READ and the auditdeny checks were for
* ACCESS
*/
if (a &&
a->selinux_audit_data.auditdeny &&
!(a->selinux_audit_data.auditdeny & avd->auditdeny))
a->selinux_audit_data->auditdeny &&
!(a->selinux_audit_data->auditdeny & avd->auditdeny))
audited = 0;
} else if (result)
audited = denied = requested;