diff options
author | Amy Griffis <amy.griffis@hp.com> | 2006-06-14 18:45:21 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2006-07-01 05:43:06 -0400 |
commit | 5adc8a6adc91c4c85a64c75a70a619fffc924817 (patch) | |
tree | ace9af6bbc3cf711f43cfd88e834baeb6989ca3f /kernel/auditsc.c | |
parent | 9262e9149f346a5443300f8c451b8e7631e81a42 (diff) |
[PATCH] add rule filterkey
Add support for a rule key, which can be used to tie audit records to audit
rules. This is useful when a watched file is accessed through a link or
symlink, as well as for general audit log analysis.
Because this patch uses a string key instead of an integer key, there is a bit
of extra overhead to do the kstrdup() when a rule fires. However, we're also
allocating memory for the audit record buffer, so it's probably not that
significant. I went ahead with a string key because it seems more
user-friendly.
Note that the user must ensure that filterkeys are unique. The kernel only
checks for duplicate rules.
Signed-off-by: Amy Griffis <amy.griffis@hpd.com>
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 dc5e3f01efe7..316657855165 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
@@ -186,6 +186,7 @@ struct audit_context { | |||
186 | int auditable; /* 1 if record should be written */ | 186 | int auditable; /* 1 if record should be written */ |
187 | int name_count; | 187 | int name_count; |
188 | struct audit_names names[AUDIT_NAMES]; | 188 | struct audit_names names[AUDIT_NAMES]; |
189 | char * filterkey; /* key for rule that triggered record */ | ||
189 | struct dentry * pwd; | 190 | struct dentry * pwd; |
190 | struct vfsmount * pwdmnt; | 191 | struct vfsmount * pwdmnt; |
191 | struct audit_context *previous; /* For nested syscalls */ | 192 | struct audit_context *previous; /* For nested syscalls */ |
@@ -348,11 +349,17 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
348 | if (ctx) | 349 | if (ctx) |
349 | result = audit_comparator(ctx->argv[f->type-AUDIT_ARG0], f->op, f->val); | 350 | result = audit_comparator(ctx->argv[f->type-AUDIT_ARG0], f->op, f->val); |
350 | break; | 351 | break; |
352 | case AUDIT_FILTERKEY: | ||
353 | /* ignore this field for filtering */ | ||
354 | result = 1; | ||
355 | break; | ||
351 | } | 356 | } |
352 | 357 | ||
353 | if (!result) | 358 | if (!result) |
354 | return 0; | 359 | return 0; |
355 | } | 360 | } |
361 | if (rule->filterkey) | ||
362 | ctx->filterkey = kstrdup(rule->filterkey, GFP_ATOMIC); | ||
356 | switch (rule->action) { | 363 | switch (rule->action) { |
357 | case AUDIT_NEVER: *state = AUDIT_DISABLED; break; | 364 | case AUDIT_NEVER: *state = AUDIT_DISABLED; break; |
358 | case AUDIT_ALWAYS: *state = AUDIT_RECORD_CONTEXT; break; | 365 | case AUDIT_ALWAYS: *state = AUDIT_RECORD_CONTEXT; break; |
@@ -627,6 +634,7 @@ static inline void audit_free_context(struct audit_context *context) | |||
627 | } | 634 | } |
628 | audit_free_names(context); | 635 | audit_free_names(context); |
629 | audit_free_aux(context); | 636 | audit_free_aux(context); |
637 | kfree(context->filterkey); | ||
630 | kfree(context); | 638 | kfree(context); |
631 | context = previous; | 639 | context = previous; |
632 | } while (context); | 640 | } while (context); |
@@ -735,6 +743,11 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
735 | context->euid, context->suid, context->fsuid, | 743 | context->euid, context->suid, context->fsuid, |
736 | context->egid, context->sgid, context->fsgid, tty); | 744 | context->egid, context->sgid, context->fsgid, tty); |
737 | audit_log_task_info(ab, tsk); | 745 | audit_log_task_info(ab, tsk); |
746 | if (context->filterkey) { | ||
747 | audit_log_format(ab, " key="); | ||
748 | audit_log_untrustedstring(ab, context->filterkey); | ||
749 | } else | ||
750 | audit_log_format(ab, " key=(null)"); | ||
738 | audit_log_end(ab); | 751 | audit_log_end(ab); |
739 | 752 | ||
740 | for (aux = context->aux; aux; aux = aux->next) { | 753 | for (aux = context->aux; aux; aux = aux->next) { |
@@ -1060,6 +1073,8 @@ void audit_syscall_exit(int valid, long return_code) | |||
1060 | } else { | 1073 | } else { |
1061 | audit_free_names(context); | 1074 | audit_free_names(context); |
1062 | audit_free_aux(context); | 1075 | audit_free_aux(context); |
1076 | kfree(context->filterkey); | ||
1077 | context->filterkey = NULL; | ||
1063 | tsk->audit_context = context; | 1078 | tsk->audit_context = context; |
1064 | } | 1079 | } |
1065 | } | 1080 | } |