>From eb7a0d5e711b555d38e3cd19c754e4a866bb07a4 Mon Sep 17 00:00:00 2001
From: William Roberts <[email protected]>
Date: Wed, 15 May 2013 18:12:31 -0700
Subject: [PATCH] Enable splitting the logs to both auditd and kernel
 simultaneously

Allow the audit subsystem to send audit events to both the kernel
message buffer and auditd at the same time.

Change-Id: I3107322c845a4cfb001352e152c0866b8a73f02d
Signed-off-by: William Roberts <[email protected]>
---
 include/linux/audit.h |  5 +++++
 kernel/audit.c        | 44 +++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 44 insertions(+), 5 deletions(-)

diff --git a/include/linux/audit.h b/include/linux/audit.h
index ed3ef19..ae8083e 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -314,6 +314,10 @@ enum {
 #define AUDIT_STATUS_PID        0x0004
 #define AUDIT_STATUS_RATE_LIMIT        0x0008
 #define AUDIT_STATUS_BACKLOG_LIMIT    0x0010
+#define AUDIT_STATUS_LOGSPLIT        0x0020
+                /* Split log actions */
+#define AUDIT_LOGSPLIT_OFF    0
+#define AUDIT_LOGSPLIT_ON    1
                 /* Failure-to-log actions */
 #define AUDIT_FAIL_SILENT    0
 #define AUDIT_FAIL_PRINTK    1
@@ -359,6 +363,7 @@ struct audit_status {
     __u32        mask;        /* Bit mask for valid entries */
     __u32        enabled;    /* 1 = enabled, 0 = disabled */
     __u32        failure;    /* Failure-to-log action */
+    __u32        logsplit;    /* Logsplit action */
     __u32        pid;        /* pid of auditd process */
     __u32        rate_limit;    /* messages rate limit (per second) */
     __u32        backlog_limit;    /* waiting messages limit */
diff --git a/kernel/audit.c b/kernel/audit.c
index 4096bcc..10f0457 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -74,6 +74,10 @@ static int    audit_initialized;
 #define AUDIT_OFF    0
 #define AUDIT_ON    1
 #define AUDIT_LOCKED    2
+
+#define AUDIT_PRINTK_NOHOLD    0
+#define AUDIT_PRINTK_HOLD    1
+
 int        audit_enabled;
 int        audit_ever_enabled;

@@ -85,6 +89,9 @@ static int    audit_default;
 /* If auditing cannot proceed, audit_failure selects what happens. */
 static int    audit_failure = AUDIT_FAIL_PRINTK;

+/* If auditing should preserve logs in dmesg even if auditd is running. */
+static int audit_logsplit = AUDIT_LOGSPLIT_OFF;
+
 /*
  * If audit records are to be written to the netlink socket, audit_pid
  * contains the pid of the auditd process and audit_nlk_pid contains
@@ -357,6 +364,16 @@ static int audit_set_failure(int state, uid_t
loginuid, u32 sessionid, u32 sid)
                       loginuid, sessionid, sid);
 }

+static int audit_set_logsplit(int state, uid_t loginuid, u32 sessionid,
u32 sid)
+{
+    if (state != AUDIT_LOGSPLIT_OFF
+        && state != AUDIT_LOGSPLIT_ON)
+        return -EINVAL;
+
+    return audit_do_config_change("audit_logsplit", &audit_logsplit, state,
+                      loginuid, sessionid, sid);
+}
+
 /*
  * Queue skbs to be sent to auditd when/if it comes back.  These skbs
should
  * already have been sent via prink/syslog and so if these messages are
dropped
@@ -375,11 +392,8 @@ static void audit_hold_skb(struct sk_buff *skb)
         kfree_skb(skb);
 }

-/*
- * For one reason or another this nlh isn't getting delivered to the
userspace
- * audit daemon, just send it to printk.
- */
-static void audit_printk_skb(struct sk_buff *skb)
+/* Just printks the skb, no audit_hold or free of any kind */
+static void __audit_printk_skb(struct sk_buff *skb)
 {
     struct nlmsghdr *nlh = nlmsg_hdr(skb);
     char *data = NLMSG_DATA(nlh);
@@ -387,7 +401,15 @@ static void audit_printk_skb(struct sk_buff *skb)
     if (nlh->nlmsg_type != AUDIT_EOE) {
         printk(KERN_NOTICE "type=%d %s\n", nlh->nlmsg_type, data);
     }
+}

+/*
+ * For one reason or another this nlh isn't getting delivered to the
userspace
+ * audit daemon, just send it to printk.
+ */
+static void audit_printk_skb(struct sk_buff *skb)
+{
+    __audit_printk_skb(skb);
     audit_hold_skb(skb);
 }

@@ -681,6 +703,7 @@ static int audit_receive_msg(struct sk_buff *skb,
struct nlmsghdr *nlh)
     case AUDIT_GET:
         status_set.enabled     = audit_enabled;
         status_set.failure     = audit_failure;
+        status_set.logsplit     = audit_logsplit;
         status_set.pid         = audit_pid;
         status_set.rate_limit     = audit_rate_limit;
         status_set.backlog_limit = audit_backlog_limit;
@@ -725,6 +748,15 @@ static int audit_receive_msg(struct sk_buff *skb,
struct nlmsghdr *nlh)
         if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT)
             err = audit_set_backlog_limit(status_get->backlog_limit,
                               loginuid, sessionid, sid);
+
+        if (status_get->mask & AUDIT_STATUS_LOGSPLIT) {
+            err = audit_set_logsplit(status_get->logsplit,
+                        loginuid, sessionid, sid);
+
+            if (err < 0) {
+                return err;
+            }
+        }
         break;
     case AUDIT_USER:
     case AUDIT_FIRST_USER_MSG ... AUDIT_LAST_USER_MSG:
@@ -1464,6 +1496,8 @@ void audit_log_end(struct audit_buffer *ab)
         nlh->nlmsg_len = ab->skb->len - NLMSG_SPACE(0);

         if (audit_pid) {
+            if(audit_logsplit == AUDIT_LOGSPLIT_ON)
+                __audit_printk_skb(ab->skb);
             skb_queue_tail(&audit_skb_queue, ab->skb);
             wake_up_interruptible(&kauditd_wait);
         } else {
-- 
1.8.2.2

Reply via email to