From 599c1422479ae9dd9501c43680bf4a1667e7c951 Mon Sep 17 00:00:00 2001 From: James Carter Date: Tue, 30 Mar 2021 13:39:15 -0400 Subject: [PATCH] libsepol/cil: Use AST to track blocks and optionals when resolving When resolving the AST, block and optional stacks are used to determine if the current rule being resolved is in a block or an optional. There is no need to do this since the parent node pointers can be used when exiting a block or an optional to determine if resolution is still within a block or an optional. When entering either a block or an optional, update the appropriate tree node pointer. When finished with the last child of a block or optional, set the appropriate pointer to NULL. If a parent of the same kind is found when the parent node pointers are followed back to the root node, then set the pointer to that tree node. Signed-off-by: James Carter --- libsepol/cil/src/cil_resolve_ast.c | 107 +++++++++-------------------- 1 file changed, 32 insertions(+), 75 deletions(-) diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c index dab8b276..e0379782 100644 --- a/libsepol/cil/src/cil_resolve_ast.c +++ b/libsepol/cil/src/cil_resolve_ast.c @@ -52,10 +52,10 @@ struct cil_args_resolve { enum cil_pass pass; uint32_t *changed; struct cil_list *disabled_optionals; - struct cil_tree_node *optstack; + struct cil_tree_node *optional; struct cil_tree_node *boolif; struct cil_tree_node *macro; - struct cil_tree_node *blockstack; + struct cil_tree_node *block; struct cil_list *sidorder_lists; struct cil_list *classorder_lists; struct cil_list *unordered_classorder_lists; @@ -3692,16 +3692,16 @@ int __cil_resolve_ast_node_helper(struct cil_tree_node *node, uint32_t *finished int rc = SEPOL_ERR; struct cil_args_resolve *args = extra_args; enum cil_pass pass = args->pass; - struct cil_tree_node *optstack = args->optstack; + struct cil_tree_node *optional = args->optional; struct cil_tree_node *boolif = args->boolif; - struct cil_tree_node *blockstack = args->blockstack; + struct cil_tree_node *block = args->block; struct cil_tree_node *macro = args->macro; if (node == NULL) { goto exit; } - if (optstack != NULL) { + if (optional != NULL) { if (node->flavor == CIL_TUNABLE || node->flavor == CIL_MACRO) { /* tuanbles and macros are not allowed in optionals*/ cil_tree_log(node, CIL_ERR, "%s statement is not allowed in optionals", cil_node_to_string(node)); @@ -3710,7 +3710,7 @@ int __cil_resolve_ast_node_helper(struct cil_tree_node *node, uint32_t *finished } } - if (blockstack != NULL) { + if (block != NULL) { if (node->flavor == CIL_CAT || node->flavor == CIL_SENS) { cil_tree_log(node, CIL_ERR, "%s statement is not allowed in blocks", cil_node_to_string(node)); rc = SEPOL_ERR; @@ -3764,11 +3764,11 @@ int __cil_resolve_ast_node_helper(struct cil_tree_node *node, uint32_t *finished if (rc == SEPOL_ENOENT) { enum cil_log_level lvl = CIL_ERR; - if (optstack != NULL) { + if (optional != NULL) { lvl = CIL_INFO; - struct cil_optional *opt = (struct cil_optional *)optstack->data; - struct cil_tree_node *opt_node = opt->datum.nodes->head->data; + struct cil_optional *opt = (struct cil_optional *)optional->data; + struct cil_tree_node *opt_node = NODE(opt);; /* disable an optional if something failed to resolve */ opt->enabled = CIL_FALSE; cil_tree_log(node, lvl, "Failed to resolve %s statement", cil_node_to_string(node)); @@ -3791,39 +3791,18 @@ int __cil_resolve_ast_first_child_helper(struct cil_tree_node *current, void *ex { int rc = SEPOL_ERR; struct cil_args_resolve *args = extra_args; - struct cil_tree_node *optstack = NULL; struct cil_tree_node *parent = NULL; - struct cil_tree_node *blockstack = NULL; - struct cil_tree_node *new = NULL; if (current == NULL || extra_args == NULL) { goto exit; } - optstack = args->optstack; parent = current->parent; - blockstack = args->blockstack; - if (parent->flavor == CIL_OPTIONAL || parent->flavor == CIL_BLOCK) { - /* push this node onto a stack */ - cil_tree_node_init(&new); - - new->data = parent->data; - new->flavor = parent->flavor; - - if (parent->flavor == CIL_OPTIONAL) { - if (optstack != NULL) { - optstack->parent = new; - new->cl_head = optstack; - } - args->optstack = new; - } else if (parent->flavor == CIL_BLOCK) { - if (blockstack != NULL) { - blockstack->parent = new; - new->cl_head = blockstack; - } - args->blockstack = new; - } + if (parent->flavor == CIL_BLOCK) { + args->block = parent; + } else if (parent->flavor == CIL_OPTIONAL) { + args->optional = parent; } else if (parent->flavor == CIL_BOOLEANIF) { args->boolif = parent; } else if (parent->flavor == CIL_MACRO) { @@ -3842,7 +3821,6 @@ int __cil_resolve_ast_last_child_helper(struct cil_tree_node *current, void *ext int rc = SEPOL_ERR; struct cil_args_resolve *args = extra_args; struct cil_tree_node *parent = NULL; - struct cil_tree_node *blockstack = NULL; if (current == NULL || extra_args == NULL) { goto exit; @@ -3853,30 +3831,31 @@ int __cil_resolve_ast_last_child_helper(struct cil_tree_node *current, void *ext if (parent->flavor == CIL_MACRO) { args->macro = NULL; } else if (parent->flavor == CIL_OPTIONAL) { - struct cil_tree_node *optstack; - + struct cil_tree_node *n = parent->parent; if (((struct cil_optional *)parent->data)->enabled == CIL_FALSE) { *(args->changed) = CIL_TRUE; cil_list_append(args->disabled_optionals, CIL_NODE, parent); } - - /* pop off the stack */ - optstack = args->optstack; - args->optstack = optstack->cl_head; - if (optstack->cl_head) { - optstack->cl_head->parent = NULL; + args->optional = NULL; + while (n && n->flavor != CIL_ROOT) { + if (n->flavor == CIL_OPTIONAL) { + args->optional = n; + break; + } + n = n->parent; } - free(optstack); } else if (parent->flavor == CIL_BOOLEANIF) { args->boolif = NULL; } else if (parent->flavor == CIL_BLOCK) { - /* pop off the stack */ - blockstack = args->blockstack; - args->blockstack = blockstack->cl_head; - if (blockstack->cl_head) { - blockstack->cl_head->parent = NULL; + struct cil_tree_node *n = parent->parent; + args->block = NULL; + while (n && n->flavor != CIL_ROOT) { + if (n->flavor == CIL_BLOCK) { + args->block = n; + break; + } + n = n->parent; } - free(blockstack); } return SEPOL_OK; @@ -3885,16 +3864,6 @@ exit: return rc; } -static void cil_destroy_tree_node_stack(struct cil_tree_node *curr) -{ - struct cil_tree_node *next; - while (curr != NULL) { - next = curr->cl_head; - free(curr); - curr = next; - } -} - int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current) { int rc = SEPOL_ERR; @@ -3909,7 +3878,8 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current) extra_args.db = db; extra_args.pass = pass; extra_args.changed = &changed; - extra_args.optstack = NULL; + extra_args.block = NULL; + extra_args.optional = NULL; extra_args.boolif= NULL; extra_args.macro = NULL; extra_args.sidorder_lists = NULL; @@ -3918,7 +3888,6 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current) extra_args.catorder_lists = NULL; extra_args.sensitivityorder_lists = NULL; extra_args.in_list = NULL; - extra_args.blockstack = NULL; cil_list_init(&extra_args.disabled_optionals, CIL_NODE); cil_list_init(&extra_args.sidorder_lists, CIL_LIST_ITEM); @@ -4022,17 +3991,7 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current) } cil_list_destroy(&extra_args.disabled_optionals, CIL_FALSE); cil_list_init(&extra_args.disabled_optionals, CIL_NODE); - } - - /* reset the arguments */ - changed = 0; - while (extra_args.optstack != NULL) { - cil_destroy_tree_node_stack(extra_args.optstack); - extra_args.optstack = NULL; - } - while (extra_args.blockstack!= NULL) { - cil_destroy_tree_node_stack(extra_args.blockstack); - extra_args.blockstack = NULL; + changed = 0; } } @@ -4043,8 +4002,6 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current) rc = SEPOL_OK; exit: - cil_destroy_tree_node_stack(extra_args.optstack); - cil_destroy_tree_node_stack(extra_args.blockstack); __cil_ordered_lists_destroy(&extra_args.sidorder_lists); __cil_ordered_lists_destroy(&extra_args.classorder_lists); __cil_ordered_lists_destroy(&extra_args.catorder_lists); -- 2.30.2