+ Bug Fixes

- Fix PROFILE_MEDIATES for untrusted input
   - enforce nullbyte at end of tag string
   - reset pos on failure to unpack for various functions
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEE7cSDD705q2rFEEf7BS82cBjVw9gFAl0JklgACgkQBS82cBjV
 w9iZag/9Ezbz8vALjABLFoaOkj7jLzFnjO0IXeV3nUwWjxuz0GWvpBbcJgFmjm7e
 DFfZHggRiJHs46HySyavNZIbe/4m7E2OiQdbeP6I0JAZCB32Gvd17wAEKJNBfyO2
 4KsfIMEC0hqjtVdNMm5BHHsycH8pQsq+Vfg8Qt/Ygiq/CAqYT2isZqCDBo1RR8OP
 Cq6eFwIpSLv4ZQ+WGcLr1cWamh0SVU9Slrag5uJNmEpDIscxn3sEB3OxtcnJjAA2
 y2JeSoc6KQqpMMkeI0cvKc2zrmOKhYJSNEOaWtUcnUp9cT9JO4JxOvYcyDeu9Pm1
 jiZM0F7VHVy5p7Wh4szx0V1TU1XPStpXl4CQDN8LaiPVlHbnSRpC/jZy1xa5V7XY
 n/NuxcpxTVza+2LdnwG2TfZFJvzTqUw0LvCl0wFq/Q6fQmigyzY2ZyfxzrCwZMWF
 EELzWbcMblLsV00sqc1jQNXkl9z1STF4gz12Bg8HA/XzPSobkPSthWagTXWHSlCY
 8wffQZIyVqs2m5Krd0pwhIj+WHWOw/ORXRnWwRM3VgL26+YVpJbRv6Qqg5btN23l
 q6ibCzCMSEhAIAnpjpFLVM6vzqd+V0ND+R8h8rql3d94dWQA5iW3wa/Y8MAzhOPG
 W9SlEHo4FjtsRnpnKG8YFlWaaHBFmPRm0/RTI+MCZtphu/B3e3M=
 =NXOk
 -----END PGP SIGNATURE-----

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
This commit is contained in:
Linus Torvalds 2019-06-19 11:39:00 -07:00
commit c3c0d546d7
2 changed files with 50 additions and 10 deletions

View File

@ -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));
}
#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,
u16 AF) {
unsigned int state = PROFILE_MEDIATES(profile, AA_CLASS_NET);

View File

@ -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 */
@ -272,7 +277,7 @@ static bool unpack_nameX(struct aa_ext *e, enum aa_code code, const char *name)
char *tag = NULL;
size_t size = unpack_u16_chunk(e, &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;
} else if (name) {
/* 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)
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)) {
@ -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;
}
@ -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;