From 62062cf8a3a99a933efdac549da380f230dbe982 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Tue, 16 Apr 2013 13:08:43 -0400 Subject: [PATCH] audit: allow checking the type of audit message in the user filter When userspace sends messages to the audit system it includes a type. We want to be able to filter messages based on that type without have to do the all or nothing option currently available on the AUDIT_FILTER_TYPE filter list. Instead we should be able to use the AUDIT_FILTER_USER filter list and just use the message type as one part of the matching decision. Signed-off-by: Eric Paris --- include/linux/audit.h | 2 +- kernel/audit.c | 2 +- kernel/auditfilter.c | 28 +++++++++++++++++++++++++--- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index 8f92e1dea966..b26d7f121ac5 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -438,7 +438,7 @@ static inline void audit_log_secctx(struct audit_buffer *ab, u32 secid) extern int audit_update_lsm_rules(void); /* Private API (for audit.c only) */ -extern int audit_filter_user(void); +extern int audit_filter_user(int type); extern int audit_filter_type(int type); extern int audit_receive_filter(int type, int pid, int seq, void *data, size_t datasz, kuid_t loginuid, diff --git a/kernel/audit.c b/kernel/audit.c index c45e6d2809d7..132271448b89 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -737,7 +737,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) if (!audit_enabled && msg_type != AUDIT_USER_AVC) return 0; - err = audit_filter_user(); + err = audit_filter_user(msg_type); if (err == 1) { err = 0; if (msg_type == AUDIT_USER_TTY) { diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index f9fc54bbe06f..9e666004e0dc 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -310,6 +310,18 @@ static u32 audit_to_op(u32 op) return n; } +/* check if a field is valid for a given list */ +static int audit_field_valid(struct audit_entry *entry, struct audit_field *f) +{ + switch(f->type) { + case AUDIT_MSGTYPE: + if (entry->rule.listnr != AUDIT_FILTER_TYPE && + entry->rule.listnr != AUDIT_FILTER_USER) + return -EINVAL; + break; + }; + return 0; +} /* Translate struct audit_rule to kernel's rule respresentation. * Exists for backward compatibility with userspace. */ @@ -459,6 +471,13 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, f->gid = INVALID_GID; f->lsm_str = NULL; f->lsm_rule = NULL; + + err = audit_field_valid(entry, f); + if (err) + goto exit_free; + + err = -EINVAL; + switch(f->type) { case AUDIT_UID: case AUDIT_EUID: @@ -1354,7 +1373,7 @@ int audit_compare_dname_path(const char *dname, const char *path, int parentlen) return strncmp(p, dname, dlen); } -static int audit_filter_user_rules(struct audit_krule *rule, +static int audit_filter_user_rules(struct audit_krule *rule, int type, enum audit_state *state) { int i; @@ -1378,6 +1397,9 @@ static int audit_filter_user_rules(struct audit_krule *rule, result = audit_uid_comparator(audit_get_loginuid(current), f->op, f->uid); break; + case AUDIT_MSGTYPE: + result = audit_comparator(type, f->op, f->val); + break; case AUDIT_SUBJ_USER: case AUDIT_SUBJ_ROLE: case AUDIT_SUBJ_TYPE: @@ -1404,7 +1426,7 @@ static int audit_filter_user_rules(struct audit_krule *rule, return 1; } -int audit_filter_user(void) +int audit_filter_user(int type) { enum audit_state state = AUDIT_DISABLED; struct audit_entry *e; @@ -1412,7 +1434,7 @@ int audit_filter_user(void) rcu_read_lock(); list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_USER], list) { - if (audit_filter_user_rules(&e->rule, &state)) { + if (audit_filter_user_rules(&e->rule, type, &state)) { if (state == AUDIT_DISABLED) ret = 0; break; -- 2.30.2