aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Emelyanov <xemul@openvz.org>2008-03-20 18:39:41 -0400
committerDavid S. Miller <davem@davemloft.net>2008-03-20 18:39:41 -0400
commit75c0371a2d385ecbd6e1f854d9dce20889f06736 (patch)
tree34a9988cfb3077c88a44b904f466d129b01caae9
parent4f42c288e66a3395e94158badbd182b2dae8eccb (diff)
audit: netlink socket can be auto-bound to pid other than current->pid (v2)
From: Pavel Emelyanov <xemul@openvz.org> This patch is based on the one from Thomas. The kauditd_thread() calls the netlink_unicast() and passes the audit_pid to it. The audit_pid, in turn, is received from the user space and the tool (I've checked the audit v1.6.9) uses getpid() to pass one in the kernel. Besides, this tool doesn't bind the netlink socket to this id, but simply creates it allowing the kernel to auto-bind one. That's the preamble. The problem is that netlink_autobind() _does_not_ guarantees that the socket will be auto-bound to the current pid. Instead it uses the current pid as a hint to start looking for a free id. So, in case of conflict, the audit messages can be sent to a wrong socket. This can happen (it's unlikely, but can be) in case some task opens more than one netlink sockets and then the audit one starts - in this case the audit's pid can be busy and its socket will be bound to another id. The proposal is to introduce an audit_nlk_pid in audit subsys, that will point to the netlink socket to send packets to. It will most often be equal to audit_pid. The socket id can be got from the skb's netlink CB right in the audit_receive_msg. The audit_nlk_pid reset to 0 is not required, since all the decisions are taken based on audit_pid value only. Later, if the audit tools will bind the socket themselves, the kernel will have to provide a way to setup the audit_nlk_pid as well. A good side effect of this patch is that audit_pid can later be converted to struct pid, as it is not longer safe to use pid_t-s in the presence of pid namespaces. But audit code still uses the tgid from task_struct in the audit_signal_info and in the audit_filter_syscall. Signed-off-by: Thomas Graf <tgraf@suug.ch> Signed-off-by: Pavel Emelyanov <xemul@openvz.org> Acked-by: Eric Paris <eparis@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--kernel/audit.c11
1 files changed, 8 insertions, 3 deletions
diff --git a/kernel/audit.c b/kernel/audit.c
index 10c4930c2bbf..be55cb503633 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -78,9 +78,13 @@ static int audit_default;
78/* If auditing cannot proceed, audit_failure selects what happens. */ 78/* If auditing cannot proceed, audit_failure selects what happens. */
79static int audit_failure = AUDIT_FAIL_PRINTK; 79static int audit_failure = AUDIT_FAIL_PRINTK;
80 80
81/* If audit records are to be written to the netlink socket, audit_pid 81/*
82 * contains the (non-zero) pid. */ 82 * If audit records are to be written to the netlink socket, audit_pid
83 * contains the pid of the auditd process and audit_nlk_pid contains
84 * the pid to use to send netlink messages to that process.
85 */
83int audit_pid; 86int audit_pid;
87static int audit_nlk_pid;
84 88
85/* If audit_rate_limit is non-zero, limit the rate of sending audit records 89/* If audit_rate_limit is non-zero, limit the rate of sending audit records
86 * to that number per second. This prevents DoS attacks, but results in 90 * to that number per second. This prevents DoS attacks, but results in
@@ -350,7 +354,7 @@ static int kauditd_thread(void *dummy)
350 wake_up(&audit_backlog_wait); 354 wake_up(&audit_backlog_wait);
351 if (skb) { 355 if (skb) {
352 if (audit_pid) { 356 if (audit_pid) {
353 int err = netlink_unicast(audit_sock, skb, audit_pid, 0); 357 int err = netlink_unicast(audit_sock, skb, audit_nlk_pid, 0);
354 if (err < 0) { 358 if (err < 0) {
355 BUG_ON(err != -ECONNREFUSED); /* Shoudn't happen */ 359 BUG_ON(err != -ECONNREFUSED); /* Shoudn't happen */
356 printk(KERN_ERR "audit: *NO* daemon at audit_pid=%d\n", audit_pid); 360 printk(KERN_ERR "audit: *NO* daemon at audit_pid=%d\n", audit_pid);
@@ -626,6 +630,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
626 sid, 1); 630 sid, 1);
627 631
628 audit_pid = new_pid; 632 audit_pid = new_pid;
633 audit_nlk_pid = NETLINK_CB(skb).pid;
629 } 634 }
630 if (status_get->mask & AUDIT_STATUS_RATE_LIMIT) 635 if (status_get->mask & AUDIT_STATUS_RATE_LIMIT)
631 err = audit_set_rate_limit(status_get->rate_limit, 636 err = audit_set_rate_limit(status_get->rate_limit,