SELinux: do not allocate stack space for AVC data unless needed
Eric Paris [Tue, 3 Apr 2012 16:38:00 +0000 (09:38 -0700)]
Instead of declaring the entire selinux_audit_data on the stack when we
start an operation on declare it on the stack if we are going to use it.
We know it's usefulness at the end of the security decision and can declare
it there.

Signed-off-by: Eric Paris <eparis@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

security/selinux/avc.c
security/selinux/include/avc.h

index b5545a8..36c42bb 100644 (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->slad->denied ? "denied" : "granted");
+       avc_dump_av(ab, ad->selinux_audit_data->slad->tclass,
+                       ad->selinux_audit_data->slad->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->slad->ssid,
+                          ad->selinux_audit_data->slad->tsid,
+                          ad->selinux_audit_data->slad->tclass);
 }
 
 /* This is the slow part of avc audit with big stack footprint */
@@ -465,6 +465,7 @@ static noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass,
 {
        struct common_audit_data stack_data;
        struct selinux_audit_data sad = {0,};
+       struct selinux_late_audit_data slad;
 
        if (!a) {
                a = &stack_data;
@@ -483,12 +484,14 @@ 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;
+       slad.tclass = tclass;
+       slad.requested = requested;
+       slad.ssid = ssid;
+       slad.tsid = tsid;
+       slad.audited = audited;
+       slad.denied = denied;
+
+       a->selinux_audit_data->slad = &slad;
        a->lsm_pre_audit = avc_audit_pre_callback;
        a->lsm_post_audit = avc_audit_post_callback;
        common_lsm_audit(a);
index 09c3eda..1931370 100644 (file)
@@ -46,19 +46,29 @@ struct avc_cache_stats {
        unsigned int frees;
 };
 
-struct selinux_audit_data {
+/*
+ * We only need this data after we have decided to send an audit message.
+ */
+struct selinux_late_audit_data {
        u32 ssid;
        u32 tsid;
        u16 tclass;
        u32 requested;
        u32 audited;
        u32 denied;
+       int result;
+};
+
+/*
+ * We collect this at the beginning or during an selinux security operation
+ */
+struct selinux_audit_data {
        /*
         * auditdeny is a bit tricky and unintuitive.  See the
         * comments in avc.c for it's meaning and usage.
         */
        u32 auditdeny;
-       int result;
+       struct selinux_late_audit_data *slad;
 };
 
 /*