fixing audit rule ordering mess, part 1
PATCH 11/15 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).
--- include/linux/audit.h | 1 + kernel/audit.h | 5 +-- kernel/auditfilter.c | 17 +++++++++-- kernel/auditsc.c | 79 ++++++++++++++++++++++++++---------------------- 4 files changed, 59 insertions(+), 43 deletions(-)
include/linux/audit.h +1 -0
@@ -371,6 +371,7 @@ struct audit_krule {struct audit_watch *watch;/* associated watch */ struct audit_tree *tree;/* associated watched tree */ struct list_head rlist;/* entry in audit_{watch,tree}.rules list */ +u64 prio; };struct audit_field {
kernel/audit.h +1 -4
@@ -159,11 +159,8 @@ static inline int audit_signal_info(int sig, struct task_struct *t)return __audit_signal_info (sig, t); return 0; } -extern enum audit_state audit_filter_inodes (struct task_struct *, -struct audit_context *); -extern void audit_set_auditable (struct audit_context *); +extern void audit_filter_inodes (struct task_struct *,struct audit_context *);#else #define audit_signal_info (s,t) AUDIT_DISABLED#define audit_filter_inodes (t,c) AUDIT_DISABLED -#define audit_set_auditable (c)#endif
kernel/auditfilter.c +14 -3
@@ -919,6 +919,7 @@ static struct audit_entry *audit_dupe_rule(struct audit_krule *old, new->action = old->action;for (i =0 ; i <AUDIT_BITMASK_SIZE ; i++) new->mask[i] = old->mask[i]; + new->prio = old->prio; new->buflen = old->buflen; new->inode_f = old->inode_f; new->watch =NULL ;
@@ -987,9 +988,8 @@ static void audit_update_watch(struct audit_parent *parent,/* If the update involves invalidating rules, do the inode-based * filtering now, so we don't omit records. */ -if (invalidating && current->audit_context && -audit_filter_inodes (current, current->audit_context) ==AUDIT_RECORD_CONTEXT ) -audit_set_auditable (current->audit_context); +if (invalidating && current->audit_context) +audit_filter_inodes (current, current->audit_context); nwatch =audit_dupe_watch (owatch);if (IS_ERR (nwatch)) {
@@ -1258,6 +1258,9 @@ static int audit_add_watch(struct audit_krule *krule, struct nameidata *ndp,return ret; } +static u64 prio_low = ~0ULL /2 ; +static u64 prio_high = ~0ULL /2 -1 ; +/* Add rule to given filterlist if not a duplicate. */ static inline int audit_add_rule (struct audit_entry *entry,struct list_head *list)
@@ -1319,6 +1322,14 @@ static inline int audit_add_rule(struct audit_entry *entry, } } + entry->rule.prio = ~0ULL ; +if (entry->rule.listnr ==AUDIT_FILTER_EXIT ) { +if (entry->rule.flags &AUDIT_FILTER_PREPEND ) + entry->rule.prio = ++prio_high; +else + entry->rule.prio = --prio_low; + } +if (entry->rule.flags &AUDIT_FILTER_PREPEND ) {list_add_rcu (&entry->list, list); entry->rule.flags &= ~AUDIT_FILTER_PREPEND ;
kernel/auditsc.c +43 -36
197 lines not on this page · raw message
Signature · 1 line
1.5.6.5
Quoted 10 lines · Al Viro
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 <[email protected]>
Signature · 2 lines
James Morris <[email protected]>
Eric Paris
maintainerQuoted 25 lines · Al Viro
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 <[email protected]>kernel/auditfilter.c +3
-0@@ -1258,6 +1258,9 @@ static int audit_add_watch(struct audit_krule *krule, struct nameidata *ndp,return ret; } +static u64 prio_low = ~0ULL /2 ; +static u64 prio_high = ~0ULL /2 -1 ; +/* Add rule to given filterlist if not a duplicate. */ static inline int audit_add_rule (struct audit_entry *entry,struct list_head *list)@@ -1319,6 +1322,14 @@ static inline int audit_add_rule(struct audit_entry *entry, } }
kernel/auditfilter.c static inline int audit_add_rule(struct audit_entry *entry, · line 1334
Quoted 10 lines
kernel/auditfilter.c +8
-0+ entry->rule.prio = ~0ULL ; +if (entry->rule.listnr ==AUDIT_FILTER_EXIT ) { +if (entry->rule.flags &AUDIT_FILTER_PREPEND ) + entry->rule.prio = ++prio_high; +else + entry->rule.prio = --prio_low; + } +if (entry->rule.flags &AUDIT_FILTER_PREPEND ) {list_add_rcu (&entry->list, list);
I don't see why prio is only important on AUDIT_FILTER_EXIT. Couldn't I end up with stupidity with entry,never ?
-Eric
Quoted 2 lines · Eric Paris
I don't see why prio is only important on
AUDIT_FILTER_EXIT. Couldn't I end up with stupidity with entry,never ?
AUDIT_WATCH and AUDIT_INODE can live only on exit chain. I.e. we don't have that problem - other chains sit on the lists of their own and there the list ordering itself takes care of everything. Exit chain has parts in sitting in hash instead of the primary list.
Eric Paris
maintainerQuoted 10 lines · Al Viro
Quoted 2 lines · Eric Paris
I don't see why prio is only important on
AUDIT_FILTER_EXIT. Couldn't I end up with stupidity with entry,never ?
AUDIT_WATCHandAUDIT_INODEcan live only on exit chain. I.e. we don't have that problem - other chains sit on the lists of their own and there the list ordering itself takes care of everything. Exit chain has parts in sitting in hash instead of the primary list.
Makes perfect sense. They all look good to me.
-Eric