summaryrefslogtreecommitdiff
path: root/security/apparmor/policy.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/apparmor/policy.c')
-rw-r--r--security/apparmor/policy.c34
1 files changed, 33 insertions, 1 deletions
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
index 9a4e29cdd8c0..29f1cfd75090 100644
--- a/security/apparmor/policy.c
+++ b/security/apparmor/policy.c
@@ -894,17 +894,44 @@ bool aa_current_policy_admin_capable(struct aa_ns *ns)
return res;
}
+static bool is_subset_of_obj_privilege(const struct cred *cred,
+ struct aa_label *label,
+ const struct cred *ocred)
+{
+ if (cred == ocred)
+ return true;
+
+ if (!aa_label_is_subset(label, cred_label(ocred)))
+ return false;
+ /* don't allow crossing userns for now */
+ if (cred->user_ns != ocred->user_ns)
+ return false;
+ if (!cap_issubset(cred->cap_inheritable, ocred->cap_inheritable))
+ return false;
+ if (!cap_issubset(cred->cap_permitted, ocred->cap_permitted))
+ return false;
+ if (!cap_issubset(cred->cap_effective, ocred->cap_effective))
+ return false;
+ if (!cap_issubset(cred->cap_bset, ocred->cap_bset))
+ return false;
+ if (!cap_issubset(cred->cap_ambient, ocred->cap_ambient))
+ return false;
+ return true;
+}
+
+
/**
* aa_may_manage_policy - can the current task manage policy
* @subj_cred: subjects cred
* @label: label to check if it can manage policy
* @ns: namespace being managed by @label (may be NULL if @label's ns)
+ * @ocred: object cred if request is coming from an open object
* @mask: contains the policy manipulation operation being done
*
* Returns: 0 if the task is allowed to manipulate policy else error
*/
int aa_may_manage_policy(const struct cred *subj_cred, struct aa_label *label,
- struct aa_ns *ns, u32 mask)
+ struct aa_ns *ns, const struct cred *ocred, u32 mask)
{
const char *op;
@@ -920,6 +947,11 @@ int aa_may_manage_policy(const struct cred *subj_cred, struct aa_label *label,
return audit_policy(label, op, NULL, NULL, "policy_locked",
-EACCES);
+ if (ocred && !is_subset_of_obj_privilege(subj_cred, label, ocred))
+ return audit_policy(label, op, NULL, NULL,
+ "not privileged for target profile",
+ -EACCES);
+
if (!aa_policy_admin_capable(subj_cred, label, ns))
return audit_policy(label, op, NULL, NULL, "not policy admin",
-EACCES);