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) |
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) | |||
438 | extern int audit_update_lsm_rules(void); | 438 | extern int audit_update_lsm_rules(void); |
439 | 439 | ||
440 | /* Private API (for audit.c only) */ | 440 | /* Private API (for audit.c only) */ |
441 | extern int audit_filter_user(void); | 441 | extern int audit_filter_user(int type); |
442 | extern int audit_filter_type(int type); | 442 | extern int audit_filter_type(int type); |
443 | extern int audit_receive_filter(int type, int pid, int seq, | 443 | extern int audit_receive_filter(int type, int pid, int seq, |
444 | void *data, size_t datasz, kuid_t loginuid, | 444 | 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) | |||
737 | if (!audit_enabled && msg_type != AUDIT_USER_AVC) | 737 | if (!audit_enabled && msg_type != AUDIT_USER_AVC) |
738 | return 0; | 738 | return 0; |
739 | 739 | ||
740 | err = audit_filter_user(); | 740 | err = audit_filter_user(msg_type); |
741 | if (err == 1) { | 741 | if (err == 1) { |
742 | err = 0; | 742 | err = 0; |
743 | if (msg_type == AUDIT_USER_TTY) { | 743 | 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) | |||
310 | return n; | 310 | return n; |
311 | } | 311 | } |
312 | 312 | ||
313 | /* check if a field is valid for a given list */ | ||
314 | static int audit_field_valid(struct audit_entry *entry, struct audit_field *f) | ||
315 | { | ||
316 | switch(f->type) { | ||
317 | case AUDIT_MSGTYPE: | ||
318 | if (entry->rule.listnr != AUDIT_FILTER_TYPE && | ||
319 | entry->rule.listnr != AUDIT_FILTER_USER) | ||
320 | return -EINVAL; | ||
321 | break; | ||
322 | }; | ||
323 | return 0; | ||
324 | } | ||
313 | 325 | ||
314 | /* Translate struct audit_rule to kernel's rule respresentation. | 326 | /* Translate struct audit_rule to kernel's rule respresentation. |
315 | * Exists for backward compatibility with userspace. */ | 327 | * Exists for backward compatibility with userspace. */ |
@@ -459,6 +471,13 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, | |||
459 | f->gid = INVALID_GID; | 471 | f->gid = INVALID_GID; |
460 | f->lsm_str = NULL; | 472 | f->lsm_str = NULL; |
461 | f->lsm_rule = NULL; | 473 | f->lsm_rule = NULL; |
474 | |||
475 | err = audit_field_valid(entry, f); | ||
476 | if (err) | ||
477 | goto exit_free; | ||
478 | |||
479 | err = -EINVAL; | ||
480 | |||
462 | switch(f->type) { | 481 | switch(f->type) { |
463 | case AUDIT_UID: | 482 | case AUDIT_UID: |
464 | case AUDIT_EUID: | 483 | case AUDIT_EUID: |
@@ -1354,7 +1373,7 @@ int audit_compare_dname_path(const char *dname, const char *path, int parentlen) | |||
1354 | return strncmp(p, dname, dlen); | 1373 | return strncmp(p, dname, dlen); |
1355 | } | 1374 | } |
1356 | 1375 | ||
1357 | static int audit_filter_user_rules(struct audit_krule *rule, | 1376 | static int audit_filter_user_rules(struct audit_krule *rule, int type, |
1358 | enum audit_state *state) | 1377 | enum audit_state *state) |
1359 | { | 1378 | { |
1360 | int i; | 1379 | int i; |
@@ -1378,6 +1397,9 @@ static int audit_filter_user_rules(struct audit_krule *rule, | |||
1378 | result = audit_uid_comparator(audit_get_loginuid(current), | 1397 | result = audit_uid_comparator(audit_get_loginuid(current), |
1379 | f->op, f->uid); | 1398 | f->op, f->uid); |
1380 | break; | 1399 | break; |
1400 | case AUDIT_MSGTYPE: | ||
1401 | result = audit_comparator(type, f->op, f->val); | ||
1402 | break; | ||
1381 | case AUDIT_SUBJ_USER: | 1403 | case AUDIT_SUBJ_USER: |
1382 | case AUDIT_SUBJ_ROLE: | 1404 | case AUDIT_SUBJ_ROLE: |
1383 | case AUDIT_SUBJ_TYPE: | 1405 | case AUDIT_SUBJ_TYPE: |
@@ -1404,7 +1426,7 @@ static int audit_filter_user_rules(struct audit_krule *rule, | |||
1404 | return 1; | 1426 | return 1; |
1405 | } | 1427 | } |
1406 | 1428 | ||
1407 | int audit_filter_user(void) | 1429 | int audit_filter_user(int type) |
1408 | { | 1430 | { |
1409 | enum audit_state state = AUDIT_DISABLED; | 1431 | enum audit_state state = AUDIT_DISABLED; |
1410 | struct audit_entry *e; | 1432 | struct audit_entry *e; |
@@ -1412,7 +1434,7 @@ int audit_filter_user(void) | |||
1412 | 1434 | ||
1413 | rcu_read_lock(); | 1435 | rcu_read_lock(); |
1414 | list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_USER], list) { | 1436 | list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_USER], list) { |
1415 | if (audit_filter_user_rules(&e->rule, &state)) { | 1437 | if (audit_filter_user_rules(&e->rule, type, &state)) { |
1416 | if (state == AUDIT_DISABLED) | 1438 | if (state == AUDIT_DISABLED) |
1417 | ret = 0; | 1439 | ret = 0; |
1418 | break; | 1440 | break; |