aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2008-12-15 01:17:50 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2009-01-04 15:14:42 -0500
commite45aa212ea81d39b38ba158df344dc3a500153e5 (patch)
treec4d55cda9e8f976d15b6b01a775a3437f932db27
parent0590b9335a1c72a3f0defcc6231287f7817e07c8 (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>
-rw-r--r--include/linux/audit.h1
-rw-r--r--kernel/audit_tree.c1
-rw-r--r--kernel/auditfilter.c95
3 files changed, 41 insertions, 56 deletions
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 5b47eeb00d5..cc71fdb56ae 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -373,6 +373,7 @@ struct audit_krule {
373 struct audit_watch *watch; /* associated watch */ 373 struct audit_watch *watch; /* associated watch */
374 struct audit_tree *tree; /* associated watched tree */ 374 struct audit_tree *tree; /* associated watched tree */
375 struct list_head rlist; /* entry in audit_{watch,tree}.rules list */ 375 struct list_head rlist; /* entry in audit_{watch,tree}.rules list */
376 struct list_head list; /* for AUDIT_LIST* purposes only */
376 u64 prio; 377 u64 prio;
377}; 378};
378 379
diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c
index 8b509441f49..48bddad2a3d 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 995a2e86808..5d4edc6f7a3 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};
89static 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
90DEFINE_MUTEX(audit_filter_mutex); 98DEFINE_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:
1443static void audit_list(int pid, int seq, struct sk_buff_head *q) 1460static 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)
1485static void audit_list_rules(int pid, int seq, struct sk_buff_head *q) 1488static 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
1792static int update_lsm_rule(struct audit_entry *entry) 1781static 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;
1798 1788
1799 if (!security_audit_rule_known(&entry->rule)) 1789 if (!security_audit_rule_known(r))
1800 return 0; 1790 return 0;
1801 1791
1802 watch = entry->rule.watch; 1792 watch = r->watch;
1803 tree = entry->rule.tree; 1793 tree = r->tree;
1804 nentry = audit_dupe_rule(&entry->rule, watch); 1794 nentry = audit_dupe_rule(r, watch);
1805 if (IS_ERR(nentry)) { 1795 if (IS_ERR(nentry)) {
1806 /* save the first error encountered for the 1796 /* save the first error encountered for the
1807 * return value */ 1797 * return value */
1808 err = PTR_ERR(nentry); 1798 err = PTR_ERR(nentry);
1809 audit_panic("error updating LSM filters"); 1799 audit_panic("error updating LSM filters");
1810 if (watch) 1800 if (watch)
1811 list_del(&entry->rule.rlist); 1801 list_del(&r->rlist);
1812 list_del_rcu(&entry->list); 1802 list_del_rcu(&entry->list);
1803 list_del(&r->list);
1813 } else { 1804 } else {
1814 if (watch) { 1805 if (watch) {
1815 list_add(&nentry->rule.rlist, &watch->rules); 1806 list_add(&nentry->rule.rlist, &watch->rules);
1816 list_del(&entry->rule.rlist); 1807 list_del(&r->rlist);
1817 } else if (tree) 1808 } else if (tree)
1818 list_replace_init(&entry->rule.rlist, 1809 list_replace_init(&r->rlist, &nentry->rule.rlist);
1819 &nentry->rule.rlist);
1820 list_replace_rcu(&entry->list, &nentry->list); 1810 list_replace_rcu(&entry->list, &nentry->list);
1811 list_replace(&r->list, &nentry->rule.list);
1821 } 1812 }
1822 call_rcu(&entry->rcu, audit_free_rule_rcu); 1813 call_rcu(&entry->rcu, audit_free_rule_rcu);
1823 1814
@@ -1831,27 +1822,19 @@ static int update_lsm_rule(struct audit_entry *entry)
1831 * updated rule. */ 1822 * updated rule. */
1832int audit_update_lsm_rules(void) 1823int audit_update_lsm_rules(void)
1833{ 1824{
1834 struct audit_entry *e, *n; 1825 struct audit_krule *r, *n;
1835 int i, err = 0; 1826 int i, err = 0;
1836 1827
1837 /* audit_filter_mutex synchronizes the writers */ 1828 /* audit_filter_mutex synchronizes the writers */
1838 mutex_lock(&audit_filter_mutex); 1829 mutex_lock(&audit_filter_mutex);
1839 1830
1840 for (i = 0; i < AUDIT_NR_FILTERS; i++) { 1831 for (i = 0; i < AUDIT_NR_FILTERS; i++) {
1841 list_for_each_entry_safe(e, n, &audit_filter_list[i], list) { 1832 list_for_each_entry_safe(r, n, &audit_rules_list[i], list) {
1842 int res = update_lsm_rule(e); 1833 int res = update_lsm_rule(r);
1843 if (!err)
1844 err = res;
1845 }
1846 }
1847 for (i=0; i< AUDIT_INODE_BUCKETS; i++) {
1848 list_for_each_entry_safe(e, n, &audit_inode_hash[i], list) {
1849 int res = update_lsm_rule(e);
1850 if (!err) 1834 if (!err)
1851 err = res; 1835 err = res;
1852 } 1836 }
1853 } 1837 }
1854
1855 mutex_unlock(&audit_filter_mutex); 1838 mutex_unlock(&audit_filter_mutex);
1856 1839
1857 return err; 1840 return err;