aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/auditsc.c
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2012-09-11 05:18:08 -0400
committerEric W. Biederman <ebiederm@xmission.com>2012-09-17 21:08:09 -0400
commitca57ec0f00c3f139c41bf6b0a5b9bcc95bbb2ad7 (patch)
tree874ac71ed75f3c9b44eca7dbd8efef16d481827d /kernel/auditsc.c
parent860c0aaff75e714c21d325f32d36a37572b4fffb (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.c150
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
467static int audit_compare_id(uid_t uid1, 467static 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); 491static 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: