diff options
Diffstat (limited to 'security')
-rw-r--r-- | security/apparmor/include/context.h | 6 | ||||
-rw-r--r-- | security/apparmor/include/policy.h | 4 | ||||
-rw-r--r-- | security/apparmor/lsm.c | 8 | ||||
-rw-r--r-- | security/apparmor/policy.c | 25 |
4 files changed, 35 insertions, 8 deletions
diff --git a/security/apparmor/include/context.h b/security/apparmor/include/context.h index a0acc2390fae..d378bff47ccd 100644 --- a/security/apparmor/include/context.h +++ b/security/apparmor/include/context.h @@ -20,6 +20,7 @@ #include <linux/sched.h> #include "policy.h" +#include "policy_ns.h" #define cred_cxt(X) (X)->security #define current_cxt() cred_cxt(current_cred()) @@ -162,6 +163,11 @@ static inline struct aa_profile *aa_current_profile(void) return cxt->profile; } +static inline struct aa_ns *aa_get_current_ns(void) +{ + return aa_get_ns(__aa_current_profile()->ns); +} + /** * aa_clear_task_cxt_trans - clear transition tracking info from the cxt * @cxt: task context to clear (NOT NULL) diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h index 8fcfb3c78d21..b0b65c525bcc 100644 --- a/security/apparmor/include/policy.h +++ b/security/apparmor/include/policy.h @@ -33,6 +33,8 @@ struct aa_ns; +extern int unprivileged_userns_apparmor_policy; + extern const char *const aa_profile_mode_names[]; #define APPARMOR_MODE_NAMES_MAX_INDEX 4 @@ -297,7 +299,7 @@ static inline int AUDIT_MODE(struct aa_profile *profile) return profile->audit; } -bool policy_view_capable(void); +bool policy_view_capable(struct aa_ns *ns); bool policy_admin_capable(void); bool aa_may_manage_policy(int op); diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index f852cd626f2e..f83ba33651a0 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -745,7 +745,7 @@ static int param_set_aalockpolicy(const char *val, const struct kernel_param *kp static int param_get_aalockpolicy(char *buffer, const struct kernel_param *kp) { - if (!policy_view_capable()) + if (!policy_view_capable(NULL)) return -EPERM; return param_get_bool(buffer, kp); } @@ -759,7 +759,7 @@ static int param_set_aabool(const char *val, const struct kernel_param *kp) static int param_get_aabool(char *buffer, const struct kernel_param *kp) { - if (!policy_view_capable()) + if (!policy_view_capable(NULL)) return -EPERM; return param_get_bool(buffer, kp); } @@ -773,14 +773,14 @@ static int param_set_aauint(const char *val, const struct kernel_param *kp) static int param_get_aauint(char *buffer, const struct kernel_param *kp) { - if (!policy_view_capable()) + if (!policy_view_capable(NULL)) return -EPERM; return param_get_uint(buffer, kp); } static int param_get_audit(char *buffer, struct kernel_param *kp) { - if (!policy_view_capable()) + if (!policy_view_capable(NULL)) return -EPERM; if (!apparmor_enabled) diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c index 0125de6061fd..f092c04c7c4e 100644 --- a/security/apparmor/policy.c +++ b/security/apparmor/policy.c @@ -76,6 +76,7 @@ #include <linux/slab.h> #include <linux/spinlock.h> #include <linux/string.h> +#include <linux/user_namespace.h> #include "include/apparmor.h" #include "include/capability.h" @@ -89,6 +90,7 @@ #include "include/policy_unpack.h" #include "include/resource.h" +int unprivileged_userns_apparmor_policy = 1; const char *const aa_profile_mode_names[] = { "enforce", @@ -607,20 +609,37 @@ static int audit_policy(struct aa_profile *profile, int op, gfp_t gfp, &sa, NULL); } -bool policy_view_capable(void) +/** + * policy_view_capable - check if viewing policy in at @ns is allowed + * ns: namespace being viewed by current task (may be NULL) + * Returns: true if viewing policy is allowed + * + * If @ns is NULL then the namespace being viewed is assumed to be the + * tasks current namespace. + */ +bool policy_view_capable(struct aa_ns *ns) { struct user_namespace *user_ns = current_user_ns(); + struct aa_ns *view_ns = aa_get_current_ns(); + bool root_in_user_ns = uid_eq(current_euid(), make_kuid(user_ns, 0)) || + in_egroup_p(make_kgid(user_ns, 0)); bool response = false; + if (!ns) + ns = view_ns; - if (ns_capable(user_ns, CAP_MAC_ADMIN)) + if (root_in_user_ns && aa_ns_visible(view_ns, ns, true) && + (user_ns == &init_user_ns || + (unprivileged_userns_apparmor_policy != 0 && + user_ns->level == view_ns->level))) response = true; + aa_put_ns(view_ns); return response; } bool policy_admin_capable(void) { - return policy_view_capable() && !aa_g_lock_policy; + return policy_view_capable(NULL) && !aa_g_lock_policy; } /** |