[PATCH ghak59 V3 4/4] audit: extend config_change mark/watch/tree rule changes

From: Richard Guy Briggs
Date: Mon Dec 10 2018 - 17:18:47 EST


Give a clue as to the source of mark, watch and tree rule changes.

See: https://github.com/linux-audit/audit-kernel/issues/50
See: https://github.com/linux-audit/audit-kernel/issues/59
Signed-off-by: Richard Guy Briggs <rgb@xxxxxxxxxx>
---
kernel/audit.h | 4 ++--
kernel/audit_fsnotify.c | 2 +-
kernel/audit_tree.c | 24 ++++++++++++------------
kernel/audit_watch.c | 6 ++++--
kernel/auditsc.c | 4 ++--
5 files changed, 21 insertions(+), 19 deletions(-)

diff --git a/kernel/audit.h b/kernel/audit.h
index 6ffb70575082..545dd8fcb036 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -314,7 +314,7 @@ extern void audit_log_d_path_exe(struct audit_buffer *ab,
extern int audit_tag_tree(char *old, char *new);
extern const char *audit_tree_path(struct audit_tree *tree);
extern void audit_put_tree(struct audit_tree *tree);
-extern void audit_kill_trees(struct audit_context *context);
+extern void audit_kill_trees(struct audit_context *context, char *trig);
#else
#define audit_remove_tree_rule(rule) BUG()
#define audit_add_tree_rule(rule) -EINVAL
@@ -323,7 +323,7 @@ extern void audit_log_d_path_exe(struct audit_buffer *ab,
#define audit_put_tree(tree) (void)0
#define audit_tag_tree(old, new) -EINVAL
#define audit_tree_path(rule) "" /* never called */
-#define audit_kill_trees(context) BUG()
+#define audit_kill_trees(context, trig) BUG()
#endif

extern char *audit_unpack_string(void **bufp, size_t *remain, size_t len);
diff --git a/kernel/audit_fsnotify.c b/kernel/audit_fsnotify.c
index 37ae95cfb7f4..d25cd3760b5d 100644
--- a/kernel/audit_fsnotify.c
+++ b/kernel/audit_fsnotify.c
@@ -156,7 +156,7 @@ static void audit_autoremove_mark_rule(struct audit_fsnotify_mark *audit_mark)
struct audit_krule *rule = audit_mark->rule;
struct audit_entry *entry = container_of(rule, struct audit_entry, rule);

- audit_mark_log_rule_change(audit_mark, "autoremove_rule");
+ audit_mark_log_rule_change(audit_mark, "autoremove_rule:mark");
audit_del_rule(entry);
}

diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c
index bf77d265e68e..160169fa45a8 100644
--- a/kernel/audit_tree.c
+++ b/kernel/audit_tree.c
@@ -524,7 +524,7 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree)
return 0;
}

-static void audit_tree_log_remove_rule(struct audit_context *context, struct audit_krule *rule)
+static void audit_tree_log_remove_rule(struct audit_context *context, struct audit_krule *rule, char *trig)
{
struct audit_buffer *ab;

@@ -533,14 +533,14 @@ static void audit_tree_log_remove_rule(struct audit_context *context, struct aud
ab = audit_log_start(context, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
if (unlikely(!ab))
return;
- audit_log_format(ab, "op=remove_rule dir=");
+ audit_log_format(ab, "op=remove_rule:tree:%s dir=", trig);
audit_log_untrustedstring(ab, rule->tree->pathname);
audit_log_key(ab, rule->filterkey);
audit_log_format(ab, " list=%d res=1", rule->listnr);
audit_log_end(ab);
}

-static void kill_rules(struct audit_context *context, struct audit_tree *tree)
+static void kill_rules(struct audit_context *context, struct audit_tree *tree, char *trig)
{
struct audit_krule *rule, *next;
struct audit_entry *entry;
@@ -551,7 +551,7 @@ static void kill_rules(struct audit_context *context, struct audit_tree *tree)
list_del_init(&rule->rlist);
if (rule->tree) {
/* not a half-baked one */
- audit_tree_log_remove_rule(context, rule);
+ audit_tree_log_remove_rule(context, rule, trig);
if (entry->rule.exe)
audit_remove_mark(entry->rule.exe);
rule->tree = NULL;
@@ -607,7 +607,7 @@ static void prune_one(struct audit_tree *victim)

/* trim the uncommitted chunks from tree */

-static void trim_marked(struct audit_tree *tree)
+static void trim_marked(struct audit_tree *tree, char *trig)
{
struct list_head *p, *q;
spin_lock(&hash_lock);
@@ -633,7 +633,7 @@ static void trim_marked(struct audit_tree *tree)
tree->goner = 1;
spin_unlock(&hash_lock);
mutex_lock(&audit_filter_mutex);
- kill_rules(audit_context(), tree);
+ kill_rules(audit_context(), tree, trig);
list_del_init(&tree->list);
mutex_unlock(&audit_filter_mutex);
prune_one(tree);
@@ -714,7 +714,7 @@ void audit_trim_trees(void)
node->index &= ~(1U<<31);
}
spin_unlock(&hash_lock);
- trim_marked(tree);
+ trim_marked(tree, "trim");
drop_collected_mounts(root_mnt);
skip_it:
put_tree(tree);
@@ -847,7 +847,7 @@ int audit_add_tree_rule(struct audit_krule *rule)
node->index &= ~(1U<<31);
spin_unlock(&hash_lock);
} else {
- trim_marked(tree);
+ trim_marked(tree, "add");
goto Err;
}

@@ -949,7 +949,7 @@ int audit_tag_tree(char *old, char *new)
node->index &= ~(1U<<31);
spin_unlock(&hash_lock);
} else {
- trim_marked(tree);
+ trim_marked(tree, "equiv");
}

put_tree(tree);
@@ -973,7 +973,7 @@ static void audit_schedule_prune(void)
* ... and that one is done if evict_chunk() decides to delay until the end
* of syscall. Runs synchronously.
*/
-void audit_kill_trees(struct audit_context *context)
+void audit_kill_trees(struct audit_context *context, char *trig)
{
struct list_head *list = &context->killed_trees;

@@ -984,7 +984,7 @@ void audit_kill_trees(struct audit_context *context)
struct audit_tree *victim;

victim = list_entry(list->next, struct audit_tree, list);
- kill_rules(context, victim);
+ kill_rules(context, victim, trig);
list_del_init(&victim->list);

mutex_unlock(&audit_filter_mutex);
@@ -1019,7 +1019,7 @@ static void evict_chunk(struct audit_chunk *chunk)
list_del_init(&owner->same_root);
spin_unlock(&hash_lock);
if (!postponed) {
- kill_rules(audit_context(), owner);
+ kill_rules(audit_context(), owner, "evict");
list_move(&owner->list, &prune_list);
need_prune = 1;
} else {
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
index e8d1adeb2223..f8a5770c6c8c 100644
--- a/kernel/audit_watch.c
+++ b/kernel/audit_watch.c
@@ -315,7 +315,9 @@ static void audit_update_watch(struct audit_parent *parent,
if (oentry->rule.exe)
audit_remove_mark(oentry->rule.exe);

- audit_watch_log_rule_change(r, owatch, "updated_rules");
+ audit_watch_log_rule_change(r, owatch, invalidating ?
+ "updated_rules:watch:inval" :
+ "updated_rules:watch:set");

call_rcu(&oentry->rcu, audit_free_rule_rcu);
}
@@ -343,7 +345,7 @@ static void audit_remove_parent_watches(struct audit_parent *parent)
list_for_each_entry_safe(w, nextw, &parent->watches, wlist) {
list_for_each_entry_safe(r, nextr, &w->rules, rlist) {
e = container_of(r, struct audit_entry, rule);
- audit_watch_log_rule_change(r, w, "remove_rule");
+ audit_watch_log_rule_change(r, w, "remove_rule:watch:parent");
if (e->rule.exe)
audit_remove_mark(e->rule.exe);
list_del(&r->rlist);
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index b585ceb2f7a2..8592448f1d8f 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -1445,7 +1445,7 @@ void __audit_free(struct task_struct *tsk)
return;

if (!list_empty(&context->killed_trees))
- audit_kill_trees(context);
+ audit_kill_trees(context, "free");

/* We are called either by do_exit() or the fork() error handling code;
* in the former case tsk == current and in the latter tsk is a
@@ -1538,7 +1538,7 @@ void __audit_syscall_exit(int success, long return_code)
return;

if (!list_empty(&context->killed_trees))
- audit_kill_trees(context);
+ audit_kill_trees(context, "exit");

if (!context->dummy && context->in_syscall) {
if (success)
--
1.8.3.1