diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2009-06-24 00:02:38 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2009-06-24 00:02:38 -0400 |
commit | 916d75761c971b6e630a26bd4ba472e90ac9a4b9 (patch) | |
tree | 3a4b18d0d29c1d12f64fefbb2bc5559813a686f7 /kernel/auditsc.c | |
parent | 9d9609851003ebed15957f0f2ce18492739ee124 (diff) |
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.c | 15 |
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 { | |||
199 | 199 | ||
200 | struct audit_tree_refs *trees, *first_trees; | 200 | struct audit_tree_refs *trees, *first_trees; |
201 | int tree_count; | 201 | int tree_count; |
202 | struct list_head killed_trees; | ||
202 | 203 | ||
203 | int type; | 204 | int type; |
204 | union { | 205 | union { |
@@ -853,6 +854,7 @@ static inline struct audit_context *audit_alloc_context(enum audit_state state) | |||
853 | if (!(context = kmalloc(sizeof(*context), GFP_KERNEL))) | 854 | if (!(context = kmalloc(sizeof(*context), GFP_KERNEL))) |
854 | return NULL; | 855 | return NULL; |
855 | audit_zero_context(context, state); | 856 | audit_zero_context(context, state); |
857 | INIT_LIST_HEAD(&context->killed_trees); | ||
856 | return context; | 858 | return context; |
857 | } | 859 | } |
858 | 860 | ||
@@ -1545,6 +1547,8 @@ void audit_free(struct task_struct *tsk) | |||
1545 | /* that can happen only if we are called from do_exit() */ | 1547 | /* that can happen only if we are called from do_exit() */ |
1546 | if (context->in_syscall && context->current_state == AUDIT_RECORD_CONTEXT) | 1548 | if (context->in_syscall && context->current_state == AUDIT_RECORD_CONTEXT) |
1547 | audit_log_exit(context, tsk); | 1549 | audit_log_exit(context, tsk); |
1550 | if (!list_empty(&context->killed_trees)) | ||
1551 | audit_kill_trees(&context->killed_trees); | ||
1548 | 1552 | ||
1549 | audit_free_context(context); | 1553 | audit_free_context(context); |
1550 | } | 1554 | } |
@@ -1688,6 +1692,9 @@ void audit_syscall_exit(int valid, long return_code) | |||
1688 | context->in_syscall = 0; | 1692 | context->in_syscall = 0; |
1689 | context->prio = context->state == AUDIT_RECORD_CONTEXT ? ~0ULL : 0; | 1693 | context->prio = context->state == AUDIT_RECORD_CONTEXT ? ~0ULL : 0; |
1690 | 1694 | ||
1695 | if (!list_empty(&context->killed_trees)) | ||
1696 | audit_kill_trees(&context->killed_trees); | ||
1697 | |||
1691 | if (context->previous) { | 1698 | if (context->previous) { |
1692 | struct audit_context *new_context = context->previous; | 1699 | struct audit_context *new_context = context->previous; |
1693 | context->previous = NULL; | 1700 | context->previous = NULL; |
@@ -2521,3 +2528,11 @@ void audit_core_dumps(long signr) | |||
2521 | audit_log_format(ab, " sig=%ld", signr); | 2528 | audit_log_format(ab, " sig=%ld", signr); |
2522 | audit_log_end(ab); | 2529 | audit_log_end(ab); |
2523 | } | 2530 | } |
2531 | |||
2532 | struct list_head *audit_killed_trees(void) | ||
2533 | { | ||
2534 | struct audit_context *ctx = current->audit_context; | ||
2535 | if (likely(!ctx || !ctx->in_syscall)) | ||
2536 | return NULL; | ||
2537 | return &ctx->killed_trees; | ||
2538 | } | ||