aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Carter <jwcart2@tycho.nsa.gov>2018-03-28 15:47:22 -0400
committerJeff Vander Stoep <jeffv@google.com>2018-04-04 11:01:12 -0700
commit742a350d2900305e4748b9a49cb07b6a422ab610 (patch)
tree49827cddb0aa23276b7b3ec0dff56953caa5cc28
parentf947ce012ddeda735bd402bcfe8e64e030ac9429 (diff)
downloadselinux-p-preview-2.tar.gz
libsepol/cil: Improve processing of context rulesandroid-p-preview-2p-preview-2
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@phh.me) Signed-off-by: James Carter <jwcart2@tycho.nsa.gov> (cherry picked from commit 4ba19b541d066d9b0aa104deefc093f468d3d8a2) Bug: 72878750 Test: build and boot taimen-userdebug to verify the compiler changes during build time. Test: build and boot aosp_sailfish-userdebug to verify the compiler changes during boot. Change-Id: Id9e6feee3b3a6cbbf628085633af8ca343861c08
-rw-r--r--libsepol/cil/src/cil_post.c331
1 files 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;