AUDIT: Add message types to audit records
Steve Grubb [Fri, 13 May 2005 17:17:42 +0000 (18:17 +0100)]
This patch adds more messages types to the audit subsystem so that audit
analysis is quicker, intuitive, and more useful.

Signed-off-by: Steve Grubb <sgrubb@redhat.com>
---
I forgot one type in the big patch. I need to add one for user space
originating SE Linux avc messages. This is used by dbus and nscd.

-Steve
---
Updated to 2.6.12-rc4-mm1.
-dwmw2

Signed-off-by: David Woodhouse <dwmw2@infradead.org>

include/linux/audit.h
kernel/audit.c
kernel/auditsc.c
security/selinux/avc.c
security/selinux/hooks.c
security/selinux/nlmsgtab.c
security/selinux/ss/services.c

index 405332e..1a15ba3 100644 (file)
 #include <linux/sched.h>
 #include <linux/elf.h>
 
-/* Request and reply types */
+/* The netlink messages for the audit system is divided into blocks:
+ * 1000 - 1099 are for commanding the audit system
+ * 1100 - 1199 user space trusted application messages
+ * 1200 - 1299 messages internal to the audit daemon
+ * 1300 - 1399 audit event messages
+ * 1400 - 1499 SE Linux use
+ * 1500 - 1999 future use
+ * 2000 is for otherwise unclassified kernel audit messages
+ *
+ * Messages from 1000-1199 are bi-directional. 1200-1299 are exclusively user
+ * space. Anything over that is kernel --> user space communication.
+ */
 #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_LIST             1002    /* List syscall filtering rules */
+#define AUDIT_ADD              1003    /* Add syscall filtering rule */
+#define AUDIT_DEL              1004    /* Delete syscall filtering rule */
+#define AUDIT_USER             1005    /* Message from userspace -- deprecated */
 #define AUDIT_LOGIN            1006    /* Define the login id and information */
-#define AUDIT_SIGNAL_INFO      1010    /* Get information about sender of signal*/
+#define AUDIT_WATCH_INS                1007    /* Insert file/dir watch entry */
+#define AUDIT_WATCH_REM                1008    /* Remove file/dir watch entry */
+#define AUDIT_WATCH_LIST       1009    /* List all file/dir watches */
+#define AUDIT_SIGNAL_INFO      1010    /* Get info about sender of signal to auditd */
+
+#define AUDIT_USER_AUTH                1100    /* User space authentication */
+#define AUDIT_USER_ACCT                1101    /* User space acct change */
+#define AUDIT_USER_MGMT                1102    /* User space acct management */
+#define AUDIT_CRED_ACQ         1103    /* User space credential acquired */
+#define AUDIT_CRED_DISP                1104    /* User space credential disposed */
+#define AUDIT_USER_START       1105    /* User space session start */ 
+#define AUDIT_USER_END         1106    /* User space session end */
+#define AUDIT_USER_AVC         1107    /* User space avc message */
+#define AUDIT_DAEMON_START      1200    /* Daemon startup record */
+#define AUDIT_DAEMON_END        1201    /* Daemon normal stop record */
+#define AUDIT_DAEMON_ABORT      1202    /* Daemon error stop record */
+#define AUDIT_DAEMON_CONFIG     1203    /* Daemon config change */
+
+#define AUDIT_SYSCALL          1300    /* Syscall event */
+#define AUDIT_FS_WATCH         1301    /* Filesystem watch event */
+#define AUDIT_PATH             1302    /* Filname path information */
+#define AUDIT_IPC              1303    /* IPC record */
+#define AUDIT_SOCKET           1304    /* Socket record */
+#define AUDIT_CONFIG_CHANGE    1305    /* Audit system configuration change */
+
+#define AUDIT_AVC              1400    /* SE Linux avc denial or grant */
+#define AUDIT_SELINUX_ERR      1401    /* Internal SE Linux Errors */
 
 #define AUDIT_KERNEL           2000    /* Asynchronous audit record. NOT A REQUEST. */
 
@@ -216,14 +254,11 @@ extern void audit_signal_info(int sig, struct task_struct *t);
 #ifdef CONFIG_AUDIT
 /* These are defined in audit.c */
                                /* Public API */
-#define audit_log(ctx, fmt, args...) \
-       audit_log_type(ctx, AUDIT_KERNEL, 0, fmt, ##args)
-extern void                audit_log_type(struct audit_context *ctx, int type,
-                                     int pid, const char *fmt, ...)
-                           __attribute__((format(printf,4,5)));
+extern void                audit_log(struct audit_context *ctx, int type,
+                                     const char *fmt, ...)
+                           __attribute__((format(printf,3,4)));
 
-extern struct audit_buffer *audit_log_start(struct audit_context *ctx, int type,
-                                           int pid);
+extern struct audit_buffer *audit_log_start(struct audit_context *ctx,int type);
 extern void                audit_log_format(struct audit_buffer *ab,
                                             const char *fmt, ...)
                            __attribute__((format(printf,2,3)));
@@ -243,9 +278,8 @@ extern void             audit_send_reply(int pid, int seq, int type,
                                             void *payload, int size);
 extern void                audit_log_lost(const char *message);
 #else
-#define audit_log(c,f,...) do { ; } while (0)
-#define audit_log_type(c,t,p,f,...) do { ; } while (0)
-#define audit_log_start(c,t,p) ({ NULL; })
+#define audit_log(c,t,f,...) do { ; } while (0)
+#define audit_log_start(c,t) ({ NULL; })
 #define audit_log_vformat(b,f,a) do { ; } while (0)
 #define audit_log_format(b,f,...) do { ; } while (0)
 #define audit_log_end(b) do { ; } while (0)
index 1871645..4e940c0 100644 (file)
@@ -140,6 +140,12 @@ struct audit_buffer {
        struct audit_context *ctx;      /* NULL or associated context */
 };
 
+static void audit_set_pid(struct audit_buffer *ab, pid_t pid)
+{
+       struct nlmsghdr *nlh = (struct nlmsghdr *)ab->skb->data;
+       nlh->nlmsg_pid = pid;
+}
+
 struct audit_entry {
        struct list_head  list;
        struct audit_rule rule;
@@ -233,7 +239,8 @@ static int audit_set_rate_limit(int limit, uid_t loginuid)
 {
        int old          = audit_rate_limit;
        audit_rate_limit = limit;
-       audit_log(NULL, "audit_rate_limit=%d old=%d by auid %u",
+       audit_log(NULL, AUDIT_CONFIG_CHANGE, 
+                       "audit_rate_limit=%d old=%d by auid %u",
                        audit_rate_limit, old, loginuid);
        return old;
 }
@@ -242,7 +249,8 @@ static int audit_set_backlog_limit(int limit, uid_t loginuid)
 {
        int old          = audit_backlog_limit;
        audit_backlog_limit = limit;
-       audit_log(NULL, "audit_backlog_limit=%d old=%d by auid %u",
+       audit_log(NULL, AUDIT_CONFIG_CHANGE,
+                       "audit_backlog_limit=%d old=%d by auid %u",
                        audit_backlog_limit, old, loginuid);
        return old;
 }
@@ -253,8 +261,9 @@ static int audit_set_enabled(int state, uid_t loginuid)
        if (state != 0 && state != 1)
                return -EINVAL;
        audit_enabled = state;
-       audit_log(NULL, "audit_enabled=%d old=%d by auid %u",
-                 audit_enabled, old, loginuid);
+       audit_log(NULL, AUDIT_CONFIG_CHANGE,
+                       "audit_enabled=%d old=%d by auid %u",
+                       audit_enabled, old, loginuid);
        return old;
 }
 
@@ -266,8 +275,9 @@ static int audit_set_failure(int state, uid_t loginuid)
            && state != AUDIT_FAIL_PANIC)
                return -EINVAL;
        audit_failure = state;
-       audit_log(NULL, "audit_failure=%d old=%d by auid %u",
-                 audit_failure, old, loginuid);
+       audit_log(NULL, AUDIT_CONFIG_CHANGE,
+                       "audit_failure=%d old=%d by auid %u",
+                       audit_failure, old, loginuid);
        return old;
 }
 
@@ -316,6 +326,14 @@ static int audit_netlink_ok(kernel_cap_t eff_cap, u16 msg_type)
                        err = -EPERM;
                break;
        case AUDIT_USER:
+       case AUDIT_USER_AUTH:
+       case AUDIT_USER_ACCT:
+       case AUDIT_USER_MGMT:
+       case AUDIT_CRED_ACQ:
+       case AUDIT_CRED_DISP:
+       case AUDIT_USER_START:
+       case AUDIT_USER_END:
+       case AUDIT_USER_AVC:
                if (!cap_raised(eff_cap, CAP_AUDIT_WRITE))
                        err = -EPERM;
                break;
@@ -332,6 +350,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
        void                    *data;
        struct audit_status     *status_get, status_set;
        int                     err;
+       struct audit_buffer     *ab;
        u16                     msg_type = nlh->nlmsg_type;
        uid_t                   loginuid; /* loginuid of sender */
        struct audit_sig_info   sig_data;
@@ -373,7 +392,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                if (status_get->mask & AUDIT_STATUS_PID) {
                        int old   = audit_pid;
                        audit_pid = status_get->pid;
-                       audit_log(NULL, "audit_pid=%d old=%d by auid %u",
+                       audit_log(NULL, AUDIT_CONFIG_CHANGE,
+                               "audit_pid=%d old=%d by auid %u",
                                  audit_pid, old, loginuid);
                }
                if (status_get->mask & AUDIT_STATUS_RATE_LIMIT)
@@ -383,13 +403,26 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                                                        loginuid);
                break;
        case AUDIT_USER:
-               audit_log_type(NULL, AUDIT_USER, pid,
+       case AUDIT_USER_AUTH:
+       case AUDIT_USER_ACCT:
+       case AUDIT_USER_MGMT:
+       case AUDIT_CRED_ACQ:
+       case AUDIT_CRED_DISP:
+       case AUDIT_USER_START:
+       case AUDIT_USER_END:
+       case AUDIT_USER_AVC:
+               ab = audit_log_start(NULL, msg_type);
+               if (!ab)
+                       break;  /* audit_panic has been called */
+               audit_log_format(ab,
                                 "user pid=%d uid=%d length=%d loginuid=%u"
                                 " msg='%.1024s'",
                                 pid, uid,
                                 (int)(nlh->nlmsg_len
                                       - ((char *)data - (char *)nlh)),
                                 loginuid, (char *)data);
+               audit_set_pid(ab, pid);
+               audit_log_end(ab);
                break;
        case AUDIT_ADD:
        case AUDIT_DEL:
@@ -504,7 +537,7 @@ static int __init audit_init(void)
 
        audit_initialized = 1;
        audit_enabled = audit_default;
-       audit_log(NULL, "initialized");
+       audit_log(NULL, AUDIT_KERNEL, "initialized");
        return 0;
 }
 __initcall(audit_init);
@@ -541,10 +574,12 @@ static void audit_buffer_free(struct audit_buffer *ab)
        spin_unlock_irqrestore(&audit_freelist_lock, flags);
 }
 
-static struct audit_buffer * audit_buffer_alloc(int gfp_mask)
+static struct audit_buffer * audit_buffer_alloc(struct audit_context *ctx,
+                                               int gfp_mask, int type)
 {
        unsigned long flags;
        struct audit_buffer *ab = NULL;
+       struct nlmsghdr *nlh;
 
        spin_lock_irqsave(&audit_freelist_lock, flags);
        if (!list_empty(&audit_freelist)) {
@@ -566,6 +601,12 @@ static struct audit_buffer * audit_buffer_alloc(int gfp_mask)
        if (!ab->skb)
                goto err;
 
+       ab->ctx   = ctx;
+       nlh = (struct nlmsghdr *)skb_put(ab->skb, NLMSG_SPACE(0));
+       nlh->nlmsg_type = type;
+       nlh->nlmsg_flags = 0;
+       nlh->nlmsg_pid = 0;
+       nlh->nlmsg_seq = 0;
        return ab;
 err:
        audit_buffer_free(ab);
@@ -578,12 +619,11 @@ err:
  * syscall, then the syscall is marked as auditable and an audit record
  * will be written at syscall exit.  If there is no associated task, tsk
  * should be NULL. */
-struct audit_buffer *audit_log_start(struct audit_context *ctx, int type, int pid)
+struct audit_buffer *audit_log_start(struct audit_context *ctx, int type)
 {
        struct audit_buffer     *ab     = NULL;
        struct timespec         t;
        unsigned int            serial;
-       struct nlmsghdr *nlh;
 
        if (!audit_initialized)
                return NULL;
@@ -600,19 +640,12 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, int type, int pi
                return NULL;
        }
 
-       ab = audit_buffer_alloc(GFP_ATOMIC);
+       ab = audit_buffer_alloc(ctx, GFP_ATOMIC, type);
        if (!ab) {
                audit_log_lost("out of memory in audit_log_start");
                return NULL;
        }
 
-       ab->ctx   = ctx;
-       nlh = (struct nlmsghdr *)skb_put(ab->skb, NLMSG_SPACE(0));
-       nlh->nlmsg_type = type;
-       nlh->nlmsg_flags = 0;
-       nlh->nlmsg_pid = pid;
-       nlh->nlmsg_seq = 0;
-
        if (!audit_get_stamp(ab->ctx, &t, &serial)) {
                t = CURRENT_TIME;
                serial = 0;
@@ -809,13 +842,12 @@ void audit_log_end(struct audit_buffer *ab)
 /* Log an audit record.  This is a convenience function that calls
  * audit_log_start, audit_log_vformat, and audit_log_end.  It may be
  * called in any context. */
-void audit_log_type(struct audit_context *ctx, int type, int pid,
-                   const char *fmt, ...)
+void audit_log(struct audit_context *ctx, int type, const char *fmt, ...)
 {
        struct audit_buffer *ab;
        va_list args;
 
-       ab = audit_log_start(ctx, type, pid);
+       ab = audit_log_start(ctx, type);
        if (ab) {
                va_start(args, fmt);
                audit_log_vformat(ab, fmt, args);
index d089263..1b7c91f 100644 (file)
@@ -286,7 +286,8 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
                        err = audit_add_rule(entry, &audit_entlist);
                if (!err && (flags & AUDIT_AT_EXIT))
                        err = audit_add_rule(entry, &audit_extlist);
-               audit_log(NULL, "auid %u added an audit rule\n", loginuid);
+               audit_log(NULL, AUDIT_CONFIG_CHANGE, 
+                               "auid %u added an audit rule\n", loginuid);
                break;
        case AUDIT_DEL:
                flags =((struct audit_rule *)data)->flags;
@@ -296,7 +297,8 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
                        err = audit_del_rule(data, &audit_entlist);
                if (!err && (flags & AUDIT_AT_EXIT))
                        err = audit_del_rule(data, &audit_extlist);
-               audit_log(NULL, "auid %u removed an audit rule\n", loginuid);
+               audit_log(NULL, AUDIT_CONFIG_CHANGE,
+                               "auid %u removed an audit rule\n", loginuid);
                break;
        default:
                return -EINVAL;
@@ -648,7 +650,7 @@ static void audit_log_exit(struct audit_context *context)
        int i;
        struct audit_buffer *ab;
 
-       ab = audit_log_start(context, AUDIT_KERNEL, 0);
+       ab = audit_log_start(context, AUDIT_SYSCALL);
        if (!ab)
                return;         /* audit_panic has been called */
        audit_log_format(ab, "syscall=%d", context->major);
@@ -680,28 +682,28 @@ static void audit_log_exit(struct audit_context *context)
        while (context->aux) {
                struct audit_aux_data *aux;
 
-               ab = audit_log_start(context, AUDIT_KERNEL, 0);
+               aux = context->aux;
+
+               ab = audit_log_start(context, aux->type);
                if (!ab)
                        continue; /* audit_panic has been called */
 
-               aux = context->aux;
-               context->aux = aux->next;
-
-               audit_log_format(ab, "auxitem=%d", aux->type);
                switch (aux->type) {
-               case AUDIT_AUX_IPCPERM: {
+               case AUDIT_IPC: {
                        struct audit_aux_data_ipcctl *axi = (void *)aux;
                        audit_log_format(ab, 
-                                        " qbytes=%lx uid=%d gid=%d mode=%x",
+                                        " qbytes=%lx iuid=%d igid=%d mode=%x",
                                         axi->qbytes, axi->uid, axi->gid, axi->mode);
                        }
                }
                audit_log_end(ab);
+
+               context->aux = aux->next;
                kfree(aux);
        }
 
        for (i = 0; i < context->name_count; i++) {
-               ab = audit_log_start(context, AUDIT_KERNEL, 0);
+               ab = audit_log_start(context, AUDIT_PATH);
                if (!ab)
                        continue; /* audit_panic has been called */
                audit_log_format(ab, "item=%d", i);
@@ -711,7 +713,7 @@ static void audit_log_exit(struct audit_context *context)
                }
                if (context->names[i].ino != (unsigned long)-1)
                        audit_log_format(ab, " inode=%lu dev=%02x:%02x mode=%#o"
-                                            " uid=%d gid=%d rdev=%02x:%02x",
+                                            " ouid=%d ogid=%d rdev=%02x:%02x",
                                         context->names[i].ino,
                                         MAJOR(context->names[i].dev),
                                         MINOR(context->names[i].dev),
@@ -1008,10 +1010,16 @@ int audit_get_stamp(struct audit_context *ctx,
 int audit_set_loginuid(struct task_struct *task, uid_t loginuid)
 {
        if (task->audit_context) {
-               audit_log_type(NULL, AUDIT_LOGIN, 0,
-                         "login pid=%d uid=%u old loginuid=%u new loginuid=%u",
-                         task->pid, task->uid, task->audit_context->loginuid,
-                         loginuid);
+               struct audit_buffer *ab;
+
+               ab = audit_log_start(NULL, AUDIT_LOGIN);
+               if (ab) {
+                       audit_log_format(ab, "login pid=%d uid=%u "
+                               "old loginuid=%u new loginuid=%u",
+                               task->pid, task->uid, 
+                               task->audit_context->loginuid, loginuid);
+                       audit_log_end(ab);
+               }
                task->audit_context->loginuid = loginuid;
        }
        return 0;
@@ -1039,7 +1047,7 @@ int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode)
        ax->gid = gid;
        ax->mode = mode;
 
-       ax->d.type = AUDIT_AUX_IPCPERM;
+       ax->d.type = AUDIT_IPC;
        ax->d.next = context->aux;
        context->aux = (void *)ax;
        return 0;
index 9e71a1b..042f91e 100644 (file)
@@ -242,7 +242,7 @@ void __init avc_init(void)
        avc_node_cachep = kmem_cache_create("avc_node", sizeof(struct avc_node),
                                             0, SLAB_PANIC, NULL, NULL);
 
-       audit_log(current->audit_context, "AVC INITIALIZED\n");
+       audit_log(current->audit_context, AUDIT_KERNEL, "AVC INITIALIZED\n");
 }
 
 int avc_get_hash_stats(char *page)
@@ -549,7 +549,7 @@ void avc_audit(u32 ssid, u32 tsid,
                        return;
        }
 
-       ab = audit_log_start(current->audit_context, AUDIT_KERNEL, 0);
+       ab = audit_log_start(current->audit_context, AUDIT_AVC);
        if (!ab)
                return;         /* audit_panic has been called */
        audit_log_format(ab, "avc:  %s ", denied ? "denied" : "granted");
index aae1e79..db845cb 100644 (file)
@@ -3419,7 +3419,7 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
        err = selinux_nlmsg_lookup(isec->sclass, nlh->nlmsg_type, &perm);
        if (err) {
                if (err == -EINVAL) {
-                       audit_log(current->audit_context,
+                       audit_log(current->audit_context, AUDIT_SELINUX_ERR,
                                  "SELinux:  unrecognized netlink message"
                                  " type=%hu for sclass=%hu\n",
                                  nlh->nlmsg_type, isec->sclass);
index deac143..67e77ac 100644 (file)
@@ -98,6 +98,14 @@ static struct nlmsg_perm nlmsg_audit_perms[] =
        { AUDIT_DEL,            NETLINK_AUDIT_SOCKET__NLMSG_WRITE    },
        { AUDIT_USER,           NETLINK_AUDIT_SOCKET__NLMSG_RELAY    },
        { AUDIT_SIGNAL_INFO,    NETLINK_AUDIT_SOCKET__NLMSG_READ     },
+       { AUDIT_USER_AUTH,      NETLINK_AUDIT_SOCKET__NLMSG_RELAY    },
+       { AUDIT_USER_ACCT,      NETLINK_AUDIT_SOCKET__NLMSG_RELAY    },
+       { AUDIT_USER_MGMT,      NETLINK_AUDIT_SOCKET__NLMSG_RELAY    },
+       { AUDIT_CRED_ACQ,       NETLINK_AUDIT_SOCKET__NLMSG_RELAY    },
+       { AUDIT_CRED_DISP,      NETLINK_AUDIT_SOCKET__NLMSG_RELAY    },
+       { AUDIT_USER_START,     NETLINK_AUDIT_SOCKET__NLMSG_RELAY    },
+       { AUDIT_USER_END,       NETLINK_AUDIT_SOCKET__NLMSG_RELAY    },
+       { AUDIT_USER_AVC,       NETLINK_AUDIT_SOCKET__NLMSG_RELAY    },
 };
 
 
index 5a820cf..07fdf6e 100644 (file)
@@ -365,7 +365,7 @@ static int security_validtrans_handle_fail(struct context *ocontext,
                goto out;
        if (context_struct_to_string(tcontext, &t, &tlen) < 0)
                goto out;
-       audit_log(current->audit_context,
+       audit_log(current->audit_context, AUDIT_SELINUX_ERR,
                  "security_validate_transition:  denied for"
                  " oldcontext=%s newcontext=%s taskcontext=%s tclass=%s",
                  o, n, t, policydb.p_class_val_to_name[tclass-1]);
@@ -742,7 +742,7 @@ static int compute_sid_handle_invalid_context(
                goto out;
        if (context_struct_to_string(newcontext, &n, &nlen) < 0)
                goto out;
-       audit_log(current->audit_context,
+       audit_log(current->audit_context, AUDIT_SELINUX_ERR,
                  "security_compute_sid:  invalid context %s"
                  " for scontext=%s"
                  " tcontext=%s"