Commit e45aa212ea81d39b38ba158df344dc3a500153e5

Authored by Al Viro
1 parent 0590b9335a

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>

Showing 3 changed files with 41 additions and 56 deletions Side-by-side Diff

include/linux/audit.h
... ... @@ -373,6 +373,7 @@
373 373 struct audit_watch *watch; /* associated watch */
374 374 struct audit_tree *tree; /* associated watched tree */
375 375 struct list_head rlist; /* entry in audit_{watch,tree}.rules list */
  376 + struct list_head list; /* for AUDIT_LIST* purposes only */
376 377 u64 prio;
377 378 };
378 379  
... ... @@ -450,6 +450,7 @@
450 450 audit_log_end(ab);
451 451 rule->tree = NULL;
452 452 list_del_rcu(&entry->list);
  453 + list_del(&entry->rule.list);
453 454 call_rcu(&entry->rcu, audit_free_rule_rcu);
454 455 }
455 456 }
kernel/auditfilter.c
... ... @@ -86,6 +86,14 @@
86 86 #error Fix audit_filter_list initialiser
87 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 98 DEFINE_MUTEX(audit_filter_mutex);
91 99  
92 100  
93 101  
... ... @@ -1007,12 +1015,15 @@
1007 1015 list_del_rcu(&oentry->list);
1008 1016  
1009 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 1020 audit_panic("error updating watch, removing");
1012   - else {
  1021 + } else {
1013 1022 int h = audit_hash_ino((u32)ino);
1014 1023 list_add(&nentry->rule.rlist, &nwatch->rules);
1015 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 1029 call_rcu(&oentry->rcu, audit_free_rule_rcu);
... ... @@ -1077,6 +1088,7 @@
1077 1088 audit_log_end(ab);
1078 1089 }
1079 1090 list_del(&r->rlist);
  1091 + list_del(&r->list);
1080 1092 list_del_rcu(&e->list);
1081 1093 call_rcu(&e->rcu, audit_free_rule_rcu);
1082 1094 }
1083 1095  
... ... @@ -1331,9 +1343,13 @@
1331 1343 }
1332 1344  
1333 1345 if (entry->rule.flags & AUDIT_FILTER_PREPEND) {
  1346 + list_add(&entry->rule.list,
  1347 + &audit_rules_list[entry->rule.listnr]);
1334 1348 list_add_rcu(&entry->list, list);
1335 1349 entry->rule.flags &= ~AUDIT_FILTER_PREPEND;
1336 1350 } else {
  1351 + list_add_tail(&entry->rule.list,
  1352 + &audit_rules_list[entry->rule.listnr]);
1337 1353 list_add_tail_rcu(&entry->list, list);
1338 1354 }
1339 1355 #ifdef CONFIG_AUDITSYSCALL
... ... @@ -1415,6 +1431,7 @@
1415 1431 audit_remove_tree_rule(&e->rule);
1416 1432  
1417 1433 list_del_rcu(&e->list);
  1434 + list_del(&e->rule.list);
1418 1435 call_rcu(&e->rcu, audit_free_rule_rcu);
1419 1436  
1420 1437 #ifdef CONFIG_AUDITSYSCALL
1421 1438  
1422 1439  
... ... @@ -1443,16 +1460,16 @@
1443 1460 static void audit_list(int pid, int seq, struct sk_buff_head *q)
1444 1461 {
1445 1462 struct sk_buff *skb;
1446   - struct audit_entry *entry;
  1463 + struct audit_krule *r;
1447 1464 int i;
1448 1465  
1449 1466 /* This is a blocking read, so use audit_filter_mutex instead of rcu
1450 1467 * iterator to sync with list writers. */
1451 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 1470 struct audit_rule *rule;
1454 1471  
1455   - rule = audit_krule_to_rule(&entry->rule);
  1472 + rule = audit_krule_to_rule(r);
1456 1473 if (unlikely(!rule))
1457 1474 break;
1458 1475 skb = audit_make_reply(pid, seq, AUDIT_LIST, 0, 1,
... ... @@ -1462,20 +1479,6 @@
1462 1479 kfree(rule);
1463 1480 }
1464 1481 }
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;
1468   -
1469   - rule = audit_krule_to_rule(&entry->rule);
1470   - if (unlikely(!rule))
1471   - break;
1472   - skb = audit_make_reply(pid, seq, AUDIT_LIST, 0, 1,
1473   - rule, sizeof(*rule));
1474   - if (skb)
1475   - skb_queue_tail(q, skb);
1476   - kfree(rule);
1477   - }
1478   - }
1479 1482 skb = audit_make_reply(pid, seq, AUDIT_LIST, 1, 1, NULL, 0);
1480 1483 if (skb)
1481 1484 skb_queue_tail(q, skb);
1482 1485  
1483 1486  
... ... @@ -1485,16 +1488,16 @@
1485 1488 static void audit_list_rules(int pid, int seq, struct sk_buff_head *q)
1486 1489 {
1487 1490 struct sk_buff *skb;
1488   - struct audit_entry *e;
  1491 + struct audit_krule *r;
1489 1492 int i;
1490 1493  
1491 1494 /* This is a blocking read, so use audit_filter_mutex instead of rcu
1492 1495 * iterator to sync with list writers. */
1493 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 1498 struct audit_rule_data *data;
1496 1499  
1497   - data = audit_krule_to_data(&e->rule);
  1500 + data = audit_krule_to_data(r);
1498 1501 if (unlikely(!data))
1499 1502 break;
1500 1503 skb = audit_make_reply(pid, seq, AUDIT_LIST_RULES, 0, 1,
... ... @@ -1504,20 +1507,6 @@
1504 1507 kfree(data);
1505 1508 }
1506 1509 }
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;
1510   -
1511   - data = audit_krule_to_data(&e->rule);
1512   - if (unlikely(!data))
1513   - break;
1514   - skb = audit_make_reply(pid, seq, AUDIT_LIST_RULES, 0, 1,
1515   - data, sizeof(*data) + data->buflen);
1516   - if (skb)
1517   - skb_queue_tail(q, skb);
1518   - kfree(data);
1519   - }
1520   - }
1521 1510 skb = audit_make_reply(pid, seq, AUDIT_LIST_RULES, 1, 1, NULL, 0);
1522 1511 if (skb)
1523 1512 skb_queue_tail(q, skb);
1524 1513  
1525 1514  
1526 1515  
1527 1516  
1528 1517  
1529 1518  
1530 1519  
1531 1520  
... ... @@ -1789,35 +1778,37 @@
1789 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 1784 struct audit_entry *nentry;
1795 1785 struct audit_watch *watch;
1796 1786 struct audit_tree *tree;
1797 1787 int err = 0;
1798 1788  
1799   - if (!security_audit_rule_known(&entry->rule))
  1789 + if (!security_audit_rule_known(r))
1800 1790 return 0;
1801 1791  
1802   - watch = entry->rule.watch;
1803   - tree = entry->rule.tree;
1804   - nentry = audit_dupe_rule(&entry->rule, watch);
  1792 + watch = r->watch;
  1793 + tree = r->tree;
  1794 + nentry = audit_dupe_rule(r, watch);
1805 1795 if (IS_ERR(nentry)) {
1806 1796 /* save the first error encountered for the
1807 1797 * return value */
1808 1798 err = PTR_ERR(nentry);
1809 1799 audit_panic("error updating LSM filters");
1810 1800 if (watch)
1811   - list_del(&entry->rule.rlist);
  1801 + list_del(&r->rlist);
1812 1802 list_del_rcu(&entry->list);
  1803 + list_del(&r->list);
1813 1804 } else {
1814 1805 if (watch) {
1815 1806 list_add(&nentry->rule.rlist, &watch->rules);
1816   - list_del(&entry->rule.rlist);
  1807 + list_del(&r->rlist);
1817 1808 } else if (tree)
1818   - list_replace_init(&entry->rule.rlist,
1819   - &nentry->rule.rlist);
  1809 + list_replace_init(&r->rlist, &nentry->rule.rlist);
1820 1810 list_replace_rcu(&entry->list, &nentry->list);
  1811 + list_replace(&r->list, &nentry->rule.list);
1821 1812 }
1822 1813 call_rcu(&entry->rcu, audit_free_rule_rcu);
1823 1814  
1824 1815  
1825 1816  
... ... @@ -1831,27 +1822,19 @@
1831 1822 * updated rule. */
1832 1823 int audit_update_lsm_rules(void)
1833 1824 {
1834   - struct audit_entry *e, *n;
  1825 + struct audit_krule *r, *n;
1835 1826 int i, err = 0;
1836 1827  
1837 1828 /* audit_filter_mutex synchronizes the writers */
1838 1829 mutex_lock(&audit_filter_mutex);
1839 1830  
1840 1831 for (i = 0; i < AUDIT_NR_FILTERS; i++) {
1841   - list_for_each_entry_safe(e, n, &audit_filter_list[i], list) {
1842   - int res = update_lsm_rule(e);
  1832 + list_for_each_entry_safe(r, n, &audit_rules_list[i], list) {
  1833 + int res = update_lsm_rule(r);
1843 1834 if (!err)
1844 1835 err = res;
1845 1836 }
1846 1837 }
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)
1851   - err = res;
1852   - }
1853   - }
1854   -
1855 1838 mutex_unlock(&audit_filter_mutex);
1856 1839  
1857 1840 return err;