[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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.