diff options
author | Eric Paris <eparis@redhat.com> | 2013-04-16 13:08:43 -0400 |
---|---|---|
committer | Eric Paris <eparis@redhat.com> | 2013-04-16 17:28:49 -0400 |
commit | 62062cf8a3a99a933efdac549da380f230dbe982 (patch) | |
tree | 8da676d774d02c3c8f0093e7f2586719072f522f | |
parent | 34c474de7b4bd451396d67647ac728b0433379a9 (diff) | |
download | linux-62062cf8a3a99a933efdac549da380f230dbe982.tar.bz2 |
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 <eparis@redhat.com>
-rw-r--r-- | include/linux/audit.h | 2 | ||||
-rw-r--r-- | kernel/audit.c | 2 | ||||
-rw-r--r-- | 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; |