summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/audit.h5
-rw-r--r--kernel/audit.c3
-rw-r--r--kernel/auditsc.c35
3 files changed, 41 insertions, 2 deletions
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 739b954cb24..8fa1a8fbc04 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -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 */
@@ -132,6 +133,7 @@
#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)
diff --git a/kernel/audit.c b/kernel/audit.c
index 6d61dd79a60..1c3eb1b12bf 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -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
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 73f932b7deb..31917ac730a 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -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,