fix secilc-fuzzer issues

This commit is contained in:
panxiaohe 2021-09-10 10:06:45 +08:00
parent 52e630698a
commit 7aa8ce6a3b
23 changed files with 3332 additions and 3 deletions

View File

@ -0,0 +1,276 @@
From 67a8dc8117e0c3887c39f7add8932e4ad23c1d9c Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
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 <jwcart2@gmail.com>
Acked-by: Nicolas Iooss <nicolas.iooss@m4x.org>
---
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

View File

@ -0,0 +1,216 @@
From 8d197879f91337c2c4d972a3dd23bb4b133ff355 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
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 <jwcart2@gmail.com>
---
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

View File

@ -0,0 +1,163 @@
From d155b410d4bbc90d28f361b966f0429598da8188 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
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 <nicolas.iooss@m4x.org>
Reported-by: Evgeny Vereshchagin <evvers@ya.ru>
Signed-off-by: James Carter <jwcart2@gmail.com>
---
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

View File

@ -0,0 +1,35 @@
From f33745a22b4133c59059356a23dbbc229067e3c1 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
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 <jwcart2@gmail.com>
Acked-by: Nicolas Iooss <nicolas.iooss@m4x.org>
---
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

View File

@ -0,0 +1,115 @@
From 0451adebdf153eee1f69914141311114a0130982 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
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 <nicolas.iooss@m4x.org>
Signed-off-by: James Carter <jwcart2@gmail.com>
Acked-by: Nicolas Iooss <nicolas.iooss@m4x.org>
---
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

View File

@ -0,0 +1,136 @@
From 74d00a8decebf940d95064ff60042dcb2cbcc2c0 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
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 <jwcart2@gmail.com>
---
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

View File

@ -0,0 +1,80 @@
From 5681c6275b5ad9cf3d84af243a66b900a0628f72 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
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 <jwcart2@gmail.com>
---
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

View File

@ -0,0 +1,55 @@
From ac8b35d910750b56d38d54f312a712a73c95749c Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
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 <jwcart2@gmail.com>
Acked-by: Nicolas Iooss <nicolas.iooss@m4x.org>
---
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

View File

@ -0,0 +1,94 @@
From 5661efd459e7aa998390ab70e3ec50125a35e9e9 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
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 <jwcart2@gmail.com>
---
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

View File

@ -0,0 +1,315 @@
From 9af91692416d01814f4b2ac22e39d3b57993af4f Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
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 <jwcart2@gmail.com>
---
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

View File

@ -0,0 +1,362 @@
From 37863b0b1444c85a1ddc6c333c8bfea0c678c592 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
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 <jwcart2@gmail.com>
Acked-by: Nicolas Iooss <nicolas.iooss@m4x.org>
---
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

View File

@ -0,0 +1,48 @@
From 69fc31d1fb5d3bc1d4a919285284d1fb9d679a6e Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
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 <jwcart2@gmail.com>
---
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

View File

@ -0,0 +1,74 @@
From 63ce05ba07fc3517900fac22efe1c761d856762f Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
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 <jwcart2@gmail.com>
---
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

View File

@ -0,0 +1,47 @@
From 9b9761cfaa09958ead2bcad256dd0f1706e8b5b3 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
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 <jwcart2@gmail.com>
---
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

View File

@ -0,0 +1,175 @@
From ef533c8fd941bfb0c9a729b757d8a5b68fe3d080 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
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 <jwcart2@gmail.com>
---
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

View File

@ -0,0 +1,249 @@
From 525f0312d51d3afd48f5e0cd8a58cced3532cfdf Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
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 <jwcart2@gmail.com>
---
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

View File

@ -0,0 +1,58 @@
From 8314076cd9cd71ee7ee3c5e668c1f0472ea8b815 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
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 <jwcart2@gmail.com>
---
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

View File

@ -0,0 +1,101 @@
From d16a1e4647a5ef2da5238f3d7829e73ceb37e5ff Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
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 <jwcart2@gmail.com>
---
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

View File

@ -0,0 +1,305 @@
From 2aac859a9542f9f7a05b3763ee2ef7071760f401 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
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 <jwcart2@gmail.com>
---
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

View File

@ -0,0 +1,189 @@
From 852c4398a9a227e0eb4de42d45c0c2845ed92bc7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
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 <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
---
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

View File

@ -0,0 +1,171 @@
From 32f8ed3d6b0bba44f2f211ff630f61f6a17cf578 Mon Sep 17 00:00:00 2001
From: Nicolas Iooss <nicolas.iooss@m4x.org>
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 <nicolas.iooss@m4x.org>
---
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

View File

@ -0,0 +1,39 @@
From 68e8871cfcbe1267ff0234a0dc78b207acc26af8 Mon Sep 17 00:00:00 2001
From: Nicolas Iooss <nicolas.iooss@m4x.org>
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 <nicolas.iooss@m4x.org>
---
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

View File

@ -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 <panxiaohe@huawei.com> - 3.1-5
- fix secilc-fuzzer issues
* Fri May 28 2021 panxiaohe <panxiaohe@huawei.com> - 3.1-4
- Drop unnecessary telinit
* Mon Mar 15 2021 yangzhuangzhuang <yangzhuangzhuang1@huawei.com> - 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 <lirui130@huawei.com> - 3.1-2
- fix NULL pointer dereference in cil_fill_ipaddr