diff --git a/backport-libsepol-cil-Allow-duplicate-optional-blocks-in-most.patch b/backport-libsepol-cil-Allow-duplicate-optional-blocks-in-most.patch new file mode 100644 index 0000000000000000000000000000000000000000..bb2af7081d47aba591734ae878a3a8ffe1531b5f --- /dev/null +++ b/backport-libsepol-cil-Allow-duplicate-optional-blocks-in-most.patch @@ -0,0 +1,276 @@ +From 67a8dc8117e0c3887c39f7add8932e4ad23c1d9c Mon Sep 17 00:00:00 2001 +From: James Carter +Date: Wed, 16 Jun 2021 17:04:00 -0400 +Subject: [PATCH] libsepol/cil: Allow duplicate optional blocks in most cases + +The commit d155b410d4bbc90d28f361b966f0429598da8188 (libsepol/cil: +Check for duplicate blocks, optionals, and macros) fixed a bug +that allowed duplicate blocks, optionals, and macros with the same +name in the same namespace. For blocks and macros, a duplicate +is always a problem, but optional block names are only used for +in-statement resolution. If no in-statement refers to an optional +block, then it does not matter if more than one with same name +exists. + +One easy way to generate multiple optional blocks with the same +name declaration is to call a macro with an optional block multiple +times in the same namespace. + +As an example, here is a portion of CIL policy + (macro m1 ((type t)) + (optional op1 + (allow t self (CLASS (PERM))) + ) + ) + (type t1) + (call m1 (t1)) + (type t2) + (call m1 (t2)) +This will result in two optional blocks with the name op1. + +There are three parts to allowing multiple optional blocks with +the same name declaration. + +1) Track an optional block's enabled status in a different way. + + One hinderance to allowing multiple optional blocks with the same + name declaration is that they cannot share the same datum. This is + because the datum is used to get the struct cil_optional which has + the enabled field and each block's enabled status is independent of + the others. + + Remove the enabled field from struct cil_optional, so it only contains + the datum. Use a stack to track which optional blocks are being + disabled, so they can be deleted in the right order. + +2) Allow multiple declarations of optional blocks. + + Update cil_allow_multiple_decls() so that a flavor of CIL_OPTIONAL + will return CIL_TRUE. Also remove the check in cil_copy_optional(). + +3) Check if an in-statement refers to an optional with multiple + declarations and exit with an error if it does. + +Signed-off-by: James Carter +Acked-by: Nicolas Iooss +--- + libsepol/cil/src/cil.c | 1 - + libsepol/cil/src/cil_build_ast.c | 3 +++ + libsepol/cil/src/cil_copy_ast.c | 11 +------- + libsepol/cil/src/cil_internal.h | 1 - + libsepol/cil/src/cil_resolve_ast.c | 55 +++++++++++++++++++++++--------------- + 5 files changed, 37 insertions(+), 34 deletions(-) + +diff --git a/libsepol/cil/src/cil.c b/libsepol/cil/src/cil.c +index 0d351b4..671b5ec 100644 +--- a/libsepol/cil/src/cil.c ++++ b/libsepol/cil/src/cil.c +@@ -2752,7 +2752,6 @@ void cil_call_init(struct cil_call **call) + void cil_optional_init(struct cil_optional **optional) + { + *optional = cil_malloc(sizeof(**optional)); +- (*optional)->enabled = CIL_TRUE; + cil_symtab_datum_init(&(*optional)->datum); + } + +diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c +index 71ddada..ea665a3 100644 +--- a/libsepol/cil/src/cil_build_ast.c ++++ b/libsepol/cil/src/cil_build_ast.c +@@ -96,6 +96,9 @@ static int cil_allow_multiple_decls(struct cil_db *db, enum cil_flavor f_new, en + return CIL_TRUE; + } + break; ++ case CIL_OPTIONAL: ++ return CIL_TRUE; ++ break; + default: + break; + } +diff --git a/libsepol/cil/src/cil_copy_ast.c b/libsepol/cil/src/cil_copy_ast.c +index 954eab3..9c0231f 100644 +--- a/libsepol/cil/src/cil_copy_ast.c ++++ b/libsepol/cil/src/cil_copy_ast.c +@@ -1529,19 +1529,10 @@ int cil_copy_macro(__attribute__((unused)) struct cil_db *db, void *data, void * + return SEPOL_OK; + } + +-int cil_copy_optional(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) ++int cil_copy_optional(__attribute__((unused)) struct cil_db *db, __attribute__((unused)) void *data, void **copy, __attribute__((unused)) symtab_t *symtab) + { +- struct cil_optional *orig = data; +- char *key = orig->datum.name; +- struct cil_symtab_datum *datum = NULL; + struct cil_optional *new; + +- cil_symtab_get_datum(symtab, key, &datum); +- if (datum != NULL) { +- cil_tree_log(NODE(datum), CIL_ERR, "Re-declaration of %s %s", cil_node_to_string(NODE(datum)), key); +- return SEPOL_ERR; +- } +- + cil_optional_init(&new); + *copy = new; + +diff --git a/libsepol/cil/src/cil_internal.h b/libsepol/cil/src/cil_internal.h +index a77c952..24be09a 100644 +--- a/libsepol/cil/src/cil_internal.h ++++ b/libsepol/cil/src/cil_internal.h +@@ -358,7 +358,6 @@ struct cil_in { + + struct cil_optional { + struct cil_symtab_datum datum; +- int enabled; + }; + + struct cil_perm { +diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c +index b5199ba..6d13544 100644 +--- a/libsepol/cil/src/cil_resolve_ast.c ++++ b/libsepol/cil/src/cil_resolve_ast.c +@@ -46,12 +46,13 @@ + #include "cil_verify.h" + #include "cil_strpool.h" + #include "cil_symtab.h" ++#include "cil_stack.h" + + struct cil_args_resolve { + struct cil_db *db; + enum cil_pass pass; + uint32_t *changed; +- struct cil_list *disabled_optionals; ++ struct cil_list *to_destroy; + struct cil_tree_node *block; + struct cil_tree_node *macro; + struct cil_tree_node *optional; +@@ -62,6 +63,7 @@ struct cil_args_resolve { + struct cil_list *catorder_lists; + struct cil_list *sensitivityorder_lists; + struct cil_list *in_list; ++ struct cil_stack *disabled_optionals; + }; + + static struct cil_name * __cil_insert_name(struct cil_db *db, hashtab_key_t key, struct cil_tree_node *ast_node) +@@ -2552,6 +2554,15 @@ int cil_resolve_in(struct cil_tree_node *current, void *extra_args) + + block_node = NODE(block_datum); + ++ if (block_node->flavor == CIL_OPTIONAL) { ++ if (block_datum->nodes && block_datum->nodes->head != block_datum->nodes->tail) { ++ cil_tree_log(current, CIL_ERR, "Multiple optional blocks referred to by in-statement"); ++ cil_tree_log(block_node, CIL_ERR, "First optional block"); ++ rc = SEPOL_ERR; ++ goto exit; ++ } ++ } ++ + rc = cil_copy_ast(db, current, block_node); + if (rc != SEPOL_OK) { + cil_tree_log(current, CIL_ERR, "Failed to copy in-statement"); +@@ -3874,6 +3885,7 @@ int __cil_resolve_ast_node_helper(struct cil_tree_node *node, uint32_t *finished + struct cil_tree_node *macro = args->macro; + struct cil_tree_node *optional = args->optional; + struct cil_tree_node *boolif = args->boolif; ++ struct cil_stack *disabled_optionals = args->disabled_optionals; + + if (node == NULL) { + goto exit; +@@ -3953,22 +3965,14 @@ int __cil_resolve_ast_node_helper(struct cil_tree_node *node, uint32_t *finished + + rc = __cil_resolve_ast_node(node, extra_args); + if (rc == SEPOL_ENOENT) { +- enum cil_log_level lvl = CIL_ERR; +- +- if (optional != NULL) { +- struct cil_optional *opt = (struct cil_optional *)optional->data; +- struct cil_tree_node *opt_node = NODE(opt); +- +- lvl = CIL_INFO; +- /* 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)); +- cil_tree_log(opt_node, lvl, "Disabling optional '%s'", opt->datum.name); ++ if (optional == NULL) { ++ cil_tree_log(node, CIL_ERR, "Failed to resolve %s statement", cil_node_to_string(node)); ++ } else { ++ cil_stack_push(disabled_optionals, CIL_NODE, optional); ++ cil_tree_log(node, CIL_INFO, "Failed to resolve %s statement", cil_node_to_string(node)); ++ cil_tree_log(optional, CIL_INFO, "Disabling optional '%s'", DATUM(optional->data)->name); + rc = SEPOL_OK; +- goto exit; + } +- +- cil_tree_log(node, lvl, "Failed to resolve %s statement", cil_node_to_string(node)); + goto exit; + } + +@@ -4011,6 +4015,7 @@ 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_stack *disabled_optionals = args->disabled_optionals; + struct cil_tree_node *parent = NULL; + + if (current == NULL || extra_args == NULL) { +@@ -4033,9 +4038,11 @@ int __cil_resolve_ast_last_child_helper(struct cil_tree_node *current, void *ext + args->macro = NULL; + } else if (parent->flavor == CIL_OPTIONAL) { + struct cil_tree_node *n = parent->parent; +- if (((struct cil_optional *)parent->data)->enabled == CIL_FALSE) { ++ struct cil_stack_item *item = cil_stack_peek(disabled_optionals); ++ if (item && item->data == parent) { ++ cil_stack_pop(disabled_optionals); + *(args->changed) = CIL_TRUE; +- cil_list_append(args->disabled_optionals, CIL_NODE, parent); ++ cil_list_append(args->to_destroy, CIL_NODE, parent); + } + args->optional = NULL; + while (n && n->flavor != CIL_ROOT) { +@@ -4079,14 +4086,17 @@ 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.disabled_optionals = NULL; + +- cil_list_init(&extra_args.disabled_optionals, CIL_NODE); ++ cil_list_init(&extra_args.to_destroy, CIL_NODE); + cil_list_init(&extra_args.sidorder_lists, CIL_LIST_ITEM); + cil_list_init(&extra_args.classorder_lists, CIL_LIST_ITEM); + cil_list_init(&extra_args.unordered_classorder_lists, CIL_LIST_ITEM); + cil_list_init(&extra_args.catorder_lists, CIL_LIST_ITEM); + cil_list_init(&extra_args.sensitivityorder_lists, CIL_LIST_ITEM); + cil_list_init(&extra_args.in_list, CIL_IN); ++ cil_stack_init(&extra_args.disabled_optionals); ++ + for (pass = CIL_PASS_TIF; pass < CIL_PASS_NUM; pass++) { + extra_args.pass = pass; + rc = cil_tree_walk(current, __cil_resolve_ast_node_helper, __cil_resolve_ast_first_child_helper, __cil_resolve_ast_last_child_helper, &extra_args); +@@ -4179,11 +4189,11 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current) + goto exit; + } + } +- cil_list_for_each(item, extra_args.disabled_optionals) { ++ cil_list_for_each(item, extra_args.to_destroy) { + cil_tree_children_destroy(item->data); + } +- cil_list_destroy(&extra_args.disabled_optionals, CIL_FALSE); +- cil_list_init(&extra_args.disabled_optionals, CIL_NODE); ++ cil_list_destroy(&extra_args.to_destroy, CIL_FALSE); ++ cil_list_init(&extra_args.to_destroy, CIL_NODE); + changed = 0; + } + } +@@ -4200,8 +4210,9 @@ exit: + __cil_ordered_lists_destroy(&extra_args.catorder_lists); + __cil_ordered_lists_destroy(&extra_args.sensitivityorder_lists); + __cil_ordered_lists_destroy(&extra_args.unordered_classorder_lists); +- cil_list_destroy(&extra_args.disabled_optionals, CIL_FALSE); ++ cil_list_destroy(&extra_args.to_destroy, CIL_FALSE); + cil_list_destroy(&extra_args.in_list, CIL_FALSE); ++ cil_stack_destroy(&extra_args.disabled_optionals); + + return rc; + } +-- +1.8.3.1 + diff --git a/backport-libsepol-cil-Allow-some-duplicate-macro-and-block-de.patch b/backport-libsepol-cil-Allow-some-duplicate-macro-and-block-de.patch new file mode 100644 index 0000000000000000000000000000000000000000..6f1540df22550acb0f1ab178ed5b68024ea8fdcc --- /dev/null +++ b/backport-libsepol-cil-Allow-some-duplicate-macro-and-block-de.patch @@ -0,0 +1,216 @@ +From 8d197879f91337c2c4d972a3dd23bb4b133ff355 Mon Sep 17 00:00:00 2001 +From: James Carter +Date: Mon, 16 Aug 2021 16:01:39 -0400 +Subject: [PATCH] libsepol/cil: Allow some duplicate macro and block + declarations + +The commit d155b410d4bbc90d28f361b966f0429598da8188 (libsepol/cil: +Check for duplicate blocks, optionals, and macros) added checks when +copying blocks, macros, and optionals so that a duplicate would cause +an exit with an error. Unfortunately, some policies exist that depend +on this behavior when using inheritance. + +The behavior is as follows. + +For macros only the first declared macro matters. +; +(macro m ((type ARG1)) + (allow ARG1 self (CLASS (PERM1))) +) +(block b + (macro m ((type ARG1)) + (allow ARG1 self (CLASS (PERM2))) + ) +) +(blockinherit b) +(type t) +(call m (t)) +; +For this policy segment, the macro m in block b will not be called. +Only the original macro m will be. + +This behavior has been used to override macros that are going to +be inherited. Only the inherited macros that have not already been +declared in the destination namespace will be used. + +Blocks seem to work fine even though there are two of them +; +(block b1 + (blockinherit b2) + (block b + (type t1) + (allow t1 self (CLASS (PERM))) + ) +) +(block b2 + (block b + (type t2) + (allow t2 self (CLASS (PERM))) + ) +) +(blockinherit b1) +; +In this example, the blockinherit of b2 will cause there to be +two block b's in block b1. Note that if both block b's tried to +declare the same type, then that would be an error. The blockinherit +of b1 will copy both block b's. + +This behavior has been used to allow the use of in-statements for +a block that is being inherited. Since the in-statements are resolved +before block inheritance, this only works if a block with the same +name as the block to be inherited is declared in the namespace. + +To support the use of these two behaviors, allow duplicate blocks +and macros when they occur as the result of block inheritance. In +any other circumstances and error for a redeclaration will be given. + +Since the duplicate macro is not going to be used it is just skipped. +The duplicate block will use the datum of the original block. In both +cases a warning message will be produced (it will only be seen if +"-v" is used when compiling the policy). + +Signed-off-by: James Carter +--- + libsepol/cil/src/cil_copy_ast.c | 69 +++++++++++++++++++++++++++++------------ + 1 file changed, 50 insertions(+), 19 deletions(-) + +diff --git a/libsepol/cil/src/cil_copy_ast.c b/libsepol/cil/src/cil_copy_ast.c +index 34282a9..cdbc84e 100644 +--- a/libsepol/cil/src/cil_copy_ast.c ++++ b/libsepol/cil/src/cil_copy_ast.c +@@ -43,6 +43,7 @@ + #include "cil_strpool.h" + + struct cil_args_copy { ++ struct cil_tree_node *orig_dest; + struct cil_tree_node *dest; + struct cil_db *db; + }; +@@ -101,17 +102,23 @@ int cil_copy_block(__attribute__((unused)) struct cil_db *db, void *data, void * + struct cil_block *orig = data; + char *key = orig->datum.name; + struct cil_symtab_datum *datum = NULL; +- struct cil_block *new; + + cil_symtab_get_datum(symtab, key, &datum); + if (datum != NULL) { +- cil_tree_log(NODE(datum), CIL_ERR, "Re-declaration of %s %s", cil_node_to_string(NODE(datum)), key); +- return SEPOL_ERR; ++ if (FLAVOR(datum) != CIL_BLOCK) { ++ cil_tree_log(NODE(orig), CIL_ERR, "Block %s being copied", key); ++ cil_tree_log(NODE(datum), CIL_ERR, " Conflicts with %s already declared", cil_node_to_string(NODE(datum))); ++ return SEPOL_ERR; ++ } ++ cil_tree_log(NODE(orig), CIL_WARN, "Block %s being copied", key); ++ cil_tree_log(NODE(datum), CIL_WARN, " Previously declared"); ++ *copy = datum; ++ } else { ++ struct cil_block *new; ++ cil_block_init(&new); ++ *copy = new; + } + +- cil_block_init(&new); +- *copy = new; +- + return SEPOL_OK; + } + +@@ -1511,21 +1518,26 @@ int cil_copy_macro(__attribute__((unused)) struct cil_db *db, void *data, void * + struct cil_macro *orig = data; + char *key = orig->datum.name; + struct cil_symtab_datum *datum = NULL; +- struct cil_macro *new; + + cil_symtab_get_datum(symtab, key, &datum); + if (datum != NULL) { +- cil_tree_log(NODE(datum), CIL_ERR, "Re-declaration of %s %s", cil_node_to_string(NODE(datum)), key); +- return SEPOL_ERR; +- } +- +- cil_macro_init(&new); +- if (orig->params != NULL) { +- cil_copy_list(orig->params, &new->params); ++ if (FLAVOR(datum) != CIL_MACRO) { ++ cil_tree_log(NODE(orig), CIL_ERR, "Macro %s being copied", key); ++ cil_tree_log(NODE(datum), CIL_ERR, " Conflicts with %s already declared", cil_node_to_string(NODE(datum))); ++ return SEPOL_ERR; ++ } ++ cil_tree_log(NODE(orig), CIL_WARN, "Skipping macro %s", key); ++ cil_tree_log(NODE(datum), CIL_WARN, " Previously declared"); ++ *copy = NULL; ++ } else { ++ struct cil_macro *new; ++ cil_macro_init(&new); ++ if (orig->params != NULL) { ++ cil_copy_list(orig->params, &new->params); ++ } ++ *copy = new; + } + +- *copy = new; +- + return SEPOL_OK; + } + +@@ -1701,7 +1713,7 @@ int cil_copy_src_info(__attribute__((unused)) struct cil_db *db, void *data, voi + return SEPOL_OK; + } + +-int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) uint32_t *finished, void *extra_args) ++int __cil_copy_node_helper(struct cil_tree_node *orig, uint32_t *finished, void *extra_args) + { + int rc = SEPOL_ERR; + struct cil_tree_node *parent = NULL; +@@ -2006,6 +2018,16 @@ int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) u + + rc = (*copy_func)(db, orig->data, &data, symtab); + if (rc == SEPOL_OK) { ++ if (orig->flavor == CIL_MACRO && data == NULL) { ++ /* Skipping macro re-declaration */ ++ if (args->orig_dest->flavor != CIL_BLOCKINHERIT) { ++ cil_log(CIL_ERR, " Re-declaration of macro is only allowed when inheriting a block\n"); ++ return SEPOL_ERR; ++ } ++ *finished = CIL_TREE_SKIP_HEAD; ++ return SEPOL_OK; ++ } ++ + cil_tree_node_init(&new); + + new->parent = parent; +@@ -2014,7 +2036,15 @@ int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) u + new->flavor = orig->flavor; + new->data = data; + +- if (orig->flavor >= CIL_MIN_DECLARATIVE) { ++ if (orig->flavor == CIL_BLOCK && DATUM(data)->nodes->head != NULL) { ++ /* Duplicate block */ ++ if (args->orig_dest->flavor != CIL_BLOCKINHERIT) { ++ cil_log(CIL_ERR, " Re-declaration of block is only allowed when inheriting a block\n"); ++ rc = SEPOL_ERR; ++ goto exit; ++ } ++ cil_list_append(DATUM(new->data)->nodes, CIL_NODE, new); ++ } else if (orig->flavor >= CIL_MIN_DECLARATIVE) { + /* Check the flavor of data if was found in the destination symtab */ + if (DATUM(data)->nodes->head && FLAVOR(data) != orig->flavor) { + cil_tree_log(orig, CIL_ERR, "Incompatible flavor when trying to copy %s", DATUM(data)->name); +@@ -2099,12 +2129,13 @@ int cil_copy_ast(struct cil_db *db, struct cil_tree_node *orig, struct cil_tree_ + int rc = SEPOL_ERR; + struct cil_args_copy extra_args; + ++ extra_args.orig_dest = dest; + extra_args.dest = dest; + extra_args.db = db; + + rc = cil_tree_walk(orig, __cil_copy_node_helper, NULL, __cil_copy_last_child_helper, &extra_args); + if (rc != SEPOL_OK) { +- cil_log(CIL_INFO, "cil_tree_walk failed, rc: %d\n", rc); ++ cil_tree_log(dest, CIL_ERR, "Failed to copy %s to %s", cil_node_to_string(orig), cil_node_to_string(dest)); + goto exit; + } + +-- +1.8.3.1 + diff --git a/backport-libsepol-cil-Check-for-duplicate-blocks-optionals-an.patch b/backport-libsepol-cil-Check-for-duplicate-blocks-optionals-an.patch new file mode 100644 index 0000000000000000000000000000000000000000..fb44a586a0f304c3e9f60759ab71d1f169d809ad --- /dev/null +++ b/backport-libsepol-cil-Check-for-duplicate-blocks-optionals-an.patch @@ -0,0 +1,163 @@ +From d155b410d4bbc90d28f361b966f0429598da8188 Mon Sep 17 00:00:00 2001 +From: James Carter +Date: Tue, 16 Mar 2021 10:26:28 -0400 +Subject: [PATCH] libsepol/cil: Check for duplicate blocks, optionals, and + macros + +In CIL, blocks, optionals, and macros share the same symbol table so +that the targets of "in" statements can be located. Because of this, +they cannot have the same name in the same namespace, but, because +they do not show up in the final policy, they can have the same name +as long as they are in different namespaces. Unfortunately, when +copying from one namespace to another, no check was being done to see +if there was a conflict. + +When copying blocks, optionals, and macros, if a datum is found in +the destination namespace, then there is a conflict with a previously +declared block, optional, or macro, so exit with an error. + +Reported-by: Nicolas Iooss +Reported-by: Evgeny Vereshchagin +Signed-off-by: James Carter +--- + libsepol/cil/src/cil_copy_ast.c | 89 ++++++++++++----------------------------- + 1 file changed, 25 insertions(+), 64 deletions(-) + +diff --git a/libsepol/cil/src/cil_copy_ast.c b/libsepol/cil/src/cil_copy_ast.c +index c9aada9..ed96786 100644 +--- a/libsepol/cil/src/cil_copy_ast.c ++++ b/libsepol/cil/src/cil_copy_ast.c +@@ -100,16 +100,17 @@ int cil_copy_block(__attribute__((unused)) struct cil_db *db, void *data, void * + struct cil_block *orig = data; + char *key = orig->datum.name; + struct cil_symtab_datum *datum = NULL; ++ struct cil_block *new; + + cil_symtab_get_datum(symtab, key, &datum); +- if (datum == NULL) { +- struct cil_block *new; +- cil_block_init(&new); +- *copy = new; +- } else { +- *copy = datum;; ++ if (datum != NULL) { ++ cil_tree_log(NODE(datum), CIL_ERR, "Re-declaration of %s %s", cil_node_to_string(NODE(datum)), key); ++ return SEPOL_ERR; + } + ++ cil_block_init(&new); ++ *copy = new; ++ + return SEPOL_OK; + } + +@@ -1509,64 +1510,22 @@ int cil_copy_macro(__attribute__((unused)) struct cil_db *db, void *data, void * + struct cil_macro *orig = data; + char *key = orig->datum.name; + struct cil_symtab_datum *datum = NULL; ++ struct cil_macro *new; + + cil_symtab_get_datum(symtab, key, &datum); +- if (datum == NULL) { +- struct cil_macro *new; +- cil_macro_init(&new); +- if (orig->params != NULL) { +- cil_copy_list(orig->params, &new->params); +- } +- +- *copy = new; +- +- } else { +- struct cil_list_item *curr_orig = NULL; +- struct cil_list_item *curr_new = NULL; +- struct cil_param *param_orig = NULL; +- struct cil_param *param_new = NULL; +- +- if (((struct cil_macro*)datum)->params != NULL) { +- curr_new = ((struct cil_macro*)datum)->params->head; +- } +- +- if (orig->params != NULL) { +- curr_orig = orig->params->head; +- } +- +- if (curr_orig != NULL && curr_new != NULL) { +- while (curr_orig != NULL) { +- if (curr_new == NULL) { +- goto exit; +- } +- +- param_orig = (struct cil_param*)curr_orig->data; +- param_new = (struct cil_param*)curr_new->data; +- if (param_orig->str != param_new->str) { +- goto exit; +- } else if (param_orig->flavor != param_new->flavor) { +- goto exit; +- } +- +- curr_orig = curr_orig->next; +- curr_new = curr_new->next; +- } +- +- if (curr_new != NULL) { +- goto exit; +- } +- } else if (!(curr_orig == NULL && curr_new == NULL)) { +- goto exit; +- } ++ if (datum != NULL) { ++ cil_tree_log(NODE(datum), CIL_ERR, "Re-declaration of %s %s", cil_node_to_string(NODE(datum)), key); ++ return SEPOL_ERR; ++ } + +- *copy = datum; ++ cil_macro_init(&new); ++ if (orig->params != NULL) { ++ cil_copy_list(orig->params, &new->params); + } + +- return SEPOL_OK; ++ *copy = new; + +-exit: +- cil_log(CIL_INFO, "cil_copy_macro: macro cannot be redefined\n"); +- return SEPOL_ERR; ++ return SEPOL_OK; + } + + int cil_copy_optional(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) +@@ -1574,16 +1533,17 @@ int cil_copy_optional(__attribute__((unused)) struct cil_db *db, void *data, voi + struct cil_optional *orig = data; + char *key = orig->datum.name; + struct cil_symtab_datum *datum = NULL; ++ struct cil_optional *new; + + cil_symtab_get_datum(symtab, key, &datum); +- if (datum == NULL) { +- struct cil_optional *new; +- cil_optional_init(&new); +- *copy = new; +- } else { +- *copy = datum; ++ if (datum != NULL) { ++ cil_tree_log(NODE(datum), CIL_ERR, "Re-declaration of %s %s", cil_node_to_string(NODE(datum)), key); ++ return SEPOL_ERR; + } + ++ cil_optional_init(&new); ++ *copy = new; ++ + return SEPOL_OK; + } + +@@ -2122,6 +2082,7 @@ int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) u + args->dest = new; + } + } else { ++ cil_tree_log(orig, CIL_ERR, "Problem copying %s node", cil_node_to_string(orig)); + goto exit; + } + +-- +1.8.3.1 + diff --git a/backport-libsepol-cil-Check-for-empty-list-when-marking-never.patch b/backport-libsepol-cil-Check-for-empty-list-when-marking-never.patch new file mode 100644 index 0000000000000000000000000000000000000000..3e8e5a403620f801f95331e9a8cb0ad023c048fd --- /dev/null +++ b/backport-libsepol-cil-Check-for-empty-list-when-marking-never.patch @@ -0,0 +1,35 @@ +From f33745a22b4133c59059356a23dbbc229067e3c1 Mon Sep 17 00:00:00 2001 +From: James Carter +Date: Mon, 21 Jun 2021 10:56:43 -0400 +Subject: [PATCH] libsepol/cil: Check for empty list when marking neverallow + attributes + +When marking a type attribute as used in a neverallow (to help determine +whether or not it should be expanded), check if the attribute's expression +list is empty (no attributes are associated with it) before iterating +over the list. + +Signed-off-by: James Carter +Acked-by: Nicolas Iooss +--- + libsepol/cil/src/cil_post.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/libsepol/cil/src/cil_post.c b/libsepol/cil/src/cil_post.c +index 7bca083..7e2c2b9 100644 +--- a/libsepol/cil/src/cil_post.c ++++ b/libsepol/cil/src/cil_post.c +@@ -1494,6 +1494,10 @@ static void __mark_neverallow_attrs(struct cil_list *expr_list) + { + struct cil_list_item *curr; + ++ if (!expr_list) { ++ return; ++ } ++ + cil_list_for_each(curr, expr_list) { + if (curr->flavor == CIL_DATUM) { + if (FLAVOR(curr->data) == CIL_TYPEATTRIBUTE) { +-- +1.8.3.1 + diff --git a/backport-libsepol-cil-Destroy-disabled-optional-blocks-after-.patch b/backport-libsepol-cil-Destroy-disabled-optional-blocks-after-.patch new file mode 100644 index 0000000000000000000000000000000000000000..546a9551c901595d1a20b54d438ef24eeef05191 --- /dev/null +++ b/backport-libsepol-cil-Destroy-disabled-optional-blocks-after-.patch @@ -0,0 +1,115 @@ +From 0451adebdf153eee1f69914141311114a0130982 Mon Sep 17 00:00:00 2001 +From: James Carter +Date: Mon, 8 Feb 2021 11:23:42 -0500 +Subject: [PATCH] libsepol/cil: Destroy disabled optional blocks after pass is + complete + +Nicolas Iooss reports: + I am continuing to investigate OSS-Fuzz crashes and the following one + is quite complex. Here is a CIL policy which triggers a + heap-use-after-free error in the CIL compiler: + + (class CLASS (PERM2)) + (classorder (CLASS)) + (classpermission CLSPRM) + (optional o + (mlsvalidatetrans x (domby l1 h1)) + (common CLSCOMMON (PERM1)) + (classcommon CLASS CLSCOMMON) + ) + (classpermissionset CLSPRM (CLASS (PERM1))) + + The issue is that the mlsvalidatetrans fails to resolve in pass + CIL_PASS_MISC3, which comes after the resolution of classcommon (in + pass CIL_PASS_MISC2). So: + + * In pass CIL_PASS_MISC2, the optional block still exists, the + classcommon is resolved and class CLASS is linked with common + CLSCOMMON. + * In pass CIL_PASS_MISC3, the optional block is destroyed, including + the common CLSCOMMON. + * When classpermissionset is resolved, function cil_resolve_classperms + uses "common_symtab = &class->common->perms;", which has been freed. + The use-after-free issue occurs in __cil_resolve_perms (in + libsepol/cil/src/cil_resolve_ast.c): + + // common_symtab was freed + rc = cil_symtab_get_datum(common_symtab, curr->data, &perm_datum); + +The fundamental problem here is that when the optional block is +disabled it is immediately destroyed in the middle of the pass, so +the class has not been reset and still refers to the now destroyed +common when the classpermissionset is resolved later in the same pass. + +Added a list, disabled_optionals, to struct cil_args_resolve which is +passed when resolving the tree. When optionals are disabled, they are +now added to this list and then are destroyed after the tree has been +reset between passes. + +Reported-by: Nicolas Iooss +Signed-off-by: James Carter +Acked-by: Nicolas Iooss +--- + libsepol/cil/src/cil_resolve_ast.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c +index 208bc01..0e07856 100644 +--- a/libsepol/cil/src/cil_resolve_ast.c ++++ b/libsepol/cil/src/cil_resolve_ast.c +@@ -51,6 +51,7 @@ struct cil_args_resolve { + struct cil_db *db; + enum cil_pass pass; + uint32_t *changed; ++ struct cil_list *disabled_optionals; + struct cil_tree_node *optstack; + struct cil_tree_node *boolif; + struct cil_tree_node *macro; +@@ -3942,7 +3943,7 @@ int __cil_resolve_ast_last_child_helper(struct cil_tree_node *current, void *ext + + if (((struct cil_optional *)parent->data)->enabled == CIL_FALSE) { + *(args->changed) = CIL_TRUE; +- cil_tree_children_destroy(parent); ++ cil_list_append(args->disabled_optionals, CIL_NODE, parent); + } + + /* pop off the stack */ +@@ -4005,6 +4006,7 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current) + 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); + cil_list_init(&extra_args.classorder_lists, CIL_LIST_ITEM); + cil_list_init(&extra_args.unordered_classorder_lists, CIL_LIST_ITEM); +@@ -4072,6 +4074,7 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current) + } + + if (changed && (pass > CIL_PASS_CALL1)) { ++ 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 +@@ -4100,6 +4103,11 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current) + 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); ++ } ++ cil_list_destroy(&extra_args.disabled_optionals, CIL_FALSE); ++ cil_list_init(&extra_args.disabled_optionals, CIL_NODE); + } + + /* reset the arguments */ +@@ -4128,6 +4136,7 @@ exit: + __cil_ordered_lists_destroy(&extra_args.catorder_lists); + __cil_ordered_lists_destroy(&extra_args.sensitivityorder_lists); + __cil_ordered_lists_destroy(&extra_args.unordered_classorder_lists); ++ cil_list_destroy(&extra_args.disabled_optionals, CIL_FALSE); + cil_list_destroy(&extra_args.in_list, CIL_FALSE); + + return rc; +-- +1.8.3.1 + diff --git a/backport-libsepol-cil-Detect-degenerate-inheritance-and-exit-.patch b/backport-libsepol-cil-Detect-degenerate-inheritance-and-exit-.patch new file mode 100644 index 0000000000000000000000000000000000000000..318b49015c46d9261faea35b4b9fbd4bcaea5bbb --- /dev/null +++ b/backport-libsepol-cil-Detect-degenerate-inheritance-and-exit-.patch @@ -0,0 +1,136 @@ +From 74d00a8decebf940d95064ff60042dcb2cbcc2c0 Mon Sep 17 00:00:00 2001 +From: James Carter +Date: Wed, 28 Apr 2021 16:07:02 -0400 +Subject: [PATCH] libsepol/cil: Detect degenerate inheritance and exit with an + error + +A CIL policy with inheritance of the form +... +(blockinherit ba) +(block ba + (block b1 + (blockinherit bb) + ) + (block bb + (block b2 + (blockinherit bc) + ) + (block bc + (block b3 + (blockinherit bd) + ) + (block bd + (block b4 + (blockinherit be) + ) + (block be + ... +will require creating 2^depth copies of the block at the bottom of +the inheritance chain. This pattern can quickly consume all the +memory of the system compiling this policy. + +The depth of the inheritance chain can be found be walking the +tree up through the parents and noting how many of the parent +blocks have been inherited. The number of times a block will be +copied is found by counting the list of nodes in the "bi_nodes" +list of the block. To minimize legitimate policies from being +falsely detected as being degenerate, both the depth and breadth +(number of copies) are checked and an error is given only if both +exceed the limits (depth >= 12 and breadth >= 4096). + +This problem was found by the secilc-fuzzer. + +Signed-off-by: James Carter +--- + libsepol/cil/src/cil_internal.h | 2 ++ + libsepol/cil/src/cil_resolve_ast.c | 54 ++++++++++++++++++++++++++++++++++++++ + 2 files changed, 56 insertions(+) + +diff --git a/libsepol/cil/src/cil_internal.h b/libsepol/cil/src/cil_internal.h +index 9bdcbdd..74e0b34 100644 +--- a/libsepol/cil/src/cil_internal.h ++++ b/libsepol/cil/src/cil_internal.h +@@ -48,6 +48,8 @@ + + #define CIL_MAX_NAME_LENGTH 2048 + ++#define CIL_DEGENERATE_INHERITANCE_DEPTH 12 ++#define CIL_DEGENERATE_INHERITANCE_BREADTH (0x1 << CIL_DEGENERATE_INHERITANCE_DEPTH) + + enum cil_pass { + CIL_PASS_INIT = 0, +diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c +index 5389df4..6890964 100644 +--- a/libsepol/cil/src/cil_resolve_ast.c ++++ b/libsepol/cil/src/cil_resolve_ast.c +@@ -2410,6 +2410,55 @@ exit: + return rc; + } + ++/* ++ * Detect degenerate inheritance of the form: ++ * ... ++ * (blockinherit ba) ++ * (block ba ++ * (block b1 ++ * (blockinherit bb) ++ * ) ++ * (block bb ++ * (block b2 ++ * (blockinherit bc) ++ * ) ++ * (block bc ++ * ... ++ */ ++static int cil_check_for_degenerate_inheritance(struct cil_tree_node *current) ++{ ++ struct cil_block *block = current->data; ++ struct cil_tree_node *node; ++ struct cil_list_item *item; ++ unsigned depth; ++ unsigned breadth = 0; ++ ++ cil_list_for_each(item, block->bi_nodes) { ++ breadth++; ++ } ++ ++ if (breadth >= CIL_DEGENERATE_INHERITANCE_BREADTH) { ++ node = current->parent; ++ depth = 0; ++ while (node && node->flavor != CIL_ROOT) { ++ if (node->flavor == CIL_BLOCK) { ++ block = node->data; ++ if (block->bi_nodes != NULL) { ++ depth++; ++ } ++ } ++ node = node->parent; ++ } ++ ++ if (depth >= CIL_DEGENERATE_INHERITANCE_DEPTH) { ++ cil_tree_log(current, CIL_ERR, "Degenerate inheritance detected (depth=%u, breadth=%u)", depth, breadth); ++ return SEPOL_ERR; ++ } ++ } ++ ++ return SEPOL_OK; ++} ++ + int cil_resolve_blockinherit_copy(struct cil_tree_node *current, void *extra_args) + { + struct cil_block *block = current->data; +@@ -2426,6 +2475,11 @@ int cil_resolve_blockinherit_copy(struct cil_tree_node *current, void *extra_arg + + db = args->db; + ++ rc = cil_check_for_degenerate_inheritance(current); ++ if (rc != SEPOL_OK) { ++ goto exit; ++ } ++ + // Make sure this is the original block and not a merged block from a blockinherit + if (current != block->datum.nodes->head->data) { + rc = SEPOL_OK; +-- +1.8.3.1 + diff --git a/backport-libsepol-cil-Fix-instances-where-an-error-returns-SE.patch b/backport-libsepol-cil-Fix-instances-where-an-error-returns-SE.patch new file mode 100644 index 0000000000000000000000000000000000000000..bfc38f3b13e5a9a7e4ef9fb70441fd2d9cde0ba6 --- /dev/null +++ b/backport-libsepol-cil-Fix-instances-where-an-error-returns-SE.patch @@ -0,0 +1,80 @@ +From 5681c6275b5ad9cf3d84af243a66b900a0628f72 Mon Sep 17 00:00:00 2001 +From: James Carter +Date: Wed, 28 Apr 2021 16:06:58 -0400 +Subject: [PATCH] libsepol/cil: Fix instances where an error returns SEPOL_OK + +There are six instances when the CIL policy is being built or +resolved where an error can be detected, but SEPOL_OK is returned +instead of SEPOL_ERR. This causes the policy compiler to continue +when it should exit with an error. + +Return SEPOL_ERR in these cases, so the compiler exits with an +error. + +Two of the instances were found by the secilc-fuzzer. + +Signed-off-by: James Carter +--- + libsepol/cil/src/cil_build_ast.c | 3 +++ + libsepol/cil/src/cil_resolve_ast.c | 3 +++ + 2 files changed, 6 insertions(+) + +diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c +index 5b1e282..87043a8 100644 +--- a/libsepol/cil/src/cil_build_ast.c ++++ b/libsepol/cil/src/cil_build_ast.c +@@ -444,6 +444,7 @@ int cil_gen_class(struct cil_db *db, struct cil_tree_node *parse_current, struct + } + if (class->num_perms > CIL_PERMS_PER_CLASS) { + cil_tree_log(parse_current, CIL_ERR, "Too many permissions in class '%s'", class->datum.name); ++ rc = SEPOL_ERR; + goto exit; + } + +@@ -1018,6 +1019,7 @@ int cil_gen_common(struct cil_db *db, struct cil_tree_node *parse_current, struc + } + if (common->num_perms > CIL_PERMS_PER_CLASS) { + cil_tree_log(parse_current, CIL_ERR, "Too many permissions in common '%s'", common->datum.name); ++ rc = SEPOL_ERR; + goto exit; + } + +@@ -3209,6 +3211,7 @@ int cil_gen_expandtypeattribute(struct cil_db *db, struct cil_tree_node *parse_c + expandattr->expand = CIL_FALSE; + } else { + cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'"); ++ rc = SEPOL_ERR; + goto exit; + } + +diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c +index 872b679..5389df4 100644 +--- a/libsepol/cil/src/cil_resolve_ast.c ++++ b/libsepol/cil/src/cil_resolve_ast.c +@@ -772,6 +772,7 @@ int cil_resolve_classcommon(struct cil_tree_node *current, void *extra_args) + class->num_perms += common->num_perms; + if (class->num_perms > CIL_PERMS_PER_CLASS) { + cil_tree_log(current, CIL_ERR, "Too many permissions in class '%s' when including common permissions", class->datum.name); ++ rc = SEPOL_ERR; + goto exit; + } + +@@ -1484,6 +1485,7 @@ int cil_resolve_classorder(struct cil_tree_node *current, void *extra_args) + rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_CLASSES, extra_args, &datum); + if (rc != SEPOL_OK) { + cil_log(CIL_ERR, "Failed to resolve class %s in classorder\n", (char *)curr->data); ++ rc = SEPOL_ERR; + goto exit; + } + cil_list_append(new, CIL_CLASS, datum); +@@ -2464,6 +2466,7 @@ int cil_resolve_blockabstract(struct cil_tree_node *current, void *extra_args) + block_node = NODE(block_datum); + if (block_node->flavor != CIL_BLOCK) { + cil_log(CIL_ERR, "Failed to resolve blockabstract to a block, rc: %d\n", rc); ++ rc = SEPOL_ERR; + goto exit; + } + +-- +1.8.3.1 + diff --git a/backport-libsepol-cil-Fix-syntax-checking-of-defaultrange-rul.patch b/backport-libsepol-cil-Fix-syntax-checking-of-defaultrange-rul.patch new file mode 100644 index 0000000000000000000000000000000000000000..136f8c76a1fefda081af18291e97e93b2f32d1ac --- /dev/null +++ b/backport-libsepol-cil-Fix-syntax-checking-of-defaultrange-rul.patch @@ -0,0 +1,55 @@ +From ac8b35d910750b56d38d54f312a712a73c95749c Mon Sep 17 00:00:00 2001 +From: James Carter +Date: Mon, 21 Jun 2021 10:34:33 -0400 +Subject: [PATCH] libsepol/cil: Fix syntax checking of defaultrange rule + +When "glblub" was added as a default for the defaultrange rule, the +syntax array was updated because the "glblub" default does not need +to specify a range of "low", "high", or "low-high". Unfortunately, +additional checking was not added for the "source" and "target" +defaults to make sure they specified a range. This means that using +the "source" or "target" defaults without specifying the range will +result in a segfault. + +When the "source" or "target" defaults are used, check that the rule +specifies a range as well. + +This bug was found by the secilc-fuzzer. + +Signed-off-by: James Carter +Acked-by: Nicolas Iooss +--- + libsepol/cil/src/cil_build_ast.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c +index ea665a3..baed3e5 100644 +--- a/libsepol/cil/src/cil_build_ast.c ++++ b/libsepol/cil/src/cil_build_ast.c +@@ -5886,6 +5886,11 @@ int cil_gen_defaultrange(struct cil_tree_node *parse_current, struct cil_tree_no + + object = parse_current->next->next->data; + if (object == CIL_KEY_SOURCE) { ++ if (!parse_current->next->next->next) { ++ cil_log(CIL_ERR, "Missing 'low', 'high', or 'low-high'\n"); ++ rc = SEPOL_ERR; ++ goto exit; ++ } + range = parse_current->next->next->next->data; + if (range == CIL_KEY_LOW) { + def->object_range = CIL_DEFAULT_SOURCE_LOW; +@@ -5899,6 +5904,11 @@ int cil_gen_defaultrange(struct cil_tree_node *parse_current, struct cil_tree_no + goto exit; + } + } else if (object == CIL_KEY_TARGET) { ++ if (!parse_current->next->next->next) { ++ cil_log(CIL_ERR, "Missing 'low', 'high', or 'low-high'\n"); ++ rc = SEPOL_ERR; ++ goto exit; ++ } + range = parse_current->next->next->next->data; + if (range == CIL_KEY_LOW) { + def->object_range = CIL_DEFAULT_TARGET_LOW; +-- +1.8.3.1 + diff --git a/backport-libsepol-cil-Handle-disabled-optional-blocks-in-earl.patch b/backport-libsepol-cil-Handle-disabled-optional-blocks-in-earl.patch new file mode 100644 index 0000000000000000000000000000000000000000..343db084c39e331176c426ab4bde049b17630caf --- /dev/null +++ b/backport-libsepol-cil-Handle-disabled-optional-blocks-in-earl.patch @@ -0,0 +1,94 @@ +From 5661efd459e7aa998390ab70e3ec50125a35e9e9 Mon Sep 17 00:00:00 2001 +From: James Carter +Date: Thu, 13 May 2021 12:30:37 -0400 +Subject: [PATCH] libsepol/cil: Handle disabled optional blocks in earlier + passes + +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 +--- + 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 74e5b78..328add0 100644 +--- a/libsepol/cil/src/cil_resolve_ast.c ++++ b/libsepol/cil/src/cil_resolve_ast.c +@@ -4132,35 +4132,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); +-- +1.8.3.1 + diff --git a/backport-libsepol-cil-Improve-checking-for-bad-inheritance-pa.patch b/backport-libsepol-cil-Improve-checking-for-bad-inheritance-pa.patch new file mode 100644 index 0000000000000000000000000000000000000000..d21aef4ea1e0370bbd603cff01a389b1e4ffbf8f --- /dev/null +++ b/backport-libsepol-cil-Improve-checking-for-bad-inheritance-pa.patch @@ -0,0 +1,315 @@ +From 9af91692416d01814f4b2ac22e39d3b57993af4f Mon Sep 17 00:00:00 2001 +From: James Carter +Date: Wed, 30 Jun 2021 15:12:16 -0400 +Subject: [PATCH] libsepol/cil: Improve checking for bad inheritance patterns + +commits 37863b0b1444c85a1ddc6c333c8bfea0c678c592 (libsepol/cil: +Improve degenerate inheritance check) and +74d00a8decebf940d95064ff60042dcb2cbcc2c0 (libsepol/cil: Detect +degenerate inheritance and exit with an error) attempted to detect +and exit with an error when compiling policies that have degenerate +inheritances. These policies result in the exponential growth of memory +usage while copying the blocks that are inherited. + +There were two problems with the previous attempts to detect this +bad inheritance problem. The first is that the quick check using +cil_possible_degenerate_inheritance() did not detect all patterns +of degenerate inheritance. The second problem is that the detection +of inheritance loops during the CIL_PASS_BLKIN_LINK pass did not +detect all inheritance loops which made it possible for the full +degenerate inheritance checking done with +cil_check_for_degenerate_inheritance() to have a stack overflow +when encountering the inheritance loops. Both the degenerate and +loop inheritance checks need to be done at the same time and done +after the CIL_PASS_BLKIN_LINK pass. Otherwise, if loops are being +detected first, then a degenerate policy can cause the consumption +of all system memory and if degenerate policy is being detected +first, then an inheritance loop can cause a stack overflow. + +With the new approach, the quick check is eliminated and the full +check is always done after the CIL_PASS_BLKIN_LINK pass. Because +of this the "inheritance_check" field in struct cil_resolve_args +is not needed and removed and the functions +cil_print_recursive_blockinherit(), cil_check_recursive_blockinherit(), +and cil_possible_degenerate_inheritance() have been deleted. The +function cil_count_potential() is renamed cil_check_inheritances() +and has checks for both degenerate inheritance and inheritance loops. +The inheritance checking is improved and uses an approach similar +to commit c28525a26fa145cb5fd911fd2a3b9125a275677f (libsepol/cil: +Properly check for loops in sets). + +As has been the case with these degenerate inheritance patches, +these issues were discovered by the secilc-fuzzer. + +Signed-off-by: James Carter +--- + libsepol/cil/src/cil_resolve_ast.c | 172 +++++++++---------------------------- + 1 file changed, 42 insertions(+), 130 deletions(-) + +diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c +index 9a02e38..145d4e7 100644 +--- a/libsepol/cil/src/cil_resolve_ast.c ++++ b/libsepol/cil/src/cil_resolve_ast.c +@@ -64,7 +64,6 @@ struct cil_args_resolve { + struct cil_list *sensitivityorder_lists; + struct cil_list *in_list; + struct cil_stack *disabled_optionals; +- int *inheritance_check; + }; + + static struct cil_name * __cil_insert_name(struct cil_db *db, hashtab_key_t key, struct cil_tree_node *ast_node) +@@ -2309,100 +2308,8 @@ exit: + return rc; + } + +-static void cil_print_recursive_blockinherit(struct cil_tree_node *bi_node, struct cil_tree_node *terminating_node) +-{ +- struct cil_list *trace = NULL; +- struct cil_list_item *item = NULL; +- struct cil_tree_node *curr = NULL; +- +- cil_list_init(&trace, CIL_NODE); +- +- for (curr = bi_node; curr != terminating_node; curr = curr->parent) { +- if (curr->flavor == CIL_BLOCK) { +- cil_list_prepend(trace, CIL_NODE, curr); +- } else if (curr->flavor == CIL_BLOCKINHERIT) { +- if (curr != bi_node) { +- cil_list_prepend(trace, CIL_NODE, NODE(((struct cil_blockinherit *)curr->data)->block)); +- } +- cil_list_prepend(trace, CIL_NODE, curr); +- } else { +- cil_list_prepend(trace, CIL_NODE, curr); +- } +- } +- cil_list_prepend(trace, CIL_NODE, terminating_node); +- +- cil_list_for_each(item, trace) { +- curr = item->data; +- if (curr->flavor == CIL_BLOCK) { +- cil_tree_log(curr, CIL_ERR, "block %s", DATUM(curr->data)->name); +- } else if (curr->flavor == CIL_BLOCKINHERIT) { +- cil_tree_log(curr, CIL_ERR, "blockinherit %s", ((struct cil_blockinherit *)curr->data)->block_str); +- } else if (curr->flavor == CIL_OPTIONAL) { +- cil_tree_log(curr, CIL_ERR, "optional %s", DATUM(curr->data)->name); +- } else { +- cil_tree_log(curr, CIL_ERR, "%s", cil_node_to_string(curr)); +- } +- } +- +- cil_list_destroy(&trace, CIL_FALSE); +-} +- +-static int cil_check_recursive_blockinherit(struct cil_tree_node *bi_node) +-{ +- struct cil_tree_node *curr = NULL; +- struct cil_blockinherit *bi = NULL; +- struct cil_block *block = NULL; +- int rc = SEPOL_ERR; +- +- bi = bi_node->data; +- +- for (curr = bi_node->parent; curr != NULL; curr = curr->parent) { +- if (curr->flavor != CIL_BLOCK) { +- continue; +- } +- +- block = curr->data; +- +- if (block != bi->block) { +- continue; +- } +- +- cil_log(CIL_ERR, "Recursive blockinherit found:\n"); +- cil_print_recursive_blockinherit(bi_node, curr); +- +- rc = SEPOL_ERR; +- goto exit; +- } +- +- rc = SEPOL_OK; +- +-exit: +- return rc; +-} +- +-static int cil_possible_degenerate_inheritance(struct cil_tree_node *node) +-{ +- unsigned depth = 1; +- +- node = node->parent; +- while (node && node->flavor != CIL_ROOT) { +- if (node->flavor == CIL_BLOCK) { +- if (((struct cil_block *)(node->data))->bi_nodes != NULL) { +- depth++; +- if (depth >= CIL_DEGENERATE_INHERITANCE_DEPTH) { +- return CIL_TRUE; +- } +- } +- } +- node = node->parent; +- } +- +- return CIL_FALSE; +-} +- + int cil_resolve_blockinherit_link(struct cil_tree_node *current, void *extra_args) + { +- struct cil_args_resolve *args = extra_args; + struct cil_blockinherit *inherit = current->data; + struct cil_symtab_datum *block_datum = NULL; + struct cil_tree_node *node = NULL; +@@ -2423,20 +2330,11 @@ int cil_resolve_blockinherit_link(struct cil_tree_node *current, void *extra_arg + + inherit->block = (struct cil_block *)block_datum; + +- rc = cil_check_recursive_blockinherit(current); +- if (rc != SEPOL_OK) { +- goto exit; +- } +- + if (inherit->block->bi_nodes == NULL) { + cil_list_init(&inherit->block->bi_nodes, CIL_NODE); + } + cil_list_append(inherit->block->bi_nodes, CIL_NODE, current); + +- if (*(args->inheritance_check) == CIL_FALSE) { +- *(args->inheritance_check) = cil_possible_degenerate_inheritance(node); +- } +- + return SEPOL_OK; + + exit: +@@ -2466,11 +2364,6 @@ int cil_resolve_blockinherit_copy(struct cil_tree_node *current, void *extra_arg + } + + cil_list_for_each(item, block->bi_nodes) { +- rc = cil_check_recursive_blockinherit(item->data); +- if (rc != SEPOL_OK) { +- goto exit; +- } +- + rc = cil_copy_ast(db, current, item->data); + if (rc != SEPOL_OK) { + cil_log(CIL_ERR, "Failed to copy block contents into blockinherit\n"); +@@ -3611,34 +3504,58 @@ static unsigned cil_count_actual(struct cil_tree_node *node) + return count; + } + +-static unsigned cil_count_potential(struct cil_tree_node *node, unsigned max) ++static int cil_check_inheritances(struct cil_tree_node *node, unsigned max, unsigned *count, struct cil_stack *stack, unsigned *loop) + { +- unsigned count = 0; ++ int rc; + + if (node->flavor == CIL_BLOCKINHERIT) { + struct cil_blockinherit *bi = node->data; +- count += 1; ++ *count += 1; ++ if (*count > max) { ++ cil_tree_log(node, CIL_ERR, "Degenerate inheritance detected"); ++ return SEPOL_ERR; ++ } + if (bi->block) { +- count += cil_count_potential(NODE(bi->block), max); +- if (count > max) { +- return count; ++ struct cil_tree_node *block_node = NODE(bi->block); ++ struct cil_stack_item *item; ++ int i = 0; ++ cil_stack_for_each(stack, i, item) { ++ if (block_node == (struct cil_tree_node *)item->data) { ++ *loop = CIL_TRUE; ++ cil_tree_log(block_node, CIL_ERR, "Block inheritance loop found"); ++ cil_tree_log(node, CIL_ERR, " blockinherit"); ++ return SEPOL_ERR; ++ } ++ } ++ cil_stack_push(stack, CIL_BLOCK, block_node); ++ rc = cil_check_inheritances(block_node, max, count, stack, loop); ++ cil_stack_pop(stack); ++ if (rc != SEPOL_OK) { ++ if (*loop == CIL_TRUE) { ++ cil_tree_log(node, CIL_ERR, " blockinherit"); ++ } ++ return SEPOL_ERR; + } + } + } + + for (node = node->cl_head; node; node = node->next) { +- count += cil_count_potential(node, max); +- if (count > max) { +- return count; ++ rc = cil_check_inheritances(node, max, count, stack, loop); ++ if (rc != SEPOL_OK) { ++ return SEPOL_ERR; + } + } + +- return count; ++ return SEPOL_OK; + } + +-static int cil_check_for_degenerate_inheritance(struct cil_tree_node *node) ++static int cil_check_for_bad_inheritance(struct cil_tree_node *node) + { +- uint64_t num_actual, num_potential, max; ++ unsigned num_actual, max; ++ unsigned num_potential = 0; ++ unsigned loop = CIL_FALSE; ++ struct cil_stack *stack; ++ int rc; + + num_actual = cil_count_actual(node); + +@@ -3647,13 +3564,11 @@ static int cil_check_for_degenerate_inheritance(struct cil_tree_node *node) + max = CIL_DEGENERATE_INHERITANCE_MINIMUM; + } + +- num_potential = cil_count_potential(node, max); ++ cil_stack_init(&stack); ++ rc = cil_check_inheritances(node, max, &num_potential, stack, &loop); ++ cil_stack_destroy(&stack); + +- if (num_potential > max) { +- return SEPOL_ERR; +- } +- +- return SEPOL_OK; ++ return rc; + } + + int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args) +@@ -4127,7 +4042,6 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current) + struct cil_args_resolve extra_args; + enum cil_pass pass = CIL_PASS_TIF; + uint32_t changed = 0; +- int inheritance_check = 0; + + if (db == NULL || current == NULL) { + return rc; +@@ -4147,7 +4061,6 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current) + extra_args.sensitivityorder_lists = NULL; + extra_args.in_list = NULL; + extra_args.disabled_optionals = NULL; +- extra_args.inheritance_check = &inheritance_check; + + cil_list_init(&extra_args.to_destroy, CIL_NODE); + cil_list_init(&extra_args.sidorder_lists, CIL_LIST_ITEM); +@@ -4174,10 +4087,9 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current) + cil_list_destroy(&extra_args.in_list, CIL_FALSE); + } + +- if (pass == CIL_PASS_BLKIN_LINK && inheritance_check == CIL_TRUE) { +- rc = cil_check_for_degenerate_inheritance(current); ++ if (pass == CIL_PASS_BLKIN_LINK) { ++ rc = cil_check_for_bad_inheritance(current); + if (rc != SEPOL_OK) { +- cil_log(CIL_ERR, "Degenerate inheritance detected\n"); + rc = SEPOL_ERR; + goto exit; + } +-- +1.8.3.1 + diff --git a/backport-libsepol-cil-Improve-degenerate-inheritance-check.patch b/backport-libsepol-cil-Improve-degenerate-inheritance-check.patch new file mode 100644 index 0000000000000000000000000000000000000000..de6d60ce10b294cd9ea9cfa0d91349d489834f91 --- /dev/null +++ b/backport-libsepol-cil-Improve-degenerate-inheritance-check.patch @@ -0,0 +1,362 @@ +From 37863b0b1444c85a1ddc6c333c8bfea0c678c592 Mon Sep 17 00:00:00 2001 +From: James Carter +Date: Mon, 21 Jun 2021 10:56:55 -0400 +Subject: [PATCH] libsepol/cil: Improve degenerate inheritance check + +The commit 74d00a8decebf940d95064ff60042dcb2cbcc2c0 (libsepol/cil: +Detect degenerate inheritance and exit with an error) detects the +use of inheritance (mostly by the secilc-fuzzer and not in any real +policies) that results in the exponential growth of the policy through +the copying of blocks that takes place with inheritance in CIL. +Unfortunately, the check takes place during the pass when all the +blocks are being copied, so it is possible to consume all of a system's +memory before an error is produced. + +The new check happens in two parts. First, a check is made while the +block inheritance is being linked to the block it will inherit. In +this check, all of the parent nodes of the inheritance rule up to the +root node are checked and if enough of these blocks are being inherited +(>= CIL_DEGENERATE_INHERITANCE_DEPTH), then a flag is set for a more +in-depth check after the pass. This in-depth check will determine the +number of potential inheritances that will occur when resolving the +all of the inheritance rules. If this value is greater than +CIL_DEGENERATE_INHERITANCE_GROWTH * the original number of inheritance +rules and greater than CIL_DEGENERATE_INHERITANCE_MINIMUM (which is +set to 0x1 << CIL_DEGENERATE_INHERITANCE_DEPTH), then degenerate +inheritance is determined to have occurred and an error result will +be returned. + +Since the potential number of inheritances can quickly be an extremely +large number, the count of potential inheritances is aborted as soon +as the threshold for degenerate inheritance has been exceeded. + +Normal policies should rarely, if ever, have the in-depth check occur. + +Signed-off-by: James Carter +Acked-by: Nicolas Iooss +--- + libsepol/cil/src/cil_internal.h | 5 +- + libsepol/cil/src/cil_resolve_ast.c | 226 ++++++++++++++++++++++++------------- + 2 files changed, 151 insertions(+), 80 deletions(-) + +diff --git a/libsepol/cil/src/cil_internal.h b/libsepol/cil/src/cil_internal.h +index 24be09a..8b9aeab 100644 +--- a/libsepol/cil/src/cil_internal.h ++++ b/libsepol/cil/src/cil_internal.h +@@ -48,8 +48,9 @@ + + #define CIL_MAX_NAME_LENGTH 2048 + +-#define CIL_DEGENERATE_INHERITANCE_DEPTH 12 +-#define CIL_DEGENERATE_INHERITANCE_BREADTH (0x1 << CIL_DEGENERATE_INHERITANCE_DEPTH) ++#define CIL_DEGENERATE_INHERITANCE_DEPTH 10UL ++#define CIL_DEGENERATE_INHERITANCE_MINIMUM (0x01 << CIL_DEGENERATE_INHERITANCE_DEPTH) ++#define CIL_DEGENERATE_INHERITANCE_GROWTH 10UL + + enum cil_pass { + CIL_PASS_INIT = 0, +diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c +index 6d13544..5245cc1 100644 +--- a/libsepol/cil/src/cil_resolve_ast.c ++++ b/libsepol/cil/src/cil_resolve_ast.c +@@ -64,6 +64,7 @@ struct cil_args_resolve { + struct cil_list *sensitivityorder_lists; + struct cil_list *in_list; + struct cil_stack *disabled_optionals; ++ int *inheritance_check; + }; + + static struct cil_name * __cil_insert_name(struct cil_db *db, hashtab_key_t key, struct cil_tree_node *ast_node) +@@ -2308,40 +2309,7 @@ exit: + return rc; + } + +-int cil_resolve_blockinherit_link(struct cil_tree_node *current, void *extra_args) +-{ +- struct cil_blockinherit *inherit = current->data; +- struct cil_symtab_datum *block_datum = NULL; +- struct cil_tree_node *node = NULL; +- int rc = SEPOL_ERR; +- +- rc = cil_resolve_name(current, inherit->block_str, CIL_SYM_BLOCKS, extra_args, &block_datum); +- if (rc != SEPOL_OK) { +- goto exit; +- } +- +- node = NODE(block_datum); +- +- if (node->flavor != CIL_BLOCK) { +- cil_log(CIL_ERR, "%s is not a block\n", cil_node_to_string(node)); +- rc = SEPOL_ERR; +- goto exit; +- } +- +- inherit->block = (struct cil_block *)block_datum; +- +- if (inherit->block->bi_nodes == NULL) { +- cil_list_init(&inherit->block->bi_nodes, CIL_NODE); +- } +- cil_list_append(inherit->block->bi_nodes, CIL_NODE, current); +- +- return SEPOL_OK; +- +-exit: +- return rc; +-} +- +-void cil_print_recursive_blockinherit(struct cil_tree_node *bi_node, struct cil_tree_node *terminating_node) ++static void cil_print_recursive_blockinherit(struct cil_tree_node *bi_node, struct cil_tree_node *terminating_node) + { + struct cil_list *trace = NULL; + struct cil_list_item *item = NULL; +@@ -2379,7 +2347,7 @@ void cil_print_recursive_blockinherit(struct cil_tree_node *bi_node, struct cil_ + cil_list_destroy(&trace, CIL_FALSE); + } + +-int cil_check_recursive_blockinherit(struct cil_tree_node *bi_node) ++static int cil_check_recursive_blockinherit(struct cil_tree_node *bi_node) + { + struct cil_tree_node *curr = NULL; + struct cil_blockinherit *bi = NULL; +@@ -2412,53 +2380,67 @@ exit: + return rc; + } + +-/* +- * Detect degenerate inheritance of the form: +- * ... +- * (blockinherit ba) +- * (block ba +- * (block b1 +- * (blockinherit bb) +- * ) +- * (block bb +- * (block b2 +- * (blockinherit bc) +- * ) +- * (block bc +- * ... +- */ +-static int cil_check_for_degenerate_inheritance(struct cil_tree_node *current) ++static int cil_possible_degenerate_inheritance(struct cil_tree_node *node) + { +- struct cil_block *block = current->data; +- struct cil_tree_node *node; +- struct cil_list_item *item; +- unsigned depth; +- unsigned breadth = 0; ++ unsigned depth = 1; + +- cil_list_for_each(item, block->bi_nodes) { +- breadth++; +- } +- +- if (breadth >= CIL_DEGENERATE_INHERITANCE_BREADTH) { +- node = current->parent; +- depth = 0; +- while (node && node->flavor != CIL_ROOT) { +- if (node->flavor == CIL_BLOCK) { +- block = node->data; +- if (block->bi_nodes != NULL) { +- depth++; ++ node = node->parent; ++ while (node && node->flavor != CIL_ROOT) { ++ if (node->flavor == CIL_BLOCK) { ++ if (((struct cil_block *)(node->data))->bi_nodes != NULL) { ++ depth++; ++ if (depth >= CIL_DEGENERATE_INHERITANCE_DEPTH) { ++ return CIL_TRUE; + } + } +- node = node->parent; + } ++ node = node->parent; ++ } + +- if (depth >= CIL_DEGENERATE_INHERITANCE_DEPTH) { +- cil_tree_log(current, CIL_ERR, "Degenerate inheritance detected (depth=%u, breadth=%u)", depth, breadth); +- return SEPOL_ERR; +- } ++ return CIL_FALSE; ++} ++ ++int cil_resolve_blockinherit_link(struct cil_tree_node *current, void *extra_args) ++{ ++ struct cil_args_resolve *args = extra_args; ++ struct cil_blockinherit *inherit = current->data; ++ struct cil_symtab_datum *block_datum = NULL; ++ struct cil_tree_node *node = NULL; ++ int rc = SEPOL_ERR; ++ ++ rc = cil_resolve_name(current, inherit->block_str, CIL_SYM_BLOCKS, extra_args, &block_datum); ++ if (rc != SEPOL_OK) { ++ goto exit; ++ } ++ ++ node = NODE(block_datum); ++ ++ if (node->flavor != CIL_BLOCK) { ++ cil_log(CIL_ERR, "%s is not a block\n", cil_node_to_string(node)); ++ rc = SEPOL_ERR; ++ goto exit; ++ } ++ ++ inherit->block = (struct cil_block *)block_datum; ++ ++ rc = cil_check_recursive_blockinherit(current); ++ if (rc != SEPOL_OK) { ++ goto exit; ++ } ++ ++ if (inherit->block->bi_nodes == NULL) { ++ cil_list_init(&inherit->block->bi_nodes, CIL_NODE); ++ } ++ cil_list_append(inherit->block->bi_nodes, CIL_NODE, current); ++ ++ if (*(args->inheritance_check) == CIL_FALSE) { ++ *(args->inheritance_check) = cil_possible_degenerate_inheritance(node); + } + + return SEPOL_OK; ++ ++exit: ++ return rc; + } + + int cil_resolve_blockinherit_copy(struct cil_tree_node *current, void *extra_args) +@@ -2477,11 +2459,6 @@ int cil_resolve_blockinherit_copy(struct cil_tree_node *current, void *extra_arg + + db = args->db; + +- rc = cil_check_for_degenerate_inheritance(current); +- if (rc != SEPOL_OK) { +- goto exit; +- } +- + // Make sure this is the original block and not a merged block from a blockinherit + if (current != block->datum.nodes->head->data) { + rc = SEPOL_OK; +@@ -3597,6 +3574,88 @@ exit: + return rc; + } + ++/* ++ * Degenerate inheritance leads to exponential growth of the policy ++ * It can take many forms, but here is one example. ++ * ... ++ * (blockinherit ba) ++ * (block b0 ++ * (block b1 ++ * (block b2 ++ * (block b3 ++ * ... ++ * ) ++ * (blockinherit b3) ++ * ) ++ * (blockinherit b2) ++ * ) ++ * (blockinherit b1) ++ * ) ++ * (blockinherit b0) ++ * ... ++ * This leads to 2^4 copies of the content of block b3, 2^3 copies of the ++ * contents of block b2, etc. ++ */ ++static unsigned cil_count_actual(struct cil_tree_node *node) ++{ ++ unsigned count = 0; ++ ++ if (node->flavor == CIL_BLOCKINHERIT) { ++ count += 1; ++ } ++ ++ for (node = node->cl_head; node; node = node->next) { ++ count += cil_count_actual(node); ++ } ++ ++ return count; ++} ++ ++static unsigned cil_count_potential(struct cil_tree_node *node, unsigned max) ++{ ++ unsigned count = 0; ++ ++ if (node->flavor == CIL_BLOCKINHERIT) { ++ struct cil_blockinherit *bi = node->data; ++ count += 1; ++ if (bi->block) { ++ count += cil_count_potential(NODE(bi->block), max); ++ if (count > max) { ++ return count; ++ } ++ } ++ } ++ ++ for (node = node->cl_head; node; node = node->next) { ++ count += cil_count_potential(node, max); ++ if (count > max) { ++ return count; ++ } ++ } ++ ++ return count; ++} ++ ++static int cil_check_for_degenerate_inheritance(struct cil_tree_node *node) ++{ ++ uint64_t num_actual, num_potential, max; ++ ++ num_actual = cil_count_actual(node); ++ ++ max = num_actual * CIL_DEGENERATE_INHERITANCE_GROWTH; ++ if (max < CIL_DEGENERATE_INHERITANCE_MINIMUM) { ++ max = CIL_DEGENERATE_INHERITANCE_MINIMUM; ++ } ++ ++ num_potential = cil_count_potential(node, max); ++ ++ if (num_potential > max) { ++ return SEPOL_ERR; ++ } ++ ++ return SEPOL_OK; ++} ++ + int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args) + { + int rc = SEPOL_OK; +@@ -4068,6 +4127,7 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current) + struct cil_args_resolve extra_args; + enum cil_pass pass = CIL_PASS_TIF; + uint32_t changed = 0; ++ int inheritance_check = 0; + + if (db == NULL || current == NULL) { + return rc; +@@ -4087,6 +4147,7 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current) + extra_args.sensitivityorder_lists = NULL; + extra_args.in_list = NULL; + extra_args.disabled_optionals = NULL; ++ extra_args.inheritance_check = &inheritance_check; + + cil_list_init(&extra_args.to_destroy, CIL_NODE); + cil_list_init(&extra_args.sidorder_lists, CIL_LIST_ITEM); +@@ -4113,6 +4174,15 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current) + cil_list_destroy(&extra_args.in_list, CIL_FALSE); + } + ++ if (pass == CIL_PASS_BLKIN_LINK && inheritance_check == CIL_TRUE) { ++ rc = cil_check_for_degenerate_inheritance(current); ++ if (rc != SEPOL_OK) { ++ cil_log(CIL_ERR, "Degenerate inheritance detected\n"); ++ rc = SEPOL_ERR; ++ goto exit; ++ } ++ } ++ + if (pass == CIL_PASS_MISC1) { + db->sidorder = __cil_ordered_lists_merge_all(&extra_args.sidorder_lists, NULL); + if (db->sidorder == NULL) { +-- +1.8.3.1 + diff --git a/backport-libsepol-cil-Limit-the-number-of-open-parenthesis-al.patch b/backport-libsepol-cil-Limit-the-number-of-open-parenthesis-al.patch new file mode 100644 index 0000000000000000000000000000000000000000..537c293afb475ba75990ba97747a7a1c86857714 --- /dev/null +++ b/backport-libsepol-cil-Limit-the-number-of-open-parenthesis-al.patch @@ -0,0 +1,48 @@ +From 69fc31d1fb5d3bc1d4a919285284d1fb9d679a6e Mon Sep 17 00:00:00 2001 +From: James Carter +Date: Thu, 13 May 2021 12:37:59 -0400 +Subject: [PATCH] libsepol/cil: Limit the number of open parenthesis allowed + +When parsing a CIL policy, the number of open parenthesis is tracked +to verify that each has a matching close parenthesis. If there are +too many open parenthesis, a stack overflow could occur during later +processing. + +Exit with an error if the number of open parenthesis exceeds 4096 +(which should be enough for any policy.) + +This bug was found by the secilc-fuzzer. + +Signed-off-by: James Carter +--- + libsepol/cil/src/cil_parser.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/libsepol/cil/src/cil_parser.c b/libsepol/cil/src/cil_parser.c +index a930621..fb95f40 100644 +--- a/libsepol/cil/src/cil_parser.c ++++ b/libsepol/cil/src/cil_parser.c +@@ -42,6 +42,8 @@ + #include "cil_strpool.h" + #include "cil_stack.h" + ++#define CIL_PARSER_MAX_EXPR_DEPTH (0x1 << 12) ++ + char *CIL_KEY_HLL_LMS; + char *CIL_KEY_HLL_LMX; + char *CIL_KEY_HLL_LME; +@@ -245,7 +247,10 @@ int cil_parser(const char *_path, char *buffer, uint32_t size, struct cil_tree * + break; + case OPAREN: + paren_count++; +- ++ if (paren_count > CIL_PARSER_MAX_EXPR_DEPTH) { ++ cil_log(CIL_ERR, "Number of open parenthesis exceeds limit of %d at line %d of %s\n", CIL_PARSER_MAX_EXPR_DEPTH, tok.line, path); ++ goto exit; ++ } + create_node(&node, current, tok.line, hll_lineno, NULL); + insert_node(node, current); + current = node; +-- +1.8.3.1 + diff --git a/backport-libsepol-cil-Refactor-helper-function-for-cil_gen_no.patch b/backport-libsepol-cil-Refactor-helper-function-for-cil_gen_no.patch new file mode 100644 index 0000000000000000000000000000000000000000..33b99d02f68dc4ce4ece7e2290102ed9221b19bb --- /dev/null +++ b/backport-libsepol-cil-Refactor-helper-function-for-cil_gen_no.patch @@ -0,0 +1,74 @@ +From 63ce05ba07fc3517900fac22efe1c761d856762f Mon Sep 17 00:00:00 2001 +From: James Carter +Date: Thu, 8 Apr 2021 13:32:16 -0400 +Subject: [PATCH] libsepol/cil: Refactor helper function for cil_gen_node() + +Change the name of cil_is_datum_multiple_decl() to +cil_allow_multiple_decls() and make it static. The new function +takes the CIL db and the flavors of the old and new datum as +arguments. Also, put all of the logic of determining if multiple +declarations are allowed into the new function. Finally, update +the call from cil_gen_node(). + +Signed-off-by: James Carter +--- + libsepol/cil/src/cil_build_ast.c | 27 ++++++++++----------------- + 1 file changed, 10 insertions(+), 17 deletions(-) + +diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c +index e57de66..14cdce1 100644 +--- a/libsepol/cil/src/cil_build_ast.c ++++ b/libsepol/cil/src/cil_build_ast.c +@@ -82,30 +82,24 @@ exit: + return rc; + } + +-/* +- * Determine whether or not multiple declarations of the same key can share a +- * datum, given the new datum and the one already present in a given symtab. +- */ +-int cil_is_datum_multiple_decl(__attribute__((unused)) struct cil_symtab_datum *cur, +- struct cil_symtab_datum *old, +- enum cil_flavor f) ++static int cil_allow_multiple_decls(struct cil_db *db, enum cil_flavor f_new, enum cil_flavor f_old) + { +- int rc = CIL_FALSE; ++ if (f_new != f_old) { ++ return CIL_FALSE; ++ } + +- switch (f) { ++ switch (f_new) { + case CIL_TYPE: + case CIL_TYPEATTRIBUTE: +- if (!old || f != FLAVOR(old)) { +- rc = CIL_FALSE; +- } else { +- /* type and typeattribute statements insert empty datums */ +- rc = CIL_TRUE; ++ if (db->multiple_decls) { ++ return CIL_TRUE; + } + break; + default: + break; + } +- return rc; ++ ++ return CIL_FALSE; + } + + int cil_gen_node(struct cil_db *db, struct cil_tree_node *ast_node, struct cil_symtab_datum *datum, hashtab_key_t key, enum cil_sym_index sflavor, enum cil_flavor nflavor) +@@ -135,8 +129,7 @@ int cil_gen_node(struct cil_db *db, struct cil_tree_node *ast_node, struct cil_s + cil_log(CIL_ERR, "Re-declaration of %s %s, but previous declaration could not be found\n",cil_node_to_string(ast_node), key); + goto exit; + } +- if (!db->multiple_decls || +- !cil_is_datum_multiple_decl(datum, prev, nflavor)) { ++ if (!cil_allow_multiple_decls(db, nflavor, FLAVOR(prev))) { + /* multiple_decls not ok, ret error */ + struct cil_tree_node *node = NODE(prev); + cil_log(CIL_ERR, "Re-declaration of %s %s\n", +-- +1.8.3.1 + diff --git a/backport-libsepol-cil-Remove-unused-field-from-struct-cil_arg.patch b/backport-libsepol-cil-Remove-unused-field-from-struct-cil_arg.patch new file mode 100644 index 0000000000000000000000000000000000000000..393c797e71b854ca2c7bf28e0e20d80cf711a7a8 --- /dev/null +++ b/backport-libsepol-cil-Remove-unused-field-from-struct-cil_arg.patch @@ -0,0 +1,47 @@ +From 9b9761cfaa09958ead2bcad256dd0f1706e8b5b3 Mon Sep 17 00:00:00 2001 +From: James Carter +Date: Mon, 16 Nov 2020 17:06:59 -0500 +Subject: [PATCH] libsepol/cil: Remove unused field from struct + cil_args_resolve + +When resolving names, the struct cil_args_resolve is passed to the +various resolve functions. The field last_resolved_name is not used. + +Remove the last_resolved_name field from struct cil_args_resolve. + +Signed-off-by: James Carter +--- + libsepol/cil/src/cil_resolve_ast.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c +index daf873b..410b8c8 100644 +--- a/libsepol/cil/src/cil_resolve_ast.c ++++ b/libsepol/cil/src/cil_resolve_ast.c +@@ -51,7 +51,6 @@ struct cil_args_resolve { + struct cil_db *db; + enum cil_pass pass; + uint32_t *changed; +- char *last_resolved_name; + struct cil_tree_node *optstack; + struct cil_tree_node *boolif; + struct cil_tree_node *macro; +@@ -3905,7 +3904,6 @@ 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.last_resolved_name = NULL; + extra_args.optstack = NULL; + extra_args.boolif= NULL; + extra_args.macro = NULL; +@@ -4234,7 +4232,5 @@ exit: + *datum = NULL; + } + +- args->last_resolved_name = name; +- + return rc; + } +-- +1.8.3.1 + diff --git a/backport-libsepol-cil-Reorder-checks-for-invalid-rules-when-r.patch b/backport-libsepol-cil-Reorder-checks-for-invalid-rules-when-r.patch new file mode 100644 index 0000000000000000000000000000000000000000..7409e33f887f51dfe25f20bd44b9b2a607bf9f91 --- /dev/null +++ b/backport-libsepol-cil-Reorder-checks-for-invalid-rules-when-r.patch @@ -0,0 +1,175 @@ +From ef533c8fd941bfb0c9a729b757d8a5b68fe3d080 Mon Sep 17 00:00:00 2001 +From: James Carter +Date: Tue, 30 Mar 2021 13:39:16 -0400 +Subject: [PATCH] libsepol/cil: Reorder checks for invalid rules when resolving + AST + +Reorder checks for invalid rules in the blocks of tunableifs, +in-statements, macros, and booleanifs when resolving the AST for +consistency. + +Order the checks in the same order the blocks will be resolved in, +so tuanbleif, in-statement, macro, booleanif, and then non-block +rules. + +Signed-off-by: James Carter +--- + libsepol/cil/src/cil_resolve_ast.c | 76 +++++++++++++++++++------------------- + 1 file changed, 39 insertions(+), 37 deletions(-) + +diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c +index a61462d..93fc0d6 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 *block; ++ struct cil_tree_node *macro; + struct cil_tree_node *optional; + struct cil_tree_node *boolif; +- struct cil_tree_node *macro; +- struct cil_tree_node *block; + struct cil_list *sidorder_lists; + struct cil_list *classorder_lists; + struct cil_list *unordered_classorder_lists; +@@ -3777,50 +3777,52 @@ 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 *optional = args->optional; +- struct cil_tree_node *boolif = args->boolif; + struct cil_tree_node *block = args->block; + struct cil_tree_node *macro = args->macro; ++ struct cil_tree_node *optional = args->optional; ++ struct cil_tree_node *boolif = args->boolif; + + if (node == NULL) { + goto exit; + } + +- 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)); ++ 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; + goto exit; + } + } + +- 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)); ++ if (macro != NULL) { ++ if (node->flavor == CIL_BLOCK || ++ node->flavor == CIL_BLOCKINHERIT || ++ node->flavor == CIL_BLOCKABSTRACT || ++ node->flavor == CIL_MACRO) { ++ cil_tree_log(node, CIL_ERR, "%s statement is not allowed in macros", cil_node_to_string(node)); + rc = SEPOL_ERR; + goto exit; + } + } + +- if (macro != NULL) { +- if (node->flavor == CIL_BLOCKINHERIT || +- node->flavor == CIL_BLOCK || +- node->flavor == CIL_BLOCKABSTRACT || +- node->flavor == CIL_MACRO) { +- cil_tree_log(node, CIL_ERR, "%s statement is not allowed in macros", cil_node_to_string(node)); ++ 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)); + rc = SEPOL_ERR; + goto exit; + } + } + + if (boolif != NULL) { +- if (!(node->flavor == CIL_CONDBLOCK || +- node->flavor == CIL_AVRULE || +- node->flavor == CIL_TYPE_RULE || +- node->flavor == CIL_CALL || +- node->flavor == CIL_TUNABLEIF || +- node->flavor == CIL_NAMETYPETRANSITION)) { ++ if (!(node->flavor == CIL_TUNABLEIF || ++ node->flavor == CIL_CALL || ++ node->flavor == CIL_CONDBLOCK || ++ node->flavor == CIL_AVRULE || ++ node->flavor == CIL_TYPE_RULE || ++ node->flavor == CIL_NAMETYPETRANSITION)) { + if (((struct cil_booleanif*)boolif->data)->preserved_tunable) { + cil_tree_log(node, CIL_ERR, "%s statement is not allowed in booleanifs (tunableif treated as a booleanif)", cil_node_to_string(node)); + } else { +@@ -3886,12 +3888,12 @@ int __cil_resolve_ast_first_child_helper(struct cil_tree_node *current, void *ex + + if (parent->flavor == CIL_BLOCK) { + args->block = parent; ++ } else if (parent->flavor == CIL_MACRO) { ++ args->macro = 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) { +- args->macro = parent; + } + + return SEPOL_OK; +@@ -3913,7 +3915,17 @@ int __cil_resolve_ast_last_child_helper(struct cil_tree_node *current, void *ext + + parent = current->parent; + +- if (parent->flavor == CIL_MACRO) { ++ if (parent->flavor == CIL_BLOCK) { ++ 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; ++ } ++ } else if (parent->flavor == CIL_MACRO) { + args->macro = NULL; + } else if (parent->flavor == CIL_OPTIONAL) { + struct cil_tree_node *n = parent->parent; +@@ -3931,16 +3943,6 @@ int __cil_resolve_ast_last_child_helper(struct cil_tree_node *current, void *ext + } + } else if (parent->flavor == CIL_BOOLEANIF) { + args->boolif = NULL; +- } else if (parent->flavor == CIL_BLOCK) { +- 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; +- } + } + + return SEPOL_OK; +@@ -3964,9 +3966,9 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current) + extra_args.pass = pass; + extra_args.changed = &changed; + extra_args.block = NULL; ++ extra_args.macro = NULL; + extra_args.optional = NULL; + extra_args.boolif= NULL; +- extra_args.macro = NULL; + extra_args.sidorder_lists = NULL; + extra_args.classorder_lists = NULL; + extra_args.unordered_classorder_lists = NULL; +-- +1.8.3.1 + diff --git a/backport-libsepol-cil-Use-AST-to-track-blocks-and-optionals-w.patch b/backport-libsepol-cil-Use-AST-to-track-blocks-and-optionals-w.patch new file mode 100644 index 0000000000000000000000000000000000000000..5048dc1b7a4714d1c6d850ef9a71a91e8ed92d66 --- /dev/null +++ b/backport-libsepol-cil-Use-AST-to-track-blocks-and-optionals-w.patch @@ -0,0 +1,249 @@ +From 525f0312d51d3afd48f5e0cd8a58cced3532cfdf 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 63beed9..a61462d 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; +@@ -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)); +@@ -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; +@@ -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)); +@@ -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) { +@@ -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; +@@ -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; +@@ -3970,16 +3949,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; +@@ -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; +@@ -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); +@@ -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; + } + } + +@@ -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); +-- +1.8.3.1 + diff --git a/backport-libsepol-cil-Use-CIL_ERR-for-error-messages-in-cil_c.patch b/backport-libsepol-cil-Use-CIL_ERR-for-error-messages-in-cil_c.patch new file mode 100644 index 0000000000000000000000000000000000000000..4f40e353a9657495164b7341ed64cc48a12564fa --- /dev/null +++ b/backport-libsepol-cil-Use-CIL_ERR-for-error-messages-in-cil_c.patch @@ -0,0 +1,58 @@ +From 8314076cd9cd71ee7ee3c5e668c1f0472ea8b815 Mon Sep 17 00:00:00 2001 +From: James Carter +Date: Tue, 30 Mar 2021 13:40:02 -0400 +Subject: [PATCH] libsepol/cil: Use CIL_ERR for error messages in cil_compile() + +In cil_compile(), CIL_INFO is being used as the priority for +error messages. This can make it difficult to tell when the error +occurred. + +Instead, use CIL_ERR as the priority for the error messages in +cil_compile(). + +Signed-off-by: James Carter +--- + libsepol/cil/src/cil.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/libsepol/cil/src/cil.c b/libsepol/cil/src/cil.c +index 99c8e28..b971922 100644 +--- a/libsepol/cil/src/cil.c ++++ b/libsepol/cil/src/cil.c +@@ -539,7 +539,7 @@ int cil_compile(struct cil_db *db) + cil_log(CIL_INFO, "Building AST from Parse Tree\n"); + rc = cil_build_ast(db, db->parse->root, db->ast->root); + if (rc != SEPOL_OK) { +- cil_log(CIL_INFO, "Failed to build ast\n"); ++ cil_log(CIL_ERR, "Failed to build AST\n"); + goto exit; + } + +@@ -549,21 +549,21 @@ int cil_compile(struct cil_db *db) + cil_log(CIL_INFO, "Resolving AST\n"); + rc = cil_resolve_ast(db, db->ast->root); + if (rc != SEPOL_OK) { +- cil_log(CIL_INFO, "Failed to resolve ast\n"); ++ cil_log(CIL_ERR, "Failed to resolve AST\n"); + goto exit; + } + + cil_log(CIL_INFO, "Qualifying Names\n"); + rc = cil_fqn_qualify(db->ast->root); + if (rc != SEPOL_OK) { +- cil_log(CIL_INFO, "Failed to qualify names\n"); ++ cil_log(CIL_ERR, "Failed to qualify names\n"); + goto exit; + } + + cil_log(CIL_INFO, "Compile post process\n"); + rc = cil_post_process(db); + if (rc != SEPOL_OK ) { +- cil_log(CIL_INFO, "Post process failed\n"); ++ cil_log(CIL_ERR, "Post process failed\n"); + goto exit; + } + +-- +1.8.3.1 + diff --git a/backport-libsepol-cil-Use-the-macro-FLAVOR-whenever-possible.patch b/backport-libsepol-cil-Use-the-macro-FLAVOR-whenever-possible.patch new file mode 100644 index 0000000000000000000000000000000000000000..be565790df7ed2465f6b0e37580a0e9d91d128e9 --- /dev/null +++ b/backport-libsepol-cil-Use-the-macro-FLAVOR-whenever-possible.patch @@ -0,0 +1,101 @@ +From d16a1e4647a5ef2da5238f3d7829e73ceb37e5ff Mon Sep 17 00:00:00 2001 +From: James Carter +Date: Mon, 16 Nov 2020 17:07:02 -0500 +Subject: [PATCH] libsepol/cil: Use the macro FLAVOR() whenever possible + +In cil_symtab.h, the macro FLAVOR() is defined. It refers to the +flavor of the first node in the list of nodes that declare the datum. +(The flavors of every node should be the same.) While the macro was +used in many places, it was not used everywhere that it could be. + +Change all the remaining places to use FLAVOR(). + +Signed-off-by: James Carter +--- + libsepol/cil/src/cil_find.c | 8 ++++---- + libsepol/cil/src/cil_post.c | 2 +- + libsepol/cil/src/cil_resolve_ast.c | 8 ++++---- + 3 files changed, 9 insertions(+), 9 deletions(-) + +diff --git a/libsepol/cil/src/cil_find.c b/libsepol/cil/src/cil_find.c +index c182406..638b675 100644 +--- a/libsepol/cil/src/cil_find.c ++++ b/libsepol/cil/src/cil_find.c +@@ -44,8 +44,8 @@ struct cil_args_find { + + static int cil_type_match_any(struct cil_symtab_datum *d1, struct cil_symtab_datum *d2) + { +- enum cil_flavor f1 = ((struct cil_tree_node*)d1->nodes->head->data)->flavor; +- enum cil_flavor f2 = ((struct cil_tree_node*)d2->nodes->head->data)->flavor; ++ enum cil_flavor f1 = FLAVOR(d1); ++ enum cil_flavor f2 = FLAVOR(d2); + + if (f1 != CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) { + struct cil_type *t1 = (struct cil_type *)d1; +@@ -81,8 +81,8 @@ static int cil_type_match_any(struct cil_symtab_datum *d1, struct cil_symtab_dat + static int cil_type_matches(ebitmap_t *matches, struct cil_symtab_datum *d1, struct cil_symtab_datum *d2) + { + int rc = SEPOL_OK; +- enum cil_flavor f1 = ((struct cil_tree_node*)d1->nodes->head->data)->flavor; +- enum cil_flavor f2 = ((struct cil_tree_node*)d2->nodes->head->data)->flavor; ++ enum cil_flavor f1 = FLAVOR(d1); ++ enum cil_flavor f2 = FLAVOR(d2); + + if (f1 != CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) { + struct cil_type *t1 = (struct cil_type *)d1; +diff --git a/libsepol/cil/src/cil_post.c b/libsepol/cil/src/cil_post.c +index a0cadfd..37a4441 100644 +--- a/libsepol/cil/src/cil_post.c ++++ b/libsepol/cil/src/cil_post.c +@@ -1482,7 +1482,7 @@ static void __mark_neverallow_attrs(struct cil_list *expr_list) + + cil_list_for_each(curr, expr_list) { + if (curr->flavor == CIL_DATUM) { +- if (NODE(curr->data)->flavor == CIL_TYPEATTRIBUTE) { ++ if (FLAVOR(curr->data) == CIL_TYPEATTRIBUTE) { + struct cil_typeattribute *attr = curr->data; + if (strstr(DATUM(attr)->name, TYPEATTR_INFIX)) { + __mark_neverallow_attrs(attr->expr_list); +diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c +index 060bc0d..f6deb10 100644 +--- a/libsepol/cil/src/cil_resolve_ast.c ++++ b/libsepol/cil/src/cil_resolve_ast.c +@@ -505,7 +505,7 @@ int cil_resolve_aliasactual(struct cil_tree_node *current, void *extra_args, enu + if (rc != SEPOL_OK) { + goto exit; + } +- if (NODE(alias_datum)->flavor != alias_flavor) { ++ if (FLAVOR(alias_datum) != alias_flavor) { + cil_log(CIL_ERR, "%s is not an alias\n",alias_datum->name); + rc = SEPOL_ERR; + goto exit; +@@ -516,7 +516,7 @@ int cil_resolve_aliasactual(struct cil_tree_node *current, void *extra_args, enu + goto exit; + } + +- if (NODE(actual_datum)->flavor != flavor && NODE(actual_datum)->flavor != alias_flavor) { ++ if (FLAVOR(actual_datum) != flavor && FLAVOR(actual_datum) != alias_flavor) { + cil_log(CIL_ERR, "%s is a %s, but aliases a %s\n", alias_datum->name, cil_node_to_string(NODE(alias_datum)), cil_node_to_string(NODE(actual_datum))); + rc = SEPOL_ERR; + goto exit; +@@ -2573,7 +2573,7 @@ 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) { ++ if (FLAVOR(parent_datum) == attr_flavor) { + cil_log(CIL_ERR, "Bounds parent %s is an attribute\n", bounds->parent_str); + rc = SEPOL_ERR; + goto exit; +@@ -2584,7 +2584,7 @@ int cil_resolve_bounds(struct cil_tree_node *current, void *extra_args, enum cil + if (rc != SEPOL_OK) { + goto exit; + } +- if (NODE(child_datum)->flavor == attr_flavor) { ++ if (FLAVOR(child_datum) == attr_flavor) { + cil_log(CIL_ERR, "Bounds child %s is an attribute\n", bounds->child_str); + rc = SEPOL_ERR; + goto exit; +-- +1.8.3.1 + diff --git a/backport-libsepol-cil-Use-the-macro-NODE-whenever-possible.patch b/backport-libsepol-cil-Use-the-macro-NODE-whenever-possible.patch new file mode 100644 index 0000000000000000000000000000000000000000..24fd8da80ae09eeda3ccc89d75a6c8f0735d6693 --- /dev/null +++ b/backport-libsepol-cil-Use-the-macro-NODE-whenever-possible.patch @@ -0,0 +1,305 @@ +From 2aac859a9542f9f7a05b3763ee2ef7071760f401 Mon Sep 17 00:00:00 2001 +From: James Carter +Date: Mon, 16 Nov 2020 17:07:01 -0500 +Subject: [PATCH] libsepol/cil: Use the macro NODE() whenever possible + +In cil_symtab.h, the macro NODE() is defined. It refers to the first +node in the list of nodes that declare that datum. (It is rare for +a datum to have more than one node in this list.) While the macro was +used in many places, it was not used everywhere that it could be. + +Change all the remaining places to use NODE(). + +Signed-off-by: James Carter +--- + libsepol/cil/src/cil.c | 2 +- + libsepol/cil/src/cil_binary.c | 12 ++++++------ + libsepol/cil/src/cil_find.c | 2 +- + libsepol/cil/src/cil_resolve_ast.c | 40 +++++++++++++++++++------------------- + libsepol/cil/src/cil_tree.c | 2 +- + 5 files changed, 29 insertions(+), 29 deletions(-) + +diff --git a/libsepol/cil/src/cil.c b/libsepol/cil/src/cil.c +index 95bdb5e..bb7f06d 100644 +--- a/libsepol/cil/src/cil.c ++++ b/libsepol/cil/src/cil.c +@@ -1380,7 +1380,7 @@ static int cil_cats_to_ebitmap(struct cil_cats *cats, struct ebitmap* cats_ebitm + } + + cil_list_for_each(i, cats->datum_expr) { +- node = DATUM(i->data)->nodes->head->data; ++ node = NODE(i->data); + if (node->flavor == CIL_CATSET) { + cs = (struct cil_catset*)i->data; + cil_list_for_each(j, cs->cats->datum_expr) { +diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c +index e417c5c..3b01ade 100644 +--- a/libsepol/cil/src/cil_binary.c ++++ b/libsepol/cil/src/cil_binary.c +@@ -147,7 +147,7 @@ static int __cil_get_sepol_level_datum(policydb_t *pdb, struct cil_symtab_datum + + static int __cil_expand_user(struct cil_symtab_datum *datum, ebitmap_t *new) + { +- struct cil_tree_node *node = datum->nodes->head->data; ++ struct cil_tree_node *node = NODE(datum); + struct cil_user *user = NULL; + struct cil_userattribute *attr = NULL; + +@@ -175,7 +175,7 @@ exit: + + static int __cil_expand_role(struct cil_symtab_datum *datum, ebitmap_t *new) + { +- struct cil_tree_node *node = datum->nodes->head->data; ++ struct cil_tree_node *node = NODE(datum); + + if (node->flavor == CIL_ROLEATTRIBUTE) { + struct cil_roleattribute *attr = (struct cil_roleattribute *)datum; +@@ -201,7 +201,7 @@ exit: + + static int __cil_expand_type(struct cil_symtab_datum *datum, ebitmap_t *new) + { +- struct cil_tree_node *node = datum->nodes->head->data; ++ struct cil_tree_node *node = NODE(datum); + + if (node->flavor == CIL_TYPEATTRIBUTE) { + struct cil_typeattribute *attr = (struct cil_typeattribute *)datum; +@@ -2943,7 +2943,7 @@ int __cil_cats_to_mls_level(policydb_t *pdb, struct cil_cats *cats, mls_level_t + cat_datum_t *sepol_cat = NULL; + + cil_list_for_each(i, cats->datum_expr) { +- struct cil_tree_node *node = DATUM(i->data)->nodes->head->data; ++ struct cil_tree_node *node = NODE(i->data); + if (node->flavor == CIL_CATSET) { + struct cil_list_item *j; + struct cil_catset *cs = i->data; +@@ -3701,7 +3701,7 @@ int __cil_node_to_policydb(struct cil_tree_node *node, void *extra_args) + type_value_to_cil = args->type_value_to_cil; + + if (node->flavor >= CIL_MIN_DECLARATIVE) { +- if (node != DATUM(node->data)->nodes->head->data) { ++ if (node != NODE(node->data)) { + goto exit; + } + } +@@ -4450,7 +4450,7 @@ static void __cil_init_sepol_type_set(type_set_t *t) + static int __cil_add_sepol_type(policydb_t *pdb, const struct cil_db *db, struct cil_symtab_datum *datum, ebitmap_t *map) + { + int rc = SEPOL_ERR; +- struct cil_tree_node *n = datum->nodes->head->data; ++ struct cil_tree_node *n = NODE(datum); + type_datum_t *sepol_datum = NULL; + + if (n->flavor == CIL_TYPEATTRIBUTE) { +diff --git a/libsepol/cil/src/cil_find.c b/libsepol/cil/src/cil_find.c +index 4134242..c182406 100644 +--- a/libsepol/cil/src/cil_find.c ++++ b/libsepol/cil/src/cil_find.c +@@ -118,7 +118,7 @@ static int cil_type_matches(ebitmap_t *matches, struct cil_symtab_datum *d1, str + static int cil_self_match_any(struct cil_symtab_datum *s1, struct cil_symtab_datum *s2, struct cil_symtab_datum *t2) + { + int rc; +- struct cil_tree_node *n1 = s1->nodes->head->data; ++ struct cil_tree_node *n1 = NODE(s1); + if (n1->flavor != CIL_TYPEATTRIBUTE) { + rc = cil_type_match_any(s1, t2); + } else { +diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c +index 9e6afca..060bc0d 100644 +--- a/libsepol/cil/src/cil_resolve_ast.c ++++ b/libsepol/cil/src/cil_resolve_ast.c +@@ -393,7 +393,7 @@ int cil_resolve_type_rule(struct cil_tree_node *current, void *extra_args) + goto exit; + } + +- result_node = result_datum->nodes->head->data; ++ result_node = NODE(result_datum); + + if (result_node->flavor != CIL_TYPE) { + cil_log(CIL_ERR, "Type rule result must be a type [%d]\n",result_node->flavor); +@@ -421,7 +421,7 @@ int cil_resolve_typeattributeset(struct cil_tree_node *current, void *extra_args + goto exit; + } + +- attr_node = attr_datum->nodes->head->data; ++ attr_node = NODE(attr_datum); + + if (attr_node->flavor != CIL_TYPEATTRIBUTE) { + rc = SEPOL_ERR; +@@ -470,7 +470,7 @@ int cil_resolve_expandtypeattribute(struct cil_tree_node *current, void *extra_a + goto exit; + } + +- attr_node = attr_datum->nodes->head->data; ++ attr_node = NODE(attr_datum); + + if (attr_node->flavor != CIL_TYPEATTRIBUTE) { + rc = SEPOL_ERR; +@@ -594,7 +594,7 @@ int cil_resolve_typepermissive(struct cil_tree_node *current, void *extra_args) + goto exit; + } + +- type_node = type_datum->nodes->head->data; ++ type_node = NODE(type_datum); + + if (type_node->flavor != CIL_TYPE && type_node->flavor != CIL_TYPEALIAS) { + cil_log(CIL_ERR, "Typepermissive must be a type or type alias\n"); +@@ -654,7 +654,7 @@ int cil_resolve_nametypetransition(struct cil_tree_node *current, void *extra_ar + goto exit; + } + +- result_node = result_datum->nodes->head->data; ++ result_node = NODE(result_datum); + + if (result_node->flavor != CIL_TYPE && result_node->flavor != CIL_TYPEALIAS) { + cil_log(CIL_ERR, "typetransition result is not a type or type alias\n"); +@@ -855,7 +855,7 @@ int cil_resolve_userlevel(struct cil_tree_node *current, void *extra_args) + goto exit; + } + +- user_node = user_datum->nodes->head->data; ++ user_node = NODE(user_datum); + + if (user_node->flavor != CIL_USER) { + cil_log(CIL_ERR, "Userlevel must be a user\n"); +@@ -908,7 +908,7 @@ int cil_resolve_userrange(struct cil_tree_node *current, void *extra_args) + goto exit; + } + +- user_node = user_datum->nodes->head->data; ++ user_node = NODE(user_datum); + + if (user_node->flavor != CIL_USER) { + cil_log(CIL_ERR, "Userrange must be a user: %s\n", user_datum->fqn); +@@ -959,7 +959,7 @@ int cil_resolve_userprefix(struct cil_tree_node *current, void *extra_args) + goto exit; + } + +- user_node = user_datum->nodes->head->data; ++ user_node = NODE(user_datum); + + if (user_node->flavor != CIL_USER) { + cil_log(CIL_ERR, "Userprefix must be a user: %s\n", user_datum->fqn); +@@ -986,7 +986,7 @@ int cil_resolve_selinuxuser(struct cil_tree_node *current, void *extra_args) + goto exit; + } + +- user_node = user_datum->nodes->head->data; ++ user_node = NODE(user_datum); + + if (user_node->flavor != CIL_USER) { + cil_log(CIL_ERR, "Selinuxuser must be a user: %s\n", user_datum->fqn); +@@ -1079,7 +1079,7 @@ int cil_resolve_roletransition(struct cil_tree_node *current, void *extra_args) + if (rc != SEPOL_OK) { + goto exit; + } +- node = result_datum->nodes->head->data; ++ node = NODE(result_datum); + if (node->flavor != CIL_ROLE) { + rc = SEPOL_ERR; + printf("%i\n", node->flavor); +@@ -1131,7 +1131,7 @@ int cil_resolve_roleattributeset(struct cil_tree_node *current, void *extra_args + if (rc != SEPOL_OK) { + goto exit; + } +- attr_node = attr_datum->nodes->head->data; ++ attr_node = NODE(attr_datum); + + if (attr_node->flavor != CIL_ROLEATTRIBUTE) { + rc = SEPOL_ERR; +@@ -1569,7 +1569,7 @@ int cil_resolve_catorder(struct cil_tree_node *current, void *extra_args) + cil_log(CIL_ERR, "Failed to resolve category %s in categoryorder\n", (char *)curr->data); + goto exit; + } +- node = cat_datum->nodes->head->data; ++ node = NODE(cat_datum); + if (node->flavor != CIL_CAT) { + cil_log(CIL_ERR, "%s is not a category. Only categories are allowed in categoryorder statements\n", cat_datum->name); + rc = SEPOL_ERR; +@@ -1832,7 +1832,7 @@ int cil_resolve_context(struct cil_tree_node *current, struct cil_context *conte + goto exit; + } + +- node = user_datum->nodes->head->data; ++ node = NODE(user_datum); + + if (node->flavor != CIL_USER) { + cil_log(CIL_ERR, "Context user must be a user: %s\n", user_datum->fqn); +@@ -1847,7 +1847,7 @@ int cil_resolve_context(struct cil_tree_node *current, struct cil_context *conte + goto exit; + } + +- node = role_datum->nodes->head->data; ++ node = NODE(role_datum); + if (node->flavor != CIL_ROLE) { + rc = SEPOL_ERR; + cil_log(CIL_ERR, "Context role not a role: %s\n", role_datum->fqn); +@@ -1861,7 +1861,7 @@ int cil_resolve_context(struct cil_tree_node *current, struct cil_context *conte + goto exit; + } + +- node = type_datum->nodes->head->data; ++ node = NODE(type_datum); + + if (node->flavor != CIL_TYPE && node->flavor != CIL_TYPEALIAS) { + rc = SEPOL_ERR; +@@ -2311,7 +2311,7 @@ int cil_resolve_blockinherit_link(struct cil_tree_node *current, void *extra_arg + goto exit; + } + +- node = block_datum->nodes->head->data; ++ node = NODE(block_datum); + + if (node->flavor != CIL_BLOCK) { + cil_log(CIL_ERR, "%s is not a block\n", cil_node_to_string(node)); +@@ -2450,7 +2450,7 @@ int cil_resolve_blockabstract(struct cil_tree_node *current, void *extra_args) + goto exit; + } + +- block_node = block_datum->nodes->head->data; ++ block_node = NODE(block_datum); + if (block_node->flavor != CIL_BLOCK) { + cil_log(CIL_ERR, "Failed to resolve blockabstract to a block, rc: %d\n", rc); + goto exit; +@@ -2482,7 +2482,7 @@ int cil_resolve_in(struct cil_tree_node *current, void *extra_args) + goto exit; + } + +- block_node = block_datum->nodes->head->data; ++ block_node = NODE(block_datum); + + rc = cil_copy_ast(db, current, block_node); + if (rc != SEPOL_OK) { +@@ -2774,7 +2774,7 @@ int cil_resolve_call1(struct cil_tree_node *current, void *extra_args) + goto exit; + } + +- macro_node = macro_datum->nodes->head->data; ++ macro_node = NODE(macro_datum); + + if (macro_node->flavor != CIL_MACRO) { + printf("Failed to resolve %s to a macro\n", new_call->macro_str); +@@ -3367,7 +3367,7 @@ int cil_resolve_userattributeset(struct cil_tree_node *current, void *extra_args + if (rc != SEPOL_OK) { + goto exit; + } +- attr_node = attr_datum->nodes->head->data; ++ attr_node = NODE(attr_datum); + + if (attr_node->flavor != CIL_USERATTRIBUTE) { + rc = SEPOL_ERR; +diff --git a/libsepol/cil/src/cil_tree.c b/libsepol/cil/src/cil_tree.c +index b1cbda9..3ab5e86 100644 +--- a/libsepol/cil/src/cil_tree.c ++++ b/libsepol/cil/src/cil_tree.c +@@ -1688,7 +1688,7 @@ void cil_tree_print_node(struct cil_tree_node *node) + struct cil_symtab_datum *datum = ((struct cil_args*)item->data)->arg; + if (datum != NULL) { + if (datum->nodes != NULL && datum->nodes->head != NULL) { +- cil_tree_print_node((struct cil_tree_node*)datum->nodes->head->data); ++ cil_tree_print_node(NODE(datum)); + } + } else if (((struct cil_args*)item->data)->arg_str != NULL) { + switch (item->flavor) { +-- +1.8.3.1 + diff --git a/backport-libsepol-cil-follow-declaration-after-statement.patch b/backport-libsepol-cil-follow-declaration-after-statement.patch new file mode 100644 index 0000000000000000000000000000000000000000..35ad6cfce1298fe33dd0957ee3867a638fbbd360 --- /dev/null +++ b/backport-libsepol-cil-follow-declaration-after-statement.patch @@ -0,0 +1,189 @@ +From 852c4398a9a227e0eb4de42d45c0c2845ed92bc7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Tue, 8 Jun 2021 17:58:57 +0200 +Subject: [PATCH] libsepol/cil: follow declaration-after-statement +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Follow the project style of no declaration after statement. + +Found by the gcc warning -Wdeclaration-after-statement + +Signed-off-by: Christian Göttsche +Acked-by: James Carter +--- + libsepol/cil/src/cil_binary.c | 5 +++-- + libsepol/cil/src/cil_build_ast.c | 5 +++-- + libsepol/cil/src/cil_fqn.c | 3 ++- + libsepol/cil/src/cil_list.c | 7 ++++--- + libsepol/cil/src/cil_post.c | 2 +- + libsepol/cil/src/cil_resolve_ast.c | 6 +++--- + libsepol/cil/src/cil_strpool.c | 3 ++- + 7 files changed, 18 insertions(+), 13 deletions(-) + +diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c +index 18532aa..85094b0 100644 +--- a/libsepol/cil/src/cil_binary.c ++++ b/libsepol/cil/src/cil_binary.c +@@ -593,11 +593,11 @@ exit: + int __cil_typeattr_bitmap_init(policydb_t *pdb) + { + int rc = SEPOL_ERR; ++ uint32_t i; + + pdb->type_attr_map = cil_malloc(pdb->p_types.nprim * sizeof(ebitmap_t)); + pdb->attr_type_map = cil_malloc(pdb->p_types.nprim * sizeof(ebitmap_t)); + +- uint32_t i = 0; + for (i = 0; i < pdb->p_types.nprim; i++) { + ebitmap_init(&pdb->type_attr_map[i]); + ebitmap_init(&pdb->attr_type_map[i]); +@@ -2657,6 +2657,7 @@ int __cil_constrain_expr_to_sepol_expr_helper(policydb_t *pdb, const struct cil_ + int rc = SEPOL_ERR; + struct cil_list_item *item; + enum cil_flavor flavor; ++ enum cil_flavor cil_op; + constraint_expr_t *op, *h1, *h2, *t1, *t2; + int is_leaf = CIL_FALSE; + +@@ -2673,7 +2674,7 @@ int __cil_constrain_expr_to_sepol_expr_helper(policydb_t *pdb, const struct cil_ + goto exit; + } + +- enum cil_flavor cil_op = (enum cil_flavor)(uintptr_t)item->data; ++ cil_op = (enum cil_flavor)(uintptr_t)item->data; + switch (cil_op) { + case CIL_NOT: + op->expr_type = CEXPR_NOT; +diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c +index 96c9726..908b033 100644 +--- a/libsepol/cil/src/cil_build_ast.c ++++ b/libsepol/cil/src/cil_build_ast.c +@@ -5173,6 +5173,7 @@ int cil_gen_macro(struct cil_db *db, struct cil_tree_node *parse_current, struct + char *key = NULL; + struct cil_macro *macro = NULL; + struct cil_tree_node *macro_content = NULL; ++ struct cil_tree_node *current_item; + enum cil_syntax syntax[] = { + CIL_SYN_STRING, + CIL_SYN_STRING, +@@ -5195,7 +5196,7 @@ int cil_gen_macro(struct cil_db *db, struct cil_tree_node *parse_current, struct + + key = parse_current->next->data; + +- struct cil_tree_node *current_item = parse_current->next->next->cl_head; ++ current_item = parse_current->next->next->cl_head; + while (current_item != NULL) { + enum cil_syntax param_syntax[] = { + CIL_SYN_STRING, +@@ -5205,6 +5206,7 @@ int cil_gen_macro(struct cil_db *db, struct cil_tree_node *parse_current, struct + int param_syntax_len = sizeof(param_syntax)/sizeof(*param_syntax); + char *kind = NULL; + struct cil_param *param = NULL; ++ struct cil_list_item *curr_param; + + rc =__cil_verify_syntax(current_item->cl_head, param_syntax, param_syntax_len); + if (rc != SEPOL_OK) { +@@ -5263,7 +5265,6 @@ int cil_gen_macro(struct cil_db *db, struct cil_tree_node *parse_current, struct + } + + //walk current list and check for duplicate parameters +- struct cil_list_item *curr_param; + cil_list_for_each(curr_param, macro->params) { + if (param->str == ((struct cil_param*)curr_param->data)->str) { + cil_log(CIL_ERR, "Duplicate parameter\n"); +diff --git a/libsepol/cil/src/cil_fqn.c b/libsepol/cil/src/cil_fqn.c +index 097222a..46db069 100644 +--- a/libsepol/cil/src/cil_fqn.c ++++ b/libsepol/cil/src/cil_fqn.c +@@ -78,12 +78,13 @@ static int __cil_fqn_qualify_blocks(__attribute__((unused)) hashtab_key_t k, has + struct cil_tree_node *node = NODE(datum); + int i; + int rc = SEPOL_OK; ++ int newlen; + + if (node->flavor != CIL_BLOCK) { + goto exit; + } + +- int newlen = fqn_args->len + strlen(datum->name) + 1; ++ newlen = fqn_args->len + strlen(datum->name) + 1; + if (newlen >= CIL_MAX_NAME_LENGTH) { + cil_log(CIL_INFO, "Fully qualified name for block %s is too long\n", datum->name); + rc = SEPOL_ERR; +diff --git a/libsepol/cil/src/cil_list.c b/libsepol/cil/src/cil_list.c +index 4e7843c..8a426f1 100644 +--- a/libsepol/cil/src/cil_list.c ++++ b/libsepol/cil/src/cil_list.c +@@ -55,15 +55,16 @@ void cil_list_init(struct cil_list **list, enum cil_flavor flavor) + + void cil_list_destroy(struct cil_list **list, unsigned destroy_data) + { ++ struct cil_list_item *item; ++ + if (*list == NULL) { + return; + } + +- struct cil_list_item *item = (*list)->head; +- struct cil_list_item *next = NULL; ++ item = (*list)->head; + while (item != NULL) + { +- next = item->next; ++ struct cil_list_item *next = item->next; + if (item->flavor == CIL_LIST) { + cil_list_destroy((struct cil_list**)&(item->data), destroy_data); + free(item); +diff --git a/libsepol/cil/src/cil_post.c b/libsepol/cil/src/cil_post.c +index 05842b6..7bca083 100644 +--- a/libsepol/cil/src/cil_post.c ++++ b/libsepol/cil/src/cil_post.c +@@ -213,8 +213,8 @@ int cil_post_filecon_compare(const void *a, const void *b) + struct fc_data *a_data = cil_malloc(sizeof(*a_data)); + struct fc_data *b_data = cil_malloc(sizeof(*b_data)); + char *a_path = cil_malloc(strlen(a_filecon->path_str) + 1); +- a_path[0] = '\0'; + char *b_path = cil_malloc(strlen(b_filecon->path_str) + 1); ++ a_path[0] = '\0'; + b_path[0] = '\0'; + strcat(a_path, a_filecon->path_str); + strcat(b_path, b_filecon->path_str); +diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c +index 92a4d29..b5199ba 100644 +--- a/libsepol/cil/src/cil_resolve_ast.c ++++ b/libsepol/cil/src/cil_resolve_ast.c +@@ -3956,10 +3956,10 @@ int __cil_resolve_ast_node_helper(struct cil_tree_node *node, uint32_t *finished + enum cil_log_level lvl = CIL_ERR; + + if (optional != NULL) { +- lvl = CIL_INFO; +- + struct cil_optional *opt = (struct cil_optional *)optional->data; +- struct cil_tree_node *opt_node = NODE(opt);; ++ struct cil_tree_node *opt_node = NODE(opt); ++ ++ lvl = CIL_INFO; + /* 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)); +diff --git a/libsepol/cil/src/cil_strpool.c b/libsepol/cil/src/cil_strpool.c +index 2598bbf..70bca36 100644 +--- a/libsepol/cil/src/cil_strpool.c ++++ b/libsepol/cil/src/cil_strpool.c +@@ -75,9 +75,10 @@ char *cil_strpool_add(const char *str) + + strpool_ref = hashtab_search(cil_strpool_tab, (hashtab_key_t)str); + if (strpool_ref == NULL) { ++ int rc; + strpool_ref = cil_malloc(sizeof(*strpool_ref)); + strpool_ref->str = cil_strdup(str); +- int rc = hashtab_insert(cil_strpool_tab, (hashtab_key_t)strpool_ref->str, strpool_ref); ++ rc = hashtab_insert(cil_strpool_tab, (hashtab_key_t)strpool_ref->str, strpool_ref); + if (rc != SEPOL_OK) { + pthread_mutex_unlock(&cil_strpool_mutex); + cil_log(CIL_ERR, "Failed to allocate memory\n"); +-- +1.8.3.1 + diff --git a/backport-libsepol-cil-introduce-intermediate-cast-to-silence-.patch b/backport-libsepol-cil-introduce-intermediate-cast-to-silence-.patch new file mode 100644 index 0000000000000000000000000000000000000000..262a8ffdba20cf23aa052dbd1864845f319822bf --- /dev/null +++ b/backport-libsepol-cil-introduce-intermediate-cast-to-silence-.patch @@ -0,0 +1,171 @@ +From 32f8ed3d6b0bba44f2f211ff630f61f6a17cf578 Mon Sep 17 00:00:00 2001 +From: Nicolas Iooss +Date: Fri, 5 Feb 2021 10:45:39 +0100 +Subject: [PATCH] libsepol/cil: introduce intermediate cast to silence + -Wvoid-pointer-to-enum-cast + +clang 11.0.0 reports the following warning several times (when building +with "make CC=clang" from libsepol directory, in the default +configuration of the git repository): + + ../cil/src/cil_binary.c:1980:8: error: cast to smaller integer type + 'enum cil_flavor' from 'void *' [-Werror,-Wvoid-pointer-to-enum-cast] + op = (enum cil_flavor)curr->data; + ^~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Silence this warning by casting the pointer to an integer the cast to +enum cil_flavor. + +Signed-off-by: Nicolas Iooss +--- + libsepol/cil/src/cil_binary.c | 12 ++++++------ + libsepol/cil/src/cil_policy.c | 12 ++++++------ + libsepol/cil/src/cil_post.c | 2 +- + libsepol/cil/src/cil_resolve_ast.c | 2 +- + 4 files changed, 14 insertions(+), 14 deletions(-) + +diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c +index 7ba2098..f80d846 100644 +--- a/libsepol/cil/src/cil_binary.c ++++ b/libsepol/cil/src/cil_binary.c +@@ -1977,7 +1977,7 @@ static void __cil_expr_to_string(struct cil_list *expr, enum cil_flavor flavor, + curr = expr->head; + + if (curr->flavor == CIL_OP) { +- op = (enum cil_flavor)curr->data; ++ op = (enum cil_flavor)(uintptr_t)curr->data; + + if (op == CIL_ALL) { + *out = cil_strdup(CIL_KEY_ALL); +@@ -2076,7 +2076,7 @@ static int __cil_cond_expr_to_sepol_expr_helper(policydb_t *pdb, struct cil_list + if (item == NULL) { + goto exit; + } else if (item->flavor == CIL_OP) { +- enum cil_flavor cil_op = (enum cil_flavor)item->data; ++ enum cil_flavor cil_op = (enum cil_flavor)(uintptr_t)item->data; + + op = cil_malloc(sizeof(*op)); + op->bool = 0; +@@ -2562,7 +2562,7 @@ int __cil_constrain_expr_leaf_to_sepol_expr(policydb_t *pdb, const struct cil_db + struct cil_list_item *l_item = op_item->next; + struct cil_list_item *r_item = op_item->next->next; + +- enum cil_flavor l_operand = (enum cil_flavor)l_item->data; ++ enum cil_flavor l_operand = (enum cil_flavor)(uintptr_t)l_item->data; + + switch (l_operand) { + case CIL_CONS_U1: +@@ -2593,7 +2593,7 @@ int __cil_constrain_expr_leaf_to_sepol_expr(policydb_t *pdb, const struct cil_db + expr->attr = CEXPR_TYPE | CEXPR_XTARGET; + break; + case CIL_CONS_L1: { +- enum cil_flavor r_operand = (enum cil_flavor)r_item->data; ++ enum cil_flavor r_operand = (enum cil_flavor)(uintptr_t)r_item->data; + + if (r_operand == CIL_CONS_L2) { + expr->attr = CEXPR_L1L2; +@@ -2608,7 +2608,7 @@ int __cil_constrain_expr_leaf_to_sepol_expr(policydb_t *pdb, const struct cil_db + expr->attr = CEXPR_L2H2; + break; + case CIL_CONS_H1: { +- enum cil_flavor r_operand = (enum cil_flavor)r_item->data; ++ enum cil_flavor r_operand = (enum cil_flavor)(uintptr_t)r_item->data; + if (r_operand == CIL_CONS_L2) { + expr->attr = CEXPR_H1L2; + } else { +@@ -2672,7 +2672,7 @@ int __cil_constrain_expr_to_sepol_expr_helper(policydb_t *pdb, const struct cil_ + goto exit; + } + +- enum cil_flavor cil_op = (enum cil_flavor)item->data; ++ enum cil_flavor cil_op = (enum cil_flavor)(uintptr_t)item->data; + switch (cil_op) { + case CIL_NOT: + op->expr_type = CEXPR_NOT; +diff --git a/libsepol/cil/src/cil_policy.c b/libsepol/cil/src/cil_policy.c +index 74edb34..30d507f 100644 +--- a/libsepol/cil/src/cil_policy.c ++++ b/libsepol/cil/src/cil_policy.c +@@ -285,7 +285,7 @@ static void cil_cond_expr_to_policy(FILE *out, struct cil_list *expr, int first) + struct cil_list_item *i1 = expr->head; + + if (i1->flavor == CIL_OP) { +- enum cil_flavor op = (enum cil_flavor)i1->data; ++ enum cil_flavor op = (enum cil_flavor)(uintptr_t)i1->data; + fprintf(out, "("); + switch (op) { + case CIL_NOT: +@@ -385,7 +385,7 @@ static size_t __cil_cons_leaf_operand_len(struct cil_db *db, struct cil_list_ite + + static size_t __cil_cons_leaf_op_len(struct cil_list_item *op) + { +- enum cil_flavor flavor = (enum cil_flavor)op->data; ++ enum cil_flavor flavor = (enum cil_flavor)(uintptr_t)op->data; + size_t len; + + switch (flavor) { +@@ -420,7 +420,7 @@ static size_t cil_cons_expr_len(struct cil_db *db, struct cil_list *cons_expr) + + i1 = cons_expr->head; + +- op = (enum cil_flavor)i1->data; ++ op = (enum cil_flavor)(uintptr_t)i1->data; + switch (op) { + case CIL_NOT: + len = 6; /* "(not )" */ +@@ -472,7 +472,7 @@ static char *__cil_cons_leaf_operand_to_string(struct cil_db *db, struct cil_lis + size_t o_len; + + if (flavor == CIL_CONS_OPERAND) { +- enum cil_flavor o_flavor = (enum cil_flavor)operand->data; ++ enum cil_flavor o_flavor = (enum cil_flavor)(uintptr_t)operand->data; + switch (o_flavor) { + case CIL_CONS_U1: + o_str = "u1"; +@@ -555,7 +555,7 @@ static char *__cil_cons_leaf_operand_to_string(struct cil_db *db, struct cil_lis + + static char *__cil_cons_leaf_op_to_string(struct cil_list_item *op, char *new) + { +- enum cil_flavor flavor = (enum cil_flavor)op->data; ++ enum cil_flavor flavor = (enum cil_flavor)(uintptr_t)op->data; + const char *op_str; + size_t len; + +@@ -599,7 +599,7 @@ static char *__cil_cons_expr_to_string(struct cil_db *db, struct cil_list *cons_ + + i1 = cons_expr->head; + +- op = (enum cil_flavor)i1->data; ++ op = (enum cil_flavor)(uintptr_t)i1->data; + switch (op) { + case CIL_NOT: + *new++ = '('; +diff --git a/libsepol/cil/src/cil_post.c b/libsepol/cil/src/cil_post.c +index 37a4441..a55df1e 100644 +--- a/libsepol/cil/src/cil_post.c ++++ b/libsepol/cil/src/cil_post.c +@@ -1301,7 +1301,7 @@ static int __cil_expr_to_bitmap(struct cil_list *expr, ebitmap_t *out, int max, + flavor = expr->flavor; + + if (curr->flavor == CIL_OP) { +- enum cil_flavor op = (enum cil_flavor)curr->data; ++ enum cil_flavor op = (enum cil_flavor)(uintptr_t)curr->data; + + if (op == CIL_ALL) { + ebitmap_init(&b1); /* all zeros */ +diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c +index 9300cd2..208bc01 100644 +--- a/libsepol/cil/src/cil_resolve_ast.c ++++ b/libsepol/cil/src/cil_resolve_ast.c +@@ -3355,7 +3355,7 @@ static int __cil_evaluate_tunable_expr(struct cil_list_item *curr) + return CIL_FALSE; + } else if (curr->flavor == CIL_OP) { + uint16_t v1, v2; +- enum cil_flavor op_flavor = (enum cil_flavor)curr->data; ++ enum cil_flavor op_flavor = (enum cil_flavor)(uintptr_t)curr->data; + + v1 = __cil_evaluate_tunable_expr_helper(curr->next); + +-- +1.8.3.1 + diff --git a/backport-libsepol-cil-replace-printf-with-proper-cil_tree_log.patch b/backport-libsepol-cil-replace-printf-with-proper-cil_tree_log.patch new file mode 100644 index 0000000000000000000000000000000000000000..36a4c0d8cd8071606c6548f6ceb52ab8b4492b55 --- /dev/null +++ b/backport-libsepol-cil-replace-printf-with-proper-cil_tree_log.patch @@ -0,0 +1,39 @@ +From 68e8871cfcbe1267ff0234a0dc78b207acc26af8 Mon Sep 17 00:00:00 2001 +From: Nicolas Iooss +Date: Sun, 14 Mar 2021 18:04:04 +0100 +Subject: [PATCH] libsepol/cil: replace printf with proper cil_tree_log + +All functions of the CIL compiler use cil_log or cil_tree_log to report +errors, but in two places which still uses printf. Replace these printf +invocation with cil_tree_log. + +Signed-off-by: Nicolas Iooss +--- + libsepol/cil/src/cil_resolve_ast.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c +index 47cdf0e..2ea106d 100644 +--- a/libsepol/cil/src/cil_resolve_ast.c ++++ b/libsepol/cil/src/cil_resolve_ast.c +@@ -2497,7 +2497,7 @@ int cil_resolve_in(struct cil_tree_node *current, void *extra_args) + + rc = cil_copy_ast(db, current, block_node); + if (rc != SEPOL_OK) { +- printf("Failed to copy in, rc: %d\n", rc); ++ cil_tree_log(current, CIL_ERR, "Failed to copy in-statement"); + goto exit; + } + +@@ -2788,7 +2788,7 @@ int cil_resolve_call1(struct cil_tree_node *current, void *extra_args) + macro_node = NODE(macro_datum); + + if (macro_node->flavor != CIL_MACRO) { +- printf("Failed to resolve %s to a macro\n", new_call->macro_str); ++ cil_tree_log(current, CIL_ERR, "Failed to resolve %s to a macro", new_call->macro_str); + rc = SEPOL_ERR; + goto exit; + } +-- +1.8.3.1 + diff --git a/libsepol.spec b/libsepol.spec index 2ece5e6694f456a634883c0b89e52f969133b1c6..e50019a9941a585b524791d7a01a2442823c5d69 100644 --- a/libsepol.spec +++ b/libsepol.spec @@ -1,6 +1,6 @@ Name: libsepol Version: 3.1 -Release: 4 +Release: 5 Summary: SELinux binary policy manipulation library License: LGPLv2+ URL: https://github.com/SELinuxProject/selinux/wiki/Releases @@ -16,6 +16,29 @@ Patch7: backport-libsepol-cil-fix-NULL-pointer-dereference-when-using.pa Patch8: backport-libsepol-cil-fix-out-of-bound-read-in-cil_print_recu.patch Patch9: backport-libsepol-cil-propagate-failure-of-cil_fill_list.patch +Patch10: backport-libsepol-cil-Use-CIL_ERR-for-error-messages-in-cil_c.patch +Patch11: backport-libsepol-cil-Detect-degenerate-inheritance-and-exit-.patch +Patch12: backport-libsepol-cil-Use-the-macro-NODE-whenever-possible.patch +Patch13: backport-libsepol-cil-Check-for-duplicate-blocks-optionals-an.patch +Patch14: backport-libsepol-cil-Refactor-helper-function-for-cil_gen_no.patch +Patch15: backport-libsepol-cil-Remove-unused-field-from-struct-cil_arg.patch +Patch16: backport-libsepol-cil-Destroy-disabled-optional-blocks-after-.patch +Patch17: backport-libsepol-cil-Use-AST-to-track-blocks-and-optionals-w.patch +Patch18: backport-libsepol-cil-Reorder-checks-for-invalid-rules-when-r.patch +Patch19: backport-libsepol-cil-replace-printf-with-proper-cil_tree_log.patch +Patch20: backport-libsepol-cil-introduce-intermediate-cast-to-silence-.patch +Patch21: backport-libsepol-cil-follow-declaration-after-statement.patch +Patch22: backport-libsepol-cil-Handle-disabled-optional-blocks-in-earl.patch +Patch23: backport-libsepol-cil-Allow-duplicate-optional-blocks-in-most.patch +Patch24: backport-libsepol-cil-Improve-degenerate-inheritance-check.patch +Patch25: backport-libsepol-cil-Improve-checking-for-bad-inheritance-pa.patch +Patch26: backport-libsepol-cil-Use-the-macro-FLAVOR-whenever-possible.patch +Patch27: backport-libsepol-cil-Check-for-empty-list-when-marking-never.patch +Patch28: backport-libsepol-cil-Fix-instances-where-an-error-returns-SE.patch +Patch29: backport-libsepol-cil-Limit-the-number-of-open-parenthesis-al.patch +Patch30: backport-libsepol-cil-Fix-syntax-checking-of-defaultrange-rul.patch +Patch31: backport-libsepol-cil-Allow-some-duplicate-macro-and-block-de.patch + BuildRequires: gcc flex %description @@ -74,13 +97,16 @@ make DESTDIR="%{buildroot}" LIBDIR="%{_libdir}" SHLIBDIR="%{_libdir}" install %{_mandir}/man3/* %changelog +* Fri Sep 10 2021 panxiaohe - 3.1-5 +- fix secilc-fuzzer issues + * Fri May 28 2021 panxiaohe - 3.1-4 - Drop unnecessary telinit * Mon Mar 15 2021 yangzhuangzhuang - 3.1-3 - fix heap-use-after-free in cil_yy_switch_to_buffer - fix heap-use-after-free in __class_reset_perm_values() - fix heap-buffer-overflow in cil_print_recursive_blockinherit +- fix heap-use-after-free in __class_reset_perm_values() +- fix heap-buffer-overflow in cil_print_recursive_blockinherit * Thu Mar 4 2021 Lirui - 3.1-2 - fix NULL pointer dereference in cil_fill_ipaddr