From: John Johansen <john.johansen@xxxxxxxxxxxxx> 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@xxxxxxxxxxxxxxx Signed-off-by: John Johansen <john.johansen@xxxxxxxxxxxxx> Reviewed-by: Jon Tourville <jontourville@xxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- 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";