Commit c3c0d546 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'apparmor-pr-2019-06-18' of...

Merge tag 'apparmor-pr-2019-06-18' of git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor

Pull apparmor bug fixes from John Johansen:

 - fix PROFILE_MEDIATES for untrusted input

 - enforce nullbyte at end of tag string

 - reset pos on failure to unpack for various functions

* tag 'apparmor-pr-2019-06-18' of git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor:
  apparmor: reset pos on failure to unpack for various functions
  apparmor: enforce nullbyte at end of tag string
  apparmor: fix PROFILE_MEDIATES for untrusted input
parents 4b6920ba 156e4299
...@@ -213,7 +213,16 @@ static inline struct aa_profile *aa_get_newest_profile(struct aa_profile *p) ...@@ -213,7 +213,16 @@ static inline struct aa_profile *aa_get_newest_profile(struct aa_profile *p)
return labels_profile(aa_get_newest_label(&p->label)); return labels_profile(aa_get_newest_label(&p->label));
} }
#define PROFILE_MEDIATES(P, T) ((P)->policy.start[(unsigned char) (T)]) static inline unsigned int PROFILE_MEDIATES(struct aa_profile *profile,
unsigned char class)
{
if (class <= AA_CLASS_LAST)
return profile->policy.start[class];
else
return aa_dfa_match_len(profile->policy.dfa,
profile->policy.start[0], &class, 1);
}
static inline unsigned int PROFILE_MEDIATES_AF(struct aa_profile *profile, static inline unsigned int PROFILE_MEDIATES_AF(struct aa_profile *profile,
u16 AF) { u16 AF) {
unsigned int state = PROFILE_MEDIATES(profile, AA_CLASS_NET); unsigned int state = PROFILE_MEDIATES(profile, AA_CLASS_NET);
......
...@@ -219,16 +219,21 @@ static void *kvmemdup(const void *src, size_t len) ...@@ -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) static size_t unpack_u16_chunk(struct aa_ext *e, char **chunk)
{ {
size_t size = 0; size_t size = 0;
void *pos = e->pos;
if (!inbounds(e, sizeof(u16))) if (!inbounds(e, sizeof(u16)))
return 0; goto fail;
size = le16_to_cpu(get_unaligned((__le16 *) e->pos)); size = le16_to_cpu(get_unaligned((__le16 *) e->pos));
e->pos += sizeof(__le16); e->pos += sizeof(__le16);
if (!inbounds(e, size)) if (!inbounds(e, size))
return 0; goto fail;
*chunk = e->pos; *chunk = e->pos;
e->pos += size; e->pos += size;
return size; return size;
fail:
e->pos = pos;
return 0;
} }
/* unpack control byte */ /* unpack control byte */
...@@ -272,7 +277,7 @@ static bool unpack_nameX(struct aa_ext *e, enum aa_code code, const char *name) ...@@ -272,7 +277,7 @@ static bool unpack_nameX(struct aa_ext *e, enum aa_code code, const char *name)
char *tag = NULL; char *tag = NULL;
size_t size = unpack_u16_chunk(e, &tag); size_t size = unpack_u16_chunk(e, &tag);
/* if a name is specified it must match. otherwise skip tag */ /* if a name is specified it must match. otherwise skip tag */
if (name && (!size || strcmp(name, tag))) if (name && (!size || tag[size-1] != '\0' || strcmp(name, tag)))
goto fail; goto fail;
} else if (name) { } else if (name) {
/* if a name is specified and there is no name tag fail */ /* if a name is specified and there is no name tag fail */
...@@ -290,62 +295,84 @@ static bool unpack_nameX(struct aa_ext *e, enum aa_code code, const char *name) ...@@ -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) 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 (unpack_nameX(e, AA_U8, name)) {
if (!inbounds(e, sizeof(u8))) if (!inbounds(e, sizeof(u8)))
return 0; goto fail;
if (data) if (data)
*data = get_unaligned((u8 *)e->pos); *data = get_unaligned((u8 *)e->pos);
e->pos += sizeof(u8); e->pos += sizeof(u8);
return 1; return 1;
} }
fail:
e->pos = pos;
return 0; return 0;
} }
static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name) 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 (unpack_nameX(e, AA_U32, name)) {
if (!inbounds(e, sizeof(u32))) if (!inbounds(e, sizeof(u32)))
return 0; goto fail;
if (data) if (data)
*data = le32_to_cpu(get_unaligned((__le32 *) e->pos)); *data = le32_to_cpu(get_unaligned((__le32 *) e->pos));
e->pos += sizeof(u32); e->pos += sizeof(u32);
return 1; return 1;
} }
fail:
e->pos = pos;
return 0; return 0;
} }
static bool unpack_u64(struct aa_ext *e, u64 *data, const char *name) 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 (unpack_nameX(e, AA_U64, name)) {
if (!inbounds(e, sizeof(u64))) if (!inbounds(e, sizeof(u64)))
return 0; goto fail;
if (data) if (data)
*data = le64_to_cpu(get_unaligned((__le64 *) e->pos)); *data = le64_to_cpu(get_unaligned((__le64 *) e->pos));
e->pos += sizeof(u64); e->pos += sizeof(u64);
return 1; return 1;
} }
fail:
e->pos = pos;
return 0; return 0;
} }
static size_t unpack_array(struct aa_ext *e, const char *name) static size_t unpack_array(struct aa_ext *e, const char *name)
{ {
void *pos = e->pos;
if (unpack_nameX(e, AA_ARRAY, name)) { if (unpack_nameX(e, AA_ARRAY, name)) {
int size; int size;
if (!inbounds(e, sizeof(u16))) if (!inbounds(e, sizeof(u16)))
return 0; goto fail;
size = (int)le16_to_cpu(get_unaligned((__le16 *) e->pos)); size = (int)le16_to_cpu(get_unaligned((__le16 *) e->pos));
e->pos += sizeof(u16); e->pos += sizeof(u16);
return size; return size;
} }
fail:
e->pos = pos;
return 0; return 0;
} }
static size_t unpack_blob(struct aa_ext *e, char **blob, const char *name) 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)) { if (unpack_nameX(e, AA_BLOB, name)) {
u32 size; u32 size;
if (!inbounds(e, sizeof(u32))) if (!inbounds(e, sizeof(u32)))
return 0; goto fail;
size = le32_to_cpu(get_unaligned((__le32 *) e->pos)); size = le32_to_cpu(get_unaligned((__le32 *) e->pos));
e->pos += sizeof(u32); e->pos += sizeof(u32);
if (inbounds(e, (size_t) size)) { if (inbounds(e, (size_t) size)) {
...@@ -354,6 +381,9 @@ static size_t unpack_blob(struct aa_ext *e, char **blob, const char *name) ...@@ -354,6 +381,9 @@ static size_t unpack_blob(struct aa_ext *e, char **blob, const char *name)
return size; return size;
} }
} }
fail:
e->pos = pos;
return 0; return 0;
} }
...@@ -370,9 +400,10 @@ static int unpack_str(struct aa_ext *e, const char **string, const char *name) ...@@ -370,9 +400,10 @@ static int unpack_str(struct aa_ext *e, const char **string, const char *name)
if (src_str[size - 1] != 0) if (src_str[size - 1] != 0)
goto fail; goto fail;
*string = src_str; *string = src_str;
return size;
} }
} }
return size;
fail: fail:
e->pos = pos; e->pos = pos;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment