libsepol/cil: Only reset AST if optional has a declaration

When disabling optionals, the AST needs to be reset only if one
of the optional blocks being disabled contains a declaration.

Call the function cil_tree_subtree_has_decl() for each optional
block being disabled and only reset the AST if one of them has
a declaration in it.

Signed-off-by: James Carter <jwcart2@gmail.com>
This commit is contained in:
James Carter 2021-06-24 15:58:15 -04:00 committed by Nicolas Iooss
parent 20271849d5
commit 4ff514a33e
No known key found for this signature in database
GPG Key ID: C191415F340DAAA0

View File

@ -4230,33 +4230,43 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current)
if (changed) {
struct cil_list_item *item;
if (pass > CIL_PASS_CALL1) {
/* Need to re-resolve because an optional was disabled that contained
* one or more declarations. We only need to reset to the call1 pass
* because things done in the preceding passes aren't allowed in
* optionals, and thus can't be disabled.
* Note: set pass to CIL_PASS_CALL1 because the pass++ will increment
* it to CIL_PASS_CALL2
*/
cil_log(CIL_INFO, "Resetting declarations\n");
int has_decls = CIL_FALSE;
if (pass >= CIL_PASS_MISC1) {
__cil_ordered_lists_reset(&extra_args.sidorder_lists);
__cil_ordered_lists_reset(&extra_args.classorder_lists);
__cil_ordered_lists_reset(&extra_args.unordered_classorder_lists);
__cil_ordered_lists_reset(&extra_args.catorder_lists);
__cil_ordered_lists_reset(&extra_args.sensitivityorder_lists);
cil_list_destroy(&db->sidorder, CIL_FALSE);
cil_list_destroy(&db->classorder, CIL_FALSE);
cil_list_destroy(&db->catorder, CIL_FALSE);
cil_list_destroy(&db->sensitivityorder, CIL_FALSE);
cil_list_for_each(item, extra_args.to_destroy) {
has_decls = cil_tree_subtree_has_decl(item->data);
if (has_decls) {
break;
}
}
pass = CIL_PASS_CALL1;
if (has_decls) {
/* Need to re-resolve because an optional was disabled that
* contained one or more declarations.
* Everything that needs to be reset comes after the
* CIL_PASS_CALL2 pass. We set pass to CIL_PASS_CALL1 because
* the pass++ will increment it to CIL_PASS_CALL2
*/
cil_log(CIL_INFO, "Resetting declarations\n");
rc = cil_reset_ast(current);
if (rc != SEPOL_OK) {
cil_log(CIL_ERR, "Failed to reset declarations\n");
goto exit;
if (pass >= CIL_PASS_MISC1) {
__cil_ordered_lists_reset(&extra_args.sidorder_lists);
__cil_ordered_lists_reset(&extra_args.classorder_lists);
__cil_ordered_lists_reset(&extra_args.unordered_classorder_lists);
__cil_ordered_lists_reset(&extra_args.catorder_lists);
__cil_ordered_lists_reset(&extra_args.sensitivityorder_lists);
cil_list_destroy(&db->sidorder, CIL_FALSE);
cil_list_destroy(&db->classorder, CIL_FALSE);
cil_list_destroy(&db->catorder, CIL_FALSE);
cil_list_destroy(&db->sensitivityorder, CIL_FALSE);
}
pass = CIL_PASS_CALL1;
rc = cil_reset_ast(current);
if (rc != SEPOL_OK) {
cil_log(CIL_ERR, "Failed to reset declarations\n");
goto exit;
}
}
}
cil_list_for_each(item, extra_args.to_destroy) {