The attached patch addresses the problem with getting the audit daemon 
shutdown credential information. It creates a new message type 
AUDIT_TERM_INFO, which is used by the audit daemon to query who issued the 
shutdown. 

It requires the placement of a hook function that gathers the information. The 
hook is after the DAC & MAC checks and before the function returns. Racing 
threads could overwrite the uid & pid - but they would have to be root and 
have policy that allows signalling the audit daemon. That should be a 
manageable risk.

The userspace component will be released later in audit 0.7.2. When it 
receives the TERM signal, it queries the kernel for shutdown information. 
When it receives it, it writes the message and exits. The message looks 
like this:

type=DAEMON msg=auditd(1114551182.000) auditd normal halt, sending pid=2650 
uid=525, auditd pid=1685

Signed-off-by: Steve Grubb <sgrubb@redhat.com>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
diff --git a/kernel/audit.c b/kernel/audit.c
index 9c4f1af..6f344b4 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -68,7 +68,7 @@
 
 /* If audit records are to be written to the netlink socket, audit_pid
  * contains the (non-zero) pid. */
-static int	audit_pid;
+int		audit_pid;
 
 /* If audit_limit is non-zero, limit the rate of sending audit records
  * to that number per second.  This prevents DoS attacks, but results in
@@ -79,6 +79,10 @@
 static int	audit_backlog_limit = 64;
 static atomic_t	audit_backlog	    = ATOMIC_INIT(0);
 
+/* The identity of the user shutting down the audit system. */
+uid_t		audit_sig_uid = -1;
+pid_t		audit_sig_pid = -1;
+
 /* Records can be lost in several ways:
    0) [suppressed in audit_alloc]
    1) out of memory in audit_log_start [kmalloc of struct audit_buffer]
@@ -321,6 +325,7 @@
 	case AUDIT_SET:
 	case AUDIT_ADD:
 	case AUDIT_DEL:
+	case AUDIT_SIGNAL_INFO:
 		if (!cap_raised(eff_cap, CAP_AUDIT_CONTROL))
 			err = -EPERM;
 		break;
@@ -344,6 +349,7 @@
 	struct audit_buffer	*ab;
 	u16			msg_type = nlh->nlmsg_type;
 	uid_t			loginuid; /* loginuid of sender */
+	struct audit_sig_info   sig_data;
 
 	err = audit_netlink_ok(NETLINK_CB(skb).eff_cap, msg_type);
 	if (err)
@@ -419,6 +425,12 @@
 		err = -EOPNOTSUPP;
 #endif
 		break;
+	case AUDIT_SIGNAL_INFO:
+		sig_data.uid = audit_sig_uid;
+		sig_data.pid = audit_sig_pid;
+		audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_SIGNAL_INFO, 
+				0, 0, &sig_data, sizeof(sig_data));
+		break;
 	default:
 		err = -EINVAL;
 		break;
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 37b3ac9..f1bf665 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -1056,3 +1056,22 @@
 	context->aux = (void *)ax;
 	return 0;
 }
+
+void audit_signal_info(int sig, struct task_struct *t)
+{
+	extern pid_t audit_sig_pid;
+	extern uid_t audit_sig_uid;
+	extern int audit_pid;
+
+	if (unlikely(audit_pid && t->pid == audit_pid)) {
+		if (sig == SIGTERM || sig == SIGHUP) {
+			struct audit_context *ctx = current->audit_context;
+			audit_sig_pid = current->pid;
+			if (ctx)
+				audit_sig_uid = ctx->loginuid;
+			else
+				audit_sig_uid = current->uid;
+		}
+	}
+}
+
diff --git a/kernel/signal.c b/kernel/signal.c
index 8f3debc..293e189 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -24,6 +24,7 @@
 #include <linux/ptrace.h>
 #include <linux/posix-timers.h>
 #include <linux/signal.h>
+#include <linux/audit.h>
 #include <asm/param.h>
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -658,7 +659,11 @@
 	    && (current->uid ^ t->suid) && (current->uid ^ t->uid)
 	    && !capable(CAP_KILL))
 		return error;
-	return security_task_kill(t, info, sig);
+
+	error = security_task_kill(t, info, sig);
+	if (!error)
+		audit_signal_info(sig, t); /* Let audit system see the signal */
+	return error;
 }
 
 /* forward decl */