[PATCH] Exclude messages by message type
Dustin Kirkland [Thu, 3 Nov 2005 16:12:36 +0000 (16:12 +0000)]
    - Add a new, 5th filter called "exclude".
    - And add a new field AUDIT_MSGTYPE.
    - Define a new function audit_filter_exclude() that takes a message type
      as input and examines all rules in the filter.  It returns '1' if the
      message is to be excluded, and '0' otherwise.
    - Call the audit_filter_exclude() function near the top of
      audit_log_start() just after asserting audit_initialized.  If the
      message type is not to be audited, return NULL very early, before
      doing a lot of work.
[combined with followup fix for bug in original patch, Nov 4, same author]
[combined with later renaming AUDIT_FILTER_EXCLUDE->AUDIT_FILTER_TYPE
and audit_filter_exclude() -> audit_filter_type()]

Signed-off-by: Dustin Kirkland <dustin.kirkland@us.ibm.com>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

include/linux/audit.h
kernel/audit.c
kernel/auditsc.c

index 739b954..8fa1a8f 100644 (file)
@@ -92,8 +92,9 @@
 #define AUDIT_FILTER_ENTRY     0x02    /* Apply rule at syscall entry */
 #define AUDIT_FILTER_WATCH     0x03    /* Apply rule to file system watches */
 #define AUDIT_FILTER_EXIT      0x04    /* Apply rule at syscall exit */
+#define AUDIT_FILTER_TYPE      0x05    /* Apply rule at audit_log_start */
 
-#define AUDIT_NR_FILTERS       5
+#define AUDIT_NR_FILTERS       6
 
 #define AUDIT_FILTER_PREPEND   0x10    /* Prepend to front of list */
 
 #define AUDIT_LOGINUID 9
 #define AUDIT_PERS     10
 #define AUDIT_ARCH     11
+#define AUDIT_MSGTYPE  12
 
                                /* These are ONLY useful when checking
                                 * at syscall exit time (AUDIT_AT_EXIT). */
@@ -289,6 +291,7 @@ extern int audit_sockaddr(int len, void *addr);
 extern int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt);
 extern void audit_signal_info(int sig, struct task_struct *t);
 extern int audit_filter_user(struct netlink_skb_parms *cb, int type);
+extern int audit_filter_type(int type);
 #else
 #define audit_alloc(t) ({ 0; })
 #define audit_free(t) do { ; } while (0)
index 6d61dd7..1c3eb1b 100644 (file)
@@ -702,6 +702,9 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
        if (!audit_initialized)
                return NULL;
 
+       if (unlikely(audit_filter_type(type)))
+               return NULL;
+
        if (gfp_mask & __GFP_WAIT)
                reserve = 0;
        else
index 73f932b..31917ac 100644 (file)
@@ -187,7 +187,8 @@ static struct list_head audit_filter_list[AUDIT_NR_FILTERS] = {
        LIST_HEAD_INIT(audit_filter_list[2]),
        LIST_HEAD_INIT(audit_filter_list[3]),
        LIST_HEAD_INIT(audit_filter_list[4]),
-#if AUDIT_NR_FILTERS != 5
+       LIST_HEAD_INIT(audit_filter_list[5]),
+#if AUDIT_NR_FILTERS != 6
 #error Fix audit_filter_list initialiser
 #endif
 };
@@ -663,6 +664,38 @@ int audit_filter_user(struct netlink_skb_parms *cb, int type)
        return ret; /* Audit by default */
 }
 
+int audit_filter_type(int type)
+{
+       struct audit_entry *e;
+       int result = 0;
+       
+       rcu_read_lock();
+       if (list_empty(&audit_filter_list[AUDIT_FILTER_TYPE]))
+               goto unlock_and_return;
+
+       list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_TYPE],
+                               list) {
+               struct audit_rule *rule = &e->rule;
+               int i;
+               for (i = 0; i < rule->field_count; i++) {
+                       u32 field  = rule->fields[i] & ~AUDIT_OPERATORS;
+                       u32 op  = rule->fields[i] & AUDIT_OPERATORS;
+                       u32 value  = rule->values[i];
+                       if ( field == AUDIT_MSGTYPE ) {
+                               result = audit_comparator(type, op, value); 
+                               if (!result)
+                                       break;
+                       }
+               }
+               if (result)
+                       goto unlock_and_return;
+       }
+unlock_and_return:
+       rcu_read_unlock();
+       return result;
+}
+
+
 /* This should be called with task_lock() held. */
 static inline struct audit_context *audit_get_context(struct task_struct *tsk,
                                                      int return_valid,