Re: linux-next: manual merge of the kunit-next tree with the apparmor tree

From: Stephen Rothwell
Date: Tue Dec 13 2022 - 19:00:17 EST


Hi all,

On Thu, 8 Dec 2022 13:53:27 +1100 Stephen Rothwell <sfr@xxxxxxxxxxxxxxxx> wrote:
>
> Today's linux-next merge of the kunit-next tree got a conflict in:
>
> security/apparmor/policy_unpack.c
>
> between commits:
>
> 371e50a0b19f ("apparmor: make unpack_array return a trianary value")
> 73c7e91c8bc9 ("apparmor: Remove unnecessary size check when unpacking trans_table")
> 217af7e2f4de ("apparmor: refactor profile rules and attachments")
> (and probably others)
>
> from the apparmor tree and commit:
>
> 2c92044683f5 ("apparmor: test: make static symbols visible during kunit testing")
>
> from the kunit-next tree.
>
> This is somewhat of a mess ... pity there is not a shared branch (or
> better routing if the patches).
>
> I fixed it up (hopefully - see below) and can carry the fix as
> necessary. This is now fixed as far as linux-next is concerned, but any
> non trivial conflicts should be mentioned to your upstream maintainer
> when your tree is submitted for merging. You may also want to consider
> cooperating with the maintainer of the conflicting tree to minimise any
> particularly complex conflicts.
>
> I also had to add this patch:
>
> From: Stephen Rothwell <sfr@xxxxxxxxxxxxxxxx>
> Date: Thu, 8 Dec 2022 13:47:43 +1100
> Subject: [PATCH] fixup for "apparmor: make unpack_array return a trianary value"
>
> Signed-off-by: Stephen Rothwell <sfr@xxxxxxxxxxxxxxxx>
> ---
> security/apparmor/include/policy_unpack.h | 8 +++++++-
> security/apparmor/policy_unpack.c | 5 -----
> 2 files changed, 7 insertions(+), 6 deletions(-)
>
> diff --git a/security/apparmor/include/policy_unpack.h b/security/apparmor/include/policy_unpack.h
> index 940da8a33e0c..8fdf8f703bd0 100644
> --- a/security/apparmor/include/policy_unpack.h
> +++ b/security/apparmor/include/policy_unpack.h
> @@ -172,7 +172,13 @@ bool aa_unpack_X(struct aa_ext *e, enum aa_code code);
> bool aa_unpack_nameX(struct aa_ext *e, enum aa_code code, const char *name);
> bool aa_unpack_u32(struct aa_ext *e, u32 *data, const char *name);
> bool aa_unpack_u64(struct aa_ext *e, u64 *data, const char *name);
> -size_t aa_unpack_array(struct aa_ext *e, const char *name);
> +
> +#define tri int
> +#define TRI_TRUE 1
> +#define TRI_NONE 0
> +#define TRI_FALSE -1
> +
> +tri aa_unpack_array(struct aa_ext *e, const char *name, u16 *size);
> size_t aa_unpack_blob(struct aa_ext *e, char **blob, const char *name);
> int aa_unpack_str(struct aa_ext *e, const char **string, const char *name);
> int aa_unpack_strdup(struct aa_ext *e, char **string, const char *name);
> diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
> index 6513545dad5e..173d832fc4ee 100644
> --- a/security/apparmor/policy_unpack.c
> +++ b/security/apparmor/policy_unpack.c
> @@ -30,11 +30,6 @@
> #include "include/policy_unpack.h"
> #include "include/policy_compat.h"
>
> -#define tri int
> -#define TRI_TRUE 1
> -#define TRI_NONE 0
> -#define TRI_FALSE -1
> -
> /* audit callback for unpack fields */
> static void audit_cb(struct audit_buffer *ab, void *va)
> {
> --
> 2.35.1
>
> --
> Cheers,
> Stephen Rothwell
>
> diff --cc security/apparmor/policy_unpack.c
> index 1bf8cfb8700a,12e535fdfa8b..000000000000
> --- a/security/apparmor/policy_unpack.c
> +++ b/security/apparmor/policy_unpack.c
> @@@ -14,9 -14,10 +14,10 @@@
> */
>
> #include <asm/unaligned.h>
> + #include <kunit/visibility.h>
> #include <linux/ctype.h>
> #include <linux/errno.h>
> -#include <linux/zlib.h>
> +#include <linux/zstd.h>
>
> #include "include/apparmor.h"
> #include "include/audit.h"
> @@@ -27,50 -27,16 +28,12 @@@
> #include "include/path.h"
> #include "include/policy.h"
> #include "include/policy_unpack.h"
> +#include "include/policy_compat.h"
>
> -
> - /*
> - * The AppArmor interface treats data as a type byte followed by the
> - * actual data. The interface has the notion of a named entry
> - * which has a name (AA_NAME typecode followed by name string) followed by
> - * the entries typecode and data. Named types allow for optional
> - * elements and extensions to be added and tested for without breaking
> - * backwards compatibility.
> - */
> -
> - enum aa_code {
> - AA_U8,
> - AA_U16,
> - AA_U32,
> - AA_U64,
> - AA_NAME, /* same as string except it is items name */
> - AA_STRING,
> - AA_BLOB,
> - AA_STRUCT,
> - AA_STRUCTEND,
> - AA_LIST,
> - AA_LISTEND,
> - AA_ARRAY,
> - AA_ARRAYEND,
> - };
> -
> - /*
> - * aa_ext is the read of the buffer containing the serialized profile. The
> - * data is copied into a kernel buffer in apparmorfs and then handed off to
> - * the unpack routines.
> - */
> - struct aa_ext {
> - void *start;
> - void *end;
> - void *pos; /* pointer to current position in the buffer */
> - u32 version;
> - };
> -#define K_ABI_MASK 0x3ff
> -#define FORCE_COMPLAIN_FLAG 0x800
> -#define VERSION_LT(X, Y) (((X) & K_ABI_MASK) < ((Y) & K_ABI_MASK))
> -#define VERSION_GT(X, Y) (((X) & K_ABI_MASK) > ((Y) & K_ABI_MASK))
> --
> -#define v5 5 /* base version */
> -#define v6 6 /* per entry policydb mediation check */
> -#define v7 7
> -#define v8 8 /* full network masking */
> +#define tri int
> +#define TRI_TRUE 1
> +#define TRI_NONE 0
> +#define TRI_FALSE -1
>
> /* audit callback for unpack fields */
> static void audit_cb(struct audit_buffer *ab, void *va)
> @@@ -348,26 -319,28 +316,28 @@@ fail
> e->pos = pos;
> return false;
> }
> + EXPORT_SYMBOL_IF_KUNIT(aa_unpack_u64);
>
> - static tri unpack_array(struct aa_ext *e, const char *name, u16 *size)
> -VISIBLE_IF_KUNIT size_t aa_unpack_array(struct aa_ext *e, const char *name)
> ++VISIBLE_IF_KUNIT tri aa_unpack_array(struct aa_ext *e, const char *name, u16 *size)
> {
> void *pos = e->pos;
>
> - if (unpack_nameX(e, AA_ARRAY, name)) {
> - if (!inbounds(e, sizeof(u16)))
> + if (aa_unpack_nameX(e, AA_ARRAY, name)) {
> - int size;
> + if (!aa_inbounds(e, sizeof(u16)))
> goto fail;
> - size = (int)le16_to_cpu(get_unaligned((__le16 *) e->pos));
> + *size = le16_to_cpu(get_unaligned((__le16 *) e->pos));
> e->pos += sizeof(u16);
> - return size;
> + return TRI_TRUE;
> }
>
> + return TRI_NONE;
> fail:
> e->pos = pos;
> - return 0;
> + return TRI_FALSE;
> }
> + EXPORT_SYMBOL_IF_KUNIT(aa_unpack_array);
>
> - static size_t unpack_blob(struct aa_ext *e, char **blob, const char *name)
> + VISIBLE_IF_KUNIT size_t aa_unpack_blob(struct aa_ext *e, char **blob, const char *name)
> {
> void *pos = e->pos;
>
> @@@ -470,36 -447,32 +443,36 @@@ static struct aa_dfa *unpack_dfa(struc
> /**
> * unpack_trans_table - unpack a profile transition table
> * @e: serialized data extent information (NOT NULL)
> - * @profile: profile to add the accept table to (NOT NULL)
> + * @table: str table to unpack to (NOT NULL)
> *
> - * Returns: true if table successfully unpacked
> + * Returns: true if table successfully unpacked or not present
> */
> -static bool unpack_trans_table(struct aa_ext *e, struct aa_profile *profile)
> +static bool unpack_trans_table(struct aa_ext *e, struct aa_str_table *strs)
> {
> void *saved_pos = e->pos;
> + char **table = NULL;
>
> /* exec table is optional */
> - if (unpack_nameX(e, AA_STRUCT, "xtable")) {
> + if (aa_unpack_nameX(e, AA_STRUCT, "xtable")) {
> - int i, size;
> -
> - size = aa_unpack_array(e, NULL);
> - /* currently 4 exec bits and entries 0-3 are reserved iupcx */
> - if (size > 16 - 4)
> + u16 size;
> + int i;
> +
> - if (unpack_array(e, NULL, &size) != TRI_TRUE)
> ++ if (aa_unpack_array(e, NULL, &size) != TRI_TRUE)
> + /*
> + * Note: index into trans table array is a max
> + * of 2^24, but unpack array can only unpack
> + * an array of 2^16 in size atm so no need
> + * for size check here
> + */
> goto fail;
> - profile->file.trans.table = kcalloc(size, sizeof(char *),
> - GFP_KERNEL);
> - if (!profile->file.trans.table)
> + table = kcalloc(size, sizeof(char *), GFP_KERNEL);
> + if (!table)
> goto fail;
>
> - profile->file.trans.size = size;
> for (i = 0; i < size; i++) {
> char *str;
> - int c, j, pos, size2 = unpack_strdup(e, &str, NULL);
> - /* unpack_strdup verifies that the last character is
> + int c, j, pos, size2 = aa_unpack_strdup(e, &str, NULL);
> + /* aa_unpack_strdup verifies that the last character is
> * null termination byte.
> */
> if (!size2)
> @@@ -534,13 -507,10 +507,13 @@@
> /* fail - all other cases with embedded \0 */
> goto fail;
> }
> - if (!unpack_nameX(e, AA_ARRAYEND, NULL))
> + if (!aa_unpack_nameX(e, AA_ARRAYEND, NULL))
> goto fail;
> - if (!unpack_nameX(e, AA_STRUCTEND, NULL))
> + if (!aa_unpack_nameX(e, AA_STRUCTEND, NULL))
> goto fail;
> +
> + strs->table = table;
> + strs->size = size;
> }
> return true;
>
> @@@ -554,23 -524,21 +527,23 @@@ static bool unpack_xattrs(struct aa_ex
> {
> void *pos = e->pos;
>
> - if (unpack_nameX(e, AA_STRUCT, "xattrs")) {
> + if (aa_unpack_nameX(e, AA_STRUCT, "xattrs")) {
> - int i, size;
> + u16 size;
> + int i;
>
> - if (unpack_array(e, NULL, &size) != TRI_TRUE)
> - size = aa_unpack_array(e, NULL);
> - profile->xattr_count = size;
> - profile->xattrs = kcalloc(size, sizeof(char *), GFP_KERNEL);
> - if (!profile->xattrs)
> ++ if (aa_unpack_array(e, NULL, &size) != TRI_TRUE)
> + goto fail;
> + profile->attach.xattr_count = size;
> + profile->attach.xattrs = kcalloc(size, sizeof(char *), GFP_KERNEL);
> + if (!profile->attach.xattrs)
> goto fail;
> for (i = 0; i < size; i++) {
> - if (!unpack_strdup(e, &profile->attach.xattrs[i], NULL))
> - if (!aa_unpack_strdup(e, &profile->xattrs[i], NULL))
> ++ if (!aa_unpack_strdup(e, &profile->attach.xattrs[i], NULL))
> goto fail;
> }
> - if (!unpack_nameX(e, AA_ARRAYEND, NULL))
> + if (!aa_unpack_nameX(e, AA_ARRAYEND, NULL))
> goto fail;
> - if (!unpack_nameX(e, AA_STRUCTEND, NULL))
> + if (!aa_unpack_nameX(e, AA_STRUCTEND, NULL))
> goto fail;
> }
>
> @@@ -581,34 -549,32 +554,34 @@@ fail
> return false;
> }
>
> -static bool unpack_secmark(struct aa_ext *e, struct aa_profile *profile)
> +static bool unpack_secmark(struct aa_ext *e, struct aa_ruleset *rules)
> {
> void *pos = e->pos;
> - int i, size;
> + u16 size;
> + int i;
>
> - if (unpack_nameX(e, AA_STRUCT, "secmark")) {
> - if (unpack_array(e, NULL, &size) != TRI_TRUE)
> + if (aa_unpack_nameX(e, AA_STRUCT, "secmark")) {
> - size = aa_unpack_array(e, NULL);
> ++ if (aa_unpack_array(e, NULL, &size) != TRI_TRUE)
> + goto fail;
>
> - profile->secmark = kcalloc(size, sizeof(struct aa_secmark),
> + rules->secmark = kcalloc(size, sizeof(struct aa_secmark),
> GFP_KERNEL);
> - if (!profile->secmark)
> + if (!rules->secmark)
> goto fail;
>
> - profile->secmark_count = size;
> + rules->secmark_count = size;
>
> for (i = 0; i < size; i++) {
> - if (!unpack_u8(e, &profile->secmark[i].audit, NULL))
> + if (!unpack_u8(e, &rules->secmark[i].audit, NULL))
> goto fail;
> - if (!unpack_u8(e, &profile->secmark[i].deny, NULL))
> + if (!unpack_u8(e, &rules->secmark[i].deny, NULL))
> goto fail;
> - if (!unpack_strdup(e, &rules->secmark[i].label, NULL))
> - if (!aa_unpack_strdup(e, &profile->secmark[i].label, NULL))
> ++ if (!aa_unpack_strdup(e, &rules->secmark[i].label, NULL))
> goto fail;
> }
> - if (!unpack_nameX(e, AA_ARRAYEND, NULL))
> + if (!aa_unpack_nameX(e, AA_ARRAYEND, NULL))
> goto fail;
> - if (!unpack_nameX(e, AA_STRUCTEND, NULL))
> + if (!aa_unpack_nameX(e, AA_STRUCTEND, NULL))
> goto fail;
> }
>
> @@@ -632,27 -598,26 +605,27 @@@ static bool unpack_rlimits(struct aa_ex
> void *pos = e->pos;
>
> /* rlimits are optional */
> - if (unpack_nameX(e, AA_STRUCT, "rlimits")) {
> + if (aa_unpack_nameX(e, AA_STRUCT, "rlimits")) {
> - int i, size;
> + u16 size;
> + int i;
> u32 tmp = 0;
> - if (!unpack_u32(e, &tmp, NULL))
> + if (!aa_unpack_u32(e, &tmp, NULL))
> goto fail;
> - profile->rlimits.mask = tmp;
> + rules->rlimits.mask = tmp;
>
> - if (unpack_array(e, NULL, &size) != TRI_TRUE ||
> - size = aa_unpack_array(e, NULL);
> - if (size > RLIM_NLIMITS)
> ++ if (aa_unpack_array(e, NULL, &size) != TRI_TRUE ||
> + size > RLIM_NLIMITS)
> goto fail;
> for (i = 0; i < size; i++) {
> u64 tmp2 = 0;
> int a = aa_map_resource(i);
> - if (!unpack_u64(e, &tmp2, NULL))
> + if (!aa_unpack_u64(e, &tmp2, NULL))
> goto fail;
> - profile->rlimits.limits[a].rlim_max = tmp2;
> + rules->rlimits.limits[a].rlim_max = tmp2;
> }
> - if (!unpack_nameX(e, AA_ARRAYEND, NULL))
> + if (!aa_unpack_nameX(e, AA_ARRAYEND, NULL))
> goto fail;
> - if (!unpack_nameX(e, AA_STRUCTEND, NULL))
> + if (!aa_unpack_nameX(e, AA_STRUCTEND, NULL))
> goto fail;
> }
> return true;
> @@@ -662,144 -627,6 +635,144 @@@ fail
> return false;
> }
>
> +static bool unpack_perm(struct aa_ext *e, u32 version, struct aa_perms *perm)
> +{
> + bool res;
> +
> + if (version != 1)
> + return false;
> +
> - res = unpack_u32(e, &perm->allow, NULL);
> - res = res && unpack_u32(e, &perm->allow, NULL);
> - res = res && unpack_u32(e, &perm->deny, NULL);
> - res = res && unpack_u32(e, &perm->subtree, NULL);
> - res = res && unpack_u32(e, &perm->cond, NULL);
> - res = res && unpack_u32(e, &perm->kill, NULL);
> - res = res && unpack_u32(e, &perm->complain, NULL);
> - res = res && unpack_u32(e, &perm->prompt, NULL);
> - res = res && unpack_u32(e, &perm->audit, NULL);
> - res = res && unpack_u32(e, &perm->quiet, NULL);
> - res = res && unpack_u32(e, &perm->hide, NULL);
> - res = res && unpack_u32(e, &perm->xindex, NULL);
> - res = res && unpack_u32(e, &perm->tag, NULL);
> - res = res && unpack_u32(e, &perm->label, NULL);
> ++ res = aa_unpack_u32(e, &perm->allow, NULL);
> ++ res = res && aa_unpack_u32(e, &perm->allow, NULL);
> ++ res = res && aa_unpack_u32(e, &perm->deny, NULL);
> ++ res = res && aa_unpack_u32(e, &perm->subtree, NULL);
> ++ res = res && aa_unpack_u32(e, &perm->cond, NULL);
> ++ res = res && aa_unpack_u32(e, &perm->kill, NULL);
> ++ res = res && aa_unpack_u32(e, &perm->complain, NULL);
> ++ res = res && aa_unpack_u32(e, &perm->prompt, NULL);
> ++ res = res && aa_unpack_u32(e, &perm->audit, NULL);
> ++ res = res && aa_unpack_u32(e, &perm->quiet, NULL);
> ++ res = res && aa_unpack_u32(e, &perm->hide, NULL);
> ++ res = res && aa_unpack_u32(e, &perm->xindex, NULL);
> ++ res = res && aa_unpack_u32(e, &perm->tag, NULL);
> ++ res = res && aa_unpack_u32(e, &perm->label, NULL);
> +
> + return res;
> +}
> +
> +static ssize_t unpack_perms_table(struct aa_ext *e, struct aa_perms **perms)
> +{
> + void *pos = e->pos;
> + u16 size = 0;
> +
> + AA_BUG(!perms);
> + /*
> + * policy perms are optional, in which case perms are embedded
> + * in the dfa accept table
> + */
> - if (unpack_nameX(e, AA_STRUCT, "perms")) {
> ++ if (aa_unpack_nameX(e, AA_STRUCT, "perms")) {
> + int i;
> + u32 version;
> +
> - if (!unpack_u32(e, &version, "version"))
> ++ if (!aa_unpack_u32(e, &version, "version"))
> + goto fail_reset;
> - if (unpack_array(e, NULL, &size) != TRI_TRUE)
> ++ if (aa_unpack_array(e, NULL, &size) != TRI_TRUE)
> + goto fail_reset;
> + *perms = kcalloc(size, sizeof(struct aa_perms), GFP_KERNEL);
> + if (!*perms)
> + goto fail_reset;
> + for (i = 0; i < size; i++) {
> + if (!unpack_perm(e, version, &(*perms)[i]))
> + goto fail;
> + }
> - if (!unpack_nameX(e, AA_ARRAYEND, NULL))
> ++ if (!aa_unpack_nameX(e, AA_ARRAYEND, NULL))
> + goto fail;
> - if (!unpack_nameX(e, AA_STRUCTEND, NULL))
> ++ if (!aa_unpack_nameX(e, AA_STRUCTEND, NULL))
> + goto fail;
> + } else
> + *perms = NULL;
> +
> + return size;
> +
> +fail:
> + kfree(*perms);
> +fail_reset:
> + e->pos = pos;
> + return -EPROTO;
> +}
> +
> +static int unpack_pdb(struct aa_ext *e, struct aa_policydb *policy,
> + bool required_dfa, bool required_trans,
> + const char **info)
> +{
> + void *pos = e->pos;
> + int i, flags, error = -EPROTO;
> + ssize_t size;
> +
> + size = unpack_perms_table(e, &policy->perms);
> + if (size < 0) {
> + error = size;
> + policy->perms = NULL;
> + *info = "failed to unpack - perms";
> + goto fail;
> + }
> + policy->size = size;
> +
> + if (policy->perms) {
> + /* perms table present accept is index */
> + flags = TO_ACCEPT1_FLAG(YYTD_DATA32);
> + } else {
> + /* packed perms in accept1 and accept2 */
> + flags = TO_ACCEPT1_FLAG(YYTD_DATA32) |
> + TO_ACCEPT2_FLAG(YYTD_DATA32);
> + }
> +
> + policy->dfa = unpack_dfa(e, flags);
> + if (IS_ERR(policy->dfa)) {
> + error = PTR_ERR(policy->dfa);
> + policy->dfa = NULL;
> + *info = "failed to unpack - dfa";
> + goto fail;
> + } else if (!policy->dfa) {
> + if (required_dfa) {
> + *info = "missing required dfa";
> + goto fail;
> + }
> + goto out;
> + }
> +
> + /*
> + * only unpack the following if a dfa is present
> + *
> + * sadly start was given different names for file and policydb
> + * but since it is optional we can try both
> + */
> - if (!unpack_u32(e, &policy->start[0], "start"))
> ++ if (!aa_unpack_u32(e, &policy->start[0], "start"))
> + /* default start state */
> + policy->start[0] = DFA_START;
> - if (!unpack_u32(e, &policy->start[AA_CLASS_FILE], "dfa_start")) {
> ++ if (!aa_unpack_u32(e, &policy->start[AA_CLASS_FILE], "dfa_start")) {
> + /* default start state for xmatch and file dfa */
> + policy->start[AA_CLASS_FILE] = DFA_START;
> + } /* setup class index */
> + for (i = AA_CLASS_FILE + 1; i <= AA_CLASS_LAST; i++) {
> + policy->start[i] = aa_dfa_next(policy->dfa, policy->start[0],
> + i);
> + }
> + if (!unpack_trans_table(e, &policy->trans) && required_trans) {
> + *info = "failed to unpack profile transition table";
> + goto fail;
> + }
> +
> + /* TODO: move compat mapping here, requires dfa merging first */
> + /* TODO: move verify here, it has to be done after compat mappings */
> +out:
> + return 0;
> +
> +fail:
> + e->pos = pos;
> + return error;
> +}
> +
> static u32 strhash(const void *data, u32 len, u32 seed)
> {
> const char * const *key = data;
> @@@ -858,29 -683,26 +831,29 @@@ static struct aa_profile *unpack_profil
> }
>
> profile = aa_alloc_profile(name, NULL, GFP_KERNEL);
> - if (!profile)
> - return ERR_PTR(-ENOMEM);
> + if (!profile) {
> + info = "out of memory";
> + error = -ENOMEM;
> + goto fail;
> + }
> + rules = list_first_entry(&profile->rules, typeof(*rules), list);
>
> /* profile renaming is optional */
> - (void) unpack_str(e, &profile->rename, "rename");
> + (void) aa_unpack_str(e, &profile->rename, "rename");
>
> /* attachment string is optional */
> - (void) unpack_str(e, &profile->attach.xmatch_str, "attach");
> - (void) aa_unpack_str(e, &profile->attach, "attach");
> ++ (void) aa_unpack_str(e, &profile->attach.xmatch_str, "attach");
>
> /* xmatch is optional and may be NULL */
> - profile->xmatch = unpack_dfa(e);
> - if (IS_ERR(profile->xmatch)) {
> - error = PTR_ERR(profile->xmatch);
> - profile->xmatch = NULL;
> + error = unpack_pdb(e, &profile->attach.xmatch, false, false, &info);
> + if (error) {
> info = "bad xmatch";
> goto fail;
> }
> - /* xmatch_len is not optional if xmatch is set */
> - if (profile->xmatch) {
> +
> + /* neither xmatch_len not xmatch_perms are optional if xmatch is set */
> + if (profile->attach.xmatch.dfa) {
> - if (!unpack_u32(e, &tmp, NULL)) {
> + if (!aa_unpack_u32(e, &tmp, NULL)) {
> info = "missing xmatch len";
> goto fail;
> }
> @@@ -943,38 -757,38 +916,38 @@@
> profile->path_flags = PATH_MEDIATE_DELETED;
>
> info = "failed to unpack profile capabilities";
> - if (!unpack_u32(e, &(rules->caps.allow.cap[0]), NULL))
> - if (!aa_unpack_u32(e, &(profile->caps.allow.cap[0]), NULL))
> ++ if (!aa_unpack_u32(e, &(rules->caps.allow.cap[0]), NULL))
> goto fail;
> - if (!unpack_u32(e, &(rules->caps.audit.cap[0]), NULL))
> - if (!aa_unpack_u32(e, &(profile->caps.audit.cap[0]), NULL))
> ++ if (!aa_unpack_u32(e, &(rules->caps.audit.cap[0]), NULL))
> goto fail;
> - if (!unpack_u32(e, &(rules->caps.quiet.cap[0]), NULL))
> - if (!aa_unpack_u32(e, &(profile->caps.quiet.cap[0]), NULL))
> ++ if (!aa_unpack_u32(e, &(rules->caps.quiet.cap[0]), NULL))
> goto fail;
> - if (!unpack_u32(e, &tmpcap.cap[0], NULL))
> + if (!aa_unpack_u32(e, &tmpcap.cap[0], NULL))
> goto fail;
>
> info = "failed to unpack upper profile capabilities";
> - if (unpack_nameX(e, AA_STRUCT, "caps64")) {
> + if (aa_unpack_nameX(e, AA_STRUCT, "caps64")) {
> /* optional upper half of 64 bit caps */
> - if (!unpack_u32(e, &(rules->caps.allow.cap[1]), NULL))
> - if (!aa_unpack_u32(e, &(profile->caps.allow.cap[1]), NULL))
> ++ if (!aa_unpack_u32(e, &(rules->caps.allow.cap[1]), NULL))
> goto fail;
> - if (!unpack_u32(e, &(rules->caps.audit.cap[1]), NULL))
> - if (!aa_unpack_u32(e, &(profile->caps.audit.cap[1]), NULL))
> ++ if (!aa_unpack_u32(e, &(rules->caps.audit.cap[1]), NULL))
> goto fail;
> - if (!unpack_u32(e, &(rules->caps.quiet.cap[1]), NULL))
> - if (!aa_unpack_u32(e, &(profile->caps.quiet.cap[1]), NULL))
> ++ if (!aa_unpack_u32(e, &(rules->caps.quiet.cap[1]), NULL))
> goto fail;
> - if (!unpack_u32(e, &(tmpcap.cap[1]), NULL))
> + if (!aa_unpack_u32(e, &(tmpcap.cap[1]), NULL))
> goto fail;
> - if (!unpack_nameX(e, AA_STRUCTEND, NULL))
> + if (!aa_unpack_nameX(e, AA_STRUCTEND, NULL))
> goto fail;
> }
>
> info = "failed to unpack extended profile capabilities";
> - if (unpack_nameX(e, AA_STRUCT, "capsx")) {
> + if (aa_unpack_nameX(e, AA_STRUCT, "capsx")) {
> /* optional extended caps mediation mask */
> - if (!unpack_u32(e, &(rules->caps.extended.cap[0]), NULL))
> - if (!aa_unpack_u32(e, &(profile->caps.extended.cap[0]), NULL))
> ++ if (!aa_unpack_u32(e, &(rules->caps.extended.cap[0]), NULL))
> goto fail;
> - if (!unpack_u32(e, &(rules->caps.extended.cap[1]), NULL))
> - if (!aa_unpack_u32(e, &(profile->caps.extended.cap[1]), NULL))
> ++ if (!aa_unpack_u32(e, &(rules->caps.extended.cap[1]), NULL))
> goto fail;
> - if (!unpack_nameX(e, AA_STRUCTEND, NULL))
> + if (!aa_unpack_nameX(e, AA_STRUCTEND, NULL))
> goto fail;
> }
>
> @@@ -993,55 -807,62 +966,55 @@@
> goto fail;
> }
>
> - if (unpack_nameX(e, AA_STRUCT, "policydb")) {
> + if (aa_unpack_nameX(e, AA_STRUCT, "policydb")) {
> /* generic policy dfa - optional and may be NULL */
> info = "failed to unpack policydb";
> - profile->policy.dfa = unpack_dfa(e);
> - if (IS_ERR(profile->policy.dfa)) {
> - error = PTR_ERR(profile->policy.dfa);
> - profile->policy.dfa = NULL;
> - goto fail;
> - } else if (!profile->policy.dfa) {
> - error = -EPROTO;
> + error = unpack_pdb(e, &rules->policy, true, false,
> + &info);
> + if (error)
> goto fail;
> - }
> - if (!aa_unpack_u32(e, &profile->policy.start[0], "start"))
> - /* default start state */
> - profile->policy.start[0] = DFA_START;
> - /* setup class index */
> - for (i = AA_CLASS_FILE; i <= AA_CLASS_LAST; i++) {
> - profile->policy.start[i] =
> - aa_dfa_next(profile->policy.dfa,
> - profile->policy.start[0],
> - i);
> - }
> + /* Fixup: drop when we get rid of start array */
> + if (aa_dfa_next(rules->policy.dfa, rules->policy.start[0],
> + AA_CLASS_FILE))
> + rules->policy.start[AA_CLASS_FILE] =
> + aa_dfa_next(rules->policy.dfa,
> + rules->policy.start[0],
> + AA_CLASS_FILE);
> - if (!unpack_nameX(e, AA_STRUCTEND, NULL))
> + if (!aa_unpack_nameX(e, AA_STRUCTEND, NULL))
> goto fail;
> + error = aa_compat_map_policy(&rules->policy, e->version);
> + if (error) {
> + info = "failed to remap policydb permission table";
> + goto fail;
> + }
> } else
> - profile->policy.dfa = aa_get_dfa(nulldfa);
> + rules->policy.dfa = aa_get_dfa(nulldfa);
>
> /* get file rules */
> - profile->file.dfa = unpack_dfa(e);
> - if (IS_ERR(profile->file.dfa)) {
> - error = PTR_ERR(profile->file.dfa);
> - profile->file.dfa = NULL;
> - info = "failed to unpack profile file rules";
> + error = unpack_pdb(e, &rules->file, false, true, &info);
> + if (error) {
> goto fail;
> - } else if (profile->file.dfa) {
> - if (!aa_unpack_u32(e, &profile->file.start, "dfa_start"))
> - /* default start state */
> - profile->file.start = DFA_START;
> - } else if (profile->policy.dfa &&
> - profile->policy.start[AA_CLASS_FILE]) {
> - profile->file.dfa = aa_get_dfa(profile->policy.dfa);
> - profile->file.start = profile->policy.start[AA_CLASS_FILE];
> + } else if (rules->file.dfa) {
> + error = aa_compat_map_file(&rules->file);
> + if (error) {
> + info = "failed to remap file permission table";
> + goto fail;
> + }
> + } else if (rules->policy.dfa &&
> + 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
> - profile->file.dfa = aa_get_dfa(nulldfa);
> -
> - if (!unpack_trans_table(e, profile)) {
> - info = "failed to unpack profile transition table";
> - goto fail;
> - }
> + rules->file.dfa = aa_get_dfa(nulldfa);
>
> + error = -EPROTO;
> - if (unpack_nameX(e, AA_STRUCT, "data")) {
> + if (aa_unpack_nameX(e, AA_STRUCT, "data")) {
> info = "out of memory";
> profile->data = kzalloc(sizeof(*profile->data), GFP_KERNEL);
> - if (!profile->data)
> + if (!profile->data) {
> + error = -ENOMEM;
> goto fail;
> -
> + }
> params.nelem_hint = 3;
> params.key_len = sizeof(void *);
> params.key_offset = offsetof(struct aa_data, key);

This is now a conflict between the apparmor tree and Linus' tree
(including the updated fix patch).

--
Cheers,
Stephen Rothwell

Attachment: pgpOIZoFayYqG.pgp
Description: OpenPGP digital signature