Skip to content

Commit

Permalink
apparmor: reset pos on failure to unpack for various functions
Browse files Browse the repository at this point in the history
Each function that manipulates the aa_ext struct should reset it's "pos"
member on failure. This ensures that, on failure, no changes are made to
the state of the aa_ext struct.

There are paths were elements are optional and the error path is
used to indicate the optional element is not present. This means
instead of just aborting on error the unpack stream can become
unsynchronized on optional elements, if using one of the affected
functions.

Cc: [email protected]
Fixes: 736ec75 ("AppArmor: policy routines for loading and unpacking policy")
Signed-off-by: Mike Salvatore <[email protected]>
Signed-off-by: John Johansen <[email protected]>
  • Loading branch information
mssalvatore authored and John Johansen committed Jun 18, 2019
1 parent 8404d7a commit 156e429
Showing 1 changed file with 39 additions and 8 deletions.
47 changes: 39 additions & 8 deletions security/apparmor/policy_unpack.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,16 +219,21 @@ static void *kvmemdup(const void *src, size_t len)
static size_t unpack_u16_chunk(struct aa_ext *e, char **chunk)
{
size_t size = 0;
void *pos = e->pos;

if (!inbounds(e, sizeof(u16)))
return 0;
goto fail;
size = le16_to_cpu(get_unaligned((__le16 *) e->pos));
e->pos += sizeof(__le16);
if (!inbounds(e, size))
return 0;
goto fail;
*chunk = e->pos;
e->pos += size;
return size;

fail:
e->pos = pos;
return 0;
}

/* unpack control byte */
Expand Down Expand Up @@ -290,62 +295,84 @@ static bool unpack_nameX(struct aa_ext *e, enum aa_code code, const char *name)

static bool unpack_u8(struct aa_ext *e, u8 *data, const char *name)
{
void *pos = e->pos;

if (unpack_nameX(e, AA_U8, name)) {
if (!inbounds(e, sizeof(u8)))
return 0;
goto fail;
if (data)
*data = get_unaligned((u8 *)e->pos);
e->pos += sizeof(u8);
return 1;
}

fail:
e->pos = pos;
return 0;
}

static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name)
{
void *pos = e->pos;

if (unpack_nameX(e, AA_U32, name)) {
if (!inbounds(e, sizeof(u32)))
return 0;
goto fail;
if (data)
*data = le32_to_cpu(get_unaligned((__le32 *) e->pos));
e->pos += sizeof(u32);
return 1;
}

fail:
e->pos = pos;
return 0;
}

static bool unpack_u64(struct aa_ext *e, u64 *data, const char *name)
{
void *pos = e->pos;

if (unpack_nameX(e, AA_U64, name)) {
if (!inbounds(e, sizeof(u64)))
return 0;
goto fail;
if (data)
*data = le64_to_cpu(get_unaligned((__le64 *) e->pos));
e->pos += sizeof(u64);
return 1;
}

fail:
e->pos = pos;
return 0;
}

static size_t unpack_array(struct aa_ext *e, const char *name)
{
void *pos = e->pos;

if (unpack_nameX(e, AA_ARRAY, name)) {
int size;
if (!inbounds(e, sizeof(u16)))
return 0;
goto fail;
size = (int)le16_to_cpu(get_unaligned((__le16 *) e->pos));
e->pos += sizeof(u16);
return size;
}

fail:
e->pos = pos;
return 0;
}

static size_t unpack_blob(struct aa_ext *e, char **blob, const char *name)
{
void *pos = e->pos;

if (unpack_nameX(e, AA_BLOB, name)) {
u32 size;
if (!inbounds(e, sizeof(u32)))
return 0;
goto fail;
size = le32_to_cpu(get_unaligned((__le32 *) e->pos));
e->pos += sizeof(u32);
if (inbounds(e, (size_t) size)) {
Expand All @@ -354,6 +381,9 @@ static size_t unpack_blob(struct aa_ext *e, char **blob, const char *name)
return size;
}
}

fail:
e->pos = pos;
return 0;
}

Expand All @@ -370,9 +400,10 @@ static int unpack_str(struct aa_ext *e, const char **string, const char *name)
if (src_str[size - 1] != 0)
goto fail;
*string = src_str;

return size;
}
}
return size;

fail:
e->pos = pos;
Expand Down

0 comments on commit 156e429

Please sign in to comment.