From: John Johansen john.johansen@canonical.com
commit 58acf9d911c8831156634a44d0b022d683e1e50c upstream.
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 Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- security/apparmor/include/policy.h | 2 ++ security/apparmor/lsm.c | 22 ++++++++++------------ security/apparmor/policy.c | 18 +++++++++++++++++- 3 files changed, 29 insertions(+), 13 deletions(-)
--- a/security/apparmor/include/policy.h +++ b/security/apparmor/include/policy.h @@ -403,6 +403,8 @@ static inline int AUDIT_MODE(struct aa_p return profile->audit; }
+bool policy_view_capable(void); +bool policy_admin_capable(void); bool aa_may_manage_policy(int op);
#endif /* __AA_POLICY_H */ --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -749,51 +749,49 @@ __setup("apparmor=", apparmor_enabled_se /* set global flag turning off the ability to load policy */ static int param_set_aalockpolicy(const char *val, const struct kernel_param *kp) { - if (!capable(CAP_MAC_ADMIN)) + if (!policy_admin_capable()) return -EPERM; - if (aa_g_lock_policy) - return -EACCES; return param_set_bool(val, kp); }
static int param_get_aalockpolicy(char *buffer, const struct kernel_param *kp) { - if (!capable(CAP_MAC_ADMIN)) + if (!policy_view_capable()) return -EPERM; return param_get_bool(buffer, kp); }
static int param_set_aabool(const char *val, const struct kernel_param *kp) { - if (!capable(CAP_MAC_ADMIN)) + if (!policy_admin_capable()) return -EPERM; return param_set_bool(val, kp); }
static int param_get_aabool(char *buffer, const struct kernel_param *kp) { - if (!capable(CAP_MAC_ADMIN)) + if (!policy_view_capable()) return -EPERM; return param_get_bool(buffer, kp); }
static int param_set_aauint(const char *val, const struct kernel_param *kp) { - if (!capable(CAP_MAC_ADMIN)) + if (!policy_admin_capable()) return -EPERM; return param_set_uint(val, kp); }
static int param_get_aauint(char *buffer, const struct kernel_param *kp) { - if (!capable(CAP_MAC_ADMIN)) + if (!policy_view_capable()) return -EPERM; return param_get_uint(buffer, kp); }
static int param_get_audit(char *buffer, struct kernel_param *kp) { - if (!capable(CAP_MAC_ADMIN)) + if (!policy_view_capable()) return -EPERM;
if (!apparmor_enabled) @@ -805,7 +803,7 @@ static int param_get_audit(char *buffer, static int param_set_audit(const char *val, struct kernel_param *kp) { int i; - if (!capable(CAP_MAC_ADMIN)) + if (!policy_admin_capable()) return -EPERM;
if (!apparmor_enabled) @@ -826,7 +824,7 @@ static int param_set_audit(const char *v
static int param_get_mode(char *buffer, struct kernel_param *kp) { - if (!capable(CAP_MAC_ADMIN)) + if (!policy_admin_capable()) return -EPERM;
if (!apparmor_enabled) @@ -838,7 +836,7 @@ static int param_get_mode(char *buffer, static int param_set_mode(const char *val, struct kernel_param *kp) { int i; - if (!capable(CAP_MAC_ADMIN)) + if (!policy_admin_capable()) return -EPERM;
if (!apparmor_enabled) --- a/security/apparmor/policy.c +++ b/security/apparmor/policy.c @@ -916,6 +916,22 @@ static int audit_policy(int op, gfp_t gf &sa, NULL); }
+bool policy_view_capable(void) +{ + struct user_namespace *user_ns = current_user_ns(); + bool response = false; + + if (ns_capable(user_ns, CAP_MAC_ADMIN)) + response = true; + + return response; +} + +bool policy_admin_capable(void) +{ + return policy_view_capable() && !aa_g_lock_policy; +} + /** * aa_may_manage_policy - can the current task manage policy * @op: the policy manipulation operation being done @@ -930,7 +946,7 @@ bool aa_may_manage_policy(int op) return 0; }
- if (!capable(CAP_MAC_ADMIN)) { + if (!policy_admin_capable()) { audit_policy(op, GFP_KERNEL, NULL, "not policy admin", -EACCES); return 0; }