aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2013-04-16 13:08:43 -0400
committerEric Paris <eparis@redhat.com>2013-04-16 17:28:49 -0400
commit62062cf8a3a99a933efdac549da380f230dbe982 (patch)
tree8da676d774d02c3c8f0093e7f2586719072f522f
parent34c474de7b4bd451396d67647ac728b0433379a9 (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.h2
-rw-r--r--kernel/audit.c2
-rw-r--r--kernel/auditfilter.c28
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)
438extern int audit_update_lsm_rules(void); 438extern int audit_update_lsm_rules(void);
439 439
440 /* Private API (for audit.c only) */ 440 /* Private API (for audit.c only) */
441extern int audit_filter_user(void); 441extern int audit_filter_user(int type);
442extern int audit_filter_type(int type); 442extern int audit_filter_type(int type);
443extern int audit_receive_filter(int type, int pid, int seq, 443extern 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 */
314static 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
1357static int audit_filter_user_rules(struct audit_krule *rule, 1376static 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
1407int audit_filter_user(void) 1429int 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;