[PATCH 1/2] audit: stop an old auditd being starved out by a new auditd

From: Richard Guy Briggs
Date: Fri Sep 18 2015 - 04:00:49 EST


Nothing prevents a new auditd starting up and replacing a valid
audit_pid when an old auditd is still running, effectively starving out
the old auditd since audit_pid no longer points to the old valid auditd.

If no message to auditd has been attempted since auditd died unnaturally
or got killed, audit_pid will still indicate it is alive. There isn't
an easy way to detect if an old auditd is still running on the existing
audit_pid other than attempting to send a message to see if it fails.
An -ECONNREFUSED almost certainly means it disappeared and can be
replaced. Other errors are not so straightforward and may indicate
transient problems that will resolve themselves and the old auditd will
recover. Yet others will likely need manual intervention for which a
new auditd will not solve the problem.

Send a new message type (AUDIT_PING) to the old auditd containing a u32
with the PID of the new auditd. If the audit ping succeeds (or doesn't
fail with certainty), fail to register the new auditd and return an
error (-EEXIST).

This is expected to make the patch preventing an old auditd orphaning a
new auditd redundant.

Signed-off-by: Richard Guy Briggs <rgb@xxxxxxxxxx>
---
include/uapi/linux/audit.h | 1 +
kernel/audit.c | 19 +++++++++++++++++--
2 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
index d3475e1..4c97e30 100644
--- a/include/uapi/linux/audit.h
+++ b/include/uapi/linux/audit.h
@@ -70,6 +70,7 @@
#define AUDIT_TTY_SET 1017 /* Set TTY auditing status */
#define AUDIT_SET_FEATURE 1018 /* Turn an audit feature on or off */
#define AUDIT_GET_FEATURE 1019 /* Get which features are enabled */
+#define AUDIT_PING 1020 /* Ping auditd to see if it is alive */

#define AUDIT_FIRST_USER_MSG 1100 /* Userspace messages mostly uninteresting to kernel */
#define AUDIT_USER_AVC 1107 /* We filter this differently */
diff --git a/kernel/audit.c b/kernel/audit.c
index 18cdfe2..3399ab2 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -810,6 +810,15 @@ static int audit_set_feature(struct sk_buff *skb)
return 0;
}

+static int audit_ping(pid_t pid, u32 seq, u32 portid)
+{
+ struct sk_buff *skb = audit_make_reply(portid, seq, AUDIT_PING, 0, 0, &pid, sizeof(pid));
+
+ if (!skb)
+ return -ENOMEM;
+ return netlink_unicast(audit_sock, skb, audit_nlk_portid, 0);
+}
+
static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
{
u32 seq;
@@ -871,13 +880,19 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
}
if (s.mask & AUDIT_STATUS_PID) {
int new_pid = s.pid;
+ pid_t requesting_pid = task_tgid_vnr(current);
+ u32 portid = NETLINK_CB(skb).portid;

- if ((!new_pid) && (task_tgid_vnr(current) != audit_pid))
+ if ((!new_pid) && (requesting_pid != audit_pid))
return -EACCES;
+ if (audit_pid && new_pid &&
+ audit_ping(requesting_pid, nlmsg_hdr(skb)->nlmsg_seq, portid) !=
+ -ECONNREFUSED)
+ return -EEXIST;
if (audit_enabled != AUDIT_OFF)
audit_log_config_change("audit_pid", new_pid, audit_pid, 1);
audit_pid = new_pid;
- audit_nlk_portid = NETLINK_CB(skb).portid;
+ audit_nlk_portid = portid;
audit_sock = skb->sk;
}
if (s.mask & AUDIT_STATUS_RATE_LIMIT) {
--
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/