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>
 
 #include <linux/elf.h>
 
 /* Request and reply types */
-#define AUDIT_GET      1000    /* Get status */
-#define AUDIT_SET      1001    /* Set status (enable/disable/auditd) */
-#define AUDIT_LIST     1002    /* List filtering rules */
-#define AUDIT_ADD      1003    /* Add filtering rule */
-#define AUDIT_DEL      1004    /* Delete filtering rule */
-#define AUDIT_USER     1005    /* Send a message from user-space */
-#define AUDIT_LOGIN    1006     /* Define the login id and informaiton */
-#define AUDIT_KERNEL   2000    /* Asynchronous audit record. NOT A REQUEST. */
+#define AUDIT_GET              1000    /* Get status */
+#define AUDIT_SET              1001    /* Set status (enable/disable/auditd) */
+#define AUDIT_LIST             1002    /* List filtering rules */
+#define AUDIT_ADD              1003    /* Add filtering rule */
+#define AUDIT_DEL              1004    /* Delete filtering rule */
+#define AUDIT_USER             1005    /* Send a message from user-space */
+#define AUDIT_LOGIN            1006    /* Define the login id and information */
+#define AUDIT_SIGNAL_INFO      1010    /* Get information about sender of signal*/
+
+#define AUDIT_KERNEL           2000    /* Asynchronous audit record. NOT A REQUEST. */
 
 /* Rule flags */
 #define AUDIT_PER_TASK 0x01    /* Apply rule at task creation (not syscall) */
 
 #ifdef __KERNEL__
 
+struct audit_sig_info {
+       uid_t           uid;
+       pid_t           pid;
+};
+
 struct audit_buffer;
 struct audit_context;
 struct inode;
 extern int  audit_set_loginuid(struct task_struct *task, uid_t loginuid);
 extern uid_t audit_get_loginuid(struct audit_context *ctx);
 extern int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode);
+extern void audit_signal_info(int sig, struct task_struct *t);
 #else
 #define audit_alloc(t) ({ 0; })
 #define audit_free(t) do { ; } while (0)
 #define audit_inode(n,i) do { ; } while (0)
 #define audit_get_loginuid(c) ({ -1; })
 #define audit_ipc_perms(q,u,g,m) ({ 0; })
+#define audit_signal_info(s,t) do { ; } while (0)
 #endif
 
 #ifdef CONFIG_AUDIT
 
 
 /* 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
 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]
        case AUDIT_SET:
        case AUDIT_ADD:
        case AUDIT_DEL:
+       case AUDIT_SIGNAL_INFO:
                if (!cap_raised(eff_cap, CAP_AUDIT_CONTROL))
                        err = -EPERM;
                break;
        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)
                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;
 
        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;
+               }
+       }
+}
+
 
 #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>
            && (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 */
 
        { AUDIT_ADD,            NETLINK_AUDIT_SOCKET__NLMSG_WRITE    },
        { AUDIT_DEL,            NETLINK_AUDIT_SOCKET__NLMSG_WRITE    },
        { AUDIT_USER,           NETLINK_AUDIT_SOCKET__NLMSG_RELAY    },
+       { AUDIT_SIGNAL_INFO,    NETLINK_AUDIT_SOCKET__NLMSG_READ     },
 };