Skip to contentSkip to conversation

fixing audit rule ordering mess, part 1

PATCH In review Al Viro 4 participants 5 messages Dec 17, 2008 Audit

lore
Share & tools
lore

Al Viro

author
#0 lore raw

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
index c5e95e7..d28682c 100644
@@ -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
index 9d67174..16f18ca 100644
@@ -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
index 0febaa0..995a2e8 100644
@@ -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
Reviewed-by on v1 11/15
#1 lore raw
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).

Signature · 2 lines
James Morris
<[email protected]>
maintainer
#2 lore raw
In reply to Al Viro
Quoted 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).

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

#3 lore raw
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.

maintainer
#4 lore raw
Quoted 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_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.

Makes perfect sense. They all look good to me.

-Eric