diff options
-rw-r--r-- | security/tomoyo/domain.c | 56 |
1 files changed, 22 insertions, 34 deletions
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index 498fea732f48..a1fc6b5f6125 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c | |||
@@ -664,9 +664,9 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) | |||
664 | struct tomoyo_domain_info *domain = NULL; | 664 | struct tomoyo_domain_info *domain = NULL; |
665 | const char *original_name = bprm->filename; | 665 | const char *original_name = bprm->filename; |
666 | int retval = -ENOMEM; | 666 | int retval = -ENOMEM; |
667 | bool need_kfree = false; | ||
668 | bool reject_on_transition_failure = false; | 667 | bool reject_on_transition_failure = false; |
669 | struct tomoyo_path_info rn = { }; /* real name */ | 668 | const struct tomoyo_path_info *candidate; |
669 | struct tomoyo_path_info exename; | ||
670 | struct tomoyo_execve *ee = kzalloc(sizeof(*ee), GFP_NOFS); | 670 | struct tomoyo_execve *ee = kzalloc(sizeof(*ee), GFP_NOFS); |
671 | 671 | ||
672 | if (!ee) | 672 | if (!ee) |
@@ -682,40 +682,33 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) | |||
682 | ee->bprm = bprm; | 682 | ee->bprm = bprm; |
683 | ee->r.obj = &ee->obj; | 683 | ee->r.obj = &ee->obj; |
684 | ee->obj.path1 = bprm->file->f_path; | 684 | ee->obj.path1 = bprm->file->f_path; |
685 | retry: | ||
686 | if (need_kfree) { | ||
687 | kfree(rn.name); | ||
688 | need_kfree = false; | ||
689 | } | ||
690 | /* Get symlink's pathname of program. */ | 685 | /* Get symlink's pathname of program. */ |
691 | retval = -ENOENT; | 686 | retval = -ENOENT; |
692 | rn.name = tomoyo_realpath_nofollow(original_name); | 687 | exename.name = tomoyo_realpath_nofollow(original_name); |
693 | if (!rn.name) | 688 | if (!exename.name) |
694 | goto out; | 689 | goto out; |
695 | tomoyo_fill_path_info(&rn); | 690 | tomoyo_fill_path_info(&exename); |
696 | need_kfree = true; | 691 | retry: |
697 | |||
698 | /* Check 'aggregator' directive. */ | 692 | /* Check 'aggregator' directive. */ |
699 | { | 693 | { |
700 | struct tomoyo_aggregator *ptr; | 694 | struct tomoyo_aggregator *ptr; |
701 | struct list_head *list = | 695 | struct list_head *list = |
702 | &old_domain->ns->policy_list[TOMOYO_ID_AGGREGATOR]; | 696 | &old_domain->ns->policy_list[TOMOYO_ID_AGGREGATOR]; |
703 | /* Check 'aggregator' directive. */ | 697 | /* Check 'aggregator' directive. */ |
698 | candidate = &exename; | ||
704 | list_for_each_entry_rcu(ptr, list, head.list) { | 699 | list_for_each_entry_rcu(ptr, list, head.list) { |
705 | if (ptr->head.is_deleted || | 700 | if (ptr->head.is_deleted || |
706 | !tomoyo_path_matches_pattern(&rn, | 701 | !tomoyo_path_matches_pattern(&exename, |
707 | ptr->original_name)) | 702 | ptr->original_name)) |
708 | continue; | 703 | continue; |
709 | kfree(rn.name); | 704 | candidate = ptr->aggregated_name; |
710 | need_kfree = false; | ||
711 | /* This is OK because it is read only. */ | ||
712 | rn = *ptr->aggregated_name; | ||
713 | break; | 705 | break; |
714 | } | 706 | } |
715 | } | 707 | } |
716 | 708 | ||
717 | /* Check execute permission. */ | 709 | /* Check execute permission. */ |
718 | retval = tomoyo_path_permission(&ee->r, TOMOYO_TYPE_EXECUTE, &rn); | 710 | retval = tomoyo_path_permission(&ee->r, TOMOYO_TYPE_EXECUTE, |
711 | candidate); | ||
719 | if (retval == TOMOYO_RETRY_REQUEST) | 712 | if (retval == TOMOYO_RETRY_REQUEST) |
720 | goto retry; | 713 | goto retry; |
721 | if (retval < 0) | 714 | if (retval < 0) |
@@ -726,20 +719,16 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) | |||
726 | * wildcard) rather than the pathname passed to execve() | 719 | * wildcard) rather than the pathname passed to execve() |
727 | * (which never contains wildcard). | 720 | * (which never contains wildcard). |
728 | */ | 721 | */ |
729 | if (ee->r.param.path.matched_path) { | 722 | if (ee->r.param.path.matched_path) |
730 | if (need_kfree) | 723 | candidate = ee->r.param.path.matched_path; |
731 | kfree(rn.name); | ||
732 | need_kfree = false; | ||
733 | /* This is OK because it is read only. */ | ||
734 | rn = *ee->r.param.path.matched_path; | ||
735 | } | ||
736 | 724 | ||
737 | /* Calculate domain to transit to. */ | 725 | /* Calculate domain to transit to. */ |
738 | switch (tomoyo_transition_type(old_domain->ns, old_domain->domainname, | 726 | switch (tomoyo_transition_type(old_domain->ns, old_domain->domainname, |
739 | &rn)) { | 727 | candidate)) { |
740 | case TOMOYO_TRANSITION_CONTROL_RESET: | 728 | case TOMOYO_TRANSITION_CONTROL_RESET: |
741 | /* Transit to the root of specified namespace. */ | 729 | /* Transit to the root of specified namespace. */ |
742 | snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "<%s>", rn.name); | 730 | snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "<%s>", |
731 | candidate->name); | ||
743 | /* | 732 | /* |
744 | * Make do_execve() fail if domain transition across namespaces | 733 | * Make do_execve() fail if domain transition across namespaces |
745 | * has failed. | 734 | * has failed. |
@@ -749,7 +738,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) | |||
749 | case TOMOYO_TRANSITION_CONTROL_INITIALIZE: | 738 | case TOMOYO_TRANSITION_CONTROL_INITIALIZE: |
750 | /* Transit to the child of current namespace's root. */ | 739 | /* Transit to the child of current namespace's root. */ |
751 | snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s", | 740 | snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s", |
752 | old_domain->ns->name, rn.name); | 741 | old_domain->ns->name, candidate->name); |
753 | break; | 742 | break; |
754 | case TOMOYO_TRANSITION_CONTROL_KEEP: | 743 | case TOMOYO_TRANSITION_CONTROL_KEEP: |
755 | /* Keep current domain. */ | 744 | /* Keep current domain. */ |
@@ -765,11 +754,11 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) | |||
765 | * before /sbin/init. | 754 | * before /sbin/init. |
766 | */ | 755 | */ |
767 | domain = old_domain; | 756 | domain = old_domain; |
768 | } else { | 757 | break; |
769 | /* Normal domain transition. */ | ||
770 | snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s", | ||
771 | old_domain->domainname->name, rn.name); | ||
772 | } | 758 | } |
759 | /* Normal domain transition. */ | ||
760 | snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s", | ||
761 | old_domain->domainname->name, candidate->name); | ||
773 | break; | 762 | break; |
774 | } | 763 | } |
775 | if (!domain) | 764 | if (!domain) |
@@ -799,8 +788,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) | |||
799 | /* Update reference count on "struct tomoyo_domain_info". */ | 788 | /* Update reference count on "struct tomoyo_domain_info". */ |
800 | atomic_inc(&domain->users); | 789 | atomic_inc(&domain->users); |
801 | bprm->cred->security = domain; | 790 | bprm->cred->security = domain; |
802 | if (need_kfree) | 791 | kfree(exename.name); |
803 | kfree(rn.name); | ||
804 | if (!retval) { | 792 | if (!retval) { |
805 | ee->r.domain = domain; | 793 | ee->r.domain = domain; |
806 | retval = tomoyo_environ(ee); | 794 | retval = tomoyo_environ(ee); |