[PATCH 2/2] libsepol: Improve the validation of type aliases
James Carter <[email protected]>
| Newsgroups | org.kernel.vger.selinux |
|---|---|
| Message-ID | <[email protected]> |
A maliciously crafted binary policy could have a type alias that refers to an attribute or that ultimately refers back to itself in a loop. Validate that type aliases ultimately refer to a primary type and not to an attribute or themselves. Signed-off-by: James Carter <[email protected]> --- libsepol/src/policydb_validate.c | 72 +++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 25 deletions(-) diff --git a/libsepol/src/policydb_validate.c b/libsepol/src/policydb_validate.c index 5687c82b..5178a2b4 100644 --- a/libsepol/src/policydb_validate.c +++ b/libsepol/src/policydb_validate.c @@ -13,6 +13,8 @@ #define bool_xor(a, b) (!(a) != !(b)) #define bool_xnor(a, b) (!bool_xor(a, b)) +#define MAX_ALIAS_REPEATS 32 + /* * Check that at least one permission bit is valid. * Older compilers might set invalid bits for the wildcard permission. @@ -660,19 +662,23 @@ static int validate_type_datum(sepol_handle_t *handle, const type_datum_t *type, { if (validate_value(type->s.value, &flavors[SYM_TYPES])) goto bad; - if (type->primary && validate_value(type->primary, &flavors[SYM_TYPES])) + + switch (type->flags) { + case 0: + case TYPE_FLAGS_NEVERAUDIT: + case TYPE_FLAGS_PERMISSIVE: + case TYPE_FLAGS_NEVERAUDIT | TYPE_FLAGS_PERMISSIVE: + case TYPE_FLAGS_EXPAND_ATTR_TRUE: + case TYPE_FLAGS_EXPAND_ATTR_FALSE: + case TYPE_FLAGS_EXPAND_ATTR: + break; + default: goto bad; + } - switch (type->flavor) { - case TYPE_TYPE: - case TYPE_ALIAS: - if (!ebitmap_is_empty(&type->types)) - goto bad; - if (type->bounds && - validate_simpletype(type->bounds, p, flavors)) + if (type->flavor == TYPE_ATTRIB) { + if (type->primary != 1) goto bad; - break; - case TYPE_ATTRIB: if (p->policy_type == POLICY_KERN) { if (!ebitmap_is_empty(&type->types)) goto bad; @@ -683,21 +689,37 @@ static int validate_type_datum(sepol_handle_t *handle, const type_datum_t *type, } if (type->bounds) goto bad; - break; - default: - goto bad; - } - - switch (type->flags) { - case 0: - case TYPE_FLAGS_NEVERAUDIT: - case TYPE_FLAGS_PERMISSIVE: - case TYPE_FLAGS_NEVERAUDIT | TYPE_FLAGS_PERMISSIVE: - case TYPE_FLAGS_EXPAND_ATTR_TRUE: - case TYPE_FLAGS_EXPAND_ATTR_FALSE: - case TYPE_FLAGS_EXPAND_ATTR: - break; - default: + } else if ((type->flavor == TYPE_TYPE) || + (type->flavor == TYPE_ALIAS)) { + if (!ebitmap_is_empty(&type->types)) + goto bad; + if (type->bounds && + validate_simpletype(type->bounds, p, flavors)) + goto bad; + if ((type->flavor == TYPE_TYPE) && type->primary) { + if (type->primary > 1) + goto bad; + } else { + const type_datum_t *t = type; + uint32_t v; + int repeats = 0; + while ((t->flavor == TYPE_ALIAS) || (t->primary == 0)) { + if (repeats >= MAX_ALIAS_REPEATS) + break; + v = (t->primary) ? t->primary : t->s.value; + if (validate_value(v, &flavors[SYM_TYPES])) + break; + t = p->type_val_to_struct[v - 1]; + if (t == type) + break; + repeats++; + } + if ((t->flavor != TYPE_TYPE) || (t->primary != 1)) { + ERR(handle, "Alias validation failed"); + goto bad; + } + } + } else { goto bad; } -- 2.55.0