diff options
Diffstat (limited to 'kernel/auditsc.c')
-rw-r--r-- | kernel/auditsc.c | 65 |
1 files changed, 60 insertions, 5 deletions
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index dc5e3f01efe7..ae40ac8c39e7 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 */ |
@@ -320,11 +321,11 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
320 | if (ctx) | 321 | if (ctx) |
321 | result = audit_comparator(ctx->loginuid, f->op, f->val); | 322 | result = audit_comparator(ctx->loginuid, f->op, f->val); |
322 | break; | 323 | break; |
323 | case AUDIT_SE_USER: | 324 | case AUDIT_SUBJ_USER: |
324 | case AUDIT_SE_ROLE: | 325 | case AUDIT_SUBJ_ROLE: |
325 | case AUDIT_SE_TYPE: | 326 | case AUDIT_SUBJ_TYPE: |
326 | case AUDIT_SE_SEN: | 327 | case AUDIT_SUBJ_SEN: |
327 | case AUDIT_SE_CLR: | 328 | case AUDIT_SUBJ_CLR: |
328 | /* NOTE: this may return negative values indicating | 329 | /* NOTE: this may return negative values indicating |
329 | a temporary error. We simply treat this as a | 330 | a temporary error. We simply treat this as a |
330 | match for now to avoid losing information that | 331 | match for now to avoid losing information that |
@@ -341,6 +342,46 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
341 | ctx); | 342 | ctx); |
342 | } | 343 | } |
343 | break; | 344 | break; |
345 | case AUDIT_OBJ_USER: | ||
346 | case AUDIT_OBJ_ROLE: | ||
347 | case AUDIT_OBJ_TYPE: | ||
348 | case AUDIT_OBJ_LEV_LOW: | ||
349 | case AUDIT_OBJ_LEV_HIGH: | ||
350 | /* The above note for AUDIT_SUBJ_USER...AUDIT_SUBJ_CLR | ||
351 | also applies here */ | ||
352 | if (f->se_rule) { | ||
353 | /* Find files that match */ | ||
354 | if (name) { | ||
355 | result = selinux_audit_rule_match( | ||
356 | name->osid, f->type, f->op, | ||
357 | f->se_rule, ctx); | ||
358 | } else if (ctx) { | ||
359 | for (j = 0; j < ctx->name_count; j++) { | ||
360 | if (selinux_audit_rule_match( | ||
361 | ctx->names[j].osid, | ||
362 | f->type, f->op, | ||
363 | f->se_rule, ctx)) { | ||
364 | ++result; | ||
365 | break; | ||
366 | } | ||
367 | } | ||
368 | } | ||
369 | /* Find ipc objects that match */ | ||
370 | if (ctx) { | ||
371 | struct audit_aux_data *aux; | ||
372 | for (aux = ctx->aux; aux; | ||
373 | aux = aux->next) { | ||
374 | if (aux->type == AUDIT_IPC) { | ||
375 | struct audit_aux_data_ipcctl *axi = (void *)aux; | ||
376 | if (selinux_audit_rule_match(axi->osid, f->type, f->op, f->se_rule, ctx)) { | ||
377 | ++result; | ||
378 | break; | ||
379 | } | ||
380 | } | ||
381 | } | ||
382 | } | ||
383 | } | ||
384 | break; | ||
344 | case AUDIT_ARG0: | 385 | case AUDIT_ARG0: |
345 | case AUDIT_ARG1: | 386 | case AUDIT_ARG1: |
346 | case AUDIT_ARG2: | 387 | case AUDIT_ARG2: |
@@ -348,11 +389,17 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
348 | if (ctx) | 389 | if (ctx) |
349 | result = audit_comparator(ctx->argv[f->type-AUDIT_ARG0], f->op, f->val); | 390 | result = audit_comparator(ctx->argv[f->type-AUDIT_ARG0], f->op, f->val); |
350 | break; | 391 | break; |
392 | case AUDIT_FILTERKEY: | ||
393 | /* ignore this field for filtering */ | ||
394 | result = 1; | ||
395 | break; | ||
351 | } | 396 | } |
352 | 397 | ||
353 | if (!result) | 398 | if (!result) |
354 | return 0; | 399 | return 0; |
355 | } | 400 | } |
401 | if (rule->filterkey) | ||
402 | ctx->filterkey = kstrdup(rule->filterkey, GFP_ATOMIC); | ||
356 | switch (rule->action) { | 403 | switch (rule->action) { |
357 | case AUDIT_NEVER: *state = AUDIT_DISABLED; break; | 404 | case AUDIT_NEVER: *state = AUDIT_DISABLED; break; |
358 | case AUDIT_ALWAYS: *state = AUDIT_RECORD_CONTEXT; break; | 405 | case AUDIT_ALWAYS: *state = AUDIT_RECORD_CONTEXT; break; |
@@ -627,6 +674,7 @@ static inline void audit_free_context(struct audit_context *context) | |||
627 | } | 674 | } |
628 | audit_free_names(context); | 675 | audit_free_names(context); |
629 | audit_free_aux(context); | 676 | audit_free_aux(context); |
677 | kfree(context->filterkey); | ||
630 | kfree(context); | 678 | kfree(context); |
631 | context = previous; | 679 | context = previous; |
632 | } while (context); | 680 | } while (context); |
@@ -735,6 +783,11 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
735 | context->euid, context->suid, context->fsuid, | 783 | context->euid, context->suid, context->fsuid, |
736 | context->egid, context->sgid, context->fsgid, tty); | 784 | context->egid, context->sgid, context->fsgid, tty); |
737 | audit_log_task_info(ab, tsk); | 785 | audit_log_task_info(ab, tsk); |
786 | if (context->filterkey) { | ||
787 | audit_log_format(ab, " key="); | ||
788 | audit_log_untrustedstring(ab, context->filterkey); | ||
789 | } else | ||
790 | audit_log_format(ab, " key=(null)"); | ||
738 | audit_log_end(ab); | 791 | audit_log_end(ab); |
739 | 792 | ||
740 | for (aux = context->aux; aux; aux = aux->next) { | 793 | for (aux = context->aux; aux; aux = aux->next) { |
@@ -1060,6 +1113,8 @@ void audit_syscall_exit(int valid, long return_code) | |||
1060 | } else { | 1113 | } else { |
1061 | audit_free_names(context); | 1114 | audit_free_names(context); |
1062 | audit_free_aux(context); | 1115 | audit_free_aux(context); |
1116 | kfree(context->filterkey); | ||
1117 | context->filterkey = NULL; | ||
1063 | tsk->audit_context = context; | 1118 | tsk->audit_context = context; |
1064 | } | 1119 | } |
1065 | } | 1120 | } |