diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2021-11-11 14:47:32 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2021-11-11 14:47:32 -0800 |
commit | 5593a733f968521444df84902901902233c17d8f (patch) | |
tree | 2a1cd30f1e3872ea940b97029971a746fa58062b /security/apparmor/policy.c | |
parent | dbf49896187fd58c577fa1574a338e4f3672b4b2 (diff) | |
parent | 582122f1d73af28407234321c94711e09aa3fd04 (diff) |
Merge tag 'apparmor-pr-2021-11-10' of git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor
Pull apparmor updates from John Johansen:
"Features
- use per file locks for transactional queries
- update policy management capability checks to work with LSM stacking
Bug Fixes:
- check/put label on apparmor_sk_clone_security()
- fix error check on update of label hname
- fix introspection of of task mode for unconfined tasks
Cleanups:
- avoid -Wempty-body warning
- remove duplicated 'Returns:' comments
- fix doc warning
- remove unneeded one-line hook wrappers
- use struct_size() helper in kzalloc()
- fix zero-length compiler warning in AA_BUG()
- file.h: delete duplicated word
- delete repeated words in comments
- remove repeated declaration"
* tag 'apparmor-pr-2021-11-10' of git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor:
apparmor: remove duplicated 'Returns:' comments
apparmor: remove unneeded one-line hook wrappers
apparmor: Use struct_size() helper in kzalloc()
apparmor: fix zero-length compiler warning in AA_BUG()
apparmor: use per file locks for transactional queries
apparmor: fix doc warning
apparmor: Remove the repeated declaration
apparmor: avoid -Wempty-body warning
apparmor: Fix internal policy capable check for policy management
apparmor: fix error check
security: apparmor: delete repeated words in comments
security: apparmor: file.h: delete duplicated word
apparmor: switch to apparmor to internal capable check for policy management
apparmor: update policy capable checks to use a label
apparmor: fix introspection of of task mode for unconfined tasks
apparmor: check/put label on apparmor_sk_clone_security()
Diffstat (limited to 'security/apparmor/policy.c')
-rw-r--r-- | security/apparmor/policy.c | 62 |
1 files changed, 51 insertions, 11 deletions
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c index 4c010c9a6af1..b0cbc4906cb3 100644 --- a/security/apparmor/policy.c +++ b/security/apparmor/policy.c @@ -260,8 +260,7 @@ struct aa_profile *aa_alloc_profile(const char *hname, struct aa_proxy *proxy, struct aa_profile *profile; /* freed by free_profile - usually through aa_put_profile */ - profile = kzalloc(sizeof(*profile) + sizeof(struct aa_profile *) * 2, - gfp); + profile = kzalloc(struct_size(profile, label.vec, 2), gfp); if (!profile) return NULL; @@ -632,18 +631,35 @@ static int audit_policy(struct aa_label *label, const char *op, return error; } +/* don't call out to other LSMs in the stack for apparmor policy admin + * permissions + */ +static int policy_ns_capable(struct aa_label *label, + struct user_namespace *userns, int cap) +{ + int err; + + /* check for MAC_ADMIN cap in cred */ + err = cap_capable(current_cred(), userns, cap, CAP_OPT_NONE); + if (!err) + err = aa_capable(label, cap, CAP_OPT_NONE); + + return err; +} + /** - * policy_view_capable - check if viewing policy in at @ns is allowed - * ns: namespace being viewed by current task (may be NULL) + * aa_policy_view_capable - check if viewing policy in at @ns is allowed + * label: label that is trying to view policy in ns + * ns: namespace being viewed by @label (may be NULL if @label's ns) * 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) +bool aa_policy_view_capable(struct aa_label *label, struct aa_ns *ns) { struct user_namespace *user_ns = current_user_ns(); - struct aa_ns *view_ns = aa_get_current_ns(); + struct aa_ns *view_ns = labels_view(label); 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; @@ -655,20 +671,44 @@ bool policy_view_capable(struct aa_ns *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(struct aa_ns *ns) +bool aa_policy_admin_capable(struct aa_label *label, struct aa_ns *ns) { struct user_namespace *user_ns = current_user_ns(); - bool capable = ns_capable(user_ns, CAP_MAC_ADMIN); + bool capable = policy_ns_capable(label, user_ns, CAP_MAC_ADMIN) == 0; AA_DEBUG("cap_mac_admin? %d\n", capable); AA_DEBUG("policy locked? %d\n", aa_g_lock_policy); - return policy_view_capable(ns) && capable && !aa_g_lock_policy; + return aa_policy_view_capable(label, ns) && capable && + !aa_g_lock_policy; +} + +bool aa_current_policy_view_capable(struct aa_ns *ns) +{ + struct aa_label *label; + bool res; + + label = __begin_current_label_crit_section(); + res = aa_policy_view_capable(label, ns); + __end_current_label_crit_section(label); + + return res; +} + +bool aa_current_policy_admin_capable(struct aa_ns *ns) +{ + struct aa_label *label; + bool res; + + label = __begin_current_label_crit_section(); + res = aa_policy_admin_capable(label, ns); + __end_current_label_crit_section(label); + + return res; } /** @@ -694,7 +734,7 @@ int aa_may_manage_policy(struct aa_label *label, struct aa_ns *ns, u32 mask) return audit_policy(label, op, NULL, NULL, "policy_locked", -EACCES); - if (!policy_admin_capable(ns)) + if (!aa_policy_admin_capable(label, ns)) return audit_policy(label, op, NULL, NULL, "not policy admin", -EACCES); |