[PATCH 2/2 v2] 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]>
Acked-by: Stephen Smalley <[email protected]>
---
v2: Remove MAX_ALIAS_REPEATS (now in private.h) and add private.h

 libsepol/src/policydb_validate.c | 71 +++++++++++++++++++++-----------
 1 file changed, 46 insertions(+), 25 deletions(-)

diff --git a/libsepol/src/policydb_validate.c b/libsepol/src/policydb_validate.c
index 5687c82b..09d90a41 100644
--- a/libsepol/src/policydb_validate.c
+++ b/libsepol/src/policydb_validate.c
@@ -7,6 +7,7 @@
 #include <sepol/policydb/services.h>
 
 #include "debug.h"
+#include "private.h"
 #include "kernel_to_common.h"
 #include "policydb_validate.h"
 
@@ -660,19 +661,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 +688,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.