diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2012-09-11 05:18:08 -0400 |
---|---|---|
committer | Eric W. Biederman <ebiederm@xmission.com> | 2012-09-17 21:08:09 -0400 |
commit | ca57ec0f00c3f139c41bf6b0a5b9bcc95bbb2ad7 (patch) | |
tree | 874ac71ed75f3c9b44eca7dbd8efef16d481827d /kernel/auditsc.c | |
parent | 860c0aaff75e714c21d325f32d36a37572b4fffb (diff) |
audit: Add typespecific uid and gid comparators
The audit filter code guarantees that uid are always compared with
uids and gids are always compared with gids, as the comparason
operations are type specific. Take advantage of this proper to define
audit_uid_comparator and audit_gid_comparator which use the type safe
comparasons from uidgid.h.
Build on audit_uid_comparator and audit_gid_comparator and replace
audit_compare_id with audit_compare_uid and audit_compare_gid. This
is one of those odd cases where being type safe and duplicating code
leads to simpler shorter and more concise code.
Don't allow bitmask operations in uid and gid comparisons in
audit_data_to_entry. Bitmask operations are already denined in
audit_rule_to_entry.
Convert constants in audit_rule_to_entry and audit_data_to_entry into
kuids and kgids when appropriate.
Convert the uid and gid field in struct audit_names to be of type
kuid_t and kgid_t respectively, so that the new uid and gid comparators
can be applied in a type safe manner.
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Eric Paris <eparis@redhat.com>
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Diffstat (limited to 'kernel/auditsc.c')
-rw-r--r-- | kernel/auditsc.c | 150 |
1 files changed, 71 insertions, 79 deletions
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 4b96415527b8..0b5b8a232b55 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
@@ -113,8 +113,8 @@ struct audit_names { | |||
113 | unsigned long ino; | 113 | unsigned long ino; |
114 | dev_t dev; | 114 | dev_t dev; |
115 | umode_t mode; | 115 | umode_t mode; |
116 | uid_t uid; | 116 | kuid_t uid; |
117 | gid_t gid; | 117 | kgid_t gid; |
118 | dev_t rdev; | 118 | dev_t rdev; |
119 | u32 osid; | 119 | u32 osid; |
120 | struct audit_cap_data fcap; | 120 | struct audit_cap_data fcap; |
@@ -464,37 +464,47 @@ static int match_tree_refs(struct audit_context *ctx, struct audit_tree *tree) | |||
464 | return 0; | 464 | return 0; |
465 | } | 465 | } |
466 | 466 | ||
467 | static int audit_compare_id(uid_t uid1, | 467 | static int audit_compare_uid(kuid_t uid, |
468 | struct audit_names *name, | 468 | struct audit_names *name, |
469 | unsigned long name_offset, | 469 | struct audit_field *f, |
470 | struct audit_field *f, | 470 | struct audit_context *ctx) |
471 | struct audit_context *ctx) | ||
472 | { | 471 | { |
473 | struct audit_names *n; | 472 | struct audit_names *n; |
474 | unsigned long addr; | ||
475 | uid_t uid2; | ||
476 | int rc; | 473 | int rc; |
477 | 474 | ||
478 | BUILD_BUG_ON(sizeof(uid_t) != sizeof(gid_t)); | ||
479 | |||
480 | if (name) { | 475 | if (name) { |
481 | addr = (unsigned long)name; | 476 | rc = audit_uid_comparator(uid, f->op, name->uid); |
482 | addr += name_offset; | ||
483 | |||
484 | uid2 = *(uid_t *)addr; | ||
485 | rc = audit_comparator(uid1, f->op, uid2); | ||
486 | if (rc) | 477 | if (rc) |
487 | return rc; | 478 | return rc; |
488 | } | 479 | } |
489 | 480 | ||
490 | if (ctx) { | 481 | if (ctx) { |
491 | list_for_each_entry(n, &ctx->names_list, list) { | 482 | list_for_each_entry(n, &ctx->names_list, list) { |
492 | addr = (unsigned long)n; | 483 | rc = audit_uid_comparator(uid, f->op, n->uid); |
493 | addr += name_offset; | 484 | if (rc) |
494 | 485 | return rc; | |
495 | uid2 = *(uid_t *)addr; | 486 | } |
487 | } | ||
488 | return 0; | ||
489 | } | ||
496 | 490 | ||
497 | rc = audit_comparator(uid1, f->op, uid2); | 491 | static int audit_compare_gid(kgid_t gid, |
492 | struct audit_names *name, | ||
493 | struct audit_field *f, | ||
494 | struct audit_context *ctx) | ||
495 | { | ||
496 | struct audit_names *n; | ||
497 | int rc; | ||
498 | |||
499 | if (name) { | ||
500 | rc = audit_gid_comparator(gid, f->op, name->gid); | ||
501 | if (rc) | ||
502 | return rc; | ||
503 | } | ||
504 | |||
505 | if (ctx) { | ||
506 | list_for_each_entry(n, &ctx->names_list, list) { | ||
507 | rc = audit_gid_comparator(gid, f->op, n->gid); | ||
498 | if (rc) | 508 | if (rc) |
499 | return rc; | 509 | return rc; |
500 | } | 510 | } |
@@ -511,80 +521,62 @@ static int audit_field_compare(struct task_struct *tsk, | |||
511 | switch (f->val) { | 521 | switch (f->val) { |
512 | /* process to file object comparisons */ | 522 | /* process to file object comparisons */ |
513 | case AUDIT_COMPARE_UID_TO_OBJ_UID: | 523 | case AUDIT_COMPARE_UID_TO_OBJ_UID: |
514 | return audit_compare_id(cred->uid, | 524 | return audit_compare_uid(cred->uid, name, f, ctx); |
515 | name, offsetof(struct audit_names, uid), | ||
516 | f, ctx); | ||
517 | case AUDIT_COMPARE_GID_TO_OBJ_GID: | 525 | case AUDIT_COMPARE_GID_TO_OBJ_GID: |
518 | return audit_compare_id(cred->gid, | 526 | return audit_compare_gid(cred->gid, name, f, ctx); |
519 | name, offsetof(struct audit_names, gid), | ||
520 | f, ctx); | ||
521 | case AUDIT_COMPARE_EUID_TO_OBJ_UID: | 527 | case AUDIT_COMPARE_EUID_TO_OBJ_UID: |
522 | return audit_compare_id(cred->euid, | 528 | return audit_compare_uid(cred->euid, name, f, ctx); |
523 | name, offsetof(struct audit_names, uid), | ||
524 | f, ctx); | ||
525 | case AUDIT_COMPARE_EGID_TO_OBJ_GID: | 529 | case AUDIT_COMPARE_EGID_TO_OBJ_GID: |
526 | return audit_compare_id(cred->egid, | 530 | return audit_compare_gid(cred->egid, name, f, ctx); |
527 | name, offsetof(struct audit_names, gid), | ||
528 | f, ctx); | ||
529 | case AUDIT_COMPARE_AUID_TO_OBJ_UID: | 531 | case AUDIT_COMPARE_AUID_TO_OBJ_UID: |
530 | return audit_compare_id(tsk->loginuid, | 532 | return audit_compare_uid(tsk->loginuid, name, f, ctx); |
531 | name, offsetof(struct audit_names, uid), | ||
532 | f, ctx); | ||
533 | case AUDIT_COMPARE_SUID_TO_OBJ_UID: | 533 | case AUDIT_COMPARE_SUID_TO_OBJ_UID: |
534 | return audit_compare_id(cred->suid, | 534 | return audit_compare_uid(cred->suid, name, f, ctx); |
535 | name, offsetof(struct audit_names, uid), | ||
536 | f, ctx); | ||
537 | case AUDIT_COMPARE_SGID_TO_OBJ_GID: | 535 | case AUDIT_COMPARE_SGID_TO_OBJ_GID: |
538 | return audit_compare_id(cred->sgid, | 536 | return audit_compare_gid(cred->sgid, name, f, ctx); |
539 | name, offsetof(struct audit_names, gid), | ||
540 | f, ctx); | ||
541 | case AUDIT_COMPARE_FSUID_TO_OBJ_UID: | 537 | case AUDIT_COMPARE_FSUID_TO_OBJ_UID: |
542 | return audit_compare_id(cred->fsuid, | 538 | return audit_compare_uid(cred->fsuid, name, f, ctx); |
543 | name, offsetof(struct audit_names, uid), | ||
544 | f, ctx); | ||
545 | case AUDIT_COMPARE_FSGID_TO_OBJ_GID: | 539 | case AUDIT_COMPARE_FSGID_TO_OBJ_GID: |
546 | return audit_compare_id(cred->fsgid, | 540 | return audit_compare_gid(cred->fsgid, name, f, ctx); |
547 | name, offsetof(struct audit_names, gid), | ||
548 | f, ctx); | ||
549 | /* uid comparisons */ | 541 | /* uid comparisons */ |
550 | case AUDIT_COMPARE_UID_TO_AUID: | 542 | case AUDIT_COMPARE_UID_TO_AUID: |
551 | return audit_comparator(cred->uid, f->op, tsk->loginuid); | 543 | return audit_uid_comparator(cred->uid, f->op, tsk->loginuid); |
552 | case AUDIT_COMPARE_UID_TO_EUID: | 544 | case AUDIT_COMPARE_UID_TO_EUID: |
553 | return audit_comparator(cred->uid, f->op, cred->euid); | 545 | return audit_uid_comparator(cred->uid, f->op, cred->euid); |
554 | case AUDIT_COMPARE_UID_TO_SUID: | 546 | case AUDIT_COMPARE_UID_TO_SUID: |
555 | return audit_comparator(cred->uid, f->op, cred->suid); | 547 | return audit_uid_comparator(cred->uid, f->op, cred->suid); |
556 | case AUDIT_COMPARE_UID_TO_FSUID: | 548 | case AUDIT_COMPARE_UID_TO_FSUID: |
557 | return audit_comparator(cred->uid, f->op, cred->fsuid); | 549 | return audit_uid_comparator(cred->uid, f->op, cred->fsuid); |
558 | /* auid comparisons */ | 550 | /* auid comparisons */ |
559 | case AUDIT_COMPARE_AUID_TO_EUID: | 551 | case AUDIT_COMPARE_AUID_TO_EUID: |
560 | return audit_comparator(tsk->loginuid, f->op, cred->euid); | 552 | return audit_uid_comparator(tsk->loginuid, f->op, cred->euid); |
561 | case AUDIT_COMPARE_AUID_TO_SUID: | 553 | case AUDIT_COMPARE_AUID_TO_SUID: |
562 | return audit_comparator(tsk->loginuid, f->op, cred->suid); | 554 | return audit_uid_comparator(tsk->loginuid, f->op, cred->suid); |
563 | case AUDIT_COMPARE_AUID_TO_FSUID: | 555 | case AUDIT_COMPARE_AUID_TO_FSUID: |
564 | return audit_comparator(tsk->loginuid, f->op, cred->fsuid); | 556 | return audit_uid_comparator(tsk->loginuid, f->op, cred->fsuid); |
565 | /* euid comparisons */ | 557 | /* euid comparisons */ |
566 | case AUDIT_COMPARE_EUID_TO_SUID: | 558 | case AUDIT_COMPARE_EUID_TO_SUID: |
567 | return audit_comparator(cred->euid, f->op, cred->suid); | 559 | return audit_uid_comparator(cred->euid, f->op, cred->suid); |
568 | case AUDIT_COMPARE_EUID_TO_FSUID: | 560 | case AUDIT_COMPARE_EUID_TO_FSUID: |
569 | return audit_comparator(cred->euid, f->op, cred->fsuid); | 561 | return audit_uid_comparator(cred->euid, f->op, cred->fsuid); |
570 | /* suid comparisons */ | 562 | /* suid comparisons */ |
571 | case AUDIT_COMPARE_SUID_TO_FSUID: | 563 | case AUDIT_COMPARE_SUID_TO_FSUID: |
572 | return audit_comparator(cred->suid, f->op, cred->fsuid); | 564 | return audit_uid_comparator(cred->suid, f->op, cred->fsuid); |
573 | /* gid comparisons */ | 565 | /* gid comparisons */ |
574 | case AUDIT_COMPARE_GID_TO_EGID: | 566 | case AUDIT_COMPARE_GID_TO_EGID: |
575 | return audit_comparator(cred->gid, f->op, cred->egid); | 567 | return audit_gid_comparator(cred->gid, f->op, cred->egid); |
576 | case AUDIT_COMPARE_GID_TO_SGID: | 568 | case AUDIT_COMPARE_GID_TO_SGID: |
577 | return audit_comparator(cred->gid, f->op, cred->sgid); | 569 | return audit_gid_comparator(cred->gid, f->op, cred->sgid); |
578 | case AUDIT_COMPARE_GID_TO_FSGID: | 570 | case AUDIT_COMPARE_GID_TO_FSGID: |
579 | return audit_comparator(cred->gid, f->op, cred->fsgid); | 571 | return audit_gid_comparator(cred->gid, f->op, cred->fsgid); |
580 | /* egid comparisons */ | 572 | /* egid comparisons */ |
581 | case AUDIT_COMPARE_EGID_TO_SGID: | 573 | case AUDIT_COMPARE_EGID_TO_SGID: |
582 | return audit_comparator(cred->egid, f->op, cred->sgid); | 574 | return audit_gid_comparator(cred->egid, f->op, cred->sgid); |
583 | case AUDIT_COMPARE_EGID_TO_FSGID: | 575 | case AUDIT_COMPARE_EGID_TO_FSGID: |
584 | return audit_comparator(cred->egid, f->op, cred->fsgid); | 576 | return audit_gid_comparator(cred->egid, f->op, cred->fsgid); |
585 | /* sgid comparison */ | 577 | /* sgid comparison */ |
586 | case AUDIT_COMPARE_SGID_TO_FSGID: | 578 | case AUDIT_COMPARE_SGID_TO_FSGID: |
587 | return audit_comparator(cred->sgid, f->op, cred->fsgid); | 579 | return audit_gid_comparator(cred->sgid, f->op, cred->fsgid); |
588 | default: | 580 | default: |
589 | WARN(1, "Missing AUDIT_COMPARE define. Report as a bug\n"); | 581 | WARN(1, "Missing AUDIT_COMPARE define. Report as a bug\n"); |
590 | return 0; | 582 | return 0; |
@@ -630,28 +622,28 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
630 | } | 622 | } |
631 | break; | 623 | break; |
632 | case AUDIT_UID: | 624 | case AUDIT_UID: |
633 | result = audit_comparator(cred->uid, f->op, f->val); | 625 | result = audit_uid_comparator(cred->uid, f->op, f->uid); |
634 | break; | 626 | break; |
635 | case AUDIT_EUID: | 627 | case AUDIT_EUID: |
636 | result = audit_comparator(cred->euid, f->op, f->val); | 628 | result = audit_uid_comparator(cred->euid, f->op, f->uid); |
637 | break; | 629 | break; |
638 | case AUDIT_SUID: | 630 | case AUDIT_SUID: |
639 | result = audit_comparator(cred->suid, f->op, f->val); | 631 | result = audit_uid_comparator(cred->suid, f->op, f->uid); |
640 | break; | 632 | break; |
641 | case AUDIT_FSUID: | 633 | case AUDIT_FSUID: |
642 | result = audit_comparator(cred->fsuid, f->op, f->val); | 634 | result = audit_uid_comparator(cred->fsuid, f->op, f->uid); |
643 | break; | 635 | break; |
644 | case AUDIT_GID: | 636 | case AUDIT_GID: |
645 | result = audit_comparator(cred->gid, f->op, f->val); | 637 | result = audit_gid_comparator(cred->gid, f->op, f->gid); |
646 | break; | 638 | break; |
647 | case AUDIT_EGID: | 639 | case AUDIT_EGID: |
648 | result = audit_comparator(cred->egid, f->op, f->val); | 640 | result = audit_gid_comparator(cred->egid, f->op, f->gid); |
649 | break; | 641 | break; |
650 | case AUDIT_SGID: | 642 | case AUDIT_SGID: |
651 | result = audit_comparator(cred->sgid, f->op, f->val); | 643 | result = audit_gid_comparator(cred->sgid, f->op, f->gid); |
652 | break; | 644 | break; |
653 | case AUDIT_FSGID: | 645 | case AUDIT_FSGID: |
654 | result = audit_comparator(cred->fsgid, f->op, f->val); | 646 | result = audit_gid_comparator(cred->fsgid, f->op, f->gid); |
655 | break; | 647 | break; |
656 | case AUDIT_PERS: | 648 | case AUDIT_PERS: |
657 | result = audit_comparator(tsk->personality, f->op, f->val); | 649 | result = audit_comparator(tsk->personality, f->op, f->val); |
@@ -717,10 +709,10 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
717 | break; | 709 | break; |
718 | case AUDIT_OBJ_UID: | 710 | case AUDIT_OBJ_UID: |
719 | if (name) { | 711 | if (name) { |
720 | result = audit_comparator(name->uid, f->op, f->val); | 712 | result = audit_uid_comparator(name->uid, f->op, f->uid); |
721 | } else if (ctx) { | 713 | } else if (ctx) { |
722 | list_for_each_entry(n, &ctx->names_list, list) { | 714 | list_for_each_entry(n, &ctx->names_list, list) { |
723 | if (audit_comparator(n->uid, f->op, f->val)) { | 715 | if (audit_uid_comparator(n->uid, f->op, f->uid)) { |
724 | ++result; | 716 | ++result; |
725 | break; | 717 | break; |
726 | } | 718 | } |
@@ -729,10 +721,10 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
729 | break; | 721 | break; |
730 | case AUDIT_OBJ_GID: | 722 | case AUDIT_OBJ_GID: |
731 | if (name) { | 723 | if (name) { |
732 | result = audit_comparator(name->gid, f->op, f->val); | 724 | result = audit_gid_comparator(name->gid, f->op, f->gid); |
733 | } else if (ctx) { | 725 | } else if (ctx) { |
734 | list_for_each_entry(n, &ctx->names_list, list) { | 726 | list_for_each_entry(n, &ctx->names_list, list) { |
735 | if (audit_comparator(n->gid, f->op, f->val)) { | 727 | if (audit_gid_comparator(n->gid, f->op, f->gid)) { |
736 | ++result; | 728 | ++result; |
737 | break; | 729 | break; |
738 | } | 730 | } |
@@ -750,7 +742,7 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
750 | case AUDIT_LOGINUID: | 742 | case AUDIT_LOGINUID: |
751 | result = 0; | 743 | result = 0; |
752 | if (ctx) | 744 | if (ctx) |
753 | result = audit_comparator(tsk->loginuid, f->op, f->val); | 745 | result = audit_uid_comparator(tsk->loginuid, f->op, f->uid); |
754 | break; | 746 | break; |
755 | case AUDIT_SUBJ_USER: | 747 | case AUDIT_SUBJ_USER: |
756 | case AUDIT_SUBJ_ROLE: | 748 | case AUDIT_SUBJ_ROLE: |