diff options
author | Eric Paris <eparis@redhat.com> | 2012-01-03 14:23:08 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-01-17 16:17:02 -0500 |
commit | b34b039324bf081554ee8678f9b8c5d937e5206c (patch) | |
tree | ff454dfed0580753defbeb87652bcf19faaf7800 /kernel | |
parent | 02d86a568c6d2d335256864451ac8ce781bc5652 (diff) |
audit: complex interfield comparison helper
Rather than code the same loop over and over implement a helper function which
uses some pointer magic to make it generic enough to be used numerous places
as we implement more audit interfield comparisons
Signed-off-by: Eric Paris <eparis@redhat.com>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/auditsc.c | 50 |
1 files changed, 39 insertions, 11 deletions
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 8fb2c8e6d624..b12cc32fe377 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
@@ -463,25 +463,53 @@ static int match_tree_refs(struct audit_context *ctx, struct audit_tree *tree) | |||
463 | return 0; | 463 | return 0; |
464 | } | 464 | } |
465 | 465 | ||
466 | static int audit_compare_id(uid_t uid1, | ||
467 | struct audit_names *name, | ||
468 | unsigned long name_offset, | ||
469 | struct audit_field *f, | ||
470 | struct audit_context *ctx) | ||
471 | { | ||
472 | struct audit_names *n; | ||
473 | unsigned long addr; | ||
474 | uid_t uid2; | ||
475 | int rc; | ||
476 | |||
477 | if (name) { | ||
478 | addr = (unsigned long)name; | ||
479 | addr += name_offset; | ||
480 | |||
481 | uid2 = *(uid_t *)addr; | ||
482 | rc = audit_comparator(uid1, f->op, uid2); | ||
483 | if (rc) | ||
484 | return rc; | ||
485 | } | ||
486 | |||
487 | if (ctx) { | ||
488 | list_for_each_entry(n, &ctx->names_list, list) { | ||
489 | addr = (unsigned long)n; | ||
490 | addr += name_offset; | ||
491 | |||
492 | uid2 = *(uid_t *)addr; | ||
493 | |||
494 | rc = audit_comparator(uid1, f->op, uid2); | ||
495 | if (rc) | ||
496 | return rc; | ||
497 | } | ||
498 | } | ||
499 | return 0; | ||
500 | } | ||
501 | |||
466 | static int audit_field_compare(struct task_struct *tsk, | 502 | static int audit_field_compare(struct task_struct *tsk, |
467 | const struct cred *cred, | 503 | const struct cred *cred, |
468 | struct audit_field *f, | 504 | struct audit_field *f, |
469 | struct audit_context *ctx, | 505 | struct audit_context *ctx, |
470 | struct audit_names *name) | 506 | struct audit_names *name) |
471 | { | 507 | { |
472 | struct audit_names *n; | ||
473 | |||
474 | switch (f->val) { | 508 | switch (f->val) { |
475 | case AUDIT_COMPARE_UID_TO_OBJ_UID: | 509 | case AUDIT_COMPARE_UID_TO_OBJ_UID: |
476 | if (name) { | 510 | return audit_compare_id(cred->uid, |
477 | return audit_comparator(cred->uid, f->op, name->uid); | 511 | name, offsetof(struct audit_names, uid), |
478 | } else if (ctx) { | 512 | f, ctx); |
479 | list_for_each_entry(n, &ctx->names_list, list) { | ||
480 | if (audit_comparator(cred->uid, f->op, n->uid)) | ||
481 | return 1; | ||
482 | } | ||
483 | } | ||
484 | break; | ||
485 | default: | 513 | default: |
486 | WARN(1, "Missing AUDIT_COMPARE define. Report as a bug\n"); | 514 | WARN(1, "Missing AUDIT_COMPARE define. Report as a bug\n"); |
487 | return 0; | 515 | return 0; |