[PATCH 1/1] libsepol/cil: Improve processing of context rules

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Improve the processing of netifcon, genfscon, ibpkeycon, ibendportcon,
portcon, nodecon, fsuse, filecon, iomemcon, ioportcon, pcidevicecon,
and devicetreecon rules.

If the multiple-decls option is not used then report errors if duplicate
context rules are found. If it is used then remove duplicate context rules
and report errors when two rules are identical except for the context.

This also changes the ordering of portcon and filecon rules. The protocol
of portcon rules will be compared if the port numbers are the same and the
path strings of filecon rules will be compared if the number of meta
characters, the stem length, string length and file types are the same.

Based on an initial patch by Pierre-Hugues Husson (phh@xxxxxx)

Signed-off-by: James Carter <jwcart2@xxxxxxxxxxxxx>
---
 libsepol/cil/src/cil_post.c | 331 ++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 318 insertions(+), 13 deletions(-)

diff --git a/libsepol/cil/src/cil_post.c b/libsepol/cil/src/cil_post.c
index a2122454..0b09cecc 100644
--- a/libsepol/cil/src/cil_post.c
+++ b/libsepol/cil/src/cil_post.c
@@ -53,6 +53,83 @@
 static int __cil_expr_to_bitmap(struct cil_list *expr, ebitmap_t *out, int max, struct cil_db *db);
 static int __cil_expr_list_to_bitmap(struct cil_list *expr_list, ebitmap_t *out, int max, struct cil_db *db);
 
+static int cats_compare(struct cil_cats *a, struct cil_cats *b)
+{
+	struct cil_list_item *i, *j;
+	int rc;
+
+	if (a == b) return 0;
+	if (!a) return -1;
+	if (!b) return 1;
+
+	/* Expects cat expression to have been evaluated */
+	cil_list_for_each(i, a->datum_expr) {
+		cil_list_for_each(j, b->datum_expr) {
+			rc = strcmp(DATUM(i->data)->fqn, DATUM(j->data)->fqn);
+			if (!rc) return rc;
+		}
+	}
+	return 0;
+}
+
+static int level_compare(struct cil_level *a, struct cil_level *b)
+{
+	int rc;
+
+	if (a == b) return 0;
+	if (!a) return -1;
+	if (!b) return 1;
+
+	if (a->sens != b->sens) {
+		rc = strcmp(DATUM(a->sens)->fqn, DATUM(b->sens)->fqn);
+		if (rc != 0) return rc;
+	}
+	if (a->cats != b->cats) {
+		return cats_compare(a->cats, b->cats);
+	}
+	return 0;
+}
+
+static int range_compare(struct cil_levelrange *a, struct cil_levelrange *b)
+{
+	int rc;
+
+	if (a == b) return 0;
+	if (!a) return -1;
+	if (!b) return 1;
+
+	if (a->low != b->low) {
+		rc = level_compare(a->low, b->low);
+		if (rc != 0) return rc;
+	}
+	if (a->high != b->high) {
+		return level_compare(a->high, b->high);
+	}
+	return 0;
+}
+
+static int context_compare(struct cil_context *a, struct cil_context *b)
+{
+	int rc;
+
+	if (a->user != b->user) {
+		rc = strcmp(DATUM(a->user)->fqn, DATUM(b->user)->fqn);
+		if (rc != 0) return rc;
+	}
+	if (a->role != b->role) {
+		rc = strcmp(DATUM(a->role)->fqn, DATUM(b->role)->fqn);
+		if (rc != 0) return rc;
+	}
+	if (a->type != b->type) {
+		rc = strcmp(DATUM(a->type)->fqn, DATUM(b->type)->fqn);
+		if (rc != 0) return rc;
+	}
+	if (a->range != b->range) {
+		return range_compare(a->range, b->range);
+	}
+	return 0;
+}
+
 static int cil_verify_is_list(struct cil_list *list, enum cil_flavor flavor)
 {
 	struct cil_list_item *curr;
@@ -145,6 +222,8 @@ int cil_post_filecon_compare(const void *a, const void *b)
 		rc = -1;
 	} else if (b_filecon->type < a_filecon->type) {
 		rc = 1;
+	} else {
+		rc = strcmp(a_filecon->path_str, b_filecon->path_str);
 	}
 
 	free(a_path);
@@ -190,6 +269,10 @@ int cil_post_portcon_compare(const void *a, const void *b)
 			rc = -1;
 		} else if (bportcon->port_low < aportcon->port_low) {
 			rc = 1;
+		} else if (aportcon->proto < bportcon->proto) {
+			rc = -1;
+		} else if (aportcon->proto > bportcon->proto) {
+			rc = 1;
 		}
 	}
 
@@ -369,6 +452,102 @@ int cil_post_fsuse_compare(const void *a, const void *b)
 	return rc;
 }
 
+int cil_post_filecon_context_compare(const void *a, const void *b)
+{
+	struct cil_filecon *a_filecon = *(struct cil_filecon**)a;
+	struct cil_filecon *b_filecon = *(struct cil_filecon**)b;
+	return context_compare(a_filecon->context, b_filecon->context);
+}
+
+int cil_post_ibpkeycon_context_compare(const void *a, const void *b)
+{
+	struct cil_ibpkeycon *a_ibpkeycon = *(struct cil_ibpkeycon **)a;
+	struct cil_ibpkeycon *b_ibpkeycon = *(struct cil_ibpkeycon **)b;
+	return context_compare(a_ibpkeycon->context, b_ibpkeycon->context);
+}
+
+int cil_post_portcon_context_compare(const void *a, const void *b)
+{
+	struct cil_portcon *a_portcon = *(struct cil_portcon**)a;
+	struct cil_portcon *b_portcon = *(struct cil_portcon**)b;
+	return context_compare(a_portcon->context, b_portcon->context);
+}
+
+int cil_post_genfscon_context_compare(const void *a, const void *b)
+{
+	struct cil_genfscon *a_genfscon = *(struct cil_genfscon**)a;
+	struct cil_genfscon *b_genfscon = *(struct cil_genfscon**)b;
+	return context_compare(a_genfscon->context, b_genfscon->context);
+}
+
+int cil_post_netifcon_context_compare(const void *a, const void *b)
+{
+	int rc;
+	struct cil_netifcon *a_netifcon = *(struct cil_netifcon**)a;
+	struct cil_netifcon *b_netifcon = *(struct cil_netifcon**)b;
+	rc = context_compare(a_netifcon->if_context, b_netifcon->if_context);
+	if (rc != 0) {
+		return rc;
+	}
+	return context_compare(a_netifcon->packet_context, b_netifcon->packet_context);
+}
+
+int cil_post_ibendportcon_context_compare(const void *a, const void *b)
+{
+	struct cil_ibendportcon *a_ibendportcon = *(struct cil_ibendportcon **)a;
+	struct cil_ibendportcon *b_ibendportcon = *(struct cil_ibendportcon **)b;
+	return context_compare(a_ibendportcon->context, b_ibendportcon->context);
+}
+
+int cil_post_nodecon_context_compare(const void *a, const void *b)
+{
+	struct cil_nodecon *a_nodecon = *(struct cil_nodecon **)a;
+	struct cil_nodecon *b_nodecon = *(struct cil_nodecon **)b;
+	return context_compare(a_nodecon->context, b_nodecon->context);
+}
+
+int cil_post_pirqcon_context_compare(const void *a, const void *b)
+{
+	struct cil_pirqcon *a_pirqcon = *(struct cil_pirqcon**)a;
+	struct cil_pirqcon *b_pirqcon = *(struct cil_pirqcon**)b;
+	return context_compare(a_pirqcon->context, b_pirqcon->context);
+}
+
+int cil_post_iomemcon_context_compare(const void *a, const void *b)
+{
+	struct cil_iomemcon *a_iomemcon = *(struct cil_iomemcon**)a;
+	struct cil_iomemcon *b_iomemcon = *(struct cil_iomemcon**)b;
+	return context_compare(a_iomemcon->context, b_iomemcon->context);
+}
+
+int cil_post_ioportcon_context_compare(const void *a, const void *b)
+{
+	struct cil_ioportcon *a_ioportcon = *(struct cil_ioportcon**)a;
+	struct cil_ioportcon *b_ioportcon = *(struct cil_ioportcon**)b;
+	return context_compare(a_ioportcon->context, b_ioportcon->context);
+}
+
+int cil_post_pcidevicecon_context_compare(const void *a, const void *b)
+{
+	struct cil_pcidevicecon *a_pcidevicecon = *(struct cil_pcidevicecon**)a;
+	struct cil_pcidevicecon *b_pcidevicecon = *(struct cil_pcidevicecon**)b;
+	return context_compare(a_pcidevicecon->context, b_pcidevicecon->context);
+}
+
+int cil_post_devicetreecon_context_compare(const void *a, const void *b)
+{
+	struct cil_devicetreecon *a_devicetreecon = *(struct cil_devicetreecon**)a;
+	struct cil_devicetreecon *b_devicetreecon = *(struct cil_devicetreecon**)b;
+	return context_compare(a_devicetreecon->context, b_devicetreecon->context);
+}
+
+int cil_post_fsuse_context_compare(const void *a, const void *b)
+{
+	struct cil_fsuse *a_fsuse = *(struct cil_fsuse**)a;
+	struct cil_fsuse *b_fsuse = *(struct cil_fsuse**)b;
+	return context_compare(a_fsuse->context, b_fsuse->context);
+}
+
 static int __cil_post_db_count_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
 {
 	struct cil_db *db = extra_args;
@@ -2064,6 +2243,74 @@ exit:
 	return rc;
 }
 
+static int __cil_post_report_conflict(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
+{
+	struct cil_list_item *li = extra_args;
+
+	if (node->flavor == CIL_BLOCK) {
+		struct cil_block *blk = node->data;
+		if (blk->is_abstract == CIL_TRUE) {
+			*finished = CIL_TREE_SKIP_HEAD;
+		}
+	} else if (node->flavor == CIL_MACRO) {
+		*finished = CIL_TREE_SKIP_HEAD;
+	} else if (node->flavor == li->flavor) {
+		if (node->data == li->data) {
+			char *path = cil_tree_get_cil_path(node);
+			cil_log(CIL_WARN, "  at %s:%d\n", path, node->line);
+		}
+	}
+	return SEPOL_OK;
+}
+
+static int __cil_post_process_context_rules(struct cil_sort *sort, int (*compar)(const void *, const void *), int (*concompar)(const void *, const void *), struct cil_db *db, enum cil_flavor flavor, const char *flavor_str)
+{
+	uint32_t count = sort->count;
+	uint32_t i, j = 0, removed = 0;
+	int rc = SEPOL_OK;
+
+	if (count < 2) {
+		return SEPOL_OK;
+	}
+
+	qsort(sort->array, sort->count, sizeof(sort->array), compar);
+
+	for (i=1; i<count; i++) {
+		if (compar(&sort->array[i], &sort->array[j]) != 0) {
+			j++;
+		} else {
+			removed++;
+			if (!db->multiple_decls ||
+			   concompar(&sort->array[i], &sort->array[j]) != 0) {
+				struct cil_list_item li;
+				int rc2;
+				cil_log(CIL_WARN, "Found conflicting %s rules\n",
+					flavor_str);
+				rc = SEPOL_ERR;
+				li.flavor = flavor;
+				li.data = sort->array[i];
+				rc2 = cil_tree_walk(db->ast->root,
+						    __cil_post_report_conflict,
+						    NULL, NULL, &li);
+				if (rc2 != SEPOL_OK) goto exit;
+				li.data = sort->array[j];
+				rc2 = cil_tree_walk(db->ast->root,
+						    __cil_post_report_conflict,
+						    NULL, NULL, &li);
+				if (rc2 != SEPOL_OK) goto exit;
+			}
+		}
+		if (i != j) {
+			sort->array[j] = sort->array[i];
+		}
+	}
+
+	sort->count = count - removed;
+
+exit:
+	return rc;
+}
+
 static int cil_post_db(struct cil_db *db)
 {
 	int rc = SEPOL_ERR;
@@ -2116,19 +2363,77 @@ static int cil_post_db(struct cil_db *db)
 		goto exit;
 	}
 
-	qsort(db->netifcon->array, db->netifcon->count, sizeof(db->netifcon->array), cil_post_netifcon_compare);
-	qsort(db->genfscon->array, db->genfscon->count, sizeof(db->genfscon->array), cil_post_genfscon_compare);
-	qsort(db->ibpkeycon->array, db->ibpkeycon->count, sizeof(db->ibpkeycon->array), cil_post_ibpkeycon_compare);
-	qsort(db->ibendportcon->array, db->ibendportcon->count, sizeof(db->ibendportcon->array), cil_post_ibendportcon_compare);
-	qsort(db->portcon->array, db->portcon->count, sizeof(db->portcon->array), cil_post_portcon_compare);
-	qsort(db->nodecon->array, db->nodecon->count, sizeof(db->nodecon->array), cil_post_nodecon_compare);
-	qsort(db->fsuse->array, db->fsuse->count, sizeof(db->fsuse->array), cil_post_fsuse_compare);
-	qsort(db->filecon->array, db->filecon->count, sizeof(db->filecon->array), cil_post_filecon_compare);
-	qsort(db->pirqcon->array, db->pirqcon->count, sizeof(db->pirqcon->array), cil_post_pirqcon_compare);
-	qsort(db->iomemcon->array, db->iomemcon->count, sizeof(db->iomemcon->array), cil_post_iomemcon_compare);
-	qsort(db->ioportcon->array, db->ioportcon->count, sizeof(db->ioportcon->array), cil_post_ioportcon_compare);
-	qsort(db->pcidevicecon->array, db->pcidevicecon->count, sizeof(db->pcidevicecon->array), cil_post_pcidevicecon_compare);
-	qsort(db->devicetreecon->array, db->devicetreecon->count, sizeof(db->devicetreecon->array), cil_post_devicetreecon_compare);
+	rc = __cil_post_process_context_rules(db->netifcon, cil_post_netifcon_compare, cil_post_netifcon_context_compare, db, CIL_NETIFCON, CIL_KEY_NETIFCON);
+	if (rc != SEPOL_OK) {
+		cil_log(CIL_ERR, "Problems processing netifcon rules\n");
+		goto exit;
+	}
+
+	rc = __cil_post_process_context_rules(db->genfscon, cil_post_genfscon_compare, cil_post_genfscon_context_compare, db, CIL_GENFSCON, CIL_KEY_GENFSCON);
+	if (rc != SEPOL_OK) {
+		cil_log(CIL_ERR, "Problems processing genfscon rules\n");
+		goto exit;
+	}
+
+	rc = __cil_post_process_context_rules(db->ibpkeycon, cil_post_ibpkeycon_compare, cil_post_ibpkeycon_context_compare, db, CIL_IBPKEYCON, CIL_KEY_IBPKEYCON);
+	if (rc != SEPOL_OK) {
+		cil_log(CIL_ERR, "Problems processing ibpkeycon rules\n");
+		goto exit;
+	}
+
+	rc = __cil_post_process_context_rules(db->ibendportcon, cil_post_ibendportcon_compare, cil_post_ibendportcon_context_compare, db, CIL_IBENDPORTCON, CIL_KEY_IBENDPORTCON);
+	if (rc != SEPOL_OK) {
+		cil_log(CIL_ERR, "Problems processing ibendportcon rules\n");
+		goto exit;
+	}
+
+	rc = __cil_post_process_context_rules(db->portcon, cil_post_portcon_compare, cil_post_portcon_context_compare, db, CIL_PORTCON, CIL_KEY_PORTCON);
+	if (rc != SEPOL_OK) {
+		cil_log(CIL_ERR, "Problems processing portcon rules\n");
+		goto exit;
+	}
+
+	rc = __cil_post_process_context_rules(db->nodecon, cil_post_nodecon_compare, cil_post_nodecon_context_compare, db, CIL_NODECON, CIL_KEY_NODECON);
+	if (rc != SEPOL_OK) {
+		cil_log(CIL_ERR, "Problems processing nodecon rules\n");
+		goto exit;
+	}
+
+	rc = __cil_post_process_context_rules(db->fsuse, cil_post_fsuse_compare, cil_post_fsuse_context_compare, db, CIL_FSUSE, CIL_KEY_FSUSE);
+	if (rc != SEPOL_OK) {
+		cil_log(CIL_ERR, "Problems processing fsuse rules\n");
+		goto exit;
+	}
+
+	rc = __cil_post_process_context_rules(db->filecon, cil_post_filecon_compare, cil_post_filecon_context_compare, db, CIL_FILECON, CIL_KEY_FILECON);
+	if (rc != SEPOL_OK) {
+		cil_log(CIL_ERR, "Problems processing filecon rules\n");
+		goto exit;
+	}
+
+	rc = __cil_post_process_context_rules(db->iomemcon, cil_post_iomemcon_compare, cil_post_iomemcon_context_compare, db, CIL_IOMEMCON, CIL_KEY_IOMEMCON);
+	if (rc != SEPOL_OK) {
+		cil_log(CIL_ERR, "Problems processing iomemcon rules\n");
+		goto exit;
+	}
+
+	rc = __cil_post_process_context_rules(db->ioportcon, cil_post_ioportcon_compare, cil_post_ioportcon_context_compare, db, CIL_IOPORTCON, CIL_KEY_IOPORTCON);
+	if (rc != SEPOL_OK) {
+		cil_log(CIL_ERR, "Problems processing ioportcon rules\n");
+		goto exit;
+	}
+
+	rc = __cil_post_process_context_rules(db->pcidevicecon, cil_post_pcidevicecon_compare, cil_post_pcidevicecon_context_compare, db, CIL_PCIDEVICECON, CIL_KEY_PCIDEVICECON);
+	if (rc != SEPOL_OK) {
+		cil_log(CIL_ERR, "Problems processing pcidevicecon rules\n");
+		goto exit;
+	}
+
+	rc = __cil_post_process_context_rules(db->devicetreecon, cil_post_devicetreecon_compare, cil_post_devicetreecon_context_compare, db, CIL_DEVICETREECON, CIL_KEY_DEVICETREECON);
+	if (rc != SEPOL_OK) {
+		cil_log(CIL_ERR, "Problems processing devicetreecon rules\n");
+		goto exit;
+	}
 
 exit:
 	return rc;
-- 
2.13.6




[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux