aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/auditfilter.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2008-12-14 23:45:27 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2009-01-04 15:14:41 -0500
commit0590b9335a1c72a3f0defcc6231287f7817e07c8 (patch)
tree289fa4668ae304f79f7484ac31b2cab0ab8894c1 /kernel/auditfilter.c
parent1a9d0797b8977d413435277bf9661efbbd584693 (diff)
fixing audit rule ordering mess, part 1
Problem: ordering between the rules on exit chain is currently lost; all watch and inode rules are listed after everything else _and_ exit,never on one kind doesn't stop exit,always on another from being matched. Solution: assign priorities to rules, keep track of the current highest-priority matching rule and its result (always/never). Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'kernel/auditfilter.c')
-rw-r--r--kernel/auditfilter.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index 0febaa0f784c..995a2e86808d 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -919,6 +919,7 @@ static struct audit_entry *audit_dupe_rule(struct audit_krule *old,
919 new->action = old->action; 919 new->action = old->action;
920 for (i = 0; i < AUDIT_BITMASK_SIZE; i++) 920 for (i = 0; i < AUDIT_BITMASK_SIZE; i++)
921 new->mask[i] = old->mask[i]; 921 new->mask[i] = old->mask[i];
922 new->prio = old->prio;
922 new->buflen = old->buflen; 923 new->buflen = old->buflen;
923 new->inode_f = old->inode_f; 924 new->inode_f = old->inode_f;
924 new->watch = NULL; 925 new->watch = NULL;
@@ -987,9 +988,8 @@ static void audit_update_watch(struct audit_parent *parent,
987 988
988 /* If the update involves invalidating rules, do the inode-based 989 /* If the update involves invalidating rules, do the inode-based
989 * filtering now, so we don't omit records. */ 990 * filtering now, so we don't omit records. */
990 if (invalidating && current->audit_context && 991 if (invalidating && current->audit_context)
991 audit_filter_inodes(current, current->audit_context) == AUDIT_RECORD_CONTEXT) 992 audit_filter_inodes(current, current->audit_context);
992 audit_set_auditable(current->audit_context);
993 993
994 nwatch = audit_dupe_watch(owatch); 994 nwatch = audit_dupe_watch(owatch);
995 if (IS_ERR(nwatch)) { 995 if (IS_ERR(nwatch)) {
@@ -1258,6 +1258,9 @@ static int audit_add_watch(struct audit_krule *krule, struct nameidata *ndp,
1258 return ret; 1258 return ret;
1259} 1259}
1260 1260
1261static u64 prio_low = ~0ULL/2;
1262static u64 prio_high = ~0ULL/2 - 1;
1263
1261/* Add rule to given filterlist if not a duplicate. */ 1264/* Add rule to given filterlist if not a duplicate. */
1262static inline int audit_add_rule(struct audit_entry *entry, 1265static inline int audit_add_rule(struct audit_entry *entry,
1263 struct list_head *list) 1266 struct list_head *list)
@@ -1319,6 +1322,14 @@ static inline int audit_add_rule(struct audit_entry *entry,
1319 } 1322 }
1320 } 1323 }
1321 1324
1325 entry->rule.prio = ~0ULL;
1326 if (entry->rule.listnr == AUDIT_FILTER_EXIT) {
1327 if (entry->rule.flags & AUDIT_FILTER_PREPEND)
1328 entry->rule.prio = ++prio_high;
1329 else
1330 entry->rule.prio = --prio_low;
1331 }
1332
1322 if (entry->rule.flags & AUDIT_FILTER_PREPEND) { 1333 if (entry->rule.flags & AUDIT_FILTER_PREPEND) {
1323 list_add_rcu(&entry->list, list); 1334 list_add_rcu(&entry->list, list);
1324 entry->rule.flags &= ~AUDIT_FILTER_PREPEND; 1335 entry->rule.flags &= ~AUDIT_FILTER_PREPEND;