[PATCH] Enable splitting the logs to both auditd and kernel simultaneously
by William Roberts
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 <w.roberts(a)sta.samsung.com>
---
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
11 years, 5 months
[PATCH] audit: fix mq_open and mq_unlink to add the MQ root as a hidden parent audit_names record
by Jeff Layton
The old audit PATH records for mq_open looked like this:
type=PATH msg=audit(1366282323.982:869): item=1 name=(null) inode=6777
dev=00:0c mode=041777 ouid=0 ogid=0 rdev=00:00
obj=system_u:object_r:tmpfs_t:s15:c0.c1023
type=PATH msg=audit(1366282323.982:869): item=0 name="test_mq" inode=26732
dev=00:0c mode=0100700 ouid=0 ogid=0 rdev=00:00
obj=staff_u:object_r:user_tmpfs_t:s15:c0.c1023
...with the audit related changes that went into 3.7, they now look like this:
type=PATH msg=audit(1366282236.776:3606): item=2 name=(null) inode=66655
dev=00:0c mode=0100700 ouid=0 ogid=0 rdev=00:00
obj=staff_u:object_r:user_tmpfs_t:s15:c0.c1023
type=PATH msg=audit(1366282236.776:3606): item=1 name=(null) inode=6926
dev=00:0c mode=041777 ouid=0 ogid=0 rdev=00:00
obj=system_u:object_r:tmpfs_t:s15:c0.c1023
type=PATH msg=audit(1366282236.776:3606): item=0 name="test_mq"
Both of these look wrong to me. As Steve Grubb pointed out:
"What we need is 1 PATH record that identifies the MQ. The other PATH
records probably should not be there."
Fix it to record the mq root as a parent, and flag it such that it
should be hidden from view when the names are logged, since the root of
the mq filesystem isn't terribly interesting. With this change, we get a
single PATH record that looks more like this:
type=PATH msg=audit(1368021604.836:484): item=0 name="test_mq" inode=16914
dev=00:0c mode=0100644 ouid=0 ogid=0 rdev=00:00
obj=unconfined_u:object_r:user_tmpfs_t:s0
In order to do this, a new audit_inode_parent_hidden() function is
added. If we do it this way, then we avoid having the existing callers
of audit_inode needing to do any sort of flag conversion if auditing is
inactive.
Cc: Steve Grubb <sgrubb(a)redhat.com>
Reported-by: Jiri Jaburek <jjaburek(a)redhat.com>
Signed-off-by: Jeff Layton <jlayton(a)redhat.com>
---
include/linux/audit.h | 26 ++++++++++++++++++++++----
ipc/mqueue.c | 2 ++
kernel/auditsc.c | 13 ++++++++++---
3 files changed, 34 insertions(+), 7 deletions(-)
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 5a6d718..89f3584 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -98,8 +98,11 @@ extern void __audit_syscall_exit(int ret_success, long ret_value);
extern struct filename *__audit_reusename(const __user char *uptr);
extern void __audit_getname(struct filename *name);
extern void audit_putname(struct filename *name);
+
+#define AUDIT_INODE_PARENT 1 /* dentry represents the parent */
+#define AUDIT_INODE_HIDDEN 2 /* audit record should be hidden */
extern void __audit_inode(struct filename *name, const struct dentry *dentry,
- unsigned int parent);
+ unsigned int flags);
extern void __audit_inode_child(const struct inode *parent,
const struct dentry *dentry,
const unsigned char type);
@@ -143,10 +146,22 @@ static inline void audit_getname(struct filename *name)
if (unlikely(!audit_dummy_context()))
__audit_getname(name);
}
-static inline void audit_inode(struct filename *name, const struct dentry *dentry,
+static inline void audit_inode(struct filename *name,
+ const struct dentry *dentry,
unsigned int parent) {
+ if (unlikely(!audit_dummy_context())) {
+ unsigned int flags = 0;
+ if (parent)
+ flags |= AUDIT_INODE_PARENT;
+ __audit_inode(name, dentry, flags);
+ }
+}
+static inline void audit_inode_parent_hidden(struct filename *name,
+ const struct dentry *dentry)
+{
if (unlikely(!audit_dummy_context()))
- __audit_inode(name, dentry, parent);
+ __audit_inode(name, dentry,
+ AUDIT_INODE_PARENT | AUDIT_INODE_HIDDEN);
}
static inline void audit_inode_child(const struct inode *parent,
const struct dentry *dentry,
@@ -307,7 +322,7 @@ static inline void audit_putname(struct filename *name)
{ }
static inline void __audit_inode(struct filename *name,
const struct dentry *dentry,
- unsigned int parent)
+ unsigned int flags)
{ }
static inline void __audit_inode_child(const struct inode *parent,
const struct dentry *dentry,
@@ -317,6 +332,9 @@ static inline void audit_inode(struct filename *name,
const struct dentry *dentry,
unsigned int parent)
{ }
+static inline void audit_inode_parent_hidden(struct filename *name,
+ const struct dentry *dentry)
+{ }
static inline void audit_inode_child(const struct inode *parent,
const struct dentry *dentry,
const unsigned char type)
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index e4e47f6..ae1996d 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -823,6 +823,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode,
error = ro;
goto out;
}
+ audit_inode_parent_hidden(name, root);
filp = do_create(ipc_ns, root->d_inode,
&path, oflag, mode,
u_attr ? &attr : NULL);
@@ -868,6 +869,7 @@ SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name)
if (IS_ERR(name))
return PTR_ERR(name);
+ audit_inode_parent_hidden(name, mnt->mnt_root);
err = mnt_want_write(mnt);
if (err)
goto out_name;
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 4f90536..a599291 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -119,6 +119,7 @@ struct audit_names {
unsigned int fcap_ver;
int name_len; /* number of name's characters to log */
unsigned char type; /* record type */
+ bool hidden; /* don't log this record */
bool name_put; /* call __putname() for this name */
/*
* This was an allocated audit_names and not from the array of
@@ -1716,8 +1717,11 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
}
i = 0;
- list_for_each_entry(n, &context->names_list, list)
+ list_for_each_entry(n, &context->names_list, list) {
+ if (n->hidden)
+ continue;
audit_log_name(context, n, i++, &call_panic);
+ }
/* Send end of event record to help user space know we are finished */
ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE);
@@ -2121,14 +2125,15 @@ static void audit_copy_inode(struct audit_names *name, const struct dentry *dent
* __audit_inode - store the inode and device from a lookup
* @name: name being audited
* @dentry: dentry being audited
- * @parent: does this dentry represent the parent?
+ * @flags: attributes for this particular entry
*/
void __audit_inode(struct filename *name, const struct dentry *dentry,
- unsigned int parent)
+ unsigned int flags)
{
struct audit_context *context = current->audit_context;
const struct inode *inode = dentry->d_inode;
struct audit_names *n;
+ bool parent = flags & AUDIT_INODE_PARENT;
if (!context->in_syscall)
return;
@@ -2183,6 +2188,8 @@ out:
if (parent) {
n->name_len = n->name ? parent_len(n->name->name) : AUDIT_NAME_FULL;
n->type = AUDIT_TYPE_PARENT;
+ if (flags & AUDIT_INODE_HIDDEN)
+ n->hidden = true;
} else {
n->name_len = AUDIT_NAME_FULL;
n->type = AUDIT_TYPE_NORMAL;
--
1.7.1
11 years, 5 months
[PATCH] audit: log the audit_names record type
by Jeff Layton
...to make it clear what the intent behind each record's operation was.
In many cases you can infer this, based on the context of the syscall
and the result. In other cases it's not so obvious. For instance, in
the case where you have a file being renamed over another, you'll have
two different records with the same filename but different inode info.
By logging this information we can clearly tell which one was created
and which was deleted.
Signed-off-by: Jeff Layton <jlayton(a)redhat.com>
---
kernel/auditsc.c | 20 ++++++++++++++++++++
1 files changed, 20 insertions(+), 0 deletions(-)
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 8d87439..4f90536 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -1575,6 +1575,26 @@ static void audit_log_name(struct audit_context *context, struct audit_names *n,
}
}
+ /* log the audit_names record type */
+ audit_log_format(ab, " nametype=");
+ switch(n->type) {
+ case AUDIT_TYPE_NORMAL:
+ audit_log_format(ab, "NORMAL");
+ break;
+ case AUDIT_TYPE_PARENT:
+ audit_log_format(ab, "PARENT");
+ break;
+ case AUDIT_TYPE_CHILD_DELETE:
+ audit_log_format(ab, "DELETE");
+ break;
+ case AUDIT_TYPE_CHILD_CREATE:
+ audit_log_format(ab, "CREATE");
+ break;
+ default:
+ audit_log_format(ab, "UNKNOWN");
+ break;
+ }
+
audit_log_fcaps(ab, n);
audit_log_end(ab);
--
1.7.1
11 years, 5 months
[PATCH] Enable splitting the logs to both auditd and kernel simultaneously
by William Roberts
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 <w.roberts(a)sta.samsung.com>
---
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
11 years, 5 months
[PATCH] Enable splitting the logs to both auditd and kernel simultaneously
by William Roberts
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 <w.roberts(a)sta.samsung.com>
---
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
11 years, 5 months
[PATCH] audit: cast decimal constant for invalid uid to unsigned
by Richard Guy Briggs
SFR reported this 2013-05-15:
> After merging the final tree, today's linux-next build (i386 defconfig)
> produced this warning:
>
> kernel/auditfilter.c: In function 'audit_data_to_entry':
> kernel/auditfilter.c:426:3: warning: this decimal constant is unsigned only
> in ISO C90 [enabled by default]
>
> Introduced by commit 780a7654cee8 ("audit: Make testing for a valid
> loginuid explicit") from Linus' tree.
Replace this decimal constant in the code with a macro to make it more readable
and add an unsigned cast to quiet the warning.
Cc: stable(a)vger.kernel.org # v3.9
Cc: Eric Paris <eparis(a)redhat.com>
Cc: Stephen Rothwell <sfr(a)canb.auug.org.au>
Cc: "Eric W. Biederman" <ebiederm(a)xmission.com>
Signed-off-by: Richard Guy Briggs <rgb(a)redhat.com>
---
include/uapi/linux/audit.h | 2 ++
kernel/auditfilter.c | 2 +-
2 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
index 75cef3f..b7cb978 100644
--- a/include/uapi/linux/audit.h
+++ b/include/uapi/linux/audit.h
@@ -374,6 +374,8 @@ struct audit_tty_status {
__u32 log_passwd; /* 1 = enabled, 0 = disabled */
};
+#define AUDIT_UID_UNSET (unsigned int)-1
+
/* 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/kernel/auditfilter.c b/kernel/auditfilter.c
index bc6595f..0d40b51 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -423,7 +423,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
f->lsm_rule = NULL;
/* Support legacy tests for a valid loginuid */
- if ((f->type == AUDIT_LOGINUID) && (f->val == 4294967295)) {
+ if ((f->type == AUDIT_LOGINUID) && (f->val == AUDIT_UID_UNSET)) {
f->type = AUDIT_LOGINUID_SET;
f->val = 0;
}
--
1.7.1
11 years, 5 months
Re: Rules mysteriously flushed
by Steve Grubb
On Monday, May 20, 2013 11:04:30 AM John Barnes wrote:
> I set up 4 simple audit rules using audictl:
>
> auditctl -w "/path/to/my/bin0" -p x
> auditctl -w "/path/to/my/bin1" -p x
>
> The rules were applied and show in auditctl -l. I tested them and
> they successfully log the execution of both binaries.
>
> However the rules were mysteriously flushed with only
> the following available in ausearch -m CONFIG_CHANGE:
>
> time->Sat May 18 00:03:19 2013
>
> type=CONFIG_CHANGE msg=audit(1368831799.081:466947): auid=4294967295
> ses=4294967295 op="remove rule" path="/path/to/my/bin0" key=(null) list=4
> res=1
>
> time->Sat May 18 00:03:19 2013
>
> type=CONFIG_CHANGE msg=audit(1368831799.081:466948): auid=4294967295
> ses=4294967295 op="remove rule" path="/path/to/my/bin1" key=(null) list=4
> res=1
>
> The uid doesn't match any known user so I presume these are initiated by
> the kernel.
Yes, these are -1, which is unset. This event is created by the kernel.
> The system wasn't under any pressure at the time (mem/load
> average fine), there was plenty of disk space available in all volumes, and
> the auditd was not restarted and the logs were not rotated.
>
> Is there anything that can cause the rules to be flushed in this way? It's
> a little concerning that they've just disappeared.
I think if your file is deleted, then it removes the associated rule.
-Steve
11 years, 5 months
ausearch
by David Flatley
I want to have ausearch search for a specific devname. Any suggestions?
Thanks.
David Flatley
"To err is human. To really screw up requires the root password." -UNKNOWN
11 years, 5 months
[PATCH] auditfilter.c: fix kernel-doc warnings
by Randy Dunlap
From: Randy Dunlap <rdunlap(a)infradead.org>
Fix kernel-doc warnings in kernel/auditfilter.c:
Warning(kernel/auditfilter.c:1029): Excess function parameter 'loginuid' description in 'audit_receive_filter'
Warning(kernel/auditfilter.c:1029): Excess function parameter 'sessionid' description in 'audit_receive_filter'
Warning(kernel/auditfilter.c:1029): Excess function parameter 'sid' description in 'audit_receive_filter'
Signed-off-by: Randy Dunlap <rdunlap(a)infradead.org>
---
kernel/auditfilter.c | 3 ---
1 file changed, 3 deletions(-)
--- lnx-310-rc1.orig/kernel/auditfilter.c
+++ lnx-310-rc1/kernel/auditfilter.c
@@ -1021,9 +1021,6 @@ static void audit_log_rule_change(char *
* @seq: netlink audit message sequence (serial) number
* @data: payload data
* @datasz: size of payload data
- * @loginuid: loginuid of sender
- * @sessionid: sessionid for netlink audit message
- * @sid: SE Linux Security ID of sender
*/
int audit_receive_filter(int type, int pid, int seq, void *data, size_t datasz)
{
11 years, 5 months