[PATCH 1/6] libsepol/cil: Handle disabled optional blocks in earlier passes

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



A failed tunable resolution in a tunableif can cause an optional
to be disabled before the CIL_PASS_CALL1 phase. If this occurs, the
optional block and its subtree should be destroyed, but no reset
will be required since tunables are not allowed inside an optional
block.

Anytime there are optional blocks in the disabled_optionals list
(changed == 1), destroy the optional block and its subtree even if
in a pass before CIL_PASS_CALL1.

This bug was found by the secilc-fuzzer.

Signed-off-by: James Carter <jwcart2@xxxxxxxxx>
---
 libsepol/cil/src/cil_resolve_ast.c | 54 ++++++++++++++++--------------
 1 file changed, 28 insertions(+), 26 deletions(-)

diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
index 5368ae80..242aea4a 100644
--- a/libsepol/cil/src/cil_resolve_ast.c
+++ b/libsepol/cil/src/cil_resolve_ast.c
@@ -4099,35 +4099,37 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current)
 			}
 		}
 
-		if (changed && (pass > CIL_PASS_CALL1)) {
+		if (changed) {
 			struct cil_list_item *item;
-			/* 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");
-
-			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);
-			}
+			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");
+
+				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;
+				pass = CIL_PASS_CALL1;
 
-			rc = cil_reset_ast(current);
-			if (rc != SEPOL_OK) {
-				cil_log(CIL_ERR, "Failed to reset declarations\n");
-				goto exit;
+				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.disabled_optionals) {
 				cil_tree_children_destroy(item->data);
-- 
2.26.3




[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux