summarylogtreecommitdiffstats
path: root/0007-libsepol-cil-Verify-neither-child-nor-parent-in-a-bo.patch
diff options
context:
space:
mode:
Diffstat (limited to '0007-libsepol-cil-Verify-neither-child-nor-parent-in-a-bo.patch')
-rw-r--r--0007-libsepol-cil-Verify-neither-child-nor-parent-in-a-bo.patch137
1 files changed, 137 insertions, 0 deletions
diff --git a/0007-libsepol-cil-Verify-neither-child-nor-parent-in-a-bo.patch b/0007-libsepol-cil-Verify-neither-child-nor-parent-in-a-bo.patch
new file mode 100644
index 000000000000..bed074d59a06
--- /dev/null
+++ b/0007-libsepol-cil-Verify-neither-child-nor-parent-in-a-bo.patch
@@ -0,0 +1,137 @@
+From ab1b88b4e9938048bafabeab7c87c456a5f96196 Mon Sep 17 00:00:00 2001
+From: James Carter <jwcart2@tycho.nsa.gov>
+Date: Tue, 18 Oct 2016 14:50:48 -0400
+Subject: [PATCH] libsepol/cil: Verify neither child nor parent in a bounds is
+ an attribute
+
+Nicolas Iooss found while fuzzing secilc with AFL that using an attribute
+as a child in a typebounds statement will cause a segfault.
+
+This happens because the child datum is assumed to be part of a cil_type
+struct when it is really part of a cil_typeattribute struct. The check to
+verify that it is a type and not an attribute comes after it is used.
+
+This bug effects user and role bounds as well because they do not check
+whether a datum refers to an attribute or not.
+
+Add checks to verify that neither the child nor the parent datum refer
+to an attribute before using them in user, role, and type bounds.
+
+Signed-off-by: James Carter <jwcart2@tycho.nsa.gov>
+---
+ libsepol/cil/src/cil_resolve_ast.c | 44 ++++++++++++++++----------------------
+ 1 file changed, 18 insertions(+), 26 deletions(-)
+
+diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
+index 149e4f4e7d42..ec547d38125d 100644
+--- a/libsepol/cil/src/cil_resolve_ast.c
++++ b/libsepol/cil/src/cil_resolve_ast.c
+@@ -2468,7 +2468,7 @@ exit:
+ }
+
+
+-int cil_resolve_bounds(struct cil_tree_node *current, void *extra_args, enum cil_flavor flavor)
++int cil_resolve_bounds(struct cil_tree_node *current, void *extra_args, enum cil_flavor flavor, enum cil_flavor attr_flavor)
+ {
+ int rc = SEPOL_ERR;
+ struct cil_bounds *bounds = current->data;
+@@ -2485,19 +2485,29 @@ int cil_resolve_bounds(struct cil_tree_node *current, void *extra_args, enum cil
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
++ if (NODE(parent_datum)->flavor == attr_flavor) {
++ cil_log(CIL_ERR, "Bounds parent %s is an attribute\n", bounds->parent_str);
++ rc = SEPOL_ERR;
++ goto exit;
++ }
++
+
+ rc = cil_resolve_name(current, bounds->child_str, index, extra_args, &child_datum);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
++ if (NODE(child_datum)->flavor == attr_flavor) {
++ cil_log(CIL_ERR, "Bounds child %s is an attribute\n", bounds->child_str);
++ rc = SEPOL_ERR;
++ goto exit;
++ }
+
+ switch (flavor) {
+ case CIL_USER: {
+ struct cil_user *user = (struct cil_user *)child_datum;
+
+ if (user->bounds != NULL) {
+- struct cil_tree_node *node = user->bounds->datum.nodes->head->data;
+- cil_tree_log(node, CIL_ERR, "User %s already bound by parent", bounds->child_str);
++ cil_tree_log(NODE(user->bounds), CIL_ERR, "User %s already bound by parent", bounds->child_str);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+@@ -2509,8 +2519,7 @@ int cil_resolve_bounds(struct cil_tree_node *current, void *extra_args, enum cil
+ struct cil_role *role = (struct cil_role *)child_datum;
+
+ if (role->bounds != NULL) {
+- struct cil_tree_node *node = role->bounds->datum.nodes->head->data;
+- cil_tree_log(node, CIL_ERR, "Role %s already bound by parent", bounds->child_str);
++ cil_tree_log(NODE(role->bounds), CIL_ERR, "Role %s already bound by parent", bounds->child_str);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+@@ -2520,26 +2529,9 @@ int cil_resolve_bounds(struct cil_tree_node *current, void *extra_args, enum cil
+ }
+ case CIL_TYPE: {
+ struct cil_type *type = (struct cil_type *)child_datum;
+- struct cil_tree_node *node = NULL;
+
+ if (type->bounds != NULL) {
+- node = ((struct cil_symtab_datum *)type->bounds)->nodes->head->data;
+- cil_tree_log(node, CIL_ERR, "Type %s already bound by parent", bounds->child_str);
+- cil_tree_log(current, CIL_ERR, "Now being bound to parent %s", bounds->parent_str);
+- rc = SEPOL_ERR;
+- goto exit;
+- }
+-
+- node = parent_datum->nodes->head->data;
+- if (node->flavor == CIL_TYPEATTRIBUTE) {
+- cil_log(CIL_ERR, "Bounds parent %s is an attribute\n", bounds->parent_str);
+- rc = SEPOL_ERR;
+- goto exit;
+- }
+-
+- node = child_datum->nodes->head->data;
+- if (node->flavor == CIL_TYPEATTRIBUTE) {
+- cil_log(CIL_ERR, "Bounds child %s is an attribute\n", bounds->child_str);
++ cil_tree_log(NODE(type->bounds), CIL_ERR, "Type %s already bound by parent", bounds->child_str);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+@@ -3445,7 +3437,7 @@ int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args)
+ rc = cil_resolve_typeattributeset(node, args);
+ break;
+ case CIL_TYPEBOUNDS:
+- rc = cil_resolve_bounds(node, args, CIL_TYPE);
++ rc = cil_resolve_bounds(node, args, CIL_TYPE, CIL_TYPEATTRIBUTE);
+ break;
+ case CIL_TYPEPERMISSIVE:
+ rc = cil_resolve_typepermissive(node, args);
+@@ -3482,7 +3474,7 @@ int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args)
+ rc = cil_resolve_userrange(node, args);
+ break;
+ case CIL_USERBOUNDS:
+- rc = cil_resolve_bounds(node, args, CIL_USER);
++ rc = cil_resolve_bounds(node, args, CIL_USER, CIL_USERATTRIBUTE);
+ break;
+ case CIL_USERPREFIX:
+ rc = cil_resolve_userprefix(node, args);
+@@ -3504,7 +3496,7 @@ int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args)
+ rc = cil_resolve_roleallow(node, args);
+ break;
+ case CIL_ROLEBOUNDS:
+- rc = cil_resolve_bounds(node, args, CIL_ROLE);
++ rc = cil_resolve_bounds(node, args, CIL_ROLE, CIL_ROLEATTRIBUTE);
+ break;
+ case CIL_LEVEL:
+ rc = cil_resolve_level(node, (struct cil_level*)node->data, args);
+--
+2.10.2
+