diff options
| author | Al Viro <viro@zeniv.linux.org.uk> | 2008-12-15 01:17:50 -0500 |
|---|---|---|
| committer | Al Viro <viro@zeniv.linux.org.uk> | 2009-01-04 15:14:42 -0500 |
| commit | e45aa212ea81d39b38ba158df344dc3a500153e5 (patch) | |
| tree | c4d55cda9e8f976d15b6b01a775a3437f932db27 /kernel | |
| parent | 0590b9335a1c72a3f0defcc6231287f7817e07c8 (diff) | |
audit rules ordering, part 2
Fix the actual rule listing; add per-type lists _not_ used for matching,
with all exit,... sitting on one such list. Simplifies "do something
for all rules" logics, while we are at it...
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/audit_tree.c | 1 | ||||
| -rw-r--r-- | kernel/auditfilter.c | 95 |
2 files changed, 40 insertions, 56 deletions
diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index 8b509441f49a..48bddad2a3dc 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c | |||
| @@ -450,6 +450,7 @@ static void kill_rules(struct audit_tree *tree) | |||
| 450 | audit_log_end(ab); | 450 | audit_log_end(ab); |
| 451 | rule->tree = NULL; | 451 | rule->tree = NULL; |
| 452 | list_del_rcu(&entry->list); | 452 | list_del_rcu(&entry->list); |
| 453 | list_del(&entry->rule.list); | ||
| 453 | call_rcu(&entry->rcu, audit_free_rule_rcu); | 454 | call_rcu(&entry->rcu, audit_free_rule_rcu); |
| 454 | } | 455 | } |
| 455 | } | 456 | } |
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 995a2e86808d..5d4edc6f7a32 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c | |||
| @@ -86,6 +86,14 @@ struct list_head audit_filter_list[AUDIT_NR_FILTERS] = { | |||
| 86 | #error Fix audit_filter_list initialiser | 86 | #error Fix audit_filter_list initialiser |
| 87 | #endif | 87 | #endif |
| 88 | }; | 88 | }; |
| 89 | static struct list_head audit_rules_list[AUDIT_NR_FILTERS] = { | ||
| 90 | LIST_HEAD_INIT(audit_rules_list[0]), | ||
| 91 | LIST_HEAD_INIT(audit_rules_list[1]), | ||
| 92 | LIST_HEAD_INIT(audit_rules_list[2]), | ||
| 93 | LIST_HEAD_INIT(audit_rules_list[3]), | ||
| 94 | LIST_HEAD_INIT(audit_rules_list[4]), | ||
| 95 | LIST_HEAD_INIT(audit_rules_list[5]), | ||
| 96 | }; | ||
| 89 | 97 | ||
| 90 | DEFINE_MUTEX(audit_filter_mutex); | 98 | DEFINE_MUTEX(audit_filter_mutex); |
| 91 | 99 | ||
| @@ -1007,12 +1015,15 @@ static void audit_update_watch(struct audit_parent *parent, | |||
| 1007 | list_del_rcu(&oentry->list); | 1015 | list_del_rcu(&oentry->list); |
| 1008 | 1016 | ||
| 1009 | nentry = audit_dupe_rule(&oentry->rule, nwatch); | 1017 | nentry = audit_dupe_rule(&oentry->rule, nwatch); |
| 1010 | if (IS_ERR(nentry)) | 1018 | if (IS_ERR(nentry)) { |
| 1019 | list_del(&oentry->rule.list); | ||
| 1011 | audit_panic("error updating watch, removing"); | 1020 | audit_panic("error updating watch, removing"); |
| 1012 | else { | 1021 | } else { |
| 1013 | int h = audit_hash_ino((u32)ino); | 1022 | int h = audit_hash_ino((u32)ino); |
| 1014 | list_add(&nentry->rule.rlist, &nwatch->rules); | 1023 | list_add(&nentry->rule.rlist, &nwatch->rules); |
| 1015 | list_add_rcu(&nentry->list, &audit_inode_hash[h]); | 1024 | list_add_rcu(&nentry->list, &audit_inode_hash[h]); |
| 1025 | list_replace(&oentry->rule.list, | ||
| 1026 | &nentry->rule.list); | ||
| 1016 | } | 1027 | } |
| 1017 | 1028 | ||
| 1018 | call_rcu(&oentry->rcu, audit_free_rule_rcu); | 1029 | call_rcu(&oentry->rcu, audit_free_rule_rcu); |
| @@ -1077,6 +1088,7 @@ static void audit_remove_parent_watches(struct audit_parent *parent) | |||
| 1077 | audit_log_end(ab); | 1088 | audit_log_end(ab); |
| 1078 | } | 1089 | } |
| 1079 | list_del(&r->rlist); | 1090 | list_del(&r->rlist); |
| 1091 | list_del(&r->list); | ||
| 1080 | list_del_rcu(&e->list); | 1092 | list_del_rcu(&e->list); |
| 1081 | call_rcu(&e->rcu, audit_free_rule_rcu); | 1093 | call_rcu(&e->rcu, audit_free_rule_rcu); |
| 1082 | } | 1094 | } |
| @@ -1331,9 +1343,13 @@ static inline int audit_add_rule(struct audit_entry *entry, | |||
| 1331 | } | 1343 | } |
| 1332 | 1344 | ||
| 1333 | if (entry->rule.flags & AUDIT_FILTER_PREPEND) { | 1345 | if (entry->rule.flags & AUDIT_FILTER_PREPEND) { |
| 1346 | list_add(&entry->rule.list, | ||
| 1347 | &audit_rules_list[entry->rule.listnr]); | ||
| 1334 | list_add_rcu(&entry->list, list); | 1348 | list_add_rcu(&entry->list, list); |
| 1335 | entry->rule.flags &= ~AUDIT_FILTER_PREPEND; | 1349 | entry->rule.flags &= ~AUDIT_FILTER_PREPEND; |
| 1336 | } else { | 1350 | } else { |
| 1351 | list_add_tail(&entry->rule.list, | ||
| 1352 | &audit_rules_list[entry->rule.listnr]); | ||
| 1337 | list_add_tail_rcu(&entry->list, list); | 1353 | list_add_tail_rcu(&entry->list, list); |
| 1338 | } | 1354 | } |
| 1339 | #ifdef CONFIG_AUDITSYSCALL | 1355 | #ifdef CONFIG_AUDITSYSCALL |
| @@ -1415,6 +1431,7 @@ static inline int audit_del_rule(struct audit_entry *entry, | |||
| 1415 | audit_remove_tree_rule(&e->rule); | 1431 | audit_remove_tree_rule(&e->rule); |
| 1416 | 1432 | ||
| 1417 | list_del_rcu(&e->list); | 1433 | list_del_rcu(&e->list); |
| 1434 | list_del(&e->rule.list); | ||
| 1418 | call_rcu(&e->rcu, audit_free_rule_rcu); | 1435 | call_rcu(&e->rcu, audit_free_rule_rcu); |
| 1419 | 1436 | ||
| 1420 | #ifdef CONFIG_AUDITSYSCALL | 1437 | #ifdef CONFIG_AUDITSYSCALL |
| @@ -1443,30 +1460,16 @@ out: | |||
| 1443 | static void audit_list(int pid, int seq, struct sk_buff_head *q) | 1460 | static void audit_list(int pid, int seq, struct sk_buff_head *q) |
| 1444 | { | 1461 | { |
| 1445 | struct sk_buff *skb; | 1462 | struct sk_buff *skb; |
| 1446 | struct audit_entry *entry; | 1463 | struct audit_krule *r; |
| 1447 | int i; | 1464 | int i; |
| 1448 | 1465 | ||
| 1449 | /* This is a blocking read, so use audit_filter_mutex instead of rcu | 1466 | /* This is a blocking read, so use audit_filter_mutex instead of rcu |
| 1450 | * iterator to sync with list writers. */ | 1467 | * iterator to sync with list writers. */ |
| 1451 | for (i=0; i<AUDIT_NR_FILTERS; i++) { | 1468 | for (i=0; i<AUDIT_NR_FILTERS; i++) { |
| 1452 | list_for_each_entry(entry, &audit_filter_list[i], list) { | 1469 | list_for_each_entry(r, &audit_rules_list[i], list) { |
| 1453 | struct audit_rule *rule; | ||
| 1454 | |||
| 1455 | rule = audit_krule_to_rule(&entry->rule); | ||
| 1456 | if (unlikely(!rule)) | ||
| 1457 | break; | ||
| 1458 | skb = audit_make_reply(pid, seq, AUDIT_LIST, 0, 1, | ||
| 1459 | rule, sizeof(*rule)); | ||
| 1460 | if (skb) | ||
| 1461 | skb_queue_tail(q, skb); | ||
| 1462 | kfree(rule); | ||
| 1463 | } | ||
| 1464 | } | ||
| 1465 | for (i = 0; i < AUDIT_INODE_BUCKETS; i++) { | ||
| 1466 | list_for_each_entry(entry, &audit_inode_hash[i], list) { | ||
| 1467 | struct audit_rule *rule; | 1470 | struct audit_rule *rule; |
| 1468 | 1471 | ||
| 1469 | rule = audit_krule_to_rule(&entry->rule); | 1472 | rule = audit_krule_to_rule(r); |
| 1470 | if (unlikely(!rule)) | 1473 | if (unlikely(!rule)) |
| 1471 | break; | 1474 | break; |
| 1472 | skb = audit_make_reply(pid, seq, AUDIT_LIST, 0, 1, | 1475 | skb = audit_make_reply(pid, seq, AUDIT_LIST, 0, 1, |
| @@ -1485,30 +1488,16 @@ static void audit_list(int pid, int seq, struct sk_buff_head *q) | |||
| 1485 | static void audit_list_rules(int pid, int seq, struct sk_buff_head *q) | 1488 | static void audit_list_rules(int pid, int seq, struct sk_buff_head *q) |
| 1486 | { | 1489 | { |
| 1487 | struct sk_buff *skb; | 1490 | struct sk_buff *skb; |
| 1488 | struct audit_entry *e; | 1491 | struct audit_krule *r; |
| 1489 | int i; | 1492 | int i; |
| 1490 | 1493 | ||
| 1491 | /* This is a blocking read, so use audit_filter_mutex instead of rcu | 1494 | /* This is a blocking read, so use audit_filter_mutex instead of rcu |
| 1492 | * iterator to sync with list writers. */ | 1495 | * iterator to sync with list writers. */ |
| 1493 | for (i=0; i<AUDIT_NR_FILTERS; i++) { | 1496 | for (i=0; i<AUDIT_NR_FILTERS; i++) { |
| 1494 | list_for_each_entry(e, &audit_filter_list[i], list) { | 1497 | list_for_each_entry(r, &audit_rules_list[i], list) { |
| 1495 | struct audit_rule_data *data; | ||
| 1496 | |||
| 1497 | data = audit_krule_to_data(&e->rule); | ||
| 1498 | if (unlikely(!data)) | ||
| 1499 | break; | ||
| 1500 | skb = audit_make_reply(pid, seq, AUDIT_LIST_RULES, 0, 1, | ||
| 1501 | data, sizeof(*data) + data->buflen); | ||
| 1502 | if (skb) | ||
| 1503 | skb_queue_tail(q, skb); | ||
| 1504 | kfree(data); | ||
| 1505 | } | ||
| 1506 | } | ||
| 1507 | for (i=0; i< AUDIT_INODE_BUCKETS; i++) { | ||
| 1508 | list_for_each_entry(e, &audit_inode_hash[i], list) { | ||
| 1509 | struct audit_rule_data *data; | 1498 | struct audit_rule_data *data; |
| 1510 | 1499 | ||
| 1511 | data = audit_krule_to_data(&e->rule); | 1500 | data = audit_krule_to_data(r); |
| 1512 | if (unlikely(!data)) | 1501 | if (unlikely(!data)) |
| 1513 | break; | 1502 | break; |
| 1514 | skb = audit_make_reply(pid, seq, AUDIT_LIST_RULES, 0, 1, | 1503 | skb = audit_make_reply(pid, seq, AUDIT_LIST_RULES, 0, 1, |
| @@ -1789,35 +1778,37 @@ unlock_and_return: | |||
| 1789 | return result; | 1778 | return result; |
| 1790 | } | 1779 | } |
| 1791 | 1780 | ||
| 1792 | static int update_lsm_rule(struct audit_entry *entry) | 1781 | static int update_lsm_rule(struct audit_krule *r) |
| 1793 | { | 1782 | { |
| 1783 | struct audit_entry *entry = container_of(r, struct audit_entry, rule); | ||
| 1794 | struct audit_entry *nentry; | 1784 | struct audit_entry *nentry; |
| 1795 | struct audit_watch *watch; | 1785 | struct audit_watch *watch; |
| 1796 | struct audit_tree *tree; | 1786 | struct audit_tree *tree; |
| 1797 | int err = 0; | 1787 | int err = 0; |
