[PATCH 6.4 523/800] apparmor: fix: kzalloc perms tables for shared dfas

Greg Kroah-Hartman
2023-07-16T20:17:23Z

From: John Johansen <john.johansen@canonical.com>

commit ec6851ae0ab4587e610e260ddda75f92f3389f91 upstream.

Currently the permstables of the shared dfas are not shared, and need
to be allocated and copied. In the future this should be addressed
with a larger rework on dfa and pdb ref counts and structure sharing.

BugLink: http://bugs.launchpad.net/bugs/2017903
Fixes: 217af7e2f4de ("apparmor: refactor profile rules and attachments")
Cc: stable@vger.kernel.org
Signed-off-by: John Johansen <john.johansen@canonical.com>
Reviewed-by: Jon Tourville <jontourville@me.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
security/apparmor/policy.c | 13 +++++++++++++
security/apparmor/policy_unpack.c | 26 ++++++++++++++++++++++----
2 files changed, 35 insertions(+), 4 deletions(-)

--- a/security/apparmor/policy.c
+++ b/security/apparmor/policy.c
@@ -591,7 +591,15 @@ struct aa_profile *aa_alloc_null(struct
profile->label.flags |= FLAG_NULL;
rules = list_first_entry(&profile->rules, typeof(*rules), list);
rules->file.dfa = aa_get_dfa(nulldfa);
+ rules->file.perms = kcalloc(2, sizeof(struct aa_perms), GFP_KERNEL);
+ if (!rules->file.perms)
+ goto fail;
+ rules->file.size = 2;
rules->policy.dfa = aa_get_dfa(nulldfa);
+ rules->policy.perms = kcalloc(2, sizeof(struct aa_perms), GFP_KERNEL);
+ if (!rules->policy.perms)
+ goto fail;
+ rules->policy.size = 2;

if (parent) {
profile->path_flags = parent->path_flags;
@@ -602,6 +610,11 @@ struct aa_profile *aa_alloc_null(struct
}

return profile;
+
+fail:
+ aa_free_profile(profile);
+
+ return NULL;
}

/**
--- a/security/apparmor/policy_unpack.c
+++ b/security/apparmor/policy_unpack.c
@@ -988,9 +988,14 @@ static struct aa_profile *unpack_profile
info = "failed to remap policydb permission table";
goto fail;
}
- } else
+ } else {
rules->policy.dfa = aa_get_dfa(nulldfa);
-
+ rules->policy.perms = kcalloc(2, sizeof(struct aa_perms),
+ GFP_KERNEL);
+ if (!rules->policy.perms)
+ goto fail;
+ rules->policy.size = 2;
+ }
/* get file rules */
error = unpack_pdb(e, &rules->file, false, true, &info);
if (error) {
@@ -1005,9 +1010,22 @@ static struct aa_profile *unpack_profile
rules->policy.start[AA_CLASS_FILE]) {
rules->file.dfa = aa_get_dfa(rules->policy.dfa);
rules->file.start[AA_CLASS_FILE] = rules->policy.start[AA_CLASS_FILE];
- } else
+ rules->file.perms = kcalloc(rules->policy.size,
+ sizeof(struct aa_perms),
+ GFP_KERNEL);
+ if (!rules->file.perms)
+ goto fail;
+ memcpy(rules->file.perms, rules->policy.perms,
+ rules->policy.size * sizeof(struct aa_perms));
+ rules->file.size = rules->policy.size;
+ } else {
rules->file.dfa = aa_get_dfa(nulldfa);
-
+ rules->file.perms = kcalloc(2, sizeof(struct aa_perms),
+ GFP_KERNEL);
+ if (!rules->file.perms)
+ goto fail;
+ rules->file.size = 2;
+ }
error = -EPROTO;
if (aa_unpack_nameX(e, AA_STRUCT, "data")) {
info = "out of memory";