!32 update to 3.3

Merge pull request !32 from panxh_purple/master
This commit is contained in:
openeuler-ci-bot 2022-01-13 08:47:43 +00:00 committed by Gitee
commit 97016e0f05
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
42 changed files with 9 additions and 4392 deletions

View File

@ -1,276 +0,0 @@
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

@ -1,75 +0,0 @@
From 22fb6f477bf10e834ece9eff84438fcaebf7d2ec Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Thu, 8 Apr 2021 13:32:14 -0400
Subject: [PATCH] libsepol/cil: Allow permission expressions when using map
classes
The following policy will cause a segfault:
(class CLASS (PERM))
(class C (P1 P2 P3))
(classorder (CLASS C))
(sid SID)
(sidorder (SID))
(user USER)
(role ROLE)
(type TYPE)
(category CAT)
(categoryorder (CAT))
(sensitivity SENS)
(sensitivityorder (SENS))
(sensitivitycategory SENS (CAT))
(allow TYPE self (CLASS (PERM)))
(roletype ROLE TYPE)
(userrole USER ROLE)
(userlevel USER (SENS))
(userrange USER ((SENS)(SENS (CAT))))
(sidcontext SID (USER ROLE TYPE ((SENS)(SENS))))
(classmap CM (PM1 PM2 PM3))
(classmapping CM PM1 (C (P1)))
(classmapping CM PM2 (C (P2)))
(classmapping CM PM3 (C (P3)))
(allow TYPE self (CM (and (all) (not PM2))))
The problem is that, while permission expressions are allowed for
normal classes, map classes are expected to only have permission
lists and no check is done to verify that only a permission list
is being used.
When the above policy is parsed, the "and" and "all" are seen as
expression operators, but when the map permissions are converted to
normal class and permissions, the permission expression is assumed
to be a list of datums and since the operators are not datums a
segfault is the result.
There is no reason to limit map classes to only using a list of
permissions and, in fact, it would be better to be able to use them
in the same way normal classes are used.
Allow permissions expressions to be used for map classes by first
evaluating the permission expression and then converting the
resulting list to normal classes and permissions.
Signed-off-by: James Carter <jwcart2@gmail.com>
---
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 fd4758d..05842b6 100644
--- a/libsepol/cil/src/cil_post.c
+++ b/libsepol/cil/src/cil_post.c
@@ -2137,6 +2137,10 @@ static int __evaluate_classperms_list(struct cil_list *classperms, struct cil_db
}
} else { /* MAP */
struct cil_list_item *i = NULL;
+ rc = __evaluate_classperms(cp, db);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
cil_list_for_each(i, cp->perms) {
struct cil_perm *cmp = i->data;
rc = __evaluate_classperms_list(cmp->classperms, db);
--
1.8.3.1

View File

@ -1,216 +0,0 @@
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

@ -1,163 +0,0 @@
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

@ -1,35 +0,0 @@
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

@ -1,115 +0,0 @@
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

@ -1,136 +0,0 @@
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

@ -1,90 +0,0 @@
From f0d98f83d28a0cdf437b4cafe229e27cb91eb493 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Wed, 6 Jan 2021 13:43:26 -0500
Subject: [PATCH] libsepol/cil: Fix heap-use-after-free in
__class_reset_perm_values()
Nicolas Iooss reports:
A few weeks ago, OSS-Fuzz got configured in order to fuzz the CIL
policy compiler (cf.
https://github.com/SELinuxProject/selinux/issues/215 and
https://github.com/google/oss-fuzz/pull/4790). It reported a bunch of
simple issues, for which I will submit patches. There are also more
subtle bugs, like the one triggered by this CIL policy:
(class CLASS (PERM))
(classorder (CLASS))
(sid SID)
(sidorder (SID))
(sensitivity SENS)
(sensitivityorder (SENS))
(type TYPE)
(allow TYPE self (CLASS (PERM)))
(block b
(optional o
(sensitivitycategory SENS (C)) ; Non-existing category
triggers disabling the optional
(common COMMON (PERM1))
(classcommon CLASS COMMON)
(allow TYPE self (CLASS (PERM1)))
)
)
On my computer, secilc manages to build this policy fine, but when
clang's Address Sanitizer is enabled, running secilc leads to the
following report:
$ make -C libsepol/src CC=clang CFLAGS='-g -fsanitize=address' libsepol.a
$ clang -g -fsanitize=address secilc/secilc.c libsepol/src/libsepol.a
-o my_secilc
$ ./my_secilc -vv testcase.cil
Parsing testcase.cil
Building AST from Parse Tree
Destroying Parse Tree
Resolving AST
Failed to resolve sensitivitycategory statement at testcase.cil:12
Disabling optional 'o' at testcase.cil:11
Resetting declarations
=================================================================
==181743==ERROR: AddressSanitizer: heap-use-after-free on address
0x6070000000c0 at pc 0x55ff7e445d24 bp 0x7ffe7eecfba0 sp
0x7ffe7eecfb98
READ of size 4 at 0x6070000000c0 thread T0
#0 0x55ff7e445d23 in __class_reset_perm_values
/git/selinux-userspace/libsepol/src/../cil/src/cil_reset_ast.c:17:17
The problem is that the optional branch is destroyed when it is disabled,
so the common has already been destroyed when the reset code tries to
access the number of common permissions, so that it can change the
value of the class permissions back to their original values.
The solution is to count the number of class permissions and then
calculate the number of common permissions.
Reported-by: Nicolas Iooss <nicolas.iooss@m4x.org>
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/cil/src/cil_reset_ast.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/libsepol/cil/src/cil_reset_ast.c b/libsepol/cil/src/cil_reset_ast.c
index 43e6b88e0..52e5f6401 100644
--- a/libsepol/cil/src/cil_reset_ast.c
+++ b/libsepol/cil/src/cil_reset_ast.c
@@ -22,11 +22,12 @@ static int __class_reset_perm_values(__attribute__((unused)) hashtab_key_t k, ha
static void cil_reset_class(struct cil_class *class)
{
if (class->common != NULL) {
- struct cil_class *common = class->common;
- cil_symtab_map(&class->perms, __class_reset_perm_values, &common->num_perms);
+ /* Must assume that the common has been destroyed */
+ int num_common_perms = class->num_perms - class->perms.nprim;
+ cil_symtab_map(&class->perms, __class_reset_perm_values, &num_common_perms);
/* during a re-resolve, we need to reset the common, so a classcommon
* statement isn't seen as a duplicate */
- class->num_perms -= common->num_perms;
+ class->num_perms = class->perms.nprim;
class->common = NULL; /* Must make this NULL or there will be an error when re-resolving */
}
class->ordered = CIL_FALSE;

View File

@ -1,80 +0,0 @@
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

@ -1,52 +0,0 @@
From 974da80e08d24e92e5409bb040f95d06a47776a2 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Fri, 8 Oct 2021 10:27:49 -0400
Subject: [PATCH] libsepol/cil: Fix potential undefined shifts
An expression of the form "1 << x" is undefined if x == 31 because
the "1" is an int and cannot be left shifted by 31.
Instead, use "UINT32_C(1) << x" which will be an unsigned int of
at least 32 bits.
This bug was found by the secilc-fuzzer.
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/cil/src/cil_binary.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c
index ec5f01e..d8aa495 100644
--- a/libsepol/cil/src/cil_binary.c
+++ b/libsepol/cil/src/cil_binary.c
@@ -1225,7 +1225,7 @@ int __perm_str_to_datum(char *perm_str, class_datum_t *sepol_class, uint32_t *da
goto exit;
}
}
- *datum |= 1 << (sepol_perm->s.value - 1);
+ *datum |= UINT32_C(1) << (sepol_perm->s.value - 1);
return SEPOL_OK;
@@ -1523,7 +1523,7 @@ int cil_avrule_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_
/* index of the u32 containing the permission */
#define XPERM_IDX(x) (x >> 5)
/* set bits 0 through x-1 within the u32 */
-#define XPERM_SETBITS(x) ((1U << (x & 0x1f)) - 1)
+#define XPERM_SETBITS(x) ((UINT32_C(1) << (x & 0x1f)) - 1)
/* low value for this u32 */
#define XPERM_LOW(x) (x << 5)
/* high value for this u32 */
@@ -4760,7 +4760,7 @@ static struct cil_list *cil_classperms_from_sepol(policydb_t *pdb, uint16_t clas
cil_list_init(&cp->perms, CIL_PERM);
for (i = 0; i < sepol_class->permissions.nprim; i++) {
struct cil_perm *perm;
- if ((data & (1 << i)) == 0) continue;
+ if ((data & (UINT32_C(1) << i)) == 0) continue;
perm = perm_value_to_cil[class][i+1];
if (!perm) goto exit;
cil_list_append(cp->perms, CIL_PERM, perm);
--
1.8.3.1

View File

@ -1,55 +0,0 @@
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

@ -1,94 +0,0 @@
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

@ -1,95 +0,0 @@
From 18f8747b28f1620903c7a3aa8a6616c199c173a6 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Thu, 16 Sep 2021 16:29:00 -0400
Subject: [PATCH] libsepol/cil: Handle operations in a class mapping when
verifying
When checking for circular class permission declarations and a class
mapping is encountered, the class permissions for each map permission
must be checked. An assumption was made that there were no operators
in the class permissions. An operator in the class permissions would
cause a segfault.
Example causing segault:
(classmap cm1 (mp1))
(classmapping cm1 mp1 (CLASS (PERM)))
(classpermission cp1)
(classpermissionset cp1 (cm1 (all)))
For map class permissions, check each item in the permission list to
see if it is an operator. If it is not, then verify the class
permissions associated with the map permission. If it is an operator
and the operator is "all", then create a list of all permissions for
that map class and verify the class permissions associated with each
map permission. If it is a different operator, then it can be skipped.
This bug was found by the secilc-fuzzer.
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/cil/src/cil_verify.c | 40 +++++++++++++++++++++++++++++++++++-----
1 file changed, 35 insertions(+), 5 deletions(-)
diff --git a/libsepol/cil/src/cil_verify.c b/libsepol/cil/src/cil_verify.c
index 5502c4d..dc29ea6 100644
--- a/libsepol/cil/src/cil_verify.c
+++ b/libsepol/cil/src/cil_verify.c
@@ -1689,6 +1689,15 @@ exit:
return rc;
}
+static int __add_perm_to_list(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args)
+{
+ struct cil_list *perm_list = (struct cil_list *)args;
+
+ cil_list_append(perm_list, CIL_DATUM, d);
+
+ return SEPOL_OK;
+}
+
static int __cil_verify_classperms(struct cil_list *classperms,
struct cil_symtab_datum *orig,
struct cil_symtab_datum *parent,
@@ -1730,13 +1739,34 @@ static int __cil_verify_classperms(struct cil_list *classperms,
if (FLAVOR(cp->class) != CIL_CLASS) { /* MAP */
struct cil_list_item *i = NULL;
cil_list_for_each(i, cp->perms) {
- struct cil_perm *cmp = i->data;
- rc = __cil_verify_classperms(cmp->classperms, orig, &cp->class->datum, &cmp->datum, CIL_MAP_PERM, steps, limit);
- if (rc != SEPOL_OK) {
- goto exit;
+ if (i->flavor != CIL_OP) {
+ struct cil_perm *cmp = i->data;
+ rc = __cil_verify_classperms(cmp->classperms, orig, &cp->class->datum, &cmp->datum, CIL_MAP_PERM, steps, limit);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
+ } else {
+ enum cil_flavor op = (enum cil_flavor)i->data;
+ if (op == CIL_ALL) {
+ struct cil_class *mc = cp->class;
+ struct cil_list *perm_list;
+ struct cil_list_item *j = NULL;
+
+ cil_list_init(&perm_list, CIL_MAP_PERM);
+ cil_symtab_map(&mc->perms, __add_perm_to_list, perm_list);
+ cil_list_for_each(j, perm_list) {
+ struct cil_perm *cmp = j->data;
+ rc = __cil_verify_classperms(cmp->classperms, orig, &cp->class->datum, &cmp->datum, CIL_MAP_PERM, steps, limit);
+ if (rc != SEPOL_OK) {
+ cil_list_destroy(&perm_list, CIL_FALSE);
+ goto exit;
+ }
+ }
+ cil_list_destroy(&perm_list, CIL_FALSE);
+ }
}
}
- }
+ }
} else { /* SET */
struct cil_classperms_set *cp_set = curr->data;
struct cil_classpermission *cp = cp_set->set;
--
1.8.3.1

View File

@ -1,315 +0,0 @@
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

@ -1,362 +0,0 @@
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

@ -1,48 +0,0 @@
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

@ -1,39 +0,0 @@
From 05d1c66aaae2b1ce3eaac7d241f24be121fddb39 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Fri, 27 Aug 2021 10:12:42 -0400
Subject: [PATCH] libsepol/cil: Properly check for parameter when inserting
name
File names for typetransition rules are stored in their own datums.
This allows them to be passed as a parameter, but there needs to be
a check in __cil_insert_name() so that parameter names are not
mistaken for file name strings. This check did not verify that a
matching parameter name had the flavor of CIL_NAME.
Check that the parameter flavor is CIL_NAME and that the paramter
name matches the file name to be stored in the datum.
This bug was found by the secilc-fuzzer.
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/cil/src/cil_resolve_ast.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
index 1800732..a4de1c7 100644
--- a/libsepol/cil/src/cil_resolve_ast.c
+++ b/libsepol/cil/src/cil_resolve_ast.c
@@ -87,7 +87,8 @@ static struct cil_name * __cil_insert_name(struct cil_db *db, hashtab_key_t key,
if (macro != NULL && macro->params != NULL) {
struct cil_list_item *item;
cil_list_for_each(item, macro->params) {
- if (((struct cil_param*)item->data)->str == key) {
+ struct cil_param *param = item->data;
+ if (param->flavor == CIL_NAME && param->str == key) {
return NULL;
}
}
--
1.8.3.1

View File

@ -1,74 +0,0 @@
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

@ -1,47 +0,0 @@
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

@ -1,175 +0,0 @@
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

@ -1,57 +0,0 @@
From b57535318af6f3f5e79c90caed06423b1f50abb1 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Fri, 27 Aug 2021 10:11:19 -0400
Subject: [PATCH] libsepol/cil: Reset expandtypeattribute rules when resetting
AST
A list is created to store type attribute datums when resolving an
expandtypeattribute rule and that list needs to be destroyed if the
AST is reset or a memory leak will occur.
Destroy the list storing type attributes datums when resetting
expandtypeattribute rules.
This bug was found by the secilc-fuzzer.
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/cil/src/cil_reset_ast.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/libsepol/cil/src/cil_reset_ast.c b/libsepol/cil/src/cil_reset_ast.c
index 6d1d2da..0ba075c 100644
--- a/libsepol/cil/src/cil_reset_ast.c
+++ b/libsepol/cil/src/cil_reset_ast.c
@@ -208,6 +208,11 @@ static void cil_reset_typeattributeset(struct cil_typeattributeset *tas)
cil_list_destroy(&tas->datum_expr, CIL_FALSE);
}
+static void cil_reset_expandtypeattribute(struct cil_expandtypeattribute *expandattr)
+{
+ cil_list_destroy(&expandattr->attr_datums, CIL_FALSE);
+}
+
static void cil_reset_avrule(struct cil_avrule *rule)
{
cil_reset_classperms_list(rule->perms.classperms);
@@ -531,6 +536,9 @@ int __cil_reset_node(struct cil_tree_node *node, __attribute__((unused)) uint32
case CIL_TYPEATTRIBUTESET:
cil_reset_typeattributeset(node->data);
break;
+ case CIL_EXPANDTYPEATTRIBUTE:
+ cil_reset_expandtypeattribute(node->data);
+ break;
case CIL_RANGETRANSITION:
cil_reset_rangetransition(node->data);
break;
@@ -630,7 +638,6 @@ int __cil_reset_node(struct cil_tree_node *node, __attribute__((unused)) uint32
case CIL_CLASSORDER:
case CIL_CATORDER:
case CIL_SENSITIVITYORDER:
- case CIL_EXPANDTYPEATTRIBUTE:
break; /* Nothing to reset */
default:
break;
--
1.8.3.1

View File

@ -1,249 +0,0 @@
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

@ -1,58 +0,0 @@
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

@ -1,101 +0,0 @@
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

@ -1,305 +0,0 @@
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

@ -1,112 +0,0 @@
From 90809674c13c03e324dff560654d0e686c5fc46b Mon Sep 17 00:00:00 2001
From: Evgeny Vereshchagin <evvers@ya.ru>
Date: Sun, 6 Dec 2020 23:29:22 +0100
Subject: [PATCH] libsepol/cil: always destroy the lexer state
It was found in https://github.com/google/oss-fuzz/pull/4790:
```
Invalid token '' at line 2 of fuzz
NEW_FUNC[1/2]: 0x67fff0 in yy_get_previous_state /src/selinux/libsepol/src/../cil/src/cil_lexer.c:1143
NEW_FUNC[2/2]: 0x6803e0 in yy_try_NUL_trans /src/selinux/libsepol/src/../cil/src/cil_lexer.c:1176
=================================================================
==12==ERROR: AddressSanitizer: heap-use-after-free on address 0x602000007992 at pc 0x000000681800 bp 0x7ffccddee530 sp 0x7ffccddee528
WRITE of size 1 at 0x602000007992 thread T0
SCARINESS: 41 (1-byte-write-heap-use-after-free)
#0 0x6817ff in cil_yy_switch_to_buffer /src/selinux/libsepol/src/../cil/src/cil_lexer.c:1315:17
#1 0x6820cc in cil_yy_scan_buffer /src/selinux/libsepol/src/../cil/src/cil_lexer.c:1571:2
#2 0x682662 in cil_lexer_setup /src/selinux/libsepol/src/../cil/src/cil_lexer.l:73:6
#3 0x5cf2ae in cil_parser /src/selinux/libsepol/src/../cil/src/cil_parser.c:220:2
#4 0x56d5e2 in cil_add_file /src/selinux/libsepol/src/../cil/src/cil.c:514:7
#5 0x556e91 in LLVMFuzzerTestOneInput /src/secilc-fuzzer.c:434:7
#6 0x459ab1 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:599:15
#7 0x45a755 in fuzzer::Fuzzer::TryDetectingAMemoryLeak(unsigned char const*, unsigned long, bool) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:675:3
#8 0x45acd9 in fuzzer::Fuzzer::MutateAndTestOne() /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:747:5
#9 0x45b875 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector<fuzzer::SizedFile, fuzzer::fuzzer_allocator<fuzzer::SizedFile> >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:883:5
#10 0x4499fb in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:906:6
#11 0x473a32 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10
#12 0x7f982296d83f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2083f)
#13 0x41e758 in _start (/out/secilc-fuzzer+0x41e758)
DEDUP_TOKEN: cil_yy_switch_to_buffer--cil_yy_scan_buffer--cil_lexer_setup
0x602000007992 is located 2 bytes inside of 4-byte region [0x602000007990,0x602000007994)
freed by thread T0 here:
#0 0x521ef2 in free /src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:127:3
#1 0x56d630 in cil_add_file /src/selinux/libsepol/src/../cil/src/cil.c:526:2
#2 0x556e91 in LLVMFuzzerTestOneInput /src/secilc-fuzzer.c:434:7
#3 0x459ab1 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:599:15
#4 0x458fba in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:505:3
#5 0x45acc7 in fuzzer::Fuzzer::MutateAndTestOne() /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:745:19
#6 0x45b875 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector<fuzzer::SizedFile, fuzzer::fuzzer_allocator<fuzzer::SizedFile> >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:883:5
#7 0x4499fb in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:906:6
#8 0x473a32 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10
#9 0x7f982296d83f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2083f)
DEDUP_TOKEN: free--cil_add_file--LLVMFuzzerTestOneInput
previously allocated by thread T0 here:
#0 0x52215d in malloc /src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:145:3
#1 0x5cecb8 in cil_malloc /src/selinux/libsepol/src/../cil/src/cil_mem.c:39:14
#2 0x56d584 in cil_add_file /src/selinux/libsepol/src/../cil/src/cil.c:510:11
#3 0x556e91 in LLVMFuzzerTestOneInput /src/secilc-fuzzer.c:434:7
#4 0x459ab1 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:599:15
#5 0x458fba in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:505:3
#6 0x45acc7 in fuzzer::Fuzzer::MutateAndTestOne() /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:745:19
#7 0x45b875 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector<fuzzer::SizedFile, fuzzer::fuzzer_allocator<fuzzer::SizedFile> >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:883:5
#8 0x4499fb in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:906:6
#9 0x473a32 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10
#10 0x7f982296d83f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2083f)
DEDUP_TOKEN: malloc--cil_malloc--cil_add_file
SUMMARY: AddressSanitizer: heap-use-after-free /src/selinux/libsepol/src/../cil/src/cil_lexer.c:1315:17 in cil_yy_switch_to_buffer
Shadow bytes around the buggy address:
0x0c047fff8ee0: fa fa fd fa fa fa fd fd fa fa fd fa fa fa fd fd
0x0c047fff8ef0: fa fa fd fa fa fa fd fd fa fa fd fa fa fa fd fd
0x0c047fff8f00: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fd
0x0c047fff8f10: fa fa fd fa fa fa fd fd fa fa fd fa fa fa fd fd
0x0c047fff8f20: fa fa fd fa fa fa fd fd fa fa fd fa fa fa fd fa
=>0x0c047fff8f30: fa fa[fd]fa fa fa fd fa fa fa fd fa fa fa fd fa
0x0c047fff8f40: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa
0x0c047fff8f50: fa fa fd fa fa fa fd fd fa fa fd fa fa fa fd fa
0x0c047fff8f60: fa fa fd fd fa fa fd fa fa fa fd fd fa fa fd fa
0x0c047fff8f70: fa fa 00 00 fa fa 02 fa fa fa 02 fa fa fa 00 fa
0x0c047fff8f80: fa fa 03 fa fa fa 00 fa fa fa 03 fa fa fa 00 fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==12==ABORTING
```
Signed-off-by: Evgeny Vereshchagin <evvers@ya.ru>
Acked-by: Nicolas Iooss <nicolas.iooss@m4x.org>
---
libsepol/cil/src/cil_parser.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/libsepol/cil/src/cil_parser.c b/libsepol/cil/src/cil_parser.c
index 585ea7704..a8af1dce2 100644
--- a/libsepol/cil/src/cil_parser.c
+++ b/libsepol/cil/src/cil_parser.c
@@ -310,6 +310,7 @@ int cil_parser(char *_path, char *buffer, uint32_t size, struct cil_tree **parse
while (!cil_stack_is_empty(stack)) {
pop_hll_info(stack, &hll_lineno, &hll_expand);
}
+ cil_lexer_destroy();
cil_stack_destroy(&stack);
return SEPOL_ERR;

View File

@ -1,53 +0,0 @@
From 4662bdc11c8f505716f8da361a07ad13083b0618 Mon Sep 17 00:00:00 2001
From: Nicolas Iooss <nicolas.iooss@m4x.org>
Date: Fri, 5 Feb 2021 10:45:38 +0100
Subject: [PATCH] libsepol/cil: be more robust when encountering <src_info>
OSS-Fuzz found a Null-dereference READ in the CIL compiler when trying
to compile the following policy:
(<src_info>)
In cil_gen_src_info(), parse_current->next is NULL even though the code
expects that both parse_current->next and parse_current->next->next
exists.
Fixes: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=28457
Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
---
libsepol/cil/src/cil_build_ast.c | 5 +++++
libsepol/cil/src/cil_tree.c | 2 +-
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c
index 5094d62..726f46c 100644
--- a/libsepol/cil/src/cil_build_ast.c
+++ b/libsepol/cil/src/cil_build_ast.c
@@ -6070,6 +6070,11 @@ int cil_gen_src_info(struct cil_tree_node *parse_current, struct cil_tree_node *
/* No need to check syntax, because this is auto generated */
struct cil_src_info *info = NULL;
+ if (parse_current->next == NULL || parse_current->next->next == NULL) {
+ cil_tree_log(parse_current, CIL_ERR, "Bad <src_info>");
+ return SEPOL_ERR;
+ }
+
cil_src_info_init(&info);
info->is_cil = (parse_current->next->data == CIL_KEY_SRC_CIL) ? CIL_TRUE : CIL_FALSE;
diff --git a/libsepol/cil/src/cil_tree.c b/libsepol/cil/src/cil_tree.c
index 886412d..3da972e 100644
--- a/libsepol/cil/src/cil_tree.c
+++ b/libsepol/cil/src/cil_tree.c
@@ -69,7 +69,7 @@ struct cil_tree_node *cil_tree_get_next_path(struct cil_tree_node *node, char **
while (node) {
if (node->flavor == CIL_NODE && node->data == NULL) {
- if (node->cl_head->data == CIL_KEY_SRC_INFO) {
+ if (node->cl_head->data == CIL_KEY_SRC_INFO && node->cl_head->next != NULL && node->cl_head->next->next != NULL) {
/* Parse Tree */
*path = node->cl_head->next->next->data;
*is_cil = (node->cl_head->next->data == CIL_KEY_SRC_CIL);
--
1.8.3.1

View File

@ -1,36 +0,0 @@
From b7ea65f547c67bfbae4ae133052583b090747e5a Mon Sep 17 00:00:00 2001
From: Nicolas Iooss <nicolas.iooss@m4x.org>
Date: Wed, 30 Dec 2020 11:07:46 +0100
Subject: [PATCH] libsepol/cil: destroy perm_datums when __cil_resolve_perms
fails
When __cil_resolve_perms fails, it does not destroy perm_datums, which
leads to a memory leak reported by OSS-Fuzz with the following CIL
policy:
(class cl01())
(classorder(cl01))
(type at02)
(type tpr3)
(allow at02 tpr3(cl01((s))))
Calling cil_list_destroy() fixes the issue.
Fixes: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=28466
Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
---
libsepol/cil/src/cil_resolve_ast.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
index 68b590bcc..0c85eabe5 100644
--- a/libsepol/cil/src/cil_resolve_ast.c
+++ b/libsepol/cil/src/cil_resolve_ast.c
@@ -146,6 +146,7 @@ static int __cil_resolve_perms(symtab_t *class_symtab, symtab_t *common_symtab,
return SEPOL_OK;
exit:
+ cil_list_destroy(perm_datums, CIL_FALSE);
return rc;
}

View File

@ -1,39 +0,0 @@
From 6c8fca10452e445edf52daffc69f2e9dfcdac54c Mon Sep 17 00:00:00 2001
From: Nicolas Iooss <nicolas.iooss@m4x.org>
Date: Wed, 30 Dec 2020 21:11:40 +0100
Subject: [PATCH] libsepol/cil: do not add a stack variable to a list
OSS-Fuzz found a heap use-after-free when the CIL compiler destroys its
database after failing to compile the following policy:
(validatetrans x (eq t3 (a)))
This is caused by the fact that the validatetrans AST object references
a stack variable local to __cil_fill_constraint_leaf_expr, when parsing
the list "(a)":
struct cil_list *sub_list;
cil_fill_list(current->next->next->cl_head, leaf_expr_flavor, &sub_list);
cil_list_append(*leaf_expr, CIL_LIST, &sub_list);
Drop the & sign to really add the list like it is supposed to be.
Fixes: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=28507
Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
---
libsepol/cil/src/cil_build_ast.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c
index 67801def0..d5b9977c0 100644
--- a/libsepol/cil/src/cil_build_ast.c
+++ b/libsepol/cil/src/cil_build_ast.c
@@ -2714,7 +2714,7 @@ static int __cil_fill_constraint_leaf_expr(struct cil_tree_node *current, enum c
} else if (r_flavor == CIL_LIST) {
struct cil_list *sub_list;
cil_fill_list(current->next->next->cl_head, leaf_expr_flavor, &sub_list);
- cil_list_append(*leaf_expr, CIL_LIST, &sub_list);
+ cil_list_append(*leaf_expr, CIL_LIST, sub_list);
} else {
cil_list_append(*leaf_expr, CIL_CONS_OPERAND, (void *)r_flavor);
}

View File

@ -1,42 +0,0 @@
From c5e6153720e713e72a65614f625a51ad44d1fc07 Mon Sep 17 00:00:00 2001
From: Nicolas Iooss <nicolas.iooss@m4x.org>
Date: Sun, 14 Mar 2021 19:25:58 +0100
Subject: [PATCH] libsepol/cil: fix NULL pointer dereference in
__cil_insert_name
OSS-Fuzz found a Null-dereference in __cil_insert_name when trying to
compile the following policy:
(macro MACRO ()
(classmap CLASS (PERM))
(type TYPE)
(typetransition TYPE TYPE CLASS "name" TYPE)
)
(call MACRO)
When using a macro with no argument, macro->params is NULL and
cil_list_for_each(item, macro->params) dereferenced a NULL pointer.
Fix this by checking that macro->params is not NULL before using it.
Fixes: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=28565
Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
---
libsepol/cil/src/cil_resolve_ast.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
index 2ea106d..63beed9 100644
--- a/libsepol/cil/src/cil_resolve_ast.c
+++ b/libsepol/cil/src/cil_resolve_ast.c
@@ -82,7 +82,7 @@ static struct cil_name * __cil_insert_name(struct cil_db *db, hashtab_key_t key,
} else if (parent->flavor == CIL_MACRO) {
macro = parent->data;
}
- if (macro != NULL) {
+ if (macro != NULL && macro->params != NULL) {
struct cil_list_item *item;
cil_list_for_each(item, macro->params) {
if (((struct cil_param*)item->data)->str == key) {
--
1.8.3.1

View File

@ -1,33 +0,0 @@
From 6238e025714b18db41354629dd40e70e27b7c37e Mon Sep 17 00:00:00 2001
From: lutianxiong <lutianxiong@huawei.com>
Date: Thu, 25 Feb 2021 18:40:02 +0800
Subject: [PATCH] libsepol/cil: fix NULL pointer dereference in cil_fill_ipaddr
Found a NULL pointer dereference by fuzzing, reproducing:
$ echo "(nodecon(())o(e()))" > tmp.cil
$ secilc tmp.cil
Segmentation fault (core dumped)
Add NULL check for addr_node->data in cil_fill_ipaddr.
Signed-off-by: lutianxiong <lutianxiong@huawei.com>
---
libsepol/cil/src/cil_build_ast.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c
index 726f46cd..4e53f06a 100644
--- a/libsepol/cil/src/cil_build_ast.c
+++ b/libsepol/cil/src/cil_build_ast.c
@@ -5660,7 +5660,7 @@ int cil_fill_ipaddr(struct cil_tree_node *addr_node, struct cil_ipaddr *addr)
{
int rc = SEPOL_ERR;
- if (addr_node == NULL || addr == NULL) {
+ if (addr_node == NULL || addr_node->data == NULL || addr == NULL) {
goto exit;
}
--
2.27.0

View File

@ -1,82 +0,0 @@
From bdf4e332b41ff358b7e8539c3d6ee6277f0be762 Mon Sep 17 00:00:00 2001
From: Nicolas Iooss <nicolas.iooss@m4x.org>
Date: Wed, 6 Jan 2021 09:13:19 +0100
Subject: [PATCH] libsepol/cil: fix NULL pointer dereference when parsing an
improper integer
OSS-Fuzz found a NULL pointer dereference when the CIL compiler tries to
compile a policy with an invalid integer:
$ echo '(ioportcon(2())n)' > tmp.cil
$ secilc tmp.cil
Segmentation fault (core dumped)
This is because strtol() is called with a NULL pointer, in
cil_fill_integer().
Fix this by checking that int_node->data is not NULL. While at it, use
strtoul() instead of strtol() to parse an unsigned integer.
When using "val > UINT32_MAX" with "unsigned long val;", it is expected
that some compilers emit a warning when the size of "unsigned long" is
32 bits. In theory gcc could be such a compiler (with warning
-Wtype-limits, which is included in -Wextra). Nevertheless this is
currently broken, according to
https://gcc.gnu.org/pipermail/gcc-help/2021-January/139755.html and
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89126 (this bug was
opened in January 2019).
In order to prevent this warning from appearing, introduce some
preprocessor macros around the bound check.
Fixes: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=28456
Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
Acked-by: James Carter <jwcart2@gmail.com>
---
libsepol/cil/src/cil_build_ast.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c
index be10d61b1..02481558a 100644
--- a/libsepol/cil/src/cil_build_ast.c
+++ b/libsepol/cil/src/cil_build_ast.c
@@ -5570,19 +5570,27 @@ int cil_fill_integer(struct cil_tree_node *int_node, uint32_t *integer, int base
{
int rc = SEPOL_ERR;
char *endptr = NULL;
- int val;
+ unsigned long val;
- if (int_node == NULL || integer == NULL) {
+ if (int_node == NULL || int_node->data == NULL || integer == NULL) {
goto exit;
}
errno = 0;
- val = strtol(int_node->data, &endptr, base);
+ val = strtoul(int_node->data, &endptr, base);
if (errno != 0 || endptr == int_node->data || *endptr != '\0') {
rc = SEPOL_ERR;
goto exit;
}
+ /* Ensure that the value fits a 32-bit integer without triggering -Wtype-limits */
+#if ULONG_MAX > UINT32_MAX
+ if (val > UINT32_MAX) {
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+#endif
+
*integer = val;
return SEPOL_OK;
@@ -5598,7 +5606,7 @@ int cil_fill_integer64(struct cil_tree_node *int_node, uint64_t *integer, int ba
char *endptr = NULL;
uint64_t val;
- if (int_node == NULL || integer == NULL) {
+ if (int_node == NULL || int_node->data == NULL || integer == NULL) {
goto exit;
}

View File

@ -1,41 +0,0 @@
From 38a09b74024bbe1c78639821f3cff3a5ceb73d0d Mon Sep 17 00:00:00 2001
From: Nicolas Iooss <nicolas.iooss@m4x.org>
Date: Wed, 30 Dec 2020 21:11:39 +0100
Subject: [PATCH] libsepol/cil: fix NULL pointer dereference when using an
unused alias
OSS-Fuzz found a NULL pointer dereference when the CIL compiler tries to
compile a policy where a categoryalias references an unused
categoryalias:
$ echo '(categoryalias c0)(categoryalias c1)(categoryaliasactual c0 c1)' > tmp.cil
$ secil tmp.cil
Segmentation fault (core dumped)
In such a case, a1 can become NULL in cil_resolve_alias_to_actual().
Add a check to report an error when this occurs. Now the error message
is:
Alias c0 references an unused alias c1 at tmp.cil:1
Fixes: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=28471
Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
---
libsepol/cil/src/cil_resolve_ast.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
index f6deb1002..affa7657b 100644
--- a/libsepol/cil/src/cil_resolve_ast.c
+++ b/libsepol/cil/src/cil_resolve_ast.c
@@ -555,6 +555,10 @@ int cil_resolve_alias_to_actual(struct cil_tree_node *current, enum cil_flavor f
a1_node = a1->datum.nodes->head->data;
while (flavor != a1_node->flavor) {
+ if (a1->actual == NULL) {
+ cil_tree_log(current, CIL_ERR, "Alias %s references an unused alias %s", alias->datum.name, a1->datum.name);
+ return SEPOL_ERR;
+ }
a1 = a1->actual;
a1_node = a1->datum.nodes->head->data;
steps += 1;

View File

@ -1,57 +0,0 @@
From 228c06d97a8a33b60b89ded17acbd0e92cca9cfe Mon Sep 17 00:00:00 2001
From: Nicolas Iooss <nicolas.iooss@m4x.org>
Date: Wed, 30 Dec 2020 11:07:45 +0100
Subject: [PATCH] libsepol/cil: fix out-of-bound read in
cil_print_recursive_blockinherit
OSS-Fuzz found a heap buffer overflow (out-of-bound reads) when the CIL
compiler tries to report a recursive blockinherit with an optional
block:
$ echo '(block b (optional o (blockinherit b)))' > tmp.cil
$ secilc tmp.cil
Segmentation fault (core dumped)
This is because cil_print_recursive_blockinherit() assumes that all
nodes are either CIL_BLOCK or CIL_BLOCKINHERIT. Add support for other
block kinds, using cil_node_to_string() to show them.
Fixes: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=28462
Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
---
libsepol/cil/src/cil_resolve_ast.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
index affa7657b..68b590bcc 100644
--- a/libsepol/cil/src/cil_resolve_ast.c
+++ b/libsepol/cil/src/cil_resolve_ast.c
@@ -2347,11 +2347,13 @@ void cil_print_recursive_blockinherit(struct cil_tree_node *bi_node, struct cil_
for (curr = bi_node; curr != terminating_node; curr = curr->parent) {
if (curr->flavor == CIL_BLOCK) {
cil_list_prepend(trace, CIL_NODE, curr);
- } else {
+ } 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);
@@ -2360,8 +2362,12 @@ void cil_print_recursive_blockinherit(struct cil_tree_node *bi_node, struct cil_
curr = item->data;
if (curr->flavor == CIL_BLOCK) {
cil_tree_log(curr, CIL_ERR, "block %s", DATUM(curr->data)->name);
- } else {
+ } 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));
}
}

View File

@ -1,92 +0,0 @@
From 521e6a2f478a4c7a7c198c017d4d12e8667d89e7 Mon Sep 17 00:00:00 2001
From: Nicolas Iooss <nicolas.iooss@m4x.org>
Date: Sat, 3 Oct 2020 15:19:08 +0200
Subject: [PATCH] libsepol/cil: fix signed overflow caused by using (1 << 31) -
1
When compiling SELinux userspace tools with -ftrapv (this option
generates traps for signed overflow on addition, subtraction,
multiplication operations, instead of silently wrapping around),
semodule crashes when running the tests from
scripts/ci/fedora-test-runner.sh in a Fedora 32 virtual machine:
[root@localhost selinux-testsuite]# make test
make -C policy load
make[1]: Entering directory '/root/selinux-testsuite/policy'
# Test for "expand-check = 0" in /etc/selinux/semanage.conf
# General policy build
make[2]: Entering directory '/root/selinux-testsuite/policy/test_policy'
Compiling targeted test_policy module
Creating targeted test_policy.pp policy package
rm tmp/test_policy.mod.fc
make[2]: Leaving directory '/root/selinux-testsuite/policy/test_policy'
# General policy load
domain_fd_use --> off
/usr/sbin/semodule -i test_policy/test_policy.pp test_mlsconstrain.cil test_overlay_defaultrange.cil test_add_levels.cil test_glblub.cil
make[1]: *** [Makefile:174: load] Aborted (core dumped)
Using "coredumpctl gdb" leads to the following strack trace:
(gdb) bt
#0 0x00007f608fe4fa25 in raise () from /lib64/libc.so.6
#1 0x00007f608fe38895 in abort () from /lib64/libc.so.6
#2 0x00007f6090028aca in __addvsi3.cold () from /lib64/libsepol.so.1
#3 0x00007f6090096f59 in __avrule_xperm_setrangebits (low=30, high=30, xperms=0x8b9eea0)
at ../cil/src/cil_binary.c:1551
#4 0x00007f60900970dd in __cil_permx_bitmap_to_sepol_xperms_list (xperms=0xb650a30, xperms_list=0x7ffce2653b18)
at ../cil/src/cil_binary.c:1596
#5 0x00007f6090097286 in __cil_avrulex_ioctl_to_policydb (k=0xb8ec200 "@\023\214\022\006", datum=0xb650a30,
args=0x239a640) at ../cil/src/cil_binary.c:1649
#6 0x00007f609003f1e5 in hashtab_map (h=0x41f8710, apply=0x7f60900971da <__cil_avrulex_ioctl_to_policydb>,
args=0x239a640) at hashtab.c:234
#7 0x00007f609009ea19 in cil_binary_create_allocated_pdb (db=0x2394f10, policydb=0x239a640)
at ../cil/src/cil_binary.c:4969
#8 0x00007f609009d19d in cil_binary_create (db=0x2394f10, policydb=0x7ffce2653d30) at ../cil/src/cil_binary.c:4329
#9 0x00007f609008ec23 in cil_build_policydb_create_pdb (db=0x2394f10, sepol_db=0x7ffce2653d30)
at ../cil/src/cil.c:631
#10 0x00007f608fff4bf3 in semanage_direct_commit () from /lib64/libsemanage.so.1
#11 0x00007f608fff9fae in semanage_commit () from /lib64/libsemanage.so.1
#12 0x0000000000403e2b in main (argc=7, argv=0x7ffce2655058) at semodule.c:753
(gdb) f 3
#3 0x00007f6090096f59 in __avrule_xperm_setrangebits (low=30, high=30, xperms=0x8b9eea0)
at ../cil/src/cil_binary.c:1551
1551 xperms->perms[i] |= XPERM_SETBITS(h) - XPERM_SETBITS(low);
A signed integer overflow therefore occurs in XPERM_SETBITS(h):
#define XPERM_SETBITS(x) ((1 << (x & 0x1f)) - 1)
This macro is expanded with h=31, so "(1 << 31) - 1" is computed:
* (1 << 31) = -0x80000000 is the lowest signed 32-bit integer value
* (1 << 31) - 1 overflows the capacity of a signed 32-bit integer and
results in 0x7fffffff (which is unsigned)
Using unsigned integers (with "1U") fixes the crash, as
(1U << 31) = 0x80000000U has no overflowing issues.
Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
Acked-by: Petr Lautrbach <plautrba@redhat.com>
Conflict:remove contents of checkpolicy/policy_define.c
---
libsepol/cil/src/cil_binary.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c
index 36720ed..e417c5c 100644
--- a/libsepol/cil/src/cil_binary.c
+++ b/libsepol/cil/src/cil_binary.c
@@ -1526,7 +1526,7 @@ int cil_avrule_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_
/* index of the u32 containing the permission */
#define XPERM_IDX(x) (x >> 5)
/* set bits 0 through x-1 within the u32 */
-#define XPERM_SETBITS(x) ((1 << (x & 0x1f)) - 1)
+#define XPERM_SETBITS(x) ((1U << (x & 0x1f)) - 1)
/* low value for this u32 */
#define XPERM_LOW(x) (x << 5)
/* high value for this u32 */
--
1.8.3.1

View File

@ -1,189 +0,0 @@
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

@ -1,171 +0,0 @@
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

@ -1,49 +0,0 @@
From e2d018423d5910e88947bba3b96d2f301d890c62 Mon Sep 17 00:00:00 2001
From: Nicolas Iooss <nicolas.iooss@m4x.org>
Date: Wed, 30 Dec 2020 21:11:41 +0100
Subject: [PATCH] libsepol/cil: propagate failure of cil_fill_list()
OSS-Fuzz found a Null-dereference READ in the CIL compiler when trying
to compile the following policy:
(optional o (validatetrans x (eq t3 (a ()))))
With some logs, secilc reports:
Invalid syntax
Destroying Parse Tree
Resolving AST
Failed to resolve validatetrans statement at fuzz:1
Disabling optional 'o' at tmp.cil:1
So there is an "Invalid syntax" error, but the compilation continues.
Fix this issue by stopping the compilation when cil_fill_list() reports
an error:
Invalid syntax
Bad expression tree for constraint
Bad validatetrans declaration at tmp.cil:1
Fixes: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=29061
Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
---
libsepol/cil/src/cil_build_ast.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c
index d5b9977c0..be10d61b1 100644
--- a/libsepol/cil/src/cil_build_ast.c
+++ b/libsepol/cil/src/cil_build_ast.c
@@ -2713,7 +2713,11 @@ static int __cil_fill_constraint_leaf_expr(struct cil_tree_node *current, enum c
cil_list_append(*leaf_expr, CIL_STRING, current->next->next->data);
} else if (r_flavor == CIL_LIST) {
struct cil_list *sub_list;
- cil_fill_list(current->next->next->cl_head, leaf_expr_flavor, &sub_list);
+ rc = cil_fill_list(current->next->next->cl_head, leaf_expr_flavor, &sub_list);
+ if (rc != SEPOL_OK) {
+ cil_list_destroy(leaf_expr, CIL_TRUE);
+ goto exit;
+ }
cil_list_append(*leaf_expr, CIL_LIST, sub_list);
} else {
cil_list_append(*leaf_expr, CIL_CONS_OPERAND, (void *)r_flavor);

View File

@ -1,39 +0,0 @@
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

Binary file not shown.

BIN
libsepol-3.3.tar.gz Normal file

Binary file not shown.

View File

@ -1,53 +1,12 @@
Name: libsepol Name: libsepol
Version: 3.1 Version: 3.3
Release: 6 Release: 1
Summary: SELinux binary policy manipulation library Summary: SELinux binary policy manipulation library
License: LGPLv2+ License: LGPLv2+
URL: https://github.com/SELinuxProject/selinux/wiki/Releases URL: https://github.com/SELinuxProject/selinux/wiki/Releases
Source0: https://github.com/SELinuxProject/selinux/releases/download/20200710/libsepol-3.1.tar.gz Source0: https://github.com/SELinuxProject/selinux/releases/download/%{version}/%{name}-%{version}.tar.gz
Patch1: backport-libsepol-cil-fix-NULL-pointer-dereference-in-cil_fil.patch BuildRequires: gcc flex libsepol
Patch2: backport-libsepol-cil-always-destroy-the-lexer-state.patch
Patch3: backport-libsepol-cil-destroy-perm_datums-when-_cil_resolve_.patch
Patch4: backport-libsepol-cil-do-not-add-a-stack-variable-to-a-list.patch
Patch5: backport-libsepol-cil-Fix-heap-use-after-free-in_class-rese.patch
Patch6: backport-libsepol-cil-fix-NULL-pointer-dereference-when-parsi.patch
Patch7: backport-libsepol-cil-fix-NULL-pointer-dereference-when-using.patch
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
Patch32: backport-libsepol-cil-fix-signed-overflow-caused-by-using-1-3.patch
Patch33: backport-libsepol-cil-Fix-potential-undefined-shifts.patch
Patch34: backport-libsepol-cil-be-more-robust-when-encountering-src_in.patch
Patch35: backport-libsepol-cil-Handle-operations-in-a-class-mapping-wh.patch
Patch36: backport-libsepol-cil-Allow-permission-expressions-when-using.patch
Patch37: backport-libsepol-cil-fix-NULL-pointer-dereference-in-__cil_i.patch
Patch38: backport-libsepol-cil-Properly-check-for-parameter-when-inser.patch
Patch39: backport-libsepol-cil-Reset-expandtypeattribute-rules-when-re.patch
BuildRequires: gcc flex
%description %description
libsepol provides an API for the manipulation of SELinux binary libsepol provides an API for the manipulation of SELinux binary
@ -77,6 +36,8 @@ make %{?_smp_mflags} CFLAGS="%{optflags}" LDFLAGS="%{?__global_ldflags}"
rm -rf %{buildroot} rm -rf %{buildroot}
make DESTDIR="%{buildroot}" LIBDIR="%{_libdir}" SHLIBDIR="%{_libdir}" install make DESTDIR="%{buildroot}" LIBDIR="%{_libdir}" SHLIBDIR="%{_libdir}" install
cp -a %{_libdir}/libsepol.so.1* %{buildroot}%{_libdir}
%pre %pre
%preun %preun
@ -105,6 +66,9 @@ make DESTDIR="%{buildroot}" LIBDIR="%{_libdir}" SHLIBDIR="%{_libdir}" install
%{_mandir}/man3/* %{_mandir}/man3/*
%changelog %changelog
* Thu Jan 13 2022 panxiaohe <panxiaohe@huawei.com> - 3.3-1
- update to 3.3
* Fri Dec 10 2021 panxiaohe <panxiaohe@huawei.com> - 3.1-6 * Fri Dec 10 2021 panxiaohe <panxiaohe@huawei.com> - 3.1-6
- fix secilc-fuzzer issues - fix secilc-fuzzer issues