summary refs log tree commit diff
path: root/kernel/auditsc.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2009-06-24 00:02:38 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2009-06-24 00:02:38 -0400
commit916d75761c971b6e630a26bd4ba472e90ac9a4b9 (patch)
tree3a4b18d0d29c1d12f64fefbb2bc5559813a686f7 /kernel/auditsc.c
parent9d9609851003ebed15957f0f2ce18492739ee124 (diff)
downloadlinux-916d75761c971b6e630a26bd4ba472e90ac9a4b9.tar.gz
Fix rule eviction order for AUDIT_DIR
If syscall removes the root of subtree being watched, we
definitely do not want the rules refering that subtree
to be destroyed without the syscall in question having
a chance to match them.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'kernel/auditsc.c')
-rw-r--r--kernel/auditsc.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 2de95d1582bc..68d3c6a0ecd6 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -199,6 +199,7 @@ struct audit_context {
 
 	struct audit_tree_refs *trees, *first_trees;
 	int tree_count;
+	struct list_head killed_trees;
 
 	int type;
 	union {
@@ -853,6 +854,7 @@ static inline struct audit_context *audit_alloc_context(enum audit_state state)
 	if (!(context = kmalloc(sizeof(*context), GFP_KERNEL)))
 		return NULL;
 	audit_zero_context(context, state);
+	INIT_LIST_HEAD(&context->killed_trees);
 	return context;
 }
 
@@ -1545,6 +1547,8 @@ void audit_free(struct task_struct *tsk)
 	/* that can happen only if we are called from do_exit() */
 	if (context->in_syscall && context->current_state == AUDIT_RECORD_CONTEXT)
 		audit_log_exit(context, tsk);
+	if (!list_empty(&context->killed_trees))
+		audit_kill_trees(&context->killed_trees);
 
 	audit_free_context(context);
 }
@@ -1688,6 +1692,9 @@ void audit_syscall_exit(int valid, long return_code)
 	context->in_syscall = 0;
 	context->prio = context->state == AUDIT_RECORD_CONTEXT ? ~0ULL : 0;
 
+	if (!list_empty(&context->killed_trees))
+		audit_kill_trees(&context->killed_trees);
+
 	if (context->previous) {
 		struct audit_context *new_context = context->previous;
 		context->previous  = NULL;
@@ -2521,3 +2528,11 @@ void audit_core_dumps(long signr)
 	audit_log_format(ab, " sig=%ld", signr);
 	audit_log_end(ab);
 }
+
+struct list_head *audit_killed_trees(void)
+{
+	struct audit_context *ctx = current->audit_context;
+	if (likely(!ctx || !ctx->in_syscall))
+		return NULL;
+	return &ctx->killed_trees;
+}