domain.c (cf797c0e5e312520b0b9f0367039fc0279a07a76) domain.c (df8073c67fd8acb7e79f203ba4c0fa456bb82762)
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor policy attachment and domain transitions
5 *
6 * Copyright (C) 2002-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd.
8 *

--- 549 unchanged lines hidden (view full) ---

558 return name;
559}
560
561/**
562 * aa_change_hat - change hat to/from subprofile
563 * @hats: vector of hat names to try changing into (MAYBE NULL if @count == 0)
564 * @count: number of hat names in @hats
565 * @token: magic value to validate the hat change
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor policy attachment and domain transitions
5 *
6 * Copyright (C) 2002-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd.
8 *

--- 549 unchanged lines hidden (view full) ---

558 return name;
559}
560
561/**
562 * aa_change_hat - change hat to/from subprofile
563 * @hats: vector of hat names to try changing into (MAYBE NULL if @count == 0)
564 * @count: number of hat names in @hats
565 * @token: magic value to validate the hat change
566 * @permtest: true if this is just a permission test
566 * @flags: flags affecting behavior of the change
567 *
568 * Change to the first profile specified in @hats that exists, and store
569 * the @hat_magic in the current task context. If the count == 0 and the
570 * @token matches that stored in the current task context, return to the
571 * top level profile.
572 *
573 * Returns %0 on success, error otherwise.
574 */
567 *
568 * Change to the first profile specified in @hats that exists, and store
569 * the @hat_magic in the current task context. If the count == 0 and the
570 * @token matches that stored in the current task context, return to the
571 * top level profile.
572 *
573 * Returns %0 on success, error otherwise.
574 */
575int aa_change_hat(const char *hats[], int count, u64 token, bool permtest)
575int aa_change_hat(const char *hats[], int count, u64 token, int flags)
576{
577 const struct cred *cred;
578 struct aa_task_ctx *ctx;
579 struct aa_profile *profile, *previous_profile, *hat = NULL;
580 char *name = NULL;
581 int i;
582 struct aa_perms perms = {};
583 const char *target = NULL, *info = NULL;

--- 27 unchanged lines hidden (view full) ---

611 else
612 root = aa_get_profile(profile);
613
614 /* find first matching hat */
615 for (i = 0; i < count && !hat; i++)
616 /* released below */
617 hat = aa_find_child(root, hats[i]);
618 if (!hat) {
576{
577 const struct cred *cred;
578 struct aa_task_ctx *ctx;
579 struct aa_profile *profile, *previous_profile, *hat = NULL;
580 char *name = NULL;
581 int i;
582 struct aa_perms perms = {};
583 const char *target = NULL, *info = NULL;

--- 27 unchanged lines hidden (view full) ---

611 else
612 root = aa_get_profile(profile);
613
614 /* find first matching hat */
615 for (i = 0; i < count && !hat; i++)
616 /* released below */
617 hat = aa_find_child(root, hats[i]);
618 if (!hat) {
619 if (!COMPLAIN_MODE(root) || permtest) {
619 if (!COMPLAIN_MODE(root) || (flags & AA_CHANGE_TEST)) {
620 if (list_empty(&root->base.profiles))
621 error = -ECHILD;
622 else
623 error = -ENOENT;
624 aa_put_profile(root);
625 goto out;
626 }
627

--- 30 unchanged lines hidden (view full) ---

658
659 error = may_change_ptraced_domain(hat);
660 if (error) {
661 info = "ptraced";
662 error = -EPERM;
663 goto audit;
664 }
665
620 if (list_empty(&root->base.profiles))
621 error = -ECHILD;
622 else
623 error = -ENOENT;
624 aa_put_profile(root);
625 goto out;
626 }
627

--- 30 unchanged lines hidden (view full) ---

658
659 error = may_change_ptraced_domain(hat);
660 if (error) {
661 info = "ptraced";
662 error = -EPERM;
663 goto audit;
664 }
665
666 if (!permtest) {
666 if (!(flags & AA_CHANGE_TEST)) {
667 error = aa_set_current_hat(hat, token);
668 if (error == -EACCES)
669 /* kill task in case of brute force attacks */
670 perms.kill = AA_MAY_CHANGEHAT;
671 else if (name && !error)
672 /* reset error for learning of new hats */
673 error = -ENOENT;
674 }

--- 4 unchanged lines hidden (view full) ---

679 target = previous_profile->base.hname;
680 error = aa_restore_previous_profile(token);
681 perms.kill = AA_MAY_CHANGEHAT;
682 } else
683 /* ignore restores when there is no saved profile */
684 goto out;
685
686audit:
667 error = aa_set_current_hat(hat, token);
668 if (error == -EACCES)
669 /* kill task in case of brute force attacks */
670 perms.kill = AA_MAY_CHANGEHAT;
671 else if (name && !error)
672 /* reset error for learning of new hats */
673 error = -ENOENT;
674 }

--- 4 unchanged lines hidden (view full) ---

679 target = previous_profile->base.hname;
680 error = aa_restore_previous_profile(token);
681 perms.kill = AA_MAY_CHANGEHAT;
682 } else
683 /* ignore restores when there is no saved profile */
684 goto out;
685
686audit:
687 if (!permtest)
687 if (!(flags & AA_CHANGE_TEST))
688 error = aa_audit_file(profile, &perms, OP_CHANGE_HAT,
689 AA_MAY_CHANGEHAT, NULL, target,
690 GLOBAL_ROOT_UID, info, error);
691
692out:
693 aa_put_profile(hat);
694 kfree(name);
695 aa_put_profile(profile);
696 aa_put_profile(previous_profile);
697 put_cred(cred);
698
699 return error;
700}
701
702/**
703 * aa_change_profile - perform a one-way profile transition
704 * @fqname: name of profile may include namespace (NOT NULL)
705 * @onexec: whether this transition is to take place immediately or at exec
688 error = aa_audit_file(profile, &perms, OP_CHANGE_HAT,
689 AA_MAY_CHANGEHAT, NULL, target,
690 GLOBAL_ROOT_UID, info, error);
691
692out:
693 aa_put_profile(hat);
694 kfree(name);
695 aa_put_profile(profile);
696 aa_put_profile(previous_profile);
697 put_cred(cred);
698
699 return error;
700}
701
702/**
703 * aa_change_profile - perform a one-way profile transition
704 * @fqname: name of profile may include namespace (NOT NULL)
705 * @onexec: whether this transition is to take place immediately or at exec
706 * @permtest: true if this is just a permission test
706 * @flags: flags affecting change behavior
707 *
708 * Change to new profile @name. Unlike with hats, there is no way
709 * to change back. If @name isn't specified the current profile name is
710 * used.
711 * If @onexec then the transition is delayed until
712 * the next exec.
713 *
714 * Returns %0 on success, error otherwise.
715 */
707 *
708 * Change to new profile @name. Unlike with hats, there is no way
709 * to change back. If @name isn't specified the current profile name is
710 * used.
711 * If @onexec then the transition is delayed until
712 * the next exec.
713 *
714 * Returns %0 on success, error otherwise.
715 */
716int aa_change_profile(const char *fqname, bool onexec,
717 bool permtest, bool stack)
716int aa_change_profile(const char *fqname, int flags)
718{
719 const struct cred *cred;
720 struct aa_profile *profile, *target = NULL;
721 struct aa_perms perms = {};
722 const char *info = NULL, *op;
723 int error = 0;
724 u32 request;
725
726 if (!fqname || !*fqname) {
727 AA_DEBUG("no profile name");
728 return -EINVAL;
729 }
730
717{
718 const struct cred *cred;
719 struct aa_profile *profile, *target = NULL;
720 struct aa_perms perms = {};
721 const char *info = NULL, *op;
722 int error = 0;
723 u32 request;
724
725 if (!fqname || !*fqname) {
726 AA_DEBUG("no profile name");
727 return -EINVAL;
728 }
729
731 if (onexec) {
730 if (flags & AA_CHANGE_ONEXEC) {
732 request = AA_MAY_ONEXEC;
733 op = OP_CHANGE_ONEXEC;
734 } else {
735 request = AA_MAY_CHANGE_PROFILE;
736 op = OP_CHANGE_PROFILE;
737 }
738
739 cred = get_current_cred();

--- 10 unchanged lines hidden (view full) ---

750 put_cred(cred);
751 return -EPERM;
752 }
753
754 target = aa_fqlookupn_profile(profile, fqname, strlen(fqname));
755 if (!target) {
756 info = "profile not found";
757 error = -ENOENT;
731 request = AA_MAY_ONEXEC;
732 op = OP_CHANGE_ONEXEC;
733 } else {
734 request = AA_MAY_CHANGE_PROFILE;
735 op = OP_CHANGE_PROFILE;
736 }
737
738 cred = get_current_cred();

--- 10 unchanged lines hidden (view full) ---

749 put_cred(cred);
750 return -EPERM;
751 }
752
753 target = aa_fqlookupn_profile(profile, fqname, strlen(fqname));
754 if (!target) {
755 info = "profile not found";
756 error = -ENOENT;
758 if (permtest || !COMPLAIN_MODE(profile))
757 if ((flags & AA_CHANGE_TEST) ||
758 !COMPLAIN_MODE(profile))
759 goto audit;
760 /* released below */
761 target = aa_new_null_profile(profile, false, fqname,
762 GFP_KERNEL);
763 if (!target) {
764 info = "failed null profile create";
765 error = -ENOMEM;
766 goto audit;

--- 9 unchanged lines hidden (view full) ---

776
777 /* check if tracing task is allowed to trace target domain */
778 error = may_change_ptraced_domain(target);
779 if (error) {
780 info = "ptrace prevents transition";
781 goto audit;
782 }
783
759 goto audit;
760 /* released below */
761 target = aa_new_null_profile(profile, false, fqname,
762 GFP_KERNEL);
763 if (!target) {
764 info = "failed null profile create";
765 error = -ENOMEM;
766 goto audit;

--- 9 unchanged lines hidden (view full) ---

776
777 /* check if tracing task is allowed to trace target domain */
778 error = may_change_ptraced_domain(target);
779 if (error) {
780 info = "ptrace prevents transition";
781 goto audit;
782 }
783
784 if (permtest)
784 if (flags & AA_CHANGE_TEST)
785 goto audit;
786
785 goto audit;
786
787 if (onexec)
787 if (flags & AA_CHANGE_ONEXEC)
788 error = aa_set_current_onexec(target);
789 else
790 error = aa_replace_current_profile(target);
791
792audit:
788 error = aa_set_current_onexec(target);
789 else
790 error = aa_replace_current_profile(target);
791
792audit:
793 if (!permtest)
793 if (!(flags & AA_CHANGE_TEST))
794 error = aa_audit_file(profile, &perms, op, request, NULL,
795 fqname, GLOBAL_ROOT_UID, info, error);
796
797 aa_put_profile(target);
798 aa_put_profile(profile);
799 put_cred(cred);
800
801 return error;
802}
794 error = aa_audit_file(profile, &perms, op, request, NULL,
795 fqname, GLOBAL_ROOT_UID, info, error);
796
797 aa_put_profile(target);
798 aa_put_profile(profile);
799 put_cred(cred);
800
801 return error;
802}