[AUDIT] make audit=0 really stop audit messages
Eric Paris [Mon, 7 Jan 2008 22:09:31 +0000 (17:09 -0500)]
Some audit messages (namely configuration changes) are still emitted even if
the audit subsystem has been explicitly disabled.  This patch turns those
messages off as well.

Signed-off-by: Eric Paris <eparis@redhat.com>

kernel/audit.c
kernel/auditfilter.c

index 26ff925..7e29372 100644 (file)
@@ -66,9 +66,9 @@
  * (Initialization happens after skb_init is called.) */
 static int     audit_initialized;
 
-/* 0 - no auditing
- * 1 - auditing enabled
- * 2 - auditing enabled and configuration is locked/unchangeable. */
+#define AUDIT_OFF      0
+#define AUDIT_ON       1
+#define AUDIT_LOCKED   2
 int            audit_enabled;
 
 /* Default state when kernel boots without any parameters. */
@@ -240,152 +240,90 @@ void audit_log_lost(const char *message)
        }
 }
 
-static int audit_set_rate_limit(int limit, uid_t loginuid, u32 sid)
+static int audit_log_config_change(char *function_name, int new, int old,
+                                  uid_t loginuid, u32 sid, int allow_changes)
 {
-       int res, rc = 0, old = audit_rate_limit;
-
-       /* check if we are locked */
-       if (audit_enabled == 2)
-               res = 0;
-       else
-               res = 1;
+       struct audit_buffer *ab;
+       int rc = 0;
 
+       ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
+       audit_log_format(ab, "%s=%d old=%d by auid=%u", function_name, new,
+                        old, loginuid);
        if (sid) {
                char *ctx = NULL;
                u32 len;
-               if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) {
-                       audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-                               "audit_rate_limit=%d old=%d by auid=%u"
-                               " subj=%s res=%d",
-                               limit, old, loginuid, ctx, res);
+
+               rc = selinux_sid_to_string(sid, &ctx, &len);
+               if (rc) {
+                       audit_log_format(ab, " sid=%u", sid);
+                       allow_changes = 0; /* Something weird, deny request */
+               } else {
+                       audit_log_format(ab, " subj=%s", ctx);
                        kfree(ctx);
-               } else
-                       res = 0; /* Something weird, deny request */
+               }
        }
-       audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-               "audit_rate_limit=%d old=%d by auid=%u res=%d",
-               limit, old, loginuid, res);
-
-       /* If we are allowed, make the change */
-       if (res == 1)
-               audit_rate_limit = limit;
-       /* Not allowed, update reason */
-       else if (rc == 0)
-               rc = -EPERM;
+       audit_log_format(ab, " res=%d", allow_changes);
+       audit_log_end(ab);
        return rc;
 }
 
-static int audit_set_backlog_limit(int limit, uid_t loginuid, u32 sid)
+static int audit_do_config_change(char *function_name, int *to_change,
+                                 int new, uid_t loginuid, u32 sid)
 {
-       int res, rc = 0, old = audit_backlog_limit;
+       int allow_changes, rc = 0, old = *to_change;
 
        /* check if we are locked */
-       if (audit_enabled == 2)
-               res = 0;
+       if (audit_enabled == AUDIT_LOCKED)
+               allow_changes = 0;
        else
-               res = 1;
+               allow_changes = 1;
 
-       if (sid) {
-               char *ctx = NULL;
-               u32 len;
-               if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) {
-                       audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-                               "audit_backlog_limit=%d old=%d by auid=%u"
-                               " subj=%s res=%d",
-                               limit, old, loginuid, ctx, res);
-                       kfree(ctx);
-               } else
-                       res = 0; /* Something weird, deny request */
+       if (audit_enabled != AUDIT_OFF) {
+               rc = audit_log_config_change(function_name, new, old,
+                                            loginuid, sid, allow_changes);
+               if (rc)
+                       allow_changes = 0;
        }
-       audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-               "audit_backlog_limit=%d old=%d by auid=%u res=%d",
-               limit, old, loginuid, res);
 
        /* If we are allowed, make the change */
-       if (res == 1)
-               audit_backlog_limit = limit;
+       if (allow_changes == 1)
+               *to_change = new;
        /* Not allowed, update reason */
        else if (rc == 0)
                rc = -EPERM;
        return rc;
 }
 
-static int audit_set_enabled(int state, uid_t loginuid, u32 sid)
+static int audit_set_rate_limit(int limit, uid_t loginuid, u32 sid)
 {
-       int res, rc = 0, old = audit_enabled;
-
-       if (state < 0 || state > 2)
-               return -EINVAL;
+       return audit_do_config_change("audit_rate_limit", &audit_rate_limit,
+                                     limit, loginuid, sid);
+}
 
-       /* check if we are locked */
-       if (audit_enabled == 2)
-               res = 0;
-       else
-               res = 1;
+static int audit_set_backlog_limit(int limit, uid_t loginuid, u32 sid)
+{
+       return audit_do_config_change("audit_backlog_limit", &audit_backlog_limit,
+                                     limit, loginuid, sid);
+}
 
-       if (sid) {
-               char *ctx = NULL;
-               u32 len;
-               if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) {
-                       audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-                               "audit_enabled=%d old=%d by auid=%u"
-                               " subj=%s res=%d",
-                               state, old, loginuid, ctx, res);
-                       kfree(ctx);
-               } else
-                       res = 0; /* Something weird, deny request */
-       }
-       audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-               "audit_enabled=%d old=%d by auid=%u res=%d",
-               state, old, loginuid, res);
+static int audit_set_enabled(int state, uid_t loginuid, u32 sid)
+{
+       if (state < AUDIT_OFF || state > AUDIT_LOCKED)
+               return -EINVAL;
 
-       /* If we are allowed, make the change */
-       if (res == 1)
-               audit_enabled = state;
-       /* Not allowed, update reason */
-       else if (rc == 0)
-               rc = -EPERM;
-       return rc;
+       return audit_do_config_change("audit_enabled", &audit_enabled, state,
+                                     loginuid, sid);
 }
 
 static int audit_set_failure(int state, uid_t loginuid, u32 sid)
 {
-       int res, rc = 0, old = audit_failure;
-
        if (state != AUDIT_FAIL_SILENT
            && state != AUDIT_FAIL_PRINTK
            && state != AUDIT_FAIL_PANIC)
                return -EINVAL;
 
-       /* check if we are locked */
-       if (audit_enabled == 2)
-               res = 0;
-       else
-               res = 1;
-
-       if (sid) {
-               char *ctx = NULL;
-               u32 len;
-               if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) {
-                       audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-                               "audit_failure=%d old=%d by auid=%u"
-                               " subj=%s res=%d",
-                               state, old, loginuid, ctx, res);
-                       kfree(ctx);
-               } else
-                       res = 0; /* Something weird, deny request */
-       }
-       audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-               "audit_failure=%d old=%d by auid=%u res=%d",
-               state, old, loginuid, res);
-
-       /* If we are allowed, make the change */
-       if (res == 1)
-               audit_failure = state;
-       /* Not allowed, update reason */
-       else if (rc == 0)
-               rc = -EPERM;
-       return rc;
+       return audit_do_config_change("audit_failure", &audit_failure, state,
+                                     loginuid, sid);
 }
 
 static int kauditd_thread(void *dummy)
@@ -634,23 +572,14 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                        if (err < 0) return err;
                }
                if (status_get->mask & AUDIT_STATUS_PID) {
-                       int old   = audit_pid;
-                       if (sid) {
-                               if ((err = selinux_sid_to_string(
-                                               sid, &ctx, &len)))
-                                       return err;
-                               else
-                                       audit_log(NULL, GFP_KERNEL,
-                                               AUDIT_CONFIG_CHANGE,
-                                               "audit_pid=%d old=%d by auid=%u subj=%s",
-                                               status_get->pid, old,
-                                               loginuid, ctx);
-                               kfree(ctx);
-                       } else
-                               audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-                                       "audit_pid=%d old=%d by auid=%u",
-                                         status_get->pid, old, loginuid);
-                       audit_pid = status_get->pid;
+                       int new_pid = status_get->pid;
+
+                       if (audit_enabled != AUDIT_OFF)
+                               audit_log_config_change("audit_pid", new_pid,
+                                                       audit_pid, loginuid,
+                                                       sid, 1);
+
+                       audit_pid = new_pid;
                }
                if (status_get->mask & AUDIT_STATUS_RATE_LIMIT)
                        err = audit_set_rate_limit(status_get->rate_limit,
@@ -709,7 +638,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
        case AUDIT_DEL:
                if (nlmsg_len(nlh) < sizeof(struct audit_rule))
                        return -EINVAL;
-               if (audit_enabled == 2) {
+               if (audit_enabled == AUDIT_LOCKED) {
                        ab = audit_log_start(NULL, GFP_KERNEL,
                                        AUDIT_CONFIG_CHANGE);
                        if (ab) {
@@ -743,7 +672,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
        case AUDIT_DEL_RULE:
                if (nlmsg_len(nlh) < sizeof(struct audit_rule_data))
                        return -EINVAL;
-               if (audit_enabled == 2) {
+               if (audit_enabled == AUDIT_LOCKED) {
                        ab = audit_log_start(NULL, GFP_KERNEL,
                                        AUDIT_CONFIG_CHANGE);
                        if (ab) {
index 5d96f2c..6f19fd4 100644 (file)
@@ -95,6 +95,8 @@ extern struct inotify_handle *audit_ih;
 /* Inotify events we care about. */
 #define AUDIT_IN_WATCH IN_MOVE|IN_CREATE|IN_DELETE|IN_DELETE_SELF|IN_MOVE_SELF
 
+extern int audit_enabled;
+
 void audit_free_parent(struct inotify_watch *i_watch)
 {
        struct audit_parent *parent;
@@ -974,7 +976,6 @@ static void audit_update_watch(struct audit_parent *parent,
        struct audit_watch *owatch, *nwatch, *nextw;
        struct audit_krule *r, *nextr;
        struct audit_entry *oentry, *nentry;
-       struct audit_buffer *ab;
 
        mutex_lock(&audit_filter_mutex);
        list_for_each_entry_safe(owatch, nextw, &parent->watches, wlist) {
@@ -1014,13 +1015,18 @@ static void audit_update_watch(struct audit_parent *parent,
                        call_rcu(&oentry->rcu, audit_free_rule_rcu);
                }
 
-               ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
-               audit_log_format(ab, "op=updated rules specifying path=");
-               audit_log_untrustedstring(ab, owatch->path);
-               audit_log_format(ab, " with dev=%u ino=%lu\n", dev, ino);
-               audit_log_format(ab, " list=%d res=1", r->listnr);
-               audit_log_end(ab);
-
+               if (audit_enabled) {
+                       struct audit_buffer *ab;
+                       ab = audit_log_start(NULL, GFP_KERNEL,
+                               AUDIT_CONFIG_CHANGE);
+                       audit_log_format(ab,
+                               "op=updated rules specifying path=");
+                       audit_log_untrustedstring(ab, owatch->path);
+                       audit_log_format(ab, " with dev=%u ino=%lu\n",
+                                dev, ino);
+                       audit_log_format(ab, " list=%d res=1", r->listnr);
+                       audit_log_end(ab);
+               }
                audit_remove_watch(owatch);
                goto add_watch_to_parent; /* event applies to a single watch */
        }
@@ -1039,25 +1045,28 @@ static void audit_remove_parent_watches(struct audit_parent *parent)
        struct audit_watch *w, *nextw;
        struct audit_krule *r, *nextr;
        struct audit_entry *e;
-       struct audit_buffer *ab;
 
        mutex_lock(&audit_filter_mutex);
        parent->flags |= AUDIT_PARENT_INVALID;
        list_for_each_entry_safe(w, nextw, &parent->watches, wlist) {
                list_for_each_entry_safe(r, nextr, &w->rules, rlist) {
                        e = container_of(r, struct audit_entry, rule);
-
-                       ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
-                       audit_log_format(ab, "op=remove rule path=");
-                       audit_log_untrustedstring(ab, w->path);
-                       if (r->filterkey) {
-                               audit_log_format(ab, " key=");
-                               audit_log_untrustedstring(ab, r->filterkey);
-                       } else
-                               audit_log_format(ab, " key=(null)");
-                       audit_log_format(ab, " list=%d res=1", r->listnr);
-                       audit_log_end(ab);
-
+                       if (audit_enabled) {
+                               struct audit_buffer *ab;
+                               ab = audit_log_start(NULL, GFP_KERNEL,
+                                       AUDIT_CONFIG_CHANGE);
+                               audit_log_format(ab, "op=remove rule path=");
+                               audit_log_untrustedstring(ab, w->path);
+                               if (r->filterkey) {
+                                       audit_log_format(ab, " key=");
+                                       audit_log_untrustedstring(ab,
+                                                       r->filterkey);
+                               } else
+                                       audit_log_format(ab, " key=(null)");
+                               audit_log_format(ab, " list=%d res=1",
+                                       r->listnr);
+                               audit_log_end(ab);
+                       }
                        list_del(&r->rlist);
                        list_del_rcu(&e->list);
                        call_rcu(&e->rcu, audit_free_rule_rcu);
@@ -1495,6 +1504,9 @@ static void audit_log_rule_change(uid_t loginuid, u32 sid, char *action,
 {
        struct audit_buffer *ab;
 
+       if (!audit_enabled)
+               return;
+
        ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
        if (!ab)
                return;