Skip to content

Commit

Permalink
libsepol/cil: Use AST to track blocks and optionals when resolving
Browse files Browse the repository at this point in the history
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 <jwcart2@gmail.com>
  • Loading branch information
jwcart2 committed Apr 19, 2021
1 parent ab90cb4 commit 525f031
Showing 1 changed file with 32 additions and 75 deletions.
107 changes: 32 additions & 75 deletions libsepol/cil/src/cil_resolve_ast.c
Expand Up @@ -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;
Expand Down Expand Up @@ -3777,16 +3777,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));
Expand All @@ -3795,7 +3795,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;
Expand Down Expand Up @@ -3849,11 +3849,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));
Expand All @@ -3876,39 +3876,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) {
Expand All @@ -3927,7 +3906,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;
Expand All @@ -3938,30 +3916,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;
Expand All @@ -3970,16 +3949,6 @@ int __cil_resolve_ast_last_child_helper(struct cil_tree_node *current, void *ext
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;
Expand All @@ -3994,7 +3963,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;
Expand All @@ -4003,7 +3973,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);
Expand Down Expand Up @@ -4107,17 +4076,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;
}
}

Expand All @@ -4128,8 +4087,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);
Expand Down

0 comments on commit 525f031

Please sign in to comment.