diff options
author | John Johansen <john.johansen@canonical.com> | 2016-06-22 21:01:08 -0400 |
---|---|---|
committer | John Johansen <john.johansen@canonical.com> | 2016-07-12 11:43:10 -0400 |
commit | 58acf9d911c8831156634a44d0b022d683e1e50c (patch) | |
tree | df76653f50579f989c36eab7139919523f50d561 | |
parent | 5f20fdfed16bc599a325a145bf0123a8e1c9beea (diff) |
apparmor: fix module parameters can be changed after policy is locked
the policy_lock parameter is a one way switch that prevents policy
from being further modified. Unfortunately some of the module parameters
can effectively modify policy by turning off enforcement.
split policy_admin_capable into a view check and a full admin check,
and update the admin check to test the policy_lock parameter.
Signed-off-by: John Johansen <john.johansen@canonical.com>
-rw-r--r-- | security/apparmor/include/policy.h | 2 | ||||
-rw-r--r-- | security/apparmor/lsm.c | 22 | ||||
-rw-r--r-- | security/apparmor/policy.c | 18 |
3 files changed, 29 insertions, 13 deletions
diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h index c28b0f20ab53..52275f040a5f 100644 --- a/security/apparmor/include/policy.h +++ b/security/apparmor/include/policy.h | |||
@@ -403,6 +403,8 @@ static inline int AUDIT_MODE(struct aa_profile *profile) | |||
403 | return profile->audit; | 403 | return profile->audit; |
404 | } | 404 | } |
405 | 405 | ||
406 | bool policy_view_capable(void); | ||
407 | bool policy_admin_capable(void); | ||
406 | bool aa_may_manage_policy(int op); | 408 | bool aa_may_manage_policy(int op); |
407 | 409 | ||
408 | #endif /* __AA_POLICY_H */ | 410 | #endif /* __AA_POLICY_H */ |
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 656b97c2e1ea..300f8336fb8e 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c | |||
@@ -730,51 +730,49 @@ __setup("apparmor=", apparmor_enabled_setup); | |||
730 | /* set global flag turning off the ability to load policy */ | 730 | /* set global flag turning off the ability to load policy */ |
731 | static int param_set_aalockpolicy(const char *val, const struct kernel_param *kp) | 731 | static int param_set_aalockpolicy(const char *val, const struct kernel_param *kp) |
732 | { | 732 | { |
733 | if (!capable(CAP_MAC_ADMIN)) | 733 | if (!policy_admin_capable()) |
734 | return -EPERM; | 734 | return -EPERM; |
735 | if (aa_g_lock_policy) | ||
736 | return -EACCES; | ||
737 | return param_set_bool(val, kp); | 735 | return param_set_bool(val, kp); |
738 | } | 736 | } |
739 | 737 | ||
740 | static int param_get_aalockpolicy(char *buffer, const struct kernel_param *kp) | 738 | static int param_get_aalockpolicy(char *buffer, const struct kernel_param *kp) |
741 | { | 739 | { |
742 | if (!capable(CAP_MAC_ADMIN)) | 740 | if (!policy_view_capable()) |
743 | return -EPERM; | 741 | return -EPERM; |
744 | return param_get_bool(buffer, kp); | 742 | return param_get_bool(buffer, kp); |
745 | } | 743 | } |
746 | 744 | ||
747 | static int param_set_aabool(const char *val, const struct kernel_param *kp) | 745 | static int param_set_aabool(const char *val, const struct kernel_param *kp) |
748 | { | 746 | { |
749 | if (!capable(CAP_MAC_ADMIN)) | 747 | if (!policy_admin_capable()) |
750 | return -EPERM; | 748 | return -EPERM; |
751 | return param_set_bool(val, kp); | 749 | return param_set_bool(val, kp); |
752 | } | 750 | } |
753 | 751 | ||
754 | static int param_get_aabool(char *buffer, const struct kernel_param *kp) | 752 | static int param_get_aabool(char *buffer, const struct kernel_param *kp) |
755 | { | 753 | { |
756 | if (!capable(CAP_MAC_ADMIN)) | 754 | if (!policy_view_capable()) |
757 | return -EPERM; | 755 | return -EPERM; |
758 | return param_get_bool(buffer, kp); | 756 | return param_get_bool(buffer, kp); |
759 | } | 757 | } |
760 | 758 | ||
761 | static int param_set_aauint(const char *val, const struct kernel_param *kp) | 759 | static int param_set_aauint(const char *val, const struct kernel_param *kp) |
762 | { | 760 | { |
763 | if (!capable(CAP_MAC_ADMIN)) | 761 | if (!policy_admin_capable()) |
764 | return -EPERM; | 762 | return -EPERM; |
765 | return param_set_uint(val, kp); | 763 | return param_set_uint(val, kp); |
766 | } | 764 | } |
767 | 765 | ||
768 | static int param_get_aauint(char *buffer, const struct kernel_param *kp) | 766 | static int param_get_aauint(char *buffer, const struct kernel_param *kp) |
769 | { | 767 | { |
770 | if (!capable(CAP_MAC_ADMIN)) | 768 | if (!policy_view_capable()) |
771 | return -EPERM; | 769 | return -EPERM; |
772 | return param_get_uint(buffer, kp); | 770 | return param_get_uint(buffer, kp); |
773 | } | 771 | } |
774 | 772 | ||
775 | static int param_get_audit(char *buffer, struct kernel_param *kp) | 773 | static int param_get_audit(char *buffer, struct kernel_param *kp) |
776 | { | 774 | { |
777 | if (!capable(CAP_MAC_ADMIN)) | 775 | if (!policy_view_capable()) |
778 | return -EPERM; | 776 | return -EPERM; |
779 | 777 | ||
780 | if (!apparmor_enabled) | 778 | if (!apparmor_enabled) |
@@ -786,7 +784,7 @@ static int param_get_audit(char *buffer, struct kernel_param *kp) | |||
786 | static int param_set_audit(const char *val, struct kernel_param *kp) | 784 | static int param_set_audit(const char *val, struct kernel_param *kp) |
787 | { | 785 | { |
788 | int i; | 786 | int i; |
789 | if (!capable(CAP_MAC_ADMIN)) | 787 | if (!policy_admin_capable()) |
790 | return -EPERM; | 788 | return -EPERM; |
791 | 789 | ||
792 | if (!apparmor_enabled) | 790 | if (!apparmor_enabled) |
@@ -807,7 +805,7 @@ static int param_set_audit(const char *val, struct kernel_param *kp) | |||
807 | 805 | ||
808 | static int param_get_mode(char *buffer, struct kernel_param *kp) | 806 | static int param_get_mode(char *buffer, struct kernel_param *kp) |
809 | { | 807 | { |
810 | if (!capable(CAP_MAC_ADMIN)) | 808 | if (!policy_admin_capable()) |
811 | return -EPERM; | 809 | return -EPERM; |
812 | 810 | ||
813 | if (!apparmor_enabled) | 811 | if (!apparmor_enabled) |
@@ -819,7 +817,7 @@ static int param_get_mode(char *buffer, struct kernel_param *kp) | |||
819 | static int param_set_mode(const char *val, struct kernel_param *kp) | 817 | static int param_set_mode(const char *val, struct kernel_param *kp) |
820 | { | 818 | { |
821 | int i; | 819 | int i; |
822 | if (!capable(CAP_MAC_ADMIN)) | 820 | if (!policy_admin_capable()) |
823 | return -EPERM; | 821 | return -EPERM; |
824 | 822 | ||
825 | if (!apparmor_enabled) | 823 | if (!apparmor_enabled) |
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c index 780712553651..179e68d7dc5f 100644 --- a/security/apparmor/policy.c +++ b/security/apparmor/policy.c | |||
@@ -918,6 +918,22 @@ static int audit_policy(int op, gfp_t gfp, const char *name, const char *info, | |||
918 | &sa, NULL); | 918 | &sa, NULL); |
919 | } | 919 | } |
920 | 920 | ||
921 | bool policy_view_capable(void) | ||
922 | { | ||
923 | struct user_namespace *user_ns = current_user_ns(); | ||
924 | bool response = false; | ||
925 | |||
926 | if (ns_capable(user_ns, CAP_MAC_ADMIN)) | ||
927 | response = true; | ||
928 | |||
929 | return response; | ||
930 | } | ||
931 | |||
932 | bool policy_admin_capable(void) | ||
933 | { | ||
934 | return policy_view_capable() && !aa_g_lock_policy; | ||
935 | } | ||
936 | |||
921 | /** | 937 | /** |
922 | * aa_may_manage_policy - can the current task manage policy | 938 | * aa_may_manage_policy - can the current task manage policy |
923 | * @op: the policy manipulation operation being done | 939 | * @op: the policy manipulation operation being done |
@@ -932,7 +948,7 @@ bool aa_may_manage_policy(int op) | |||
932 | return 0; | 948 | return 0; |
933 | } | 949 | } |
934 | 950 | ||
935 | if (!capable(CAP_MAC_ADMIN)) { | 951 | if (!policy_admin_capable()) { |
936 | audit_policy(op, GFP_KERNEL, NULL, "not policy admin", -EACCES); | 952 | audit_policy(op, GFP_KERNEL, NULL, "not policy admin", -EACCES); |
937 | return 0; | 953 | return 0; |
938 | } | 954 | } |