Allow the audit subsystem to send audit events to both the kernel message buffer and auditd at the same time.
Signed-off-by: William Roberts <[email protected]> --- include/uapi/linux/audit.h | 11 ++++++++++ init/Kconfig | 8 +++++++ kernel/audit.c | 52 ++++++++++++++++++++++++++++++++++++++++------ kernel/audit.h | 6 ++++++ 4 files changed, 71 insertions(+), 6 deletions(-) diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index 75cef3f..0af5d78 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -68,6 +68,8 @@ #define AUDIT_MAKE_EQUIV 1015 /* Append to watched tree */ #define AUDIT_TTY_GET 1016 /* Get TTY auditing status */ #define AUDIT_TTY_SET 1017 /* Set TTY auditing status */ +#define AUDIT_LOGSPLIT_GET 1018 /* Get logsplit status */ +#define AUDIT_LOGSPLIT_SET 1019 /* Set logsplit status */ #define AUDIT_FIRST_USER_MSG 1100 /* Userspace messages mostly uninteresting to kernel */ #define AUDIT_USER_AVC 1107 /* We filter this differently */ @@ -321,6 +323,10 @@ enum { #define AUDIT_FAIL_PRINTK 1 #define AUDIT_FAIL_PANIC 2 +/* Audit splitlog options */ +#define AUDIT_LOGSPLIT_OFF 0 +#define AUDIT_LOGSPLIT_ON 1 + /* distinguish syscall tables */ #define __AUDIT_ARCH_64BIT 0x80000000 #define __AUDIT_ARCH_LE 0x40000000 @@ -374,6 +380,11 @@ struct audit_tty_status { __u32 log_passwd; /* 1 = enabled, 0 = disabled */ }; +struct audit_logsplit_status { + __u32 enabled; /* AUDIT_LOGSPLIT_ON or + AUDIT_LOGSPLIT_OFF */ +}; + /* audit_rule_data supports filter rules with both integer and string * fields. It corresponds with AUDIT_ADD_RULE, AUDIT_DEL_RULE and * AUDIT_LIST_RULES requests. diff --git a/init/Kconfig b/init/Kconfig index 9d3a788..52efca6 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -286,6 +286,14 @@ config AUDIT_LOGINUID_IMMUTABLE one to drop potentially dangerous capabilites from the login tasks, but may not be backwards compatible with older init systems. +config AUDIT_SPLITLOG + bool "Split audit messages to userspace and kernel by default" + depends on AUDIT + help + Setting this to true will cause the audit messages to be split + by default to both the kernel message log and a userspace audit + daemon if registered. + source "kernel/irq/Kconfig" source "kernel/time/Kconfig" diff --git a/kernel/audit.c b/kernel/audit.c index 21c7fa6..ccd2f60 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -88,6 +88,9 @@ static int audit_default; /* If auditing cannot proceed, audit_failure selects what happens. */ static int audit_failure = AUDIT_FAIL_PRINTK; +/* Whether or not logsplit is enabled */ +static int audit_logsplit = AUDIT_SPLITLOG_INIT; + /* * If audit records are to be written to the netlink socket, audit_pid * contains the pid of the auditd process and audit_nlk_portid contains @@ -343,6 +346,17 @@ static int audit_set_failure(int state) return audit_do_config_change("audit_failure", &audit_failure, state); } +static int audit_set_logsplit(int state) +{ + if (state != AUDIT_LOGSPLIT_OFF + && state != AUDIT_LOGSPLIT_ON) + return -EINVAL; + + return audit_do_config_change("audit_logsplit", &audit_logsplit, state); +} + + + /* * 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 @@ -361,11 +375,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); @@ -376,7 +387,14 @@ static void audit_printk_skb(struct sk_buff *skb) else audit_log_lost("printk limit exceeded\n"); } - +} +/* + * 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); } @@ -590,6 +608,8 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type) case AUDIT_SIGNAL_INFO: case AUDIT_TTY_GET: case AUDIT_TTY_SET: + case AUDIT_LOGSPLIT_GET: + case AUDIT_LOGSPLIT_SET: case AUDIT_TRIM: case AUDIT_MAKE_EQUIV: if (!capable(CAP_AUDIT_CONTROL)) @@ -843,7 +863,24 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) spin_unlock(&tsk->sighand->siglock); break; } + case AUDIT_LOGSPLIT_GET: { + struct audit_logsplit_status s; + s.enabled = audit_logsplit; + audit_send_reply(NETLINK_CB(skb).portid, seq, + AUDIT_LOGSPLIT_GET, 0, 0, &s, sizeof(s)); + break; + } + case AUDIT_LOGSPLIT_SET: { + struct audit_logsplit_status *s; + if (nlh->nlmsg_len < sizeof(struct audit_logsplit_status)) + return -EINVAL; + s = data; + err = audit_set_logsplit(s->enabled); + break; + } + default: + printk(KERN_ERR "Unkown audit command"); err = -EINVAL; break; } @@ -1670,6 +1707,9 @@ void audit_log_end(struct audit_buffer *ab) nlh->nlmsg_len = ab->skb->len - NLMSG_HDRLEN; 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 { diff --git a/kernel/audit.h b/kernel/audit.h index 1c95131..ef43bb1 100644 --- a/kernel/audit.h +++ b/kernel/audit.h @@ -321,4 +321,10 @@ extern struct list_head *audit_killed_trees(void); #define audit_filter_inodes(t,c) AUDIT_DISABLED #endif +#ifdef CONFIG_AUDIT_SPLITLOG +#define AUDIT_SPLITLOG_INIT AUDIT_LOGSPLIT_ON +#else +#define AUDIT_SPLITLOG_INIT AUDIT_LOGSPLIT_OFF +#endif + extern struct mutex audit_cmd_mutex; -- 1.8.2.2 -- Linux-audit mailing list [email protected] https://www.redhat.com/mailman/listinfo/linux-audit
