Blame SOURCES/0047-libsepol-cil-Check-for-self-referential-loops-in-set.patch

71cd55
From 61fbdce666f24c4a118b249ece6b014d54b65074 Mon Sep 17 00:00:00 2001
71cd55
From: James Carter <jwcart2@gmail.com>
71cd55
Date: Tue, 4 May 2021 16:14:55 -0400
71cd55
Subject: [PATCH] libsepol/cil: Check for self-referential loops in sets
71cd55
71cd55
The secilc-fuzzer found a self-referential loop using category sets.
71cd55
Any set declaration in CIL that allows sets in it is susceptible to
71cd55
the creation of a self-referential loop. There is a check, but only
71cd55
for the name of the set being declared being used in the set
71cd55
declaration.
71cd55
71cd55
Check for self-refential loops in user, role, and type attributes
71cd55
and in category sets. Since all of the sets need to be declared,
71cd55
this check has to be done when verifying the CIL db before doing
71cd55
the post phase.
71cd55
71cd55
Signed-off-by: James Carter <jwcart2@gmail.com>
71cd55
---
71cd55
 libsepol/cil/src/cil_resolve_ast.c | 31 +---------
71cd55
 libsepol/cil/src/cil_verify.c      | 97 +++++++++++++++++++++---------
71cd55
 libsepol/cil/src/cil_verify.h      |  1 -
71cd55
 3 files changed, 71 insertions(+), 58 deletions(-)
71cd55
71cd55
diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
71cd55
index f251ed1582fc..5368ae80ede9 100644
71cd55
--- a/libsepol/cil/src/cil_resolve_ast.c
71cd55
+++ b/libsepol/cil/src/cil_resolve_ast.c
71cd55
@@ -438,11 +438,6 @@ int cil_resolve_typeattributeset(struct cil_tree_node *current, void *extra_args
71cd55
 		goto exit;
71cd55
 	}
71cd55
 
71cd55
-	rc = cil_verify_no_self_reference(attr_datum, attrtypes->datum_expr);
71cd55
-	if (rc != SEPOL_OK) {
71cd55
-		goto exit;
71cd55
-	}
71cd55
-
71cd55
 	if (attr->expr_list == NULL) {
71cd55
 		cil_list_init(&attr->expr_list, CIL_TYPEATTRIBUTE);
71cd55
 	}
71cd55
@@ -1151,11 +1146,6 @@ int cil_resolve_roleattributeset(struct cil_tree_node *current, void *extra_args
71cd55
 		goto exit;
71cd55
 	}
71cd55
 
71cd55
-	rc = cil_verify_no_self_reference(attr_datum, attrroles->datum_expr);
71cd55
-	if (rc != SEPOL_OK) {
71cd55
-		goto exit;
71cd55
-	}
71cd55
-
71cd55
 	if (attr->expr_list == NULL) {
71cd55
 		cil_list_init(&attr->expr_list, CIL_ROLEATTRIBUTE);
71cd55
 	}
71cd55
@@ -1666,21 +1656,7 @@ exit:
71cd55
 
71cd55
 int cil_resolve_catset(struct cil_tree_node *current, struct cil_catset *catset, void *extra_args)
71cd55
 {
71cd55
-	int rc = SEPOL_ERR;
71cd55
-
71cd55
-	rc = cil_resolve_cats(current, catset->cats, extra_args);
71cd55
-	if (rc != SEPOL_OK) {
71cd55
-		goto exit;
71cd55
-	}
71cd55
-
71cd55
-	rc = cil_verify_no_self_reference((struct cil_symtab_datum *)catset, catset->cats->datum_expr);
71cd55
-	if (rc != SEPOL_OK) {
71cd55
-		cil_list_destroy(&catset->cats->datum_expr, CIL_FALSE);
71cd55
-		goto exit;
71cd55
-	}
71cd55
-
71cd55
-exit:
71cd55
-	return rc;
71cd55
+	return cil_resolve_cats(current, catset->cats, extra_args);
71cd55
 }
71cd55
 
71cd55
 int cil_resolve_senscat(struct cil_tree_node *current, void *extra_args)
71cd55
@@ -3545,11 +3521,6 @@ int cil_resolve_userattributeset(struct cil_tree_node *current, void *extra_args
71cd55
 		goto exit;
71cd55
 	}
71cd55
 
71cd55
-	rc = cil_verify_no_self_reference(attr_datum, attrusers->datum_expr);
71cd55
-	if (rc != SEPOL_OK) {
71cd55
-		goto exit;
71cd55
-	}
71cd55
-
71cd55
 	if (attr->expr_list == NULL) {
71cd55
 		cil_list_init(&attr->expr_list, CIL_USERATTRIBUTE);
71cd55
 	}
71cd55
diff --git a/libsepol/cil/src/cil_verify.c b/libsepol/cil/src/cil_verify.c
71cd55
index 5a37dd2f76bc..8e15a0e68a69 100644
71cd55
--- a/libsepol/cil/src/cil_verify.c
71cd55
+++ b/libsepol/cil/src/cil_verify.c
71cd55
@@ -430,28 +430,71 @@ int cil_verify_decl_does_not_shadow_macro_parameter(struct cil_macro *macro, str
71cd55
 	return SEPOL_OK;
71cd55
 }
71cd55
 
71cd55
-int cil_verify_no_self_reference(struct cil_symtab_datum *datum, struct cil_list *datum_list)
71cd55
+static int cil_verify_no_self_reference(enum cil_flavor flavor, struct cil_symtab_datum *datum, struct cil_symtab_datum *orig);
71cd55
+
71cd55
+static int __verify_no_self_reference_in_expr(struct cil_list *expr, struct cil_symtab_datum *orig)
71cd55
 {
71cd55
-	struct cil_list_item *i;
71cd55
+	struct cil_list_item *item;
71cd55
+	int rc = SEPOL_OK;
71cd55
 
71cd55
-	cil_list_for_each(i, datum_list) {
71cd55
-		if (i->flavor == CIL_DATUM) {
71cd55
-			struct cil_symtab_datum *d = i->data;
71cd55
-			if (d == datum) {
71cd55
-				cil_log(CIL_ERR,"Self-reference found for %s\n",datum->name);
71cd55
-				return SEPOL_ERR;
71cd55
-			}
71cd55
-		} else if (i->flavor == CIL_LIST) {
71cd55
-			int rc = cil_verify_no_self_reference(datum, i->data);
71cd55
-			if (rc != SEPOL_OK) {
71cd55
-				return SEPOL_ERR;
71cd55
-			}
71cd55
+	if (!expr) {
71cd55
+		return SEPOL_OK;
71cd55
+	}
71cd55
+
71cd55
+	cil_list_for_each(item, expr) {
71cd55
+		if (item->flavor == CIL_DATUM) {
71cd55
+			struct cil_symtab_datum* datum = item->data;
71cd55
+			rc = cil_verify_no_self_reference(FLAVOR(datum), datum, orig);
71cd55
+		} else if (item->flavor == CIL_LIST) {
71cd55
+			rc = __verify_no_self_reference_in_expr(item->data, orig);
71cd55
+		}
71cd55
+		if (rc != SEPOL_OK) {
71cd55
+			return SEPOL_ERR;
71cd55
 		}
71cd55
 	}
71cd55
 
71cd55
 	return SEPOL_OK;
71cd55
 }
71cd55
 
71cd55
+static int cil_verify_no_self_reference(enum cil_flavor flavor, struct cil_symtab_datum *datum, struct cil_symtab_datum *orig)
71cd55
+{
71cd55
+	int rc = SEPOL_OK;
71cd55
+
71cd55
+	if (datum == orig) {
71cd55
+		cil_tree_log(NODE(orig), CIL_ERR, "Self-reference found for %s", orig->name);
71cd55
+		return SEPOL_ERR;
71cd55
+	} else if (orig == NULL) {
71cd55
+		orig = datum;
71cd55
+	}
71cd55
+
71cd55
+	switch (flavor) {
71cd55
+	case CIL_USERATTRIBUTE: {
71cd55
+		struct cil_userattribute *attr = (struct cil_userattribute *)datum;
71cd55
+		rc = __verify_no_self_reference_in_expr(attr->expr_list, orig);
71cd55
+		break;
71cd55
+	}
71cd55
+	case CIL_ROLEATTRIBUTE: {
71cd55
+		struct cil_roleattribute *attr = (struct cil_roleattribute *)datum;
71cd55
+		rc = __verify_no_self_reference_in_expr(attr->expr_list, orig);
71cd55
+		break;
71cd55
+	}
71cd55
+	case CIL_TYPEATTRIBUTE: {
71cd55
+		struct cil_typeattribute *attr = (struct cil_typeattribute *)datum;
71cd55
+		rc = __verify_no_self_reference_in_expr(attr->expr_list, orig);
71cd55
+		break;
71cd55
+	}
71cd55
+	case CIL_CATSET: {
71cd55
+		struct cil_catset *set = (struct cil_catset *)datum;
71cd55
+		rc = __verify_no_self_reference_in_expr(set->cats->datum_expr, orig);
71cd55
+		break;
71cd55
+	}
71cd55
+	default:
71cd55
+		break;
71cd55
+	}
71cd55
+
71cd55
+	return rc;
71cd55
+}
71cd55
+
71cd55
 int __cil_verify_ranges(struct cil_list *list)
71cd55
 {
71cd55
 	int rc = SEPOL_ERR;
71cd55
@@ -1757,27 +1800,22 @@ static int __cil_verify_map_class(struct cil_tree_node *node)
71cd55
 
71cd55
 int __cil_pre_verify_helper(struct cil_tree_node *node, uint32_t *finished, __attribute__((unused)) void *extra_args)
71cd55
 {
71cd55
-	int rc = SEPOL_ERR;
71cd55
+	int rc = SEPOL_OK;
71cd55
 
71cd55
-	if (node->flavor == CIL_MACRO) {
71cd55
+	switch (node->flavor) {
71cd55
+	case CIL_MACRO: {
71cd55
 		*finished = CIL_TREE_SKIP_HEAD;
71cd55
-		rc = SEPOL_OK;
71cd55
-		goto exit;
71cd55
-	} else if (node->flavor == CIL_BLOCK) {
71cd55
+		break;
71cd55
+	}
71cd55
+	case CIL_BLOCK: {
71cd55
 		struct cil_block *blk = node->data;
71cd55
 		if (blk->is_abstract == CIL_TRUE) {
71cd55
 			*finished = CIL_TREE_SKIP_HEAD;
71cd55
 		}
71cd55
-		rc = SEPOL_OK;
71cd55
-		goto exit;
71cd55
+		break;
71cd55
 	}
71cd55
-
71cd55
-	switch (node->flavor) {
71cd55
 	case CIL_USER:
71cd55
 		rc = __cil_verify_user_pre_eval(node);
71cd55
-		if (rc != SEPOL_OK) {
71cd55
-			goto exit;
71cd55
-		}
71cd55
 		break;
71cd55
 	case CIL_MAP_CLASS:
71cd55
 		rc = __cil_verify_map_class(node);
71cd55
@@ -1785,11 +1823,16 @@ int __cil_pre_verify_helper(struct cil_tree_node *node, uint32_t *finished, __at
71cd55
 	case CIL_CLASSPERMISSION:
71cd55
 		rc = __cil_verify_classpermission(node);
71cd55
 		break;
71cd55
+	case CIL_USERATTRIBUTE:
71cd55
+	case CIL_ROLEATTRIBUTE:
71cd55
+	case CIL_TYPEATTRIBUTE:
71cd55
+	case CIL_CATSET:
71cd55
+		rc = cil_verify_no_self_reference(node->flavor, node->data, NULL);
71cd55
+		break;
71cd55
 	default:
71cd55
 		rc = SEPOL_OK;
71cd55
 		break;
71cd55
 	}
71cd55
 
71cd55
-exit:
71cd55
 	return rc;
71cd55
 }
71cd55
diff --git a/libsepol/cil/src/cil_verify.h b/libsepol/cil/src/cil_verify.h
71cd55
index c497018f8a95..4ea14f5b0a9a 100644
71cd55
--- a/libsepol/cil/src/cil_verify.h
71cd55
+++ b/libsepol/cil/src/cil_verify.h
71cd55
@@ -63,7 +63,6 @@ int cil_verify_constraint_leaf_expr_syntax(enum cil_flavor l_flavor, enum cil_fl
71cd55
 int cil_verify_constraint_expr_syntax(struct cil_tree_node *current, enum cil_flavor op);
71cd55
 int cil_verify_conditional_blocks(struct cil_tree_node *current);
71cd55
 int cil_verify_decl_does_not_shadow_macro_parameter(struct cil_macro *macro, struct cil_tree_node *node, const char *name);
71cd55
-int cil_verify_no_self_reference(struct cil_symtab_datum *datum, struct cil_list *datum_list);
71cd55
 int __cil_verify_ranges(struct cil_list *list);
71cd55
 int __cil_verify_ordered_node_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args);
71cd55
 int __cil_verify_ordered(struct cil_tree_node *current, enum cil_flavor flavor);
71cd55
-- 
71cd55
2.32.0
71cd55