SELinux userspace 3.3-rc2 release

This commit is contained in:
Petr Lautrbach 2021-09-29 13:55:33 +02:00
parent c59879b8aa
commit 394d26d7f2
104 changed files with 10 additions and 13834 deletions

1
.gitignore vendored
View File

@ -180,3 +180,4 @@ libsepol-2.0.41.tgz
/libsepol-3.2-rc1.tar.gz
/libsepol-3.2-rc2.tar.gz
/libsepol-3.2.tar.gz
/libsepol-3.3-rc2.tar.gz

View File

@ -1,79 +0,0 @@
From f7431d0e0ed9f695a6a8af74c3f239f80649a167 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Wed, 10 Mar 2021 14:30:12 -0500
Subject: [PATCH] libsepol: Expand role attributes in constraint expressions
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
When creating the kernel binary policy, role attributes in constraint
expressions are not expanded. This causes the constraint expression
to refer to a non-existent role in the kernel policy. This can lead
to a segfault when converting the binary policy back to conf or CIL
source or when using policy tools such as seinfo.
Expand role attributes in constraint expressions when creating the
kernel binary policy.
Reported-by: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/src/expand.c | 35 +++++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/libsepol/src/expand.c b/libsepol/src/expand.c
index eac7e4507d02..2d9cb566fe1e 100644
--- a/libsepol/src/expand.c
+++ b/libsepol/src/expand.c
@@ -71,6 +71,38 @@ static int map_ebitmap(ebitmap_t * src, ebitmap_t * dst, uint32_t * map)
return 0;
}
+static int ebitmap_expand_roles(policydb_t *p, ebitmap_t *roles)
+{
+ ebitmap_node_t *node;
+ unsigned int bit;
+ role_datum_t *role;
+ ebitmap_t tmp;
+
+ ebitmap_init(&tmp);
+ ebitmap_for_each_positive_bit(roles, node, bit) {
+ role = p->role_val_to_struct[bit];
+ assert(role);
+ if (role->flavor != ROLE_ATTRIB) {
+ if (ebitmap_set_bit(&tmp, bit, 1)) {
+ ebitmap_destroy(&tmp);
+ return -1;
+ }
+ } else {
+ if (ebitmap_union(&tmp, &role->roles)) {
+ ebitmap_destroy(&tmp);
+ return -1;
+ }
+ }
+ }
+ ebitmap_destroy(roles);
+ if (ebitmap_cpy(roles, &tmp)) {
+ ebitmap_destroy(&tmp);
+ return -1;
+ }
+ ebitmap_destroy(&tmp);
+ return 0;
+}
+
static int type_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
void *data)
{
@@ -333,6 +365,9 @@ static int constraint_node_clone(constraint_node_t ** dst,
if (map_ebitmap(&expr->names, &new_expr->names, state->rolemap)) {
goto out_of_mem;
}
+ if (ebitmap_expand_roles(state->out, &new_expr->names)) {
+ goto out_of_mem;
+ }
} else if (new_expr->attr & CEXPR_USER) {
if (map_ebitmap(&expr->names, &new_expr->names, state->usermap)) {
goto out_of_mem;
--
2.32.0

View File

@ -1,70 +0,0 @@
From 6015b05d068515201f5d053910c6587fff8407d4 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Tue, 9 Mar 2021 16:36:40 -0500
Subject: [PATCH] libsepol: Properly handle types associated to role attributes
Types associated to role attributes in optional blocks are not
associated with the roles that have that attribute. The problem
is that role_fix_callback is called before the avrule_decls are
walked.
Example/
class CLASS1
sid kernel
class CLASS1 { PERM1 }
type TYPE1;
type TYPE1A;
allow TYPE1 self : CLASS1 PERM1;
attribute_role ROLE_ATTR1A;
role ROLE1;
role ROLE1A;
roleattribute ROLE1A ROLE_ATTR1A;
role ROLE1 types TYPE1;
optional {
require {
class CLASS1 PERM1;
}
role ROLE_ATTR1A types TYPE1A;
}
user USER1 roles ROLE1;
sid kernel USER1:ROLE1:TYPE1
In this example ROLE1A will not have TYPE1A associated to it.
Call role_fix_callback() after the avrule_decls are walked.
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/src/expand.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/libsepol/src/expand.c b/libsepol/src/expand.c
index 2d9cb566fe1e..a656ffad3a71 100644
--- a/libsepol/src/expand.c
+++ b/libsepol/src/expand.c
@@ -3052,10 +3052,6 @@ int expand_module(sepol_handle_t * handle,
if (hashtab_map(state.base->p_roles.table,
role_bounds_copy_callback, &state))
goto cleanup;
- /* escalate the type_set_t in a role attribute to all regular roles
- * that belongs to it. */
- if (hashtab_map(state.base->p_roles.table, role_fix_callback, &state))
- goto cleanup;
/* copy MLS's sensitivity level and categories - this needs to be done
* before expanding users (they need to be indexed too) */
@@ -3121,6 +3117,11 @@ int expand_module(sepol_handle_t * handle,
goto cleanup;
}
+ /* escalate the type_set_t in a role attribute to all regular roles
+ * that belongs to it. */
+ if (hashtab_map(state.base->p_roles.table, role_fix_callback, &state))
+ goto cleanup;
+
if (copy_and_expand_avrule_block(&state) < 0) {
ERR(handle, "Error during expand");
goto cleanup;
--
2.32.0

View File

@ -1,58 +0,0 @@
From 859857def94bd6c8ad9e9ecce88c85d19dc19933 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Thu, 11 Mar 2021 11:56:44 -0500
Subject: [PATCH] libsepol: Remove unnecessary copying of declarations from
link.c
At one point link_modules() might have needed this initial copying,
but now it serves no purpose, so remove it.
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/src/link.c | 30 ------------------------------
1 file changed, 30 deletions(-)
diff --git a/libsepol/src/link.c b/libsepol/src/link.c
index 83bbc8a5c7d1..bdc1fcbf59d3 100644
--- a/libsepol/src/link.c
+++ b/libsepol/src/link.c
@@ -2573,36 +2573,6 @@ int link_modules(sepol_handle_t * handle,
goto cleanup;
}
- /* copy all types, declared and required */
- for (i = 0; i < len; i++) {
- state.cur = modules[i];
- state.cur_mod_name = modules[i]->policy->name;
- ret =
- hashtab_map(modules[i]->policy->p_types.table,
- type_copy_callback, &state);
- if (ret) {
- retval = ret;
- goto cleanup;
- }
- }
-
- /* then copy everything else, including aliases, and fixup attributes */
- for (i = 0; i < len; i++) {
- state.cur = modules[i];
- state.cur_mod_name = modules[i]->policy->name;
- ret =
- copy_identifiers(&state, modules[i]->policy->symtab, NULL);
- if (ret) {
- retval = ret;
- goto cleanup;
- }
- }
-
- if (policydb_index_others(state.handle, state.base, 0)) {
- ERR(state.handle, "Error while indexing others");
- goto cleanup;
- }
-
/* copy and remap the module's data over to base */
for (i = 0; i < len; i++) {
state.cur = modules[i];
--
2.32.0

View File

@ -1,91 +0,0 @@
From 43c5ed469c2f3bc1beed9110b72bcc29c367ecfb Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Mon, 15 Mar 2021 11:09:38 -0400
Subject: [PATCH] libsepol: Check kernel to CIL and Conf functions for
supported versions
For policy versions between 20 and 23, attributes exist in the
policy, but only in the type_attr_map. This means that there are
gaps in both the type_val_to_struct and p_type_val_to_name arrays
and policy rules can refer to those gaps which can lead to NULL
dereferences when using sepol_kernel_policydb_to_conf() and
sepol_kernel_policydb_to_cil().
This can be seen with the following policy:
class CLASS1
sid SID1
class CLASS1 { PERM1 }
attribute TYPE_ATTR1;
type TYPE1;
typeattribute TYPE1 TYPE_ATTR1;
allow TYPE_ATTR1 self : CLASS1 PERM1;
role ROLE1;
role ROLE1 types TYPE1;
user USER1 roles ROLE1;
sid SID1 USER1:ROLE1:TYPE1
Compile the policy:
checkpolicy -c 23 -o policy.bin policy.conf
Converting back to a policy.conf causes a segfault:
checkpolicy -F -b -o policy.bin.conf policy.bin
Have both sepol_kernel_policydb_to_conf() and
sepol_kernel_policydb_to_cil() exit with an error if the kernel
policy version is between 20 and 23.
Acked-by: Nicolas Iooss <nicolas.iooss@m4x.org>
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/src/kernel_to_cil.c | 12 ++++++++++++
libsepol/src/kernel_to_conf.c | 12 ++++++++++++
2 files changed, 24 insertions(+)
diff --git a/libsepol/src/kernel_to_cil.c b/libsepol/src/kernel_to_cil.c
index a146ac514018..edfebeafe283 100644
--- a/libsepol/src/kernel_to_cil.c
+++ b/libsepol/src/kernel_to_cil.c
@@ -3164,6 +3164,18 @@ int sepol_kernel_policydb_to_cil(FILE *out, struct policydb *pdb)
goto exit;
}
+ if (pdb->policyvers >= POLICYDB_VERSION_AVTAB && pdb->policyvers <= POLICYDB_VERSION_PERMISSIVE) {
+ /*
+ * For policy versions between 20 and 23, attributes exist in the policy,
+ * but only in the type_attr_map. This means that there are gaps in both
+ * the type_val_to_struct and p_type_val_to_name arrays and policy rules
+ * can refer to those gaps.
+ */
+ sepol_log_err("Writing policy versions between 20 and 23 as CIL is not supported");
+ rc = -1;
+ goto exit;
+ }
+
rc = constraint_rules_to_strs(pdb, mls_constraints, non_mls_constraints);
if (rc != 0) {
goto exit;
diff --git a/libsepol/src/kernel_to_conf.c b/libsepol/src/kernel_to_conf.c
index a22f196df9e9..ea58a026501f 100644
--- a/libsepol/src/kernel_to_conf.c
+++ b/libsepol/src/kernel_to_conf.c
@@ -3041,6 +3041,18 @@ int sepol_kernel_policydb_to_conf(FILE *out, struct policydb *pdb)
goto exit;
}
+ if (pdb->policyvers >= POLICYDB_VERSION_AVTAB && pdb->policyvers <= POLICYDB_VERSION_PERMISSIVE) {
+ /*
+ * For policy versions between 20 and 23, attributes exist in the policy,
+ * but only in the type_attr_map. This means that there are gaps in both
+ * the type_val_to_struct and p_type_val_to_name arrays and policy rules
+ * can refer to those gaps.
+ */
+ sepol_log_err("Writing policy versions between 20 and 23 as a policy.conf is not supported");
+ rc = -1;
+ goto exit;
+ }
+
rc = constraint_rules_to_strs(pdb, mls_constraints, non_mls_constraints);
if (rc != 0) {
goto exit;
--
2.32.0

View File

@ -1,77 +0,0 @@
From ba5fb7a41bb481cb870da273dd2faea4f2343c6d Mon Sep 17 00:00:00 2001
From: Nicolas Iooss <nicolas.iooss@m4x.org>
Date: Sun, 14 Mar 2021 16:58:44 +0100
Subject: [PATCH] libsepol/cil: make cil_post_fc_fill_data static
cil_post_fc_fill_data() is not used outside of cil_post.c, and is not
exported in libsepol.so. Make it static, in order to ease the analysis
of static analyzers.
While at it, make its path argument "const char*" and the fields of
"struct fc_data" "unsigned int" or "size_t", in order to make the types
better match the values.
Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
---
libsepol/cil/src/cil_post.c | 11 +++++++++--
libsepol/cil/src/cil_post.h | 7 -------
2 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/libsepol/cil/src/cil_post.c b/libsepol/cil/src/cil_post.c
index a55df1ea5bb0..d2ecbd430aa3 100644
--- a/libsepol/cil/src/cil_post.c
+++ b/libsepol/cil/src/cil_post.c
@@ -27,6 +27,7 @@
* either expressed or implied, of Tresys Technology, LLC.
*/
+#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -50,6 +51,12 @@
#define GEN_REQUIRE_ATTR "cil_gen_require" /* Also in libsepol/src/module_to_cil.c */
#define TYPEATTR_INFIX "_typeattr_" /* Also in libsepol/src/module_to_cil.c */
+struct fc_data {
+ unsigned int meta;
+ size_t stem_len;
+ size_t str_len;
+};
+
static int __cil_expr_to_bitmap(struct cil_list *expr, ebitmap_t *out, int max, struct cil_db *db);
static int __cil_expr_list_to_bitmap(struct cil_list *expr_list, ebitmap_t *out, int max, struct cil_db *db);
@@ -156,9 +163,9 @@ static int cil_verify_is_list(struct cil_list *list, enum cil_flavor flavor)
return CIL_TRUE;
}
-void cil_post_fc_fill_data(struct fc_data *fc, char *path)
+static void cil_post_fc_fill_data(struct fc_data *fc, const char *path)
{
- int c = 0;
+ size_t c = 0;
fc->meta = 0;
fc->stem_len = 0;
fc->str_len = 0;
diff --git a/libsepol/cil/src/cil_post.h b/libsepol/cil/src/cil_post.h
index 3d5415486b77..b1d2206f9ef6 100644
--- a/libsepol/cil/src/cil_post.h
+++ b/libsepol/cil/src/cil_post.h
@@ -30,13 +30,6 @@
#ifndef CIL_POST_H_
#define CIL_POST_H_
-struct fc_data {
- int meta;
- int stem_len;
- int str_len;
-};
-
-void cil_post_fc_fill_data(struct fc_data *fc, char *path);
int cil_post_filecon_compare(const void *a, const void *b);
int cil_post_ibpkeycon_compare(const void *a, const void *b);
int cil_post_portcon_compare(const void *a, const void *b);
--
2.32.0

View File

@ -1,28 +0,0 @@
From fba672edfbe3fef4969c947eb3f7d62f5da6be2f Mon Sep 17 00:00:00 2001
From: Nicolas Iooss <nicolas.iooss@m4x.org>
Date: Sun, 14 Mar 2021 17:58:01 +0100
Subject: [PATCH] libsepol/cil: remove stray printf
printf("%i\n", node->flavor); looks very much like a statement which was
added for debugging purpose and was unintentionally left.
Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
---
libsepol/cil/src/cil_resolve_ast.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
index 0e07856133e5..47cdf0e7c0b9 100644
--- a/libsepol/cil/src/cil_resolve_ast.c
+++ b/libsepol/cil/src/cil_resolve_ast.c
@@ -1088,7 +1088,6 @@ int cil_resolve_roletransition(struct cil_tree_node *current, void *extra_args)
node = NODE(result_datum);
if (node->flavor != CIL_ROLE) {
rc = SEPOL_ERR;
- printf("%i\n", node->flavor);
cil_log(CIL_ERR, "roletransition must result in a role, but %s is a %s\n", roletrans->result_str, cil_node_to_string(node));
goto exit;
}
--
2.32.0

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 47cdf0e7c0b9..2ea106d63505 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;
}
--
2.32.0

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 2ea106d63505..63beed9230b9 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) {
--
2.32.0

View File

@ -1,173 +0,0 @@
From 78d458d16393d8f2dd2cd2a7b066222da4e87975 Mon Sep 17 00:00:00 2001
From: Nicolas Iooss <nicolas.iooss@m4x.org>
Date: Sun, 14 Mar 2021 19:53:25 +0100
Subject: [PATCH] libsepol/cil: do not leak avrulex_ioctl_table memory when an
error occurs
OSS-Fuzz found a memory leak when trying to compile the following
policy:
(class CLASS (PERM ioctl))
(classorder (CLASS))
(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))))
(permissionx ioctl_test (ioctl CLASS (and (range 0x1600 0x19FF) (not (range 0x1750 0x175F)))))
(allowx TYPE TYPE ioctl_test)
(boolean BOOLEAN false)
(booleanif (not (xor (eq BOOLEAN BOOLEAN)
(and (not (xor (eq BOOLEAN BOOLEAN)
(and (not (xor (eq BOOLEAN BOOLEAN)
(and (not (xor (eq BOOLEAN BOOLEAN)
(and (not (xor (eq BOOLEAN BOOLEAN)
(and (not (xor (eq BOOLEAN BOOLEAN)
(and (not (xor (eq BOOLEAN BOOLEAN)
(and (not (xor (eq BOOLEAN BOOLEAN)
(and (not (xor (eq BOOLEAN BOOLEAN)
(and (not (xor (eq BOOLEAN BOOLEAN)
(and (not (xor (eq BOOLEAN BOOLEAN)
(and (not (xor (eq BOOLEAN BOOLEAN)
(and (not (xor (eq BOOLEAN BOOLEAN)
(and (not (xor (eq BOOLEAN BOOLEAN)
(and (not (xor (eq BOOLEAN BOOLEAN)
(and (not (xor (eq BOOLEAN BOOLEAN)
(and (not (xor (eq BOOLEAN BOOLEAN)
(and (not (xor (eq BOOLEAN BOOLEAN)
(and (not (xor (eq BOOLEAN BOOLEAN)
(and (not (xor (eq BOOLEAN BOOLEAN)
(and (not (xor (eq BOOLEAN BOOLEAN)
(and (not (xor (eq BOOLEAN BOOLEAN)
(and (not (xor (eq BOOLEAN BOOLEAN)
(and (not (xor (eq BOOLEAN BOOLEAN)
(and (not (xor (eq BOOLEAN BOOLEAN)
(and (not (xor (eq BOOLEAN BOOLEAN)
(and (not (xor (eq BOOLEAN BOOLEAN)
(and (not (xor (eq BOOLEAN BOOLEAN)
(and (not (xor (eq BOOLEAN BOOLEAN)
(and (not (xor (eq BOOLEAN BOOLEAN)
(and (not (xor (eq BOOLEAN BOOLEAN)
(and (not (xor (eq BOOLEAN BOOLEAN)
(and (not (xor (eq BOOLEAN BOOLEAN)
(and (not (xor (eq BOOLEAN BOOLEAN)
(and (not (xor (eq BOOLEAN BOOLEAN)
(and (not (xor (eq BOOLEAN BOOLEAN)
(and (not (xor (eq BOOLEAN BOOLEAN)
(and (eq BOOLEAN BOOLEAN) BOOLEAN ) ) )
BOOLEAN ) ) )
BOOLEAN ) ) )
BOOLEAN ) ) )
BOOLEAN ) ) )
BOOLEAN ) ) )
BOOLEAN ) ) )
BOOLEAN ) ) )
BOOLEAN ) ) )
BOOLEAN ) ) )
BOOLEAN ) ) )
BOOLEAN ) ) )
BOOLEAN ) ) )
BOOLEAN ) ) )
BOOLEAN ) ) )
BOOLEAN ) ) )
BOOLEAN ) ) )
BOOLEAN ) ) )
BOOLEAN ) ) )
BOOLEAN ) ) )
BOOLEAN ) ) )
BOOLEAN ) ) )
BOOLEAN ) ) )
BOOLEAN ) ) )
BOOLEAN ) ) )
BOOLEAN ) ) )
BOOLEAN ) ) )
BOOLEAN ) ) )
BOOLEAN ) ) )
BOOLEAN ) ) )
BOOLEAN ) ) )
BOOLEAN ) ) )
BOOLEAN ) ) )
BOOLEAN ) ) )
BOOLEAN ) ) )
BOOLEAN ) ) )
BOOLEAN ) ) )
(true
(allow TYPE TYPE (CLASS (PERM)))
)
)
When the CIL compiler reports "Conditional expression exceeded max
allowable depth" because of the loooooong expression in the booleanif
statement, cil_binary_create_allocated_pdb returns without freeing the
memory which was allocated to store the keys and values of hash table
avrulex_ioctl_table.
Fix this by moving the freeing logic to a dedicated destructor function
and calling it in the exit block of cil_binary_create_allocated_pdb.
Fixes: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=28618
Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
---
libsepol/cil/src/cil_binary.c | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c
index f80d84679f85..18532aad9801 100644
--- a/libsepol/cil/src/cil_binary.c
+++ b/libsepol/cil/src/cil_binary.c
@@ -1668,14 +1668,6 @@ exit:
}
cil_list_destroy(&xperms_list, CIL_FALSE);
}
-
- // hashtab_t does not have a way to free keys or datum since it doesn't
- // know what they are. We won't need the keys/datum after this function, so
- // clean them up here.
- free(avtab_key);
- ebitmap_destroy(datum);
- free(datum);
-
return rc;
}
@@ -1885,6 +1877,15 @@ exit:
return rc;
}
+static int __cil_avrulex_ioctl_destroy(hashtab_key_t k, hashtab_datum_t datum, __attribute__((unused)) void *args)
+{
+ free(k);
+ ebitmap_destroy(datum);
+ free(datum);
+
+ return SEPOL_OK;
+}
+
int __cil_cond_to_policydb_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args)
{
int rc;
@@ -5037,6 +5038,7 @@ int cil_binary_create_allocated_pdb(const struct cil_db *db, sepol_policydb_t *p
exit:
hashtab_destroy(role_trans_table);
+ hashtab_map(avrulex_ioctl_table, __cil_avrulex_ioctl_destroy, NULL);
hashtab_destroy(avrulex_ioctl_table);
free(type_value_to_cil);
free(class_value_to_cil);
--
2.32.0

View File

@ -1,234 +0,0 @@
From 13eaba21ef523325f226c14c4c792ce404b58970 Mon Sep 17 00:00:00 2001
From: Nicolas Iooss <nicolas.iooss@m4x.org>
Date: Tue, 16 Mar 2021 23:23:13 +0100
Subject: [PATCH] libsepol: make num_* unsigned int in module_to_cil
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Using signed integer to represent counts can troube some gcc
optimisation passes, for example in
https://github.com/fishilico/selinux/runs/2125501324?check_suite_focus=true#step:9:107
In function name_list_to_string,
inlined from constraint_expr_to_string at module_to_cil.c:1799:11:
module_to_cil.c:1156:8: error: argument 1 range
[18446744071562067968, 18446744073709551615] exceeds maximum
object size 9223372036854775807 [-Werror=alloc-size-larger-than=]
1156 | str = malloc(len);
| ^~~~~~~~~~~
In file included from module_to_cil.c:39:
module_to_cil.c: In function constraint_expr_to_string:
/usr/include/stdlib.h:539:14: note: in a call to allocation
function malloc declared here
539 | extern void *malloc (size_t __size) __THROW __attribute_malloc__
| ^~~~~~
The wide range (from 18446744071562067968 = 0xffffffff80000000 to
18446744073709551615 = 0xffffffffffffffff) was caused by num_names being
a signed int used in "len += num_names;", even though it should always
be non-negative.
Prevent such issues from occurring by using "unsigned int" where
appropriate.
Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
---
libsepol/src/module_to_cil.c | 62 ++++++++++++++++++------------------
1 file changed, 31 insertions(+), 31 deletions(-)
diff --git a/libsepol/src/module_to_cil.c b/libsepol/src/module_to_cil.c
index a87bc15e7610..cb1069caffdf 100644
--- a/libsepol/src/module_to_cil.c
+++ b/libsepol/src/module_to_cil.c
@@ -717,9 +717,9 @@ exit:
return rc;
}
-static int num_digits(int n)
+static unsigned int num_digits(unsigned int n)
{
- int num = 1;
+ unsigned int num = 1;
while (n >= 10) {
n /= 10;
num++;
@@ -945,7 +945,7 @@ static char *search_attr_list(struct list *attr_list, int is_type, void *set)
return NULL;
}
-static int set_to_names(struct policydb *pdb, int is_type, void *set, struct list *attr_list, char ***names, int *num_names)
+static int set_to_names(struct policydb *pdb, int is_type, void *set, struct list *attr_list, char ***names, unsigned int *num_names)
{
char *attr_name = NULL;
int rc = 0;
@@ -982,12 +982,12 @@ exit:
return rc;
}
-static int ebitmap_to_names(struct ebitmap *map, char **vals_to_names, char ***names, int *num_names)
+static int ebitmap_to_names(struct ebitmap *map, char **vals_to_names, char ***names, unsigned int *num_names)
{
int rc = 0;
struct ebitmap_node *node;
uint32_t i;
- uint32_t num;
+ unsigned int num;
char **name_arr;
num = 0;
@@ -1026,7 +1026,7 @@ exit:
return rc;
}
-static int process_roleset(struct policydb *pdb, struct role_set *rs, struct list *attr_list, char ***names, int *num_names)
+static int process_roleset(struct policydb *pdb, struct role_set *rs, struct list *attr_list, char ***names, unsigned int *num_names)
{
int rc = 0;
@@ -1049,7 +1049,7 @@ exit:
return rc;
}
-static int process_typeset(struct policydb *pdb, struct type_set *ts, struct list *attr_list, char ***names, int *num_names)
+static int process_typeset(struct policydb *pdb, struct type_set *ts, struct list *attr_list, char ***names, unsigned int *num_names)
{
int rc = 0;
@@ -1072,7 +1072,7 @@ exit:
return rc;
}
-static void names_destroy(char ***names, int *num_names)
+static void names_destroy(char ***names, unsigned int *num_names)
{
free(*names);
*names = NULL;
@@ -1083,7 +1083,7 @@ static int roletype_role_in_ancestor_to_cil(struct policydb *pdb, struct stack *
{
struct list_node *curr;
char **tnames = NULL;
- int num_tnames, i;
+ unsigned int num_tnames, i;
struct role_list_node *role_node = NULL;
int rc;
struct type_set *ts;
@@ -1124,12 +1124,12 @@ exit:
}
-static int name_list_to_string(char **names, int num_names, char **string)
+static int name_list_to_string(char **names, unsigned int num_names, char **string)
{
// create a space separated string of the names
int rc = -1;
size_t len = 0;
- int i;
+ unsigned int i;
char *str;
char *strpos;
@@ -1184,7 +1184,7 @@ static int avrule_list_to_cil(int indent, struct policydb *pdb, struct avrule *a
struct avrule *avrule;
char **snames = NULL;
char **tnames = NULL;
- int s, t, num_snames, num_tnames;
+ unsigned int s, t, num_snames, num_tnames;
struct type_set *ts;
for (avrule = avrule_list; avrule != NULL; avrule = avrule->next) {
@@ -1257,7 +1257,7 @@ static int cond_expr_to_cil(int indent, struct policydb *pdb, struct cond_expr *
char *new_val = NULL;
char *val1 = NULL;
char *val2 = NULL;
- int num_params;
+ unsigned int num_params;
const char *op;
const char *fmt_str;
const char *type;
@@ -1432,11 +1432,11 @@ static int role_trans_to_cil(int indent, struct policydb *pdb, struct role_trans
int rc = 0;
struct role_trans_rule *rule;
char **role_names = NULL;
- int num_role_names = 0;
- int role;
+ unsigned int num_role_names = 0;
+ unsigned int role;
char **type_names = NULL;
- int num_type_names = 0;
- int type;
+ unsigned int num_type_names = 0;
+ unsigned int type;
uint32_t i;
struct ebitmap_node *node;
struct type_set *ts;
@@ -1482,10 +1482,10 @@ static int role_allows_to_cil(int indent, struct policydb *pdb, struct role_allo
int rc = -1;
struct role_allow_rule *rule;
char **roles = NULL;
- int num_roles = 0;
+ unsigned int num_roles = 0;
char **new_roles = NULL;
- int num_new_roles = 0;
- int i,j;
+ unsigned int num_new_roles = 0;
+ unsigned int i, j;
struct role_set *rs;
for (rule = rules; rule != NULL; rule = rule->next) {
@@ -1525,11 +1525,11 @@ static int range_trans_to_cil(int indent, struct policydb *pdb, struct range_tra
int rc = -1;
struct range_trans_rule *rule;
char **stypes = NULL;
- int num_stypes = 0;
- int stype;
+ unsigned int num_stypes = 0;
+ unsigned int stype;
char **ttypes = NULL;
- int num_ttypes = 0;
- int ttype;
+ unsigned int num_ttypes = 0;
+ unsigned int ttype;
struct ebitmap_node *node;
uint32_t i;
struct type_set *ts;
@@ -1594,11 +1594,11 @@ static int filename_trans_to_cil(int indent, struct policydb *pdb, struct filena
{
int rc = -1;
char **stypes = NULL;
- int num_stypes = 0;
- int stype;
+ unsigned int num_stypes = 0;
+ unsigned int stype;
char **ttypes = NULL;
- int num_ttypes = 0;
- int ttype;
+ unsigned int num_ttypes = 0;
+ unsigned int ttype;
struct type_set *ts;
struct filename_trans_rule *rule;
@@ -1716,7 +1716,7 @@ static int constraint_expr_to_string(struct policydb *pdb, struct constraint_exp
const char *attr2;
char *names = NULL;
char **name_list = NULL;
- int num_names = 0;
+ unsigned int num_names = 0;
struct type_set *ts;
rc = stack_init(&stack);
@@ -2090,9 +2090,9 @@ static int role_to_cil(int indent, struct policydb *pdb, struct avrule_block *UN
int rc = -1;
struct ebitmap_node *node;
uint32_t i;
- int j;
+ unsigned int j;
char **types = NULL;
- int num_types = 0;
+ unsigned int num_types = 0;
struct role_datum *role = datum;
struct type_set *ts;
struct list *attr_list = NULL;
--
2.32.0

View File

@ -1,37 +0,0 @@
From d4d0955c67f5b928ef134ee7e7e23a9c40a266ea Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Tue, 16 Mar 2021 14:30:02 -0400
Subject: [PATCH] libsepol: Write "NO_IDENTIFIER" for empty constraint
expression
If a role attribute with no roles associated with it is used in a
constraint expression, then the role bitmap will be empty. This is
not a problem for the kernel, but does cause problems when
converting a kernel policy to policy.conf.
When creating a policy.conf from a kernel policy, if an empty bitmap
is encountered, use the string "NO_IDENTIFIER". An error will occur
if an attempt is made to compile the resulting policy, but this is
better than exiting with an error without creating a policy.conf.
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/src/kernel_to_conf.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libsepol/src/kernel_to_conf.c b/libsepol/src/kernel_to_conf.c
index ea58a026501f..cd5a517abb59 100644
--- a/libsepol/src/kernel_to_conf.c
+++ b/libsepol/src/kernel_to_conf.c
@@ -186,7 +186,7 @@ static char *constraint_expr_to_str(struct policydb *pdb, struct constraint_expr
names = ebitmap_to_str(&curr->names, pdb->p_role_val_to_name, 1);
}
if (!names) {
- goto exit;
+ names = strdup("NO_IDENTIFIER");
}
new_val = create_str("%s %s %s", 3, attr1, op, names);
free(names);
--
2.32.0

View File

@ -1,38 +0,0 @@
From dbe890ab9f74c9514a0f8839591eb3c4c70a6e03 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Tue, 16 Mar 2021 14:42:36 -0400
Subject: [PATCH] libsepol: Enclose identifier lists in constraint expressions
When writing a policy.conf from a kernel policy, if there are
multiple users, roles, or types, then the list needs to be enclosed
by "{" and "}".
When writing a constraint expression, check to see if there are
multiple identifiers in the names string and enclose the list
with "{" and "}" if there are.
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/src/kernel_to_conf.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/libsepol/src/kernel_to_conf.c b/libsepol/src/kernel_to_conf.c
index cd5a517abb59..5db47fe4f567 100644
--- a/libsepol/src/kernel_to_conf.c
+++ b/libsepol/src/kernel_to_conf.c
@@ -188,7 +188,11 @@ static char *constraint_expr_to_str(struct policydb *pdb, struct constraint_expr
if (!names) {
names = strdup("NO_IDENTIFIER");
}
- new_val = create_str("%s %s %s", 3, attr1, op, names);
+ if (strchr(names, ' ')) {
+ new_val = create_str("%s %s { %s }", 3, attr1, op, names);
+ } else {
+ new_val = create_str("%s %s %s", 3, attr1, op, names);
+ }
free(names);
}
} else {
--
2.32.0

View File

@ -1,40 +0,0 @@
From 48ca44c8bc3bffd276fae0e7cc8c5b04af4f8736 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Tue, 16 Mar 2021 15:18:31 -0400
Subject: [PATCH] libsepol/cil: Allow lists in constraint expressions
The expectation in CIL was to use user, role, or type attributes in
constraint expressions. The problem is that neither user nor role
attributes are part of the kernel binary policy, so when converting
from a kernel policy to CIL, that would require the creation of a
role or user attribute. The better solution is to just allow a list
to be used. In fact, the only thing preventing a list to be used
is a check in cil_verify_constraint_leaf_expr_syntax().
Remove the check and allow lists in constraint expressions.
The following is now allowed:
(constrain (CLASS1 (PERM1)) (eq r1 (ROLE1 ROLE2 ROLE_ATTR3)))
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/cil/src/cil_verify.c | 3 ---
1 file changed, 3 deletions(-)
diff --git a/libsepol/cil/src/cil_verify.c b/libsepol/cil/src/cil_verify.c
index 6706e21921fe..09e3daf94cc7 100644
--- a/libsepol/cil/src/cil_verify.c
+++ b/libsepol/cil/src/cil_verify.c
@@ -225,9 +225,6 @@ int cil_verify_constraint_leaf_expr_syntax(enum cil_flavor l_flavor, enum cil_fl
cil_log(CIL_ERR, "u3, r3, and t3 can only be used with (mls)validatetrans rules\n");
goto exit;
}
- } else if (r_flavor == CIL_LIST) {
- cil_log(CIL_ERR, "t1, t2, r1, r2, u1, u2 cannot be used on the left side with a list on the right side\n");
- goto exit;
}
} else {
if (r_flavor == CIL_CONS_U2) {
--
2.32.0

View File

@ -1,66 +0,0 @@
From 6758addf8592d950cba489703abedd4a3430602f Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Tue, 16 Mar 2021 15:24:14 -0400
Subject: [PATCH] libsepol: Enclose identifier lists in CIL constraint
expressions
When writing CIL policy from a kernel policy or module, if there are
multiple users, roles, or types, then the list needs to be enclosed
by "(" and ")".
When writing a constraint expression, check to see if there are
multiple identifiers in the names string and enclose the list with
"(" and ")" if there are.
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/src/kernel_to_cil.c | 6 +++++-
libsepol/src/module_to_cil.c | 9 ++++++++-
2 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/libsepol/src/kernel_to_cil.c b/libsepol/src/kernel_to_cil.c
index edfebeafe283..101cb61240f5 100644
--- a/libsepol/src/kernel_to_cil.c
+++ b/libsepol/src/kernel_to_cil.c
@@ -191,7 +191,11 @@ static char *constraint_expr_to_str(struct policydb *pdb, struct constraint_expr
if (!names) {
goto exit;
}
- new_val = create_str("(%s %s %s)", 3, op, attr1, names);
+ if (strchr(names, ' ')) {
+ new_val = create_str("(%s %s (%s))", 3, op, attr1, names);
+ } else {
+ new_val = create_str("(%s %s %s)", 3, op, attr1, names);
+ }
free(names);
}
} else {
diff --git a/libsepol/src/module_to_cil.c b/libsepol/src/module_to_cil.c
index cb1069caffdf..fdf56b701e2c 100644
--- a/libsepol/src/module_to_cil.c
+++ b/libsepol/src/module_to_cil.c
@@ -1800,13 +1800,20 @@ static int constraint_expr_to_string(struct policydb *pdb, struct constraint_exp
// length of values/oper + 2 spaces + 2 parens + null terminator
len = strlen(op) + strlen(attr1) + strlen(names) + 2 + 2 + 1;
+ if (num_names > 1) {
+ len += 2; // 2 more parens
+ }
new_val = malloc(len);
if (new_val == NULL) {
log_err("Out of memory");
rc = -1;
goto exit;
}
- rlen = snprintf(new_val, len, "(%s %s %s)", op, attr1, names);
+ if (num_names > 1) {
+ rlen = snprintf(new_val, len, "(%s %s (%s))", op, attr1, names);
+ } else {
+ rlen = snprintf(new_val, len, "(%s %s %s)", op, attr1, names);
+ }
if (rlen < 0 || rlen >= len) {
log_err("Failed to generate constraint expression");
rc = -1;
--
2.32.0

View File

@ -1,60 +0,0 @@
From b839e9a1cb78d67c18df8b2e75e2fa53cca74392 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Tue, 16 Mar 2021 15:31:06 -0400
Subject: [PATCH] libsepol: Write "NO_IDENTIFIER" for empty CIL constraint
expression
If a role or user attribute with nothing associated with it is used
in a constraint expression, then the bitmap will be empty. This is
not a problem for the kernel, but does cause problems when converting
a kernel policy or module to CIL.
When creating a CIL policy from a kernel policy or module, if an
empty bitmap is encountered, use the string "NO_IDENTIFIER". An
error will occur if an attempt is made to compile the resulting
policy, but a valid policy was not being produced before anyway.
Treat types the same way even though empty bitmaps are not expected.
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/src/kernel_to_cil.c | 2 +-
libsepol/src/module_to_cil.c | 10 +++++++---
2 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/libsepol/src/kernel_to_cil.c b/libsepol/src/kernel_to_cil.c
index 101cb61240f5..989aacde8a12 100644
--- a/libsepol/src/kernel_to_cil.c
+++ b/libsepol/src/kernel_to_cil.c
@@ -189,7 +189,7 @@ static char *constraint_expr_to_str(struct policydb *pdb, struct constraint_expr
names = ebitmap_to_str(&curr->names, pdb->p_role_val_to_name, 1);
}
if (!names) {
- goto exit;
+ names = strdup("NO_IDENTIFIER");
}
if (strchr(names, ' ')) {
new_val = create_str("(%s %s (%s))", 3, op, attr1, names);
diff --git a/libsepol/src/module_to_cil.c b/libsepol/src/module_to_cil.c
index fdf56b701e2c..58df0d4f6d77 100644
--- a/libsepol/src/module_to_cil.c
+++ b/libsepol/src/module_to_cil.c
@@ -1793,9 +1793,13 @@ static int constraint_expr_to_string(struct policydb *pdb, struct constraint_exp
goto exit;
}
}
- rc = name_list_to_string(name_list, num_names, &names);
- if (rc != 0) {
- goto exit;
+ if (num_names == 0) {
+ names = strdup("NO_IDENTIFIER");
+ } else {
+ rc = name_list_to_string(name_list, num_names, &names);
+ if (rc != 0) {
+ goto exit;
+ }
}
// length of values/oper + 2 spaces + 2 parens + null terminator
--
2.32.0

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 c9aada9db348..ed96786115d3 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;
}
--
2.32.0

View File

@ -1,50 +0,0 @@
From e13c8162656665f9ec1c76a033cae5b011b8c658 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Thu, 8 Apr 2021 13:24:29 -0400
Subject: [PATCH] libsepol/cil: Fix out-of-bound read of file context pattern
ending with "\"
Based on patch by Nicolas Iooss, who writes:
OSS-Fuzz found a Heap-buffer-overflow in the CIL compiler when trying
to compile the following policy:
(sid SID)
(sidorder(SID))
(filecon "\" any ())
(filecon "" any ())
When cil_post_fc_fill_data() processes "\", it goes beyond the NUL
terminator of the string. Fix this by returning when '\0' is read
after a backslash.
To be consistent with the function compute_diffdata() in
refpolicy/support/fc_sort.py, also increment str_len in this case.
Fixes: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=28484
Reported-by: Nicolas Iooss <nicolas.iooss@m4x.org>
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/cil/src/cil_post.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/libsepol/cil/src/cil_post.c b/libsepol/cil/src/cil_post.c
index d2ecbd430aa3..fd4758dc580e 100644
--- a/libsepol/cil/src/cil_post.c
+++ b/libsepol/cil/src/cil_post.c
@@ -186,6 +186,13 @@ static void cil_post_fc_fill_data(struct fc_data *fc, const char *path)
break;
case '\\':
c++;
+ if (path[c] == '\0') {
+ if (!fc->meta) {
+ fc->stem_len++;
+ }
+ fc->str_len++;
+ return;
+ }
/* FALLTHRU */
default:
if (!fc->meta) {
--
2.32.0

View File

@ -1,97 +0,0 @@
From f34d3d30c8325e4847a6b696fe7a3936a8a361f3 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Thu, 8 Apr 2021 13:32:01 -0400
Subject: [PATCH] libsepol/cil: Destroy classperms list when resetting
classpermission
Nicolas Iooss reports:
A few months ago, OSS-Fuzz found a crash in the CIL compiler, which
got reported as
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=28648 (the title
is misleading, or is caused by another issue that conflicts with the
one I report in this message). Here is a minimized CIL policy which
reproduces the issue:
(class CLASS (PERM))
(classorder (CLASS))
(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))))
(classpermission CLAPERM)
(optional OPT
(roletype nonexistingrole nonexistingtype)
(classpermissionset CLAPERM (CLASS (PERM)))
)
The CIL policy fuzzer (which mimics secilc built with clang Address
Sanitizer) reports:
==36541==ERROR: AddressSanitizer: heap-use-after-free on address
0x603000004f98 at pc 0x56445134c842 bp 0x7ffe2a256590 sp
0x7ffe2a256588
READ of size 8 at 0x603000004f98 thread T0
#0 0x56445134c841 in __cil_verify_classperms
/selinux/libsepol/src/../cil/src/cil_verify.c:1620:8
#1 0x56445134a43e in __cil_verify_classpermission
/selinux/libsepol/src/../cil/src/cil_verify.c:1650:9
#2 0x56445134a43e in __cil_pre_verify_helper
/selinux/libsepol/src/../cil/src/cil_verify.c:1715:8
#3 0x5644513225ac in cil_tree_walk_core
/selinux/libsepol/src/../cil/src/cil_tree.c:272:9
#4 0x564451322ab1 in cil_tree_walk
/selinux/libsepol/src/../cil/src/cil_tree.c:316:7
#5 0x5644513226af in cil_tree_walk_core
/selinux/libsepol/src/../cil/src/cil_tree.c:284:9
#6 0x564451322ab1 in cil_tree_walk
/selinux/libsepol/src/../cil/src/cil_tree.c:316:7
#7 0x5644512b88fd in cil_pre_verify
/selinux/libsepol/src/../cil/src/cil_post.c:2510:7
#8 0x5644512b88fd in cil_post_process
/selinux/libsepol/src/../cil/src/cil_post.c:2524:7
#9 0x5644511856ff in cil_compile
/selinux/libsepol/src/../cil/src/cil.c:564:7
The classperms list of a classpermission rule is created and filled
in when classpermissionset rules are processed, so it doesn't own any
part of the list and shouldn't retain any of it when it is reset.
Destroy the classperms list (without destroying the data in it) when
resetting a classpermission rule.
Reported-by: Nicolas Iooss <nicolas.iooss@m4x.org>
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/cil/src/cil_reset_ast.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libsepol/cil/src/cil_reset_ast.c b/libsepol/cil/src/cil_reset_ast.c
index 3da1b9a64167..db70a535bd42 100644
--- a/libsepol/cil/src/cil_reset_ast.c
+++ b/libsepol/cil/src/cil_reset_ast.c
@@ -54,7 +54,7 @@ static void cil_reset_classpermission(struct cil_classpermission *cp)
return;
}
- cil_reset_classperms_list(cp->classperms);
+ cil_list_destroy(&cp->classperms, CIL_FALSE);
}
static void cil_reset_classperms_set(struct cil_classperms_set *cp_set)
--
2.32.0

View File

@ -1,36 +0,0 @@
From 2d35fcc7e9e976a2346b1de20e54f8663e8a6cba Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Thu, 8 Apr 2021 13:32:04 -0400
Subject: [PATCH] libsepol/cil: Destroy classperm list when resetting map perms
Map perms share the same struct as regular perms, but only the
map perms use the classperms field. This field is a pointer to a
list of classperms that is created and added to when resolving
classmapping rules, so the map permission doesn't own any of the
data in the list and this list should be destroyed when the AST is
reset.
When resetting a perm, destroy the classperms list without destroying
the data in the list.
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/cil/src/cil_reset_ast.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libsepol/cil/src/cil_reset_ast.c b/libsepol/cil/src/cil_reset_ast.c
index db70a535bd42..89f91e568d0e 100644
--- a/libsepol/cil/src/cil_reset_ast.c
+++ b/libsepol/cil/src/cil_reset_ast.c
@@ -36,7 +36,7 @@ static void cil_reset_class(struct cil_class *class)
static void cil_reset_perm(struct cil_perm *perm)
{
- cil_reset_classperms_list(perm->classperms);
+ cil_list_destroy(&perm->classperms, CIL_FALSE);
}
static inline void cil_reset_classperms(struct cil_classperms *cp)
--
2.32.0

View File

@ -1,39 +0,0 @@
From c49a8ea09501ad66e799ea41b8154b6770fec2c8 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Thu, 8 Apr 2021 13:32:06 -0400
Subject: [PATCH] libsepol/cil: cil_reset_classperms_set() should not reset
classpermission
In struct cil_classperms_set, the set field is a pointer to a
struct cil_classpermission which is looked up in the symbol table.
Since the cil_classperms_set does not create the cil_classpermission,
it should not reset it.
Set the set field to NULL instead of resetting the classpermission
that it points to.
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/cil/src/cil_reset_ast.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/libsepol/cil/src/cil_reset_ast.c b/libsepol/cil/src/cil_reset_ast.c
index 89f91e568d0e..1d9ca704e3ea 100644
--- a/libsepol/cil/src/cil_reset_ast.c
+++ b/libsepol/cil/src/cil_reset_ast.c
@@ -59,7 +59,11 @@ static void cil_reset_classpermission(struct cil_classpermission *cp)
static void cil_reset_classperms_set(struct cil_classperms_set *cp_set)
{
- cil_reset_classpermission(cp_set->set);
+ if (cp_set == NULL) {
+ return;
+ }
+
+ cp_set->set = NULL;
}
static inline void cil_reset_classperms_list(struct cil_list *cp_list)
--
2.32.0

View File

@ -1,32 +0,0 @@
From a7a80ef51b915071f0339e5e0262f06d84112874 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Thu, 8 Apr 2021 13:32:08 -0400
Subject: [PATCH] libsepol/cil: Set class field to NULL when resetting struct
cil_classperms
The class field of a struct cil_classperms points to the class looked
up in the symbol table, so that field should be set to NULL when
the cil_classperms is reset.
Set the class field to NULL when resetting the struct cil_classperms.
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/cil/src/cil_reset_ast.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/libsepol/cil/src/cil_reset_ast.c b/libsepol/cil/src/cil_reset_ast.c
index 1d9ca704e3ea..76405aba6194 100644
--- a/libsepol/cil/src/cil_reset_ast.c
+++ b/libsepol/cil/src/cil_reset_ast.c
@@ -45,6 +45,7 @@ static inline void cil_reset_classperms(struct cil_classperms *cp)
return;
}
+ cp->class = NULL;
cil_list_destroy(&cp->perms, CIL_FALSE);
}
--
2.32.0

View File

@ -1,42 +0,0 @@
From e978e7692e16d6d8b801700d1dc5129ca31dfbad Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Thu, 8 Apr 2021 13:32:11 -0400
Subject: [PATCH] libsepol/cil: More strict verification of constraint leaf
expressions
In constraint expressions u1, u3, r1, r3, t1, and t3 are never
allowed on the right side of an expression, but there were no checks
to verify that they were not used on the right side. The result was
that the expression "(eq t1 t1)" would be silently turned into
"(eq t1 t2)" when the binary policy was created.
Verify that u1, u3, r1, r3, t1, and t3 are not used on the right
side of a constraint expression.
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/cil/src/cil_verify.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/libsepol/cil/src/cil_verify.c b/libsepol/cil/src/cil_verify.c
index 09e3daf94cc7..2707b6c97d15 100644
--- a/libsepol/cil/src/cil_verify.c
+++ b/libsepol/cil/src/cil_verify.c
@@ -227,7 +227,13 @@ int cil_verify_constraint_leaf_expr_syntax(enum cil_flavor l_flavor, enum cil_fl
}
}
} else {
- if (r_flavor == CIL_CONS_U2) {
+ if (r_flavor == CIL_CONS_U1 || r_flavor == CIL_CONS_R1 || r_flavor == CIL_CONS_T1) {
+ cil_log(CIL_ERR, "u1, r1, and t1 are not allowed on the right side\n");
+ goto exit;
+ } else if (r_flavor == CIL_CONS_U3 || r_flavor == CIL_CONS_R3 || r_flavor == CIL_CONS_T3) {
+ cil_log(CIL_ERR, "u3, r3, and t3 are not allowed on the right side\n");
+ goto exit;
+ } else if (r_flavor == CIL_CONS_U2) {
if (op != CIL_EQ && op != CIL_NEQ) {
cil_log(CIL_ERR, "u2 on the right side must be used with eq or neq as the operator\n");
goto exit;
--
2.32.0

View File

@ -1,194 +0,0 @@
From 532469a251607cfd8bd5e9299d3bba3764345ab6 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Thu, 8 Apr 2021 13:32:12 -0400
Subject: [PATCH] libsepol/cil: Exit with an error if declaration name is a
reserved word
When CIL parses sets or conditional expressions, any identifier that
matches an operator name will always be taken as an operator. If a
declaration has the same name as an operator, then there is the
possibility of causing either confusion or a syntax error if it is
used in an expression. The potential for problems is much greater
than any possible advantage in allowing a declaration to share the
name of a reserved word.
Create a new function, __cil_is_reserved_name() that is called when
an identifier is declared and its name is being validated. In this
function, check if the declaration has the same name as a reserved
word for an expression operator that can be used with the identifer's
flavor and exit with an error if it does.
Also, move the check for types, type aliases, and type attributes
matching the reserved word "self" to this new function.
Finally, change the name of the function __cil_verify_name() to
cil_verify_name(), since this function is neither static nor a
helper function.
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/cil/src/cil_build_ast.c | 28 ++---------------
libsepol/cil/src/cil_verify.c | 52 +++++++++++++++++++++++++++++++-
libsepol/cil/src/cil_verify.h | 2 +-
3 files changed, 54 insertions(+), 28 deletions(-)
diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c
index 4e53f06a98f4..e57de662dbd9 100644
--- a/libsepol/cil/src/cil_build_ast.c
+++ b/libsepol/cil/src/cil_build_ast.c
@@ -114,7 +114,7 @@ int cil_gen_node(struct cil_db *db, struct cil_tree_node *ast_node, struct cil_s
symtab_t *symtab = NULL;
struct cil_symtab_datum *prev;
- rc = __cil_verify_name((const char*)key);
+ rc = cil_verify_name((const char*)key, nflavor);
if (rc != SEPOL_OK) {
goto exit;
}
@@ -1953,12 +1953,6 @@ int cil_gen_roleattribute(struct cil_db *db, struct cil_tree_node *parse_current
goto exit;
}
- if (parse_current->next->data == CIL_KEY_SELF) {
- cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF);
- rc = SEPOL_ERR;
- goto exit;
- }
-
cil_roleattribute_init(&attr);
key = parse_current->next->data;
@@ -2337,12 +2331,6 @@ int cil_gen_type(struct cil_db *db, struct cil_tree_node *parse_current, struct
goto exit;
}
- if (parse_current->next->data == CIL_KEY_SELF) {
- cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF);
- rc = SEPOL_ERR;
- goto exit;
- }
-
cil_type_init(&type);
key = parse_current->next->data;
@@ -2391,12 +2379,6 @@ int cil_gen_typeattribute(struct cil_db *db, struct cil_tree_node *parse_current
goto exit;
}
- if (parse_current->next->data == CIL_KEY_SELF) {
- cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF);
- rc = SEPOL_ERR;
- goto exit;
- }
-
cil_typeattribute_init(&attr);
key = parse_current->next->data;
@@ -3048,12 +3030,6 @@ int cil_gen_alias(struct cil_db *db, struct cil_tree_node *parse_current, struct
goto exit;
}
- if (flavor == CIL_TYPEALIAS && parse_current->next->data == CIL_KEY_SELF) {
- cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF);
- rc = SEPOL_ERR;
- goto exit;
- }
-
cil_alias_init(&alias);
key = parse_current->next->data;
@@ -5278,7 +5254,7 @@ int cil_gen_macro(struct cil_db *db, struct cil_tree_node *parse_current, struct
param->str = current_item->cl_head->next->data;
- rc = __cil_verify_name(param->str);
+ rc = cil_verify_name(param->str, param->flavor);
if (rc != SEPOL_OK) {
cil_destroy_param(param);
goto exit;
diff --git a/libsepol/cil/src/cil_verify.c b/libsepol/cil/src/cil_verify.c
index 2707b6c97d15..8fd54360698d 100644
--- a/libsepol/cil/src/cil_verify.c
+++ b/libsepol/cil/src/cil_verify.c
@@ -47,7 +47,51 @@
#include "cil_verify.h"
-int __cil_verify_name(const char *name)
+static int __cil_is_reserved_name(const char *name, enum cil_flavor flavor)
+{
+ switch (flavor) {
+ case CIL_BOOL:
+ case CIL_TUNABLE:
+ if ((name == CIL_KEY_EQ) || (name == CIL_KEY_NEQ))
+ return CIL_TRUE;
+ break;
+ case CIL_PERM:
+ case CIL_MAP_PERM:
+ case CIL_USER:
+ case CIL_USERATTRIBUTE:
+ case CIL_ROLE:
+ case CIL_ROLEATTRIBUTE:
+ if (name == CIL_KEY_ALL)
+ return CIL_TRUE;
+ break;
+ case CIL_TYPE:
+ case CIL_TYPEATTRIBUTE:
+ case CIL_TYPEALIAS:
+ if ((name == CIL_KEY_ALL) || (name == CIL_KEY_SELF))
+ return CIL_TRUE;
+ break;
+ case CIL_CAT:
+ case CIL_CATSET:
+ case CIL_CATALIAS:
+ case CIL_PERMISSIONX:
+ if ((name == CIL_KEY_ALL) || (name == CIL_KEY_RANGE))
+ return CIL_TRUE;
+ break;
+ default:
+ /* All of these are not used in expressions */
+ return CIL_FALSE;
+ break;
+ }
+
+ /* Everything not under the default case is also checked for these */
+ if ((name == CIL_KEY_AND) || (name == CIL_KEY_OR) || (name == CIL_KEY_NOT) || (name == CIL_KEY_XOR)) {
+ return CIL_TRUE;
+ }
+
+ return CIL_FALSE;
+}
+
+int cil_verify_name(const char *name, enum cil_flavor flavor)
{
int rc = SEPOL_ERR;
int len;
@@ -77,6 +121,12 @@ int __cil_verify_name(const char *name)
goto exit;
}
}
+
+ if (__cil_is_reserved_name(name, flavor)) {
+ cil_log(CIL_ERR, "Name %s is a reserved word\n", name);
+ goto exit;
+ }
+
return SEPOL_OK;
exit:
diff --git a/libsepol/cil/src/cil_verify.h b/libsepol/cil/src/cil_verify.h
index 905761b0a19c..1887ae3f13a1 100644
--- a/libsepol/cil/src/cil_verify.h
+++ b/libsepol/cil/src/cil_verify.h
@@ -56,7 +56,7 @@ struct cil_args_verify {
int *pass;
};
-int __cil_verify_name(const char *name);
+int cil_verify_name(const char *name, enum cil_flavor flavor);
int __cil_verify_syntax(struct cil_tree_node *parse_current, enum cil_syntax s[], int len);
int cil_verify_expr_syntax(struct cil_tree_node *current, enum cil_flavor op, enum cil_flavor expr_flavor);
int cil_verify_constraint_leaf_expr_syntax(enum cil_flavor l_flavor, enum cil_flavor r_flavor, enum cil_flavor op, enum cil_flavor expr_flavor);
--
2.32.0

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 fd4758dc580e..05842b644807 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);
--
2.32.0

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 e57de662dbd9..14cdce1482a0 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",
--
2.32.0

View File

@ -1,141 +0,0 @@
From 0d4e568afe5a28edc5fcdcff8e925d4ec1d0d3d0 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Thu, 8 Apr 2021 13:32:19 -0400
Subject: [PATCH] libsepol/cil: Create function cil_add_decl_to_symtab() and
refactor
The functionality of adding a declaration to a symbol table is also
needed in __cil_copy_node_helper() and not just cil_gen_node().
Create a new function called cil_add_decl_to_symtab() to add a
declaration to a symtab and refactor cil_gen_node() and
__cil_copy_node_helper() to use the new function.
By using the new function, __cil_copy_node_helper() will now allow
duplicate declarations when appropriate.
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/cil/src/cil_build_ast.c | 63 +++++++++++++++++++-------------
libsepol/cil/src/cil_build_ast.h | 2 +
libsepol/cil/src/cil_copy_ast.c | 6 ++-
3 files changed, 45 insertions(+), 26 deletions(-)
diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c
index 14cdce1482a0..ec81db554b22 100644
--- a/libsepol/cil/src/cil_build_ast.c
+++ b/libsepol/cil/src/cil_build_ast.c
@@ -102,11 +102,45 @@ static int cil_allow_multiple_decls(struct cil_db *db, enum cil_flavor f_new, en
return CIL_FALSE;
}
+int cil_add_decl_to_symtab(struct cil_db *db, symtab_t *symtab, hashtab_key_t key, struct cil_symtab_datum *datum, struct cil_tree_node *node)
+{
+ int rc;
+
+ if (symtab == NULL || datum == NULL || node == NULL) {
+ return SEPOL_ERR;
+ }
+
+ rc = cil_symtab_insert(symtab, key, datum, node);
+ if (rc == SEPOL_EEXIST) {
+ struct cil_symtab_datum *prev;
+ rc = cil_symtab_get_datum(symtab, key, &prev);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Re-declaration of %s %s, but previous declaration could not be found\n",cil_node_to_string(node), key);
+ return SEPOL_ERR;
+ }
+ if (!cil_allow_multiple_decls(db, node->flavor, FLAVOR(prev))) {
+ /* multiple_decls not ok, ret error */
+ struct cil_tree_node *n = NODE(prev);
+ cil_log(CIL_ERR, "Re-declaration of %s %s\n",
+ cil_node_to_string(node), key);
+ cil_tree_log(node, CIL_ERR, "Previous declaration of %s",
+ cil_node_to_string(n));
+ return SEPOL_ERR;
+ }
+ /* multiple_decls is enabled and works for this datum type, add node */
+ cil_list_append(prev->nodes, CIL_NODE, node);
+ node->data = prev;
+ cil_symtab_datum_destroy(datum);
+ free(datum);
+ }
+
+ return SEPOL_OK;
+}
+
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)
{
int rc = SEPOL_ERR;
symtab_t *symtab = NULL;
- struct cil_symtab_datum *prev;
rc = cil_verify_name((const char*)key, nflavor);
if (rc != SEPOL_OK) {
@@ -121,30 +155,9 @@ int cil_gen_node(struct cil_db *db, struct cil_tree_node *ast_node, struct cil_s
ast_node->data = datum;
ast_node->flavor = nflavor;
- if (symtab != NULL) {
- rc = cil_symtab_insert(symtab, (hashtab_key_t)key, datum, ast_node);
- if (rc == SEPOL_EEXIST) {
- rc = cil_symtab_get_datum(symtab, (hashtab_key_t)key, &prev);
- if (rc != SEPOL_OK) {
- 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 (!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",
- cil_node_to_string(ast_node), key);
- cil_tree_log(node, CIL_ERR, "Previous declaration of %s",
- cil_node_to_string(node));
- rc = SEPOL_ERR;
- goto exit;
- }
- /* multiple_decls is enabled and works for this datum type, add node */
- cil_list_append(prev->nodes, CIL_NODE, ast_node);
- ast_node->data = prev;
- cil_symtab_datum_destroy(datum);
- free(datum);
- }
+ rc = cil_add_decl_to_symtab(db, symtab, key, datum, ast_node);
+ if (rc != SEPOL_OK) {
+ goto exit;
}
if (ast_node->parent->flavor == CIL_MACRO) {
diff --git a/libsepol/cil/src/cil_build_ast.h b/libsepol/cil/src/cil_build_ast.h
index 8153e51e3a97..fd9053ce55ca 100644
--- a/libsepol/cil/src/cil_build_ast.h
+++ b/libsepol/cil/src/cil_build_ast.h
@@ -37,6 +37,8 @@
#include "cil_tree.h"
#include "cil_list.h"
+int cil_add_decl_to_symtab(struct cil_db *db, symtab_t *symtab, hashtab_key_t key, struct cil_symtab_datum *datum, struct cil_tree_node *node);
+
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);
int cil_parse_to_list(struct cil_tree_node *parse_cl_head, struct cil_list *ast_cl, enum cil_flavor flavor);
diff --git a/libsepol/cil/src/cil_copy_ast.c b/libsepol/cil/src/cil_copy_ast.c
index ed96786115d3..12bc553c6594 100644
--- a/libsepol/cil/src/cil_copy_ast.c
+++ b/libsepol/cil/src/cil_copy_ast.c
@@ -2031,7 +2031,11 @@ int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) u
rc = SEPOL_ERR;
goto exit;
}
- rc = cil_symtab_insert(symtab, ((struct cil_symtab_datum*)orig->data)->name, ((struct cil_symtab_datum*)data), new);
+
+ rc = cil_add_decl_to_symtab(db, symtab, DATUM(orig->data)->name, DATUM(data), new);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
namespace = new;
while (namespace->flavor != CIL_MACRO && namespace->flavor != CIL_BLOCK && namespace->flavor != CIL_ROOT) {
--
2.32.0

View File

@ -1,140 +0,0 @@
From e65cf030b784dbb1ff4415e0b63a3bdf0158ccf6 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Thu, 8 Apr 2021 13:32:23 -0400
Subject: [PATCH] libsepol/cil: Move check for the shadowing of macro
parameters
In cil_gen_node(), after the declaration is added to the symbol
table, if the parent is a macro, then a check is made to ensure
the declaration does not shadow any of the macro's parameters.
This check also needs to be done when copying the AST.
Move the check for the shadowing of macro parameters to its own
function, cil_verify_decl_does_not_shadow_macro_parameter(), and
refactor cil_gen_node() and __cil_copy_node_helper() to use the
new function.
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/cil/src/cil_build_ast.c | 16 +++-------------
libsepol/cil/src/cil_copy_ast.c | 20 ++++----------------
libsepol/cil/src/cil_verify.c | 18 ++++++++++++++++++
libsepol/cil/src/cil_verify.h | 1 +
4 files changed, 26 insertions(+), 29 deletions(-)
diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c
index ec81db554b22..a4a2baa0f53b 100644
--- a/libsepol/cil/src/cil_build_ast.c
+++ b/libsepol/cil/src/cil_build_ast.c
@@ -161,19 +161,9 @@ int cil_gen_node(struct cil_db *db, struct cil_tree_node *ast_node, struct cil_s
}
if (ast_node->parent->flavor == CIL_MACRO) {
- struct cil_list_item *item;
- struct cil_list *param_list = ((struct cil_macro*)ast_node->parent->data)->params;
- if (param_list != NULL) {
- cil_list_for_each(item, param_list) {
- struct cil_param *param = item->data;
- if (param->flavor == ast_node->flavor) {
- if (param->str == key) {
- cil_log(CIL_ERR, "%s %s shadows a macro parameter in macro declaration\n", cil_node_to_string(ast_node), key);
- rc = SEPOL_ERR;
- goto exit;
- }
- }
- }
+ rc = cil_verify_decl_does_not_shadow_macro_parameter(ast_node->parent->data, ast_node, key);
+ if (rc != SEPOL_OK) {
+ goto exit;
}
}
diff --git a/libsepol/cil/src/cil_copy_ast.c b/libsepol/cil/src/cil_copy_ast.c
index 12bc553c6594..954eab330340 100644
--- a/libsepol/cil/src/cil_copy_ast.c
+++ b/libsepol/cil/src/cil_copy_ast.c
@@ -40,6 +40,7 @@
#include "cil_copy_ast.h"
#include "cil_build_ast.h"
#include "cil_strpool.h"
+#include "cil_verify.h"
struct cil_args_copy {
struct cil_tree_node *dest;
@@ -1716,7 +1717,6 @@ int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) u
struct cil_db *db = NULL;
struct cil_args_copy *args = NULL;
struct cil_tree_node *namespace = NULL;
- struct cil_param *param = NULL;
enum cil_sym_index sym_index = CIL_SYM_UNKNOWN;
symtab_t *symtab = NULL;
void *data = NULL;
@@ -2043,21 +2043,9 @@ int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) u
}
if (namespace->flavor == CIL_MACRO) {
- struct cil_macro *macro = namespace->data;
- struct cil_list *param_list = macro->params;
- if (param_list != NULL) {
- struct cil_list_item *item;
- cil_list_for_each(item, param_list) {
- param = item->data;
- if (param->flavor == new->flavor) {
- if (param->str == ((struct cil_symtab_datum*)new->data)->name) {
- cil_tree_log(orig, CIL_ERR, "%s %s shadows a macro parameter", cil_node_to_string(new), ((struct cil_symtab_datum*)orig->data)->name);
- cil_tree_log(namespace, CIL_ERR, "Note: macro declaration");
- rc = SEPOL_ERR;
- goto exit;
- }
- }
- }
+ rc = cil_verify_decl_does_not_shadow_macro_parameter(namespace->data, orig, DATUM(orig->data)->name);
+ if (rc != SEPOL_OK) {
+ goto exit;
}
}
}
diff --git a/libsepol/cil/src/cil_verify.c b/libsepol/cil/src/cil_verify.c
index 8fd54360698d..5a37dd2f76bc 100644
--- a/libsepol/cil/src/cil_verify.c
+++ b/libsepol/cil/src/cil_verify.c
@@ -412,6 +412,24 @@ int cil_verify_conditional_blocks(struct cil_tree_node *current)
return SEPOL_OK;
}
+int cil_verify_decl_does_not_shadow_macro_parameter(struct cil_macro *macro, struct cil_tree_node *node, const char *name)
+{
+ struct cil_list_item *item;
+ struct cil_list *param_list = macro->params;
+ if (param_list != NULL) {
+ cil_list_for_each(item, param_list) {
+ struct cil_param *param = item->data;
+ if (param->flavor == node->flavor) {
+ if (param->str == name) {
+ cil_log(CIL_ERR, "%s %s shadows a macro parameter in macro declaration\n", cil_node_to_string(node), name);
+ return SEPOL_ERR;
+ }
+ }
+ }
+ }
+ return SEPOL_OK;
+}
+
int cil_verify_no_self_reference(struct cil_symtab_datum *datum, struct cil_list *datum_list)
{
struct cil_list_item *i;
diff --git a/libsepol/cil/src/cil_verify.h b/libsepol/cil/src/cil_verify.h
index 1887ae3f13a1..c497018f8a95 100644
--- a/libsepol/cil/src/cil_verify.h
+++ b/libsepol/cil/src/cil_verify.h
@@ -62,6 +62,7 @@ int cil_verify_expr_syntax(struct cil_tree_node *current, enum cil_flavor op, en
int cil_verify_constraint_leaf_expr_syntax(enum cil_flavor l_flavor, enum cil_flavor r_flavor, enum cil_flavor op, enum cil_flavor expr_flavor);
int cil_verify_constraint_expr_syntax(struct cil_tree_node *current, enum cil_flavor op);
int cil_verify_conditional_blocks(struct cil_tree_node *current);
+int cil_verify_decl_does_not_shadow_macro_parameter(struct cil_macro *macro, struct cil_tree_node *node, const char *name);
int cil_verify_no_self_reference(struct cil_symtab_datum *datum, struct cil_list *datum_list);
int __cil_verify_ranges(struct cil_list *list);
int __cil_verify_ordered_node_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args);
--
2.32.0

View File

@ -1,219 +0,0 @@
From 69bfe64cdf659cc47c544e6b376f0a653ff06f6f Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Tue, 30 Mar 2021 13:39:12 -0400
Subject: [PATCH] libsepol/cil: Reorder checks for invalid rules when building
AST
Reorder checks for invalid rules in the blocks of tunableifs,
in-statements, macros, and booleanifs when building 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_build_ast.c | 100 +++++++++++++++----------------
1 file changed, 50 insertions(+), 50 deletions(-)
diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c
index a4a2baa0f53b..eee21086bba8 100644
--- a/libsepol/cil/src/cil_build_ast.c
+++ b/libsepol/cil/src/cil_build_ast.c
@@ -49,10 +49,10 @@
struct cil_args_build {
struct cil_tree_node *ast;
struct cil_db *db;
- struct cil_tree_node *macro;
- struct cil_tree_node *boolif;
struct cil_tree_node *tunif;
struct cil_tree_node *in;
+ struct cil_tree_node *macro;
+ struct cil_tree_node *boolif;
};
int cil_fill_list(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **list)
@@ -6069,10 +6069,10 @@ int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *f
struct cil_tree_node *ast_current = NULL;
struct cil_db *db = NULL;
struct cil_tree_node *ast_node = NULL;
- struct cil_tree_node *macro = NULL;
- struct cil_tree_node *boolif = NULL;
struct cil_tree_node *tunif = NULL;
struct cil_tree_node *in = NULL;
+ struct cil_tree_node *macro = NULL;
+ struct cil_tree_node *boolif = NULL;
int rc = SEPOL_ERR;
if (parse_current == NULL || finished == NULL || extra_args == NULL) {
@@ -6082,10 +6082,10 @@ int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *f
args = extra_args;
ast_current = args->ast;
db = args->db;
- macro = args->macro;
- boolif = args->boolif;
tunif = args->tunif;
in = args->in;
+ macro = args->macro;
+ boolif = args->boolif;
if (parse_current->parent->cl_head != parse_current) {
/* ignore anything that isn't following a parenthesis */
@@ -6102,13 +6102,31 @@ int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *f
goto exit;
}
+ if (tunif != NULL) {
+ if (parse_current->data == CIL_KEY_TUNABLE) {
+ rc = SEPOL_ERR;
+ cil_tree_log(parse_current, CIL_ERR, "Found tunable");
+ cil_log(CIL_ERR, "Tunables cannot be defined within tunableif statement\n");
+ goto exit;
+ }
+ }
+
+ if (in != NULL) {
+ if (parse_current->data == CIL_KEY_IN) {
+ rc = SEPOL_ERR;
+ cil_tree_log(parse_current, CIL_ERR, "Found in-statement");
+ cil_log(CIL_ERR, "in-statements cannot be defined within in-statements\n");
+ goto exit;
+ }
+ }
+
if (macro != NULL) {
- if (parse_current->data == CIL_KEY_MACRO ||
- parse_current->data == CIL_KEY_TUNABLE ||
+ if (parse_current->data == CIL_KEY_TUNABLE ||
parse_current->data == CIL_KEY_IN ||
parse_current->data == CIL_KEY_BLOCK ||
parse_current->data == CIL_KEY_BLOCKINHERIT ||
- parse_current->data == CIL_KEY_BLOCKABSTRACT) {
+ parse_current->data == CIL_KEY_BLOCKABSTRACT ||
+ parse_current->data == CIL_KEY_MACRO) {
rc = SEPOL_ERR;
cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in macros", (char *)parse_current->data);
goto exit;
@@ -6116,15 +6134,15 @@ int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *f
}
if (boolif != NULL) {
- if (parse_current->data != CIL_KEY_CONDTRUE &&
+ if (parse_current->data != CIL_KEY_TUNABLEIF &&
+ parse_current->data != CIL_KEY_CALL &&
+ parse_current->data != CIL_KEY_CONDTRUE &&
parse_current->data != CIL_KEY_CONDFALSE &&
- parse_current->data != CIL_KEY_AUDITALLOW &&
- parse_current->data != CIL_KEY_TUNABLEIF &&
parse_current->data != CIL_KEY_ALLOW &&
parse_current->data != CIL_KEY_DONTAUDIT &&
+ parse_current->data != CIL_KEY_AUDITALLOW &&
parse_current->data != CIL_KEY_TYPETRANSITION &&
- parse_current->data != CIL_KEY_TYPECHANGE &&
- parse_current->data != CIL_KEY_CALL) {
+ parse_current->data != CIL_KEY_TYPECHANGE) {
rc = SEPOL_ERR;
cil_tree_log(parse_current, CIL_ERR, "Found %s", (char*)parse_current->data);
if (((struct cil_booleanif*)boolif->data)->preserved_tunable) {
@@ -6138,24 +6156,6 @@ int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *f
}
}
- if (tunif != NULL) {
- if (parse_current->data == CIL_KEY_TUNABLE) {
- rc = SEPOL_ERR;
- cil_tree_log(parse_current, CIL_ERR, "Found tunable");
- cil_log(CIL_ERR, "Tunables cannot be defined within tunableif statement\n");
- goto exit;
- }
- }
-
- if (in != NULL) {
- if (parse_current->data == CIL_KEY_IN) {
- rc = SEPOL_ERR;
- cil_tree_log(parse_current, CIL_ERR, "Found in-statement");
- cil_log(CIL_ERR, "in-statements cannot be defined within in-statements\n");
- goto exit;
- }
- }
-
cil_tree_node_init(&ast_node);
ast_node->parent = ast_current;
@@ -6441,14 +6441,6 @@ int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *f
if (rc == SEPOL_OK) {
if (ast_current->cl_head == NULL) {
- if (ast_current->flavor == CIL_MACRO) {
- args->macro = ast_current;
- }
-
- if (ast_current->flavor == CIL_BOOLEANIF) {
- args->boolif = ast_current;
- }
-
if (ast_current->flavor == CIL_TUNABLEIF) {
args->tunif = ast_current;
}
@@ -6457,6 +6449,14 @@ int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *f
args->in = ast_current;
}
+ if (ast_current->flavor == CIL_MACRO) {
+ args->macro = ast_current;
+ }
+
+ if (ast_current->flavor == CIL_BOOLEANIF) {
+ args->boolif = ast_current;
+ }
+
ast_current->cl_head = ast_node;
} else {
ast_current->cl_tail->next = ast_node;
@@ -6492,14 +6492,6 @@ int __cil_build_ast_last_child_helper(struct cil_tree_node *parse_current, void
args->ast = ast->parent;
- if (ast->flavor == CIL_MACRO) {
- args->macro = NULL;
- }
-
- if (ast->flavor == CIL_BOOLEANIF) {
- args->boolif = NULL;
- }
-
if (ast->flavor == CIL_TUNABLEIF) {
args->tunif = NULL;
}
@@ -6508,6 +6500,14 @@ int __cil_build_ast_last_child_helper(struct cil_tree_node *parse_current, void
args->in = NULL;
}
+ if (ast->flavor == CIL_MACRO) {
+ args->macro = NULL;
+ }
+
+ if (ast->flavor == CIL_BOOLEANIF) {
+ args->boolif = NULL;
+ }
+
// At this point we no longer have any need for parse_current or any of its
// siblings; they have all been converted to the appropriate AST node. The
// full parse tree will get deleted elsewhere, but in an attempt to
@@ -6532,10 +6532,10 @@ int cil_build_ast(struct cil_db *db, struct cil_tree_node *parse_tree, struct ci
extra_args.ast = ast;
extra_args.db = db;
- extra_args.macro = NULL;
- extra_args.boolif = NULL;
extra_args.tunif = NULL;
extra_args.in = NULL;
+ extra_args.macro = NULL;
+ extra_args.boolif = NULL;
rc = cil_tree_walk(parse_tree, __cil_build_ast_node_helper, NULL, __cil_build_ast_last_child_helper, &extra_args);
if (rc != SEPOL_OK) {
--
2.32.0

View File

@ -1,91 +0,0 @@
From f043078f1debeb1c84d4f6943aa689c33dd9cefc Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Tue, 30 Mar 2021 13:39:13 -0400
Subject: [PATCH] libsepol/cil: Cleanup build AST helper functions
Since parse_current, finished, and extra_args can never be NULL,
remove the useless check and directly assign local variables from
extra_args.
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/cil/src/cil_build_ast.c | 44 ++++++++------------------------
1 file changed, 10 insertions(+), 34 deletions(-)
diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c
index eee21086bba8..0d6d91a7dc34 100644
--- a/libsepol/cil/src/cil_build_ast.c
+++ b/libsepol/cil/src/cil_build_ast.c
@@ -6065,28 +6065,16 @@ void cil_destroy_src_info(struct cil_src_info *info)
int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *finished, void *extra_args)
{
- struct cil_args_build *args = NULL;
- struct cil_tree_node *ast_current = NULL;
- struct cil_db *db = NULL;
+ struct cil_args_build *args = extra_args;
+ struct cil_db *db = args->db;
+ struct cil_tree_node *ast_current = args->ast;
+ struct cil_tree_node *tunif = args->tunif;
+ struct cil_tree_node *in = args->in;
+ struct cil_tree_node *macro = args->macro;
+ struct cil_tree_node *boolif = args->boolif;
struct cil_tree_node *ast_node = NULL;
- struct cil_tree_node *tunif = NULL;
- struct cil_tree_node *in = NULL;
- struct cil_tree_node *macro = NULL;
- struct cil_tree_node *boolif = NULL;
int rc = SEPOL_ERR;
- if (parse_current == NULL || finished == NULL || extra_args == NULL) {
- goto exit;
- }
-
- args = extra_args;
- ast_current = args->ast;
- db = args->db;
- tunif = args->tunif;
- in = args->in;
- macro = args->macro;
- boolif = args->boolif;
-
if (parse_current->parent->cl_head != parse_current) {
/* ignore anything that isn't following a parenthesis */
rc = SEPOL_OK;
@@ -6474,20 +6462,11 @@ exit:
int __cil_build_ast_last_child_helper(struct cil_tree_node *parse_current, void *extra_args)
{
- int rc = SEPOL_ERR;
- struct cil_tree_node *ast = NULL;
- struct cil_args_build *args = NULL;
-
- if (extra_args == NULL) {
- goto exit;
- }
-
- args = extra_args;
- ast = args->ast;
+ struct cil_args_build *args = extra_args;
+ struct cil_tree_node *ast = args->ast;
if (ast->flavor == CIL_ROOT) {
- rc = SEPOL_OK;
- goto exit;
+ return SEPOL_OK;
}
args->ast = ast->parent;
@@ -6516,9 +6495,6 @@ int __cil_build_ast_last_child_helper(struct cil_tree_node *parse_current, void
cil_tree_children_destroy(parse_current->parent);
return SEPOL_OK;
-
-exit:
- return rc;
}
int cil_build_ast(struct cil_db *db, struct cil_tree_node *parse_tree, struct cil_tree_node *ast)
--
2.32.0

View File

@ -1,98 +0,0 @@
From ab90cb46abd4cfc5927f48c7b61782aa97e2561f Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Tue, 30 Mar 2021 13:39:14 -0400
Subject: [PATCH] libsepol/cil: Create new first child helper function for
building AST
In order to find statements not allowed in tunableifs, in-statements,
macros, and booleanifs, there are tree node pointers that point to
each of these kinds of statements when its block is being parsed.
If the pointer is non-NULL, then the rule being parsed is in the block
of that kind of statement.
The tree node pointers were being updated at the wrong point which
prevented an invalid statement from being found if it was the first
statement in the block of a tunableif, in-statement, macro, or
booleanif.
Create a first child helper function for walking the parse tree and
in that function set the appropriate tree node pointer if the
current AST node is a tunableif, in-statement, macro, or booleanif.
This also makes the code symmetrical with the last child helper
where the tree node pointers are set to NULL.
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/cil/src/cil_build_ast.c | 42 +++++++++++++++++++-------------
1 file changed, 25 insertions(+), 17 deletions(-)
diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c
index 0d6d91a7dc34..9836f044553c 100644
--- a/libsepol/cil/src/cil_build_ast.c
+++ b/libsepol/cil/src/cil_build_ast.c
@@ -6429,22 +6429,6 @@ int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *f
if (rc == SEPOL_OK) {
if (ast_current->cl_head == NULL) {
- if (ast_current->flavor == CIL_TUNABLEIF) {
- args->tunif = ast_current;
- }
-
- if (ast_current->flavor == CIL_IN) {
- args->in = ast_current;
- }
-
- if (ast_current->flavor == CIL_MACRO) {
- args->macro = ast_current;
- }
-
- if (ast_current->flavor == CIL_BOOLEANIF) {
- args->boolif = ast_current;
- }
-
ast_current->cl_head = ast_node;
} else {
ast_current->cl_tail->next = ast_node;
@@ -6460,6 +6444,30 @@ exit:
return rc;
}
+int __cil_build_ast_first_child_helper(__attribute__((unused)) struct cil_tree_node *parse_current, void *extra_args)
+{
+ struct cil_args_build *args = extra_args;
+ struct cil_tree_node *ast = args->ast;
+
+ if (ast->flavor == CIL_TUNABLEIF) {
+ args->tunif = ast;
+ }
+
+ if (ast->flavor == CIL_IN) {
+ args->in = ast;
+ }
+
+ if (ast->flavor == CIL_MACRO) {
+ args->macro = ast;
+ }
+
+ if (ast->flavor == CIL_BOOLEANIF) {
+ args->boolif = ast;
+ }
+
+ return SEPOL_OK;
+}
+
int __cil_build_ast_last_child_helper(struct cil_tree_node *parse_current, void *extra_args)
{
struct cil_args_build *args = extra_args;
@@ -6513,7 +6521,7 @@ int cil_build_ast(struct cil_db *db, struct cil_tree_node *parse_tree, struct ci
extra_args.macro = NULL;
extra_args.boolif = NULL;
- rc = cil_tree_walk(parse_tree, __cil_build_ast_node_helper, NULL, __cil_build_ast_last_child_helper, &extra_args);
+ rc = cil_tree_walk(parse_tree, __cil_build_ast_node_helper, __cil_build_ast_first_child_helper, __cil_build_ast_last_child_helper, &extra_args);
if (rc != SEPOL_OK) {
goto exit;
}
--
2.32.0

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 63beed9230b9..a61462d0eb31 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);
--
2.32.0

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 a61462d0eb31..93fc0d633cc7 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;
--
2.32.0

View File

@ -1,86 +0,0 @@
From 8a74c05b97050bd226d61fc162e04dcdf8e91247 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Tue, 30 Mar 2021 13:39:17 -0400
Subject: [PATCH] libsepol/cil: Sync checks for invalid rules in booleanifs
When building the AST, typemember rules in a booleanif block will
be incorrectly called invalid. They are allowed in the kernel
policy and should be allowed in CIL.
When resolving the AST, if a neverallow rule is copied into a
booleanif block, it will not be considered an invalid rule, even
though this is not allowed in the kernel policy.
Update the booleanif checks to allow typemember rules and to not
allow neverallow rules in booleanifs. Also use the same form of
conditional for the checks when building and resolving the AST.
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/cil/src/cil_build_ast.c | 3 ++-
libsepol/cil/src/cil_resolve_ast.c | 23 +++++++++++++++--------
2 files changed, 17 insertions(+), 9 deletions(-)
diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c
index 9836f044553c..96c944975def 100644
--- a/libsepol/cil/src/cil_build_ast.c
+++ b/libsepol/cil/src/cil_build_ast.c
@@ -6130,7 +6130,8 @@ int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *f
parse_current->data != CIL_KEY_DONTAUDIT &&
parse_current->data != CIL_KEY_AUDITALLOW &&
parse_current->data != CIL_KEY_TYPETRANSITION &&
- parse_current->data != CIL_KEY_TYPECHANGE) {
+ parse_current->data != CIL_KEY_TYPECHANGE &&
+ parse_current->data != CIL_KEY_TYPEMEMBER) {
rc = SEPOL_ERR;
cil_tree_log(parse_current, CIL_ERR, "Found %s", (char*)parse_current->data);
if (((struct cil_booleanif*)boolif->data)->preserved_tunable) {
diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
index 93fc0d633cc7..56295a047ba2 100644
--- a/libsepol/cil/src/cil_resolve_ast.c
+++ b/libsepol/cil/src/cil_resolve_ast.c
@@ -3774,7 +3774,7 @@ exit:
int __cil_resolve_ast_node_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
{
- int rc = SEPOL_ERR;
+ int rc = SEPOL_OK;
struct cil_args_resolve *args = extra_args;
enum cil_pass pass = args->pass;
struct cil_tree_node *block = args->block;
@@ -3817,18 +3817,25 @@ int __cil_resolve_ast_node_helper(struct cil_tree_node *node, uint32_t *finished
}
if (boolif != NULL) {
- 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 (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) {
+ rc = SEPOL_ERR;
+ } else if (node->flavor == CIL_AVRULE) {
+ struct cil_avrule *rule = node->data;
+ if (rule->rule_kind == CIL_AVRULE_NEVERALLOW) {
+ rc = SEPOL_ERR;
+ }
+ }
+ if (rc == SEPOL_ERR) {
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 {
cil_tree_log(node, CIL_ERR, "%s statement is not allowed in booleanifs", cil_node_to_string(node));
}
- rc = SEPOL_ERR;
goto exit;
}
}
--
2.32.0

View File

@ -1,151 +0,0 @@
From 340f0eb7f3673e8aacaf0a96cbfcd4d12a405521 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Tue, 30 Mar 2021 13:39:18 -0400
Subject: [PATCH] libsepol/cil: Check for statements not allowed in optional
blocks
While there are some checks for invalid statements in an optional
block when resolving the AST, there are no checks when building the
AST.
OSS-Fuzz found the following policy which caused a null dereference
in cil_tree_get_next_path().
(blockinherit b3)
(sid SID)
(sidorder(SID))
(optional o
(ibpkeycon :(1 0)s)
(block b3
(filecon""block())
(filecon""block())))
The problem is that the blockinherit copies block b3 before
the optional block is disabled. When the optional is disabled,
block b3 is deleted along with everything else in the optional.
Later, when filecon statements with the same path are found an
error message is produced and in trying to find out where the block
was copied from, the reference to the deleted block is used. The
error handling code assumes (rightly) that if something was copied
from a block then that block should still exist.
It is clear that in-statements, blocks, and macros cannot be in an
optional, because that allows nodes to be copied from the optional
block to somewhere outside even though the optional could be disabled
later. When optionals are disabled the AST is reset and the
resolution is restarted at the point of resolving macro calls, so
anything resolved before macro calls will never be re-resolved.
This includes tunableifs, in-statements, blockinherits,
blockabstracts, and macro definitions. Tunable declarations also
cannot be in an optional block because they are needed to resolve
tunableifs. It should be fine to allow blockinherit statements in
an optional, because that is copying nodes from outside the optional
to the optional and if the optional is later disabled, everything
will be deleted anyway.
Check and quit with an error if a tunable declaration, in-statement,
block, blockabstract, or macro definition is found within an
optional when either building or resolving the AST.
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/cil/src/cil_build_ast.c | 32 ++++++++++++++++++++++++++++++
libsepol/cil/src/cil_resolve_ast.c | 4 +++-
2 files changed, 35 insertions(+), 1 deletion(-)
diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c
index 96c944975def..8825485855f6 100644
--- a/libsepol/cil/src/cil_build_ast.c
+++ b/libsepol/cil/src/cil_build_ast.c
@@ -52,6 +52,7 @@ struct cil_args_build {
struct cil_tree_node *tunif;
struct cil_tree_node *in;
struct cil_tree_node *macro;
+ struct cil_tree_node *optional;
struct cil_tree_node *boolif;
};
@@ -6071,6 +6072,7 @@ int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *f
struct cil_tree_node *tunif = args->tunif;
struct cil_tree_node *in = args->in;
struct cil_tree_node *macro = args->macro;
+ struct cil_tree_node *optional = args->optional;
struct cil_tree_node *boolif = args->boolif;
struct cil_tree_node *ast_node = NULL;
int rc = SEPOL_ERR;
@@ -6121,6 +6123,18 @@ int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *f
}
}
+ if (optional != NULL) {
+ if (parse_current->data == CIL_KEY_TUNABLE ||
+ parse_current->data == CIL_KEY_IN ||
+ parse_current->data == CIL_KEY_BLOCK ||
+ parse_current->data == CIL_KEY_BLOCKABSTRACT ||
+ parse_current->data == CIL_KEY_MACRO) {
+ rc = SEPOL_ERR;
+ cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in optionals", (char *)parse_current->data);
+ goto exit;
+ }
+ }
+
if (boolif != NULL) {
if (parse_current->data != CIL_KEY_TUNABLEIF &&
parse_current->data != CIL_KEY_CALL &&
@@ -6462,6 +6476,10 @@ int __cil_build_ast_first_child_helper(__attribute__((unused)) struct cil_tree_n
args->macro = ast;
}
+ if (ast->flavor == CIL_OPTIONAL) {
+ args->optional = ast;
+ }
+
if (ast->flavor == CIL_BOOLEANIF) {
args->boolif = ast;
}
@@ -6492,6 +6510,19 @@ int __cil_build_ast_last_child_helper(struct cil_tree_node *parse_current, void
args->macro = NULL;
}
+ if (ast->flavor == CIL_OPTIONAL) {
+ struct cil_tree_node *n = ast->parent;
+ args->optional = NULL;
+ /* Optionals can be nested */
+ while (n && n->flavor != CIL_ROOT) {
+ if (n->flavor == CIL_OPTIONAL) {
+ args->optional = n;
+ break;
+ }
+ n = n->parent;
+ }
+ }
+
if (ast->flavor == CIL_BOOLEANIF) {
args->boolif = NULL;
}
@@ -6520,6 +6551,7 @@ int cil_build_ast(struct cil_db *db, struct cil_tree_node *parse_tree, struct ci
extra_args.tunif = NULL;
extra_args.in = NULL;
extra_args.macro = NULL;
+ extra_args.optional = NULL;
extra_args.boolif = NULL;
rc = cil_tree_walk(parse_tree, __cil_build_ast_node_helper, __cil_build_ast_first_child_helper, __cil_build_ast_last_child_helper, &extra_args);
diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
index 56295a047ba2..efff0f2ec49d 100644
--- a/libsepol/cil/src/cil_resolve_ast.c
+++ b/libsepol/cil/src/cil_resolve_ast.c
@@ -3808,8 +3808,10 @@ int __cil_resolve_ast_node_helper(struct cil_tree_node *node, uint32_t *finished
if (optional != NULL) {
if (node->flavor == CIL_TUNABLE ||
+ node->flavor == CIL_IN ||
+ node->flavor == CIL_BLOCK ||
+ node->flavor == CIL_BLOCKABSTRACT ||
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;
--
2.32.0

View File

@ -1,35 +0,0 @@
From f38b7ea300e83d4b14d817c35f4ff24071e4990e Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Tue, 30 Mar 2021 13:39:19 -0400
Subject: [PATCH] libsepol/cil: Sync checks for invalid rules in macros
When resolving the AST, tunable and in-statements are not considered
to be invalid in macros. This is inconsistent with the checks when
building the AST.
Add checks to make tunable and in-statments invalid in macros when
resolving the AST.
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/cil/src/cil_resolve_ast.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
index efff0f2ec49d..7229a3b4e990 100644
--- a/libsepol/cil/src/cil_resolve_ast.c
+++ b/libsepol/cil/src/cil_resolve_ast.c
@@ -3796,7 +3796,9 @@ int __cil_resolve_ast_node_helper(struct cil_tree_node *node, uint32_t *finished
}
if (macro != NULL) {
- if (node->flavor == CIL_BLOCK ||
+ if (node->flavor == CIL_TUNABLE ||
+ node->flavor == CIL_IN ||
+ node->flavor == CIL_BLOCK ||
node->flavor == CIL_BLOCKINHERIT ||
node->flavor == CIL_BLOCKABSTRACT ||
node->flavor == CIL_MACRO) {
--
2.32.0

View File

@ -1,35 +0,0 @@
From ea34dbf041f0c75f2b0261ddf6fa014121d69a1a Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Tue, 30 Mar 2021 13:39:20 -0400
Subject: [PATCH] libsepol/cil: Do not allow tunable declarations in
in-statements
Since tunableifs are resolved before in-statements, do not allow
tuanble declarations in in-statements.
Since in-statements are the first flavor of statement that causes
part of the AST to be copied to another part, there is no need to
check the in-statements when resolving the AST.
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/cil/src/cil_build_ast.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c
index 8825485855f6..3f83c228fec1 100644
--- a/libsepol/cil/src/cil_build_ast.c
+++ b/libsepol/cil/src/cil_build_ast.c
@@ -6102,7 +6102,8 @@ int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *f
}
if (in != NULL) {
- if (parse_current->data == CIL_KEY_IN) {
+ if (parse_current->data == CIL_KEY_TUNABLE ||
+ parse_current->data == CIL_KEY_IN) {
rc = SEPOL_ERR;
cil_tree_log(parse_current, CIL_ERR, "Found in-statement");
cil_log(CIL_ERR, "in-statements cannot be defined within in-statements\n");
--
2.32.0

View File

@ -1,120 +0,0 @@
From ca339eb49da6fe5b191de5c3ee7196453fa14e23 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Tue, 30 Mar 2021 13:40:01 -0400
Subject: [PATCH] libsepol/cil: Make invalid statement error messages
consistent
Use a consistent style for the error messages when an invalid
statement is found within tunableif, in-statement, block, macro,
optional, and booleanif blocks.
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/cil/src/cil_build_ast.c | 17 ++++++-----------
libsepol/cil/src/cil_resolve_ast.c | 10 +++++-----
2 files changed, 11 insertions(+), 16 deletions(-)
diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c
index 3f83c228fec1..5b1e28246b2e 100644
--- a/libsepol/cil/src/cil_build_ast.c
+++ b/libsepol/cil/src/cil_build_ast.c
@@ -6095,8 +6095,7 @@ int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *f
if (tunif != NULL) {
if (parse_current->data == CIL_KEY_TUNABLE) {
rc = SEPOL_ERR;
- cil_tree_log(parse_current, CIL_ERR, "Found tunable");
- cil_log(CIL_ERR, "Tunables cannot be defined within tunableif statement\n");
+ cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in tunableif", (char *)parse_current->data);
goto exit;
}
}
@@ -6105,8 +6104,7 @@ int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *f
if (parse_current->data == CIL_KEY_TUNABLE ||
parse_current->data == CIL_KEY_IN) {
rc = SEPOL_ERR;
- cil_tree_log(parse_current, CIL_ERR, "Found in-statement");
- cil_log(CIL_ERR, "in-statements cannot be defined within in-statements\n");
+ cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in in-statement", (char *)parse_current->data);
goto exit;
}
}
@@ -6119,7 +6117,7 @@ int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *f
parse_current->data == CIL_KEY_BLOCKABSTRACT ||
parse_current->data == CIL_KEY_MACRO) {
rc = SEPOL_ERR;
- cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in macros", (char *)parse_current->data);
+ cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in macro", (char *)parse_current->data);
goto exit;
}
}
@@ -6131,7 +6129,7 @@ int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *f
parse_current->data == CIL_KEY_BLOCKABSTRACT ||
parse_current->data == CIL_KEY_MACRO) {
rc = SEPOL_ERR;
- cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in optionals", (char *)parse_current->data);
+ cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in optional", (char *)parse_current->data);
goto exit;
}
}
@@ -6148,13 +6146,10 @@ int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *f
parse_current->data != CIL_KEY_TYPECHANGE &&
parse_current->data != CIL_KEY_TYPEMEMBER) {
rc = SEPOL_ERR;
- cil_tree_log(parse_current, CIL_ERR, "Found %s", (char*)parse_current->data);
if (((struct cil_booleanif*)boolif->data)->preserved_tunable) {
- cil_log(CIL_ERR, "%s cannot be defined within tunableif statement (treated as a booleanif due to preserve-tunables)\n",
- (char*)parse_current->data);
+ cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in tunableif being treated as a booleanif", (char *)parse_current->data);
} else {
- cil_log(CIL_ERR, "%s cannot be defined within booleanif statement\n",
- (char*)parse_current->data);
+ cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in booleanif", (char *)parse_current->data);
}
goto exit;
}
diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
index 7229a3b4e990..872b6799b0bf 100644
--- a/libsepol/cil/src/cil_resolve_ast.c
+++ b/libsepol/cil/src/cil_resolve_ast.c
@@ -3789,7 +3789,7 @@ int __cil_resolve_ast_node_helper(struct cil_tree_node *node, uint32_t *finished
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));
+ cil_tree_log(node, CIL_ERR, "%s is not allowed in block", cil_node_to_string(node));
rc = SEPOL_ERR;
goto exit;
}
@@ -3802,7 +3802,7 @@ int __cil_resolve_ast_node_helper(struct cil_tree_node *node, uint32_t *finished
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));
+ cil_tree_log(node, CIL_ERR, "%s is not allowed in macro", cil_node_to_string(node));
rc = SEPOL_ERR;
goto exit;
}
@@ -3814,7 +3814,7 @@ int __cil_resolve_ast_node_helper(struct cil_tree_node *node, uint32_t *finished
node->flavor == CIL_BLOCK ||
node->flavor == CIL_BLOCKABSTRACT ||
node->flavor == CIL_MACRO) {
- cil_tree_log(node, CIL_ERR, "%s statement is not allowed in optionals", cil_node_to_string(node));
+ cil_tree_log(node, CIL_ERR, "%s is not allowed in optional", cil_node_to_string(node));
rc = SEPOL_ERR;
goto exit;
}
@@ -3836,9 +3836,9 @@ int __cil_resolve_ast_node_helper(struct cil_tree_node *node, uint32_t *finished
}
if (rc == SEPOL_ERR) {
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));
+ cil_tree_log(node, CIL_ERR, "%s is not allowed in tunableif being treated as a booleanif", cil_node_to_string(node));
} else {
- cil_tree_log(node, CIL_ERR, "%s statement is not allowed in booleanifs", cil_node_to_string(node));
+ cil_tree_log(node, CIL_ERR, "%s is not allowed in booleanif", cil_node_to_string(node));
}
goto exit;
}
--
2.32.0

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 99c8e288912c..b971922c70b5 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;
}
--
2.32.0

File diff suppressed because it is too large Load Diff

View File

@ -1,158 +0,0 @@
From 86ec04cfded8b2a76953ca2682d2a32bf6b24721 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Wed, 21 Apr 2021 13:21:11 -0400
Subject: [PATCH] libsepol/cil: Add functions to make use of cil_write_ast()
Add the functions cil_write_parse_ast(), cil_write_build_ast(),
and cil_write_resolve_ast() that can be used outside of libsepol.
These functions take a FILE pointer and CIL db, do the CIL build
through the desired phase, and then call cil_write_ast() to write
the CIL AST at that point.
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/cil/include/cil/cil.h | 3 ++
libsepol/cil/src/cil.c | 92 ++++++++++++++++++++++++++++++++++
libsepol/src/libsepol.map.in | 3 ++
3 files changed, 98 insertions(+)
diff --git a/libsepol/cil/include/cil/cil.h b/libsepol/cil/include/cil/cil.h
index e6f4503eb33a..92fac6e1619a 100644
--- a/libsepol/cil/include/cil/cil.h
+++ b/libsepol/cil/include/cil/cil.h
@@ -60,6 +60,9 @@ extern void cil_set_attrs_expand_size(struct cil_db *db, unsigned attrs_expand_s
extern void cil_set_target_platform(cil_db_t *db, int target_platform);
extern void cil_set_policy_version(cil_db_t *db, int policy_version);
extern void cil_write_policy_conf(FILE *out, struct cil_db *db);
+extern int cil_write_parse_ast(FILE *out, cil_db_t *db);
+extern int cil_write_build_ast(FILE *out, cil_db_t *db);
+extern int cil_write_resolve_ast(FILE *out, cil_db_t *db);
enum cil_log_level {
CIL_ERR = 1,
diff --git a/libsepol/cil/src/cil.c b/libsepol/cil/src/cil.c
index b971922c70b5..0d351b491c2c 100644
--- a/libsepol/cil/src/cil.c
+++ b/libsepol/cil/src/cil.c
@@ -50,6 +50,7 @@
#include "cil_binary.h"
#include "cil_policy.h"
#include "cil_strpool.h"
+#include "cil_write_ast.h"
int cil_sym_sizes[CIL_SYM_ARRAY_NUM][CIL_SYM_NUM] = {
{64, 64, 64, 1 << 13, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64},
@@ -572,6 +573,97 @@ exit:
return rc;
}
+int cil_write_parse_ast(FILE *out, cil_db_t *db)
+{
+ int rc = SEPOL_ERR;
+
+ if (db == NULL) {
+ goto exit;
+ }
+
+ cil_log(CIL_INFO, "Writing Parse AST\n");
+ rc = cil_write_ast(out, CIL_WRITE_AST_PHASE_PARSE, db->parse->root);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to write parse ast\n");
+ goto exit;
+ }
+
+exit:
+ return rc;
+}
+
+int cil_write_build_ast(FILE *out, cil_db_t *db)
+{
+ int rc = SEPOL_ERR;
+
+ if (db == NULL) {
+ goto exit;
+ }
+
+ 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_ERR, "Failed to build ast\n");
+ goto exit;
+ }
+
+ cil_log(CIL_INFO, "Destroying Parse Tree\n");
+ cil_tree_destroy(&db->parse);
+
+ cil_log(CIL_INFO, "Writing Build AST\n");
+ rc = cil_write_ast(out, CIL_WRITE_AST_PHASE_BUILD, db->ast->root);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to write build ast\n");
+ goto exit;
+ }
+
+exit:
+ return rc;
+}
+
+int cil_write_resolve_ast(FILE *out, cil_db_t *db)
+{
+ int rc = SEPOL_ERR;
+
+ if (db == NULL) {
+ goto exit;
+ }
+
+ 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_ERR, "Failed to build ast\n");
+ goto exit;
+ }
+
+ cil_log(CIL_INFO, "Destroying Parse Tree\n");
+ cil_tree_destroy(&db->parse);
+
+ cil_log(CIL_INFO, "Resolving AST\n");
+ rc = cil_resolve_ast(db, db->ast->root);
+ if (rc != SEPOL_OK) {
+ 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_ERR, "Failed to qualify names\n");
+ goto exit;
+ }
+
+ cil_log(CIL_INFO, "Writing Resolve AST\n");
+ rc = cil_write_ast(out, CIL_WRITE_AST_PHASE_RESOLVE, db->ast->root);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to write resolve ast\n");
+ goto exit;
+ }
+
+exit:
+ return rc;
+}
+
int cil_build_policydb(cil_db_t *db, sepol_policydb_t **sepol_db)
{
int rc;
diff --git a/libsepol/src/libsepol.map.in b/libsepol/src/libsepol.map.in
index eb5721257638..2e503bd1b453 100644
--- a/libsepol/src/libsepol.map.in
+++ b/libsepol/src/libsepol.map.in
@@ -269,4 +269,7 @@ LIBSEPOL_1.1 {
LIBSEPOL_3.0 {
global:
sepol_policydb_optimize;
+ cil_write_parse_ast;
+ cil_write_build_ast;
+ cil_write_resolve_ast;
} LIBSEPOL_1.1;
--
2.32.0

View File

@ -1,103 +0,0 @@
From 0744fa4f533c765d0a704fe8aa7174a0f93eb7bc Mon Sep 17 00:00:00 2001
From: Nicolas Iooss <nicolas.iooss@m4x.org>
Date: Thu, 22 Apr 2021 08:46:04 +0200
Subject: [PATCH] libsepol: use checked arithmetic builtin to perform safe
addition
Checking whether an overflow occurred after adding two values can be
achieved using checked arithmetic builtin functions such as:
bool __builtin_add_overflow(type1 x, type2 y, type3 *sum);
This function is available at least in clang
(at least since clang 3.8.0,
https://releases.llvm.org/3.8.0/tools/clang/docs/LanguageExtensions.html#checked-arithmetic-builtins)
and gcc
(https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html,
since gcc 5 according to https://gcc.gnu.org/gcc-5/changes.html)
Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
---
libsepol/src/context_record.c | 29 ++++++-----------------------
libsepol/src/module_to_cil.c | 6 ++----
2 files changed, 8 insertions(+), 27 deletions(-)
diff --git a/libsepol/src/context_record.c b/libsepol/src/context_record.c
index 317a42133884..435f788058c4 100644
--- a/libsepol/src/context_record.c
+++ b/libsepol/src/context_record.c
@@ -267,31 +267,13 @@ int sepol_context_from_string(sepol_handle_t * handle,
return STATUS_ERR;
}
-
-static inline int safe_sum(size_t *sum, const size_t augends[], const size_t cnt) {
-
- size_t a, i;
-
- *sum = 0;
- for(i=0; i < cnt; i++) {
- /* sum should not be smaller than the addend */
- a = augends[i];
- *sum += a;
- if (*sum < a) {
- return i;
- }
- }
-
- return 0;
-}
-
int sepol_context_to_string(sepol_handle_t * handle,
const sepol_context_t * con, char **str_ptr)
{
int rc;
char *str = NULL;
- size_t total_sz, err;
+ size_t total_sz = 0, i;
const size_t sizes[] = {
strlen(con->user), /* user length */
strlen(con->role), /* role length */
@@ -300,10 +282,11 @@ int sepol_context_to_string(sepol_handle_t * handle,
((con->mls) ? 3 : 2) + 1 /* mls has extra ":" also null byte */
};
- err = safe_sum(&total_sz, sizes, ARRAY_SIZE(sizes));
- if (err) {
- ERR(handle, "invalid size, overflow at position: %zu", err);
- goto err;
+ for (i = 0; i < ARRAY_SIZE(sizes); i++) {
+ if (__builtin_add_overflow(total_sz, sizes[i], &total_sz)) {
+ ERR(handle, "invalid size, overflow at position: %zu", i);
+ goto err;
+ }
}
str = (char *)malloc(total_sz);
diff --git a/libsepol/src/module_to_cil.c b/libsepol/src/module_to_cil.c
index 58df0d4f6d77..496693f4616e 100644
--- a/libsepol/src/module_to_cil.c
+++ b/libsepol/src/module_to_cil.c
@@ -1134,16 +1134,14 @@ static int name_list_to_string(char **names, unsigned int num_names, char **stri
char *strpos;
for (i = 0; i < num_names; i++) {
- len += strlen(names[i]);
- if (len < strlen(names[i])) {
+ if (__builtin_add_overflow(len, strlen(names[i]), &len)) {
log_err("Overflow");
return -1;
}
}
// add spaces + null terminator
- len += num_names;
- if (len < (size_t)num_names) {
+ if (__builtin_add_overflow(len, (size_t)num_names, &len)) {
log_err("Overflow");
return -1;
}
--
2.32.0

View File

@ -1,51 +0,0 @@
From 2d2c76fc613ba338476a3a1741c2a3af5e04d154 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Mon, 26 Apr 2021 15:22:05 -0400
Subject: [PATCH] libsepol/cil: Properly reset an anonymous classperm set
In struct cil_classperms_set, the "set" field is a pointer to a
struct cil_classpermission. Normally the classpermission is created
in a classpermissionset rule with a name declared in a
classpermission rule and stored in a symbol table. Commit c49a8ea0
("libsepol/cil: cil_reset_classperms_set() should not reset
classpermission") fixed the resetting of classperms sets by setting
the "set" field to NULL rather than resetting the classpermission
that it pointed to.
But this fix mixed the special case where an anonymous classperm
set is passed as an argument to a call. In this case the
classpermission is not named and not stored in a symtab, it is
created just for the classperms set and its classperms list needs
to be reset.
Reset the classperms list if the classperms set is anonymous (which
is when the datum name is NULL).
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/cil/src/cil_reset_ast.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/libsepol/cil/src/cil_reset_ast.c b/libsepol/cil/src/cil_reset_ast.c
index 76405aba6194..d24d4f8159a3 100644
--- a/libsepol/cil/src/cil_reset_ast.c
+++ b/libsepol/cil/src/cil_reset_ast.c
@@ -60,10 +60,14 @@ static void cil_reset_classpermission(struct cil_classpermission *cp)
static void cil_reset_classperms_set(struct cil_classperms_set *cp_set)
{
- if (cp_set == NULL) {
+ if (cp_set == NULL || cp_set->set == NULL) {
return;
}
+ if (cp_set->set->datum.name == NULL) {
+ cil_reset_classperms_list(cp_set->set->classperms);
+ }
+
cp_set->set = NULL;
}
--
2.32.0

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 5b1e28246b2e..87043a8fa183 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 872b6799b0bf..5389df43fed7 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;
}
--
2.32.0

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 9bdcbdd013c0..74e0b34d6cbd 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 5389df43fed7..6890964728cb 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;
--
2.32.0

View File

@ -1,69 +0,0 @@
From d438b6cfb3d4b60cd9ced49be817f67902910912 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Wed, 28 Apr 2021 16:07:03 -0400
Subject: [PATCH] libsepol/cil: Check datum in ordered list for expected flavor
The secilc-fuzzer found an out of bounds memory access occurs
when building the binary policy if a map class is included in a
classorder statement.
The order statements in CIL (sidorder, classorder, categoryorder,
and sensitivityorder) are used to specify an ordering for sids,
classes, categories, and sensitivities. When the order statments
are resolved and merged, only in the case of the category order
list is the datum resolved checked to see if it is the expected
flavor.
When resolving the sid, class, and sensitivity order statements,
check that each name resolved to a datum of the expected flavor
and return an error if it does not.
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/cil/src/cil_resolve_ast.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
index 6890964728cb..b081d45d4cb5 100644
--- a/libsepol/cil/src/cil_resolve_ast.c
+++ b/libsepol/cil/src/cil_resolve_ast.c
@@ -1488,6 +1488,11 @@ int cil_resolve_classorder(struct cil_tree_node *current, void *extra_args)
rc = SEPOL_ERR;
goto exit;
}
+ if (FLAVOR(datum) != CIL_CLASS) {
+ cil_log(CIL_ERR, "%s is not a class. Only classes are allowed in classorder statements\n", datum->name);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
cil_list_append(new, CIL_CLASS, datum);
}
@@ -1526,6 +1531,12 @@ int cil_resolve_sidorder(struct cil_tree_node *current, void *extra_args)
cil_log(CIL_ERR, "Failed to resolve sid %s in sidorder\n", (char *)curr->data);
goto exit;
}
+ if (FLAVOR(datum) != CIL_SID) {
+ cil_log(CIL_ERR, "%s is not a sid. Only sids are allowed in sidorder statements\n", datum->name);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+
cil_list_append(new, CIL_SID, datum);
}
@@ -1617,6 +1628,11 @@ int cil_resolve_sensitivityorder(struct cil_tree_node *current, void *extra_args
cil_log(CIL_ERR, "Failed to resolve sensitivty %s in sensitivityorder\n", (char *)curr->data);
goto exit;
}
+ if (FLAVOR(datum) != CIL_SENS) {
+ cil_log(CIL_ERR, "%s is not a sensitivity. Only sensitivities are allowed in sensitivityorder statements\n", datum->name);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
cil_list_append(new, CIL_SENS, datum);
}
--
2.32.0

View File

@ -1,40 +0,0 @@
From d9433692c782b65e5397234950c6d9993fbcaa70 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Wed, 28 Apr 2021 16:07:09 -0400
Subject: [PATCH] libsepol/cil: Return an error if a call argument fails to
resolve
Return an error if a call argument fails to resolve so that
the resolution phase stops and returns an error.
This problem 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 b081d45d4cb5..f251ed1582fc 100644
--- a/libsepol/cil/src/cil_resolve_ast.c
+++ b/libsepol/cil/src/cil_resolve_ast.c
@@ -3277,6 +3277,7 @@ int cil_resolve_call2(struct cil_tree_node *current, void *extra_args)
if (sym_index != CIL_SYM_UNKNOWN) {
rc = cil_resolve_name(current, arg->arg_str, sym_index, extra_args, &(arg->arg));
if (rc != SEPOL_OK) {
+ cil_tree_log(current, CIL_ERR, "Failed to resolve %s in call argument list", arg->arg_str);
goto exit;
}
}
@@ -3308,7 +3309,7 @@ int cil_resolve_name_call_args(struct cil_call *call, char *name, enum cil_sym_i
if (param_index == sym_index) {
if (name == arg->param_str) {
*datum = arg->arg;
- rc = SEPOL_OK;
+ rc = *datum ? SEPOL_OK : SEPOL_ERR;
goto exit;
}
}
--
2.32.0

View File

@ -1,244 +0,0 @@
From 61fbdce666f24c4a118b249ece6b014d54b65074 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Tue, 4 May 2021 16:14:55 -0400
Subject: [PATCH] libsepol/cil: Check for self-referential loops in sets
The secilc-fuzzer found a self-referential loop using category sets.
Any set declaration in CIL that allows sets in it is susceptible to
the creation of a self-referential loop. There is a check, but only
for the name of the set being declared being used in the set
declaration.
Check for self-refential loops in user, role, and type attributes
and in category sets. Since all of the sets need to be declared,
this check has to be done when verifying the CIL db before doing
the post phase.
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/cil/src/cil_resolve_ast.c | 31 +---------
libsepol/cil/src/cil_verify.c | 97 +++++++++++++++++++++---------
libsepol/cil/src/cil_verify.h | 1 -
3 files changed, 71 insertions(+), 58 deletions(-)
diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
index f251ed1582fc..5368ae80ede9 100644
--- a/libsepol/cil/src/cil_resolve_ast.c
+++ b/libsepol/cil/src/cil_resolve_ast.c
@@ -438,11 +438,6 @@ int cil_resolve_typeattributeset(struct cil_tree_node *current, void *extra_args
goto exit;
}
- rc = cil_verify_no_self_reference(attr_datum, attrtypes->datum_expr);
- if (rc != SEPOL_OK) {
- goto exit;
- }
-
if (attr->expr_list == NULL) {
cil_list_init(&attr->expr_list, CIL_TYPEATTRIBUTE);
}
@@ -1151,11 +1146,6 @@ int cil_resolve_roleattributeset(struct cil_tree_node *current, void *extra_args
goto exit;
}
- rc = cil_verify_no_self_reference(attr_datum, attrroles->datum_expr);
- if (rc != SEPOL_OK) {
- goto exit;
- }
-
if (attr->expr_list == NULL) {
cil_list_init(&attr->expr_list, CIL_ROLEATTRIBUTE);
}
@@ -1666,21 +1656,7 @@ exit:
int cil_resolve_catset(struct cil_tree_node *current, struct cil_catset *catset, void *extra_args)
{
- int rc = SEPOL_ERR;
-
- rc = cil_resolve_cats(current, catset->cats, extra_args);
- if (rc != SEPOL_OK) {
- goto exit;
- }
-
- rc = cil_verify_no_self_reference((struct cil_symtab_datum *)catset, catset->cats->datum_expr);
- if (rc != SEPOL_OK) {
- cil_list_destroy(&catset->cats->datum_expr, CIL_FALSE);
- goto exit;
- }
-
-exit:
- return rc;
+ return cil_resolve_cats(current, catset->cats, extra_args);
}
int cil_resolve_senscat(struct cil_tree_node *current, void *extra_args)
@@ -3545,11 +3521,6 @@ int cil_resolve_userattributeset(struct cil_tree_node *current, void *extra_args
goto exit;
}
- rc = cil_verify_no_self_reference(attr_datum, attrusers->datum_expr);
- if (rc != SEPOL_OK) {
- goto exit;
- }
-
if (attr->expr_list == NULL) {
cil_list_init(&attr->expr_list, CIL_USERATTRIBUTE);
}
diff --git a/libsepol/cil/src/cil_verify.c b/libsepol/cil/src/cil_verify.c
index 5a37dd2f76bc..8e15a0e68a69 100644
--- a/libsepol/cil/src/cil_verify.c
+++ b/libsepol/cil/src/cil_verify.c
@@ -430,28 +430,71 @@ int cil_verify_decl_does_not_shadow_macro_parameter(struct cil_macro *macro, str
return SEPOL_OK;
}
-int cil_verify_no_self_reference(struct cil_symtab_datum *datum, struct cil_list *datum_list)
+static int cil_verify_no_self_reference(enum cil_flavor flavor, struct cil_symtab_datum *datum, struct cil_symtab_datum *orig);
+
+static int __verify_no_self_reference_in_expr(struct cil_list *expr, struct cil_symtab_datum *orig)
{
- struct cil_list_item *i;
+ struct cil_list_item *item;
+ int rc = SEPOL_OK;
- cil_list_for_each(i, datum_list) {
- if (i->flavor == CIL_DATUM) {
- struct cil_symtab_datum *d = i->data;
- if (d == datum) {
- cil_log(CIL_ERR,"Self-reference found for %s\n",datum->name);
- return SEPOL_ERR;
- }
- } else if (i->flavor == CIL_LIST) {
- int rc = cil_verify_no_self_reference(datum, i->data);
- if (rc != SEPOL_OK) {
- return SEPOL_ERR;
- }
+ if (!expr) {
+ return SEPOL_OK;
+ }
+
+ cil_list_for_each(item, expr) {
+ if (item->flavor == CIL_DATUM) {
+ struct cil_symtab_datum* datum = item->data;
+ rc = cil_verify_no_self_reference(FLAVOR(datum), datum, orig);
+ } else if (item->flavor == CIL_LIST) {
+ rc = __verify_no_self_reference_in_expr(item->data, orig);
+ }
+ if (rc != SEPOL_OK) {
+ return SEPOL_ERR;
}
}
return SEPOL_OK;
}
+static int cil_verify_no_self_reference(enum cil_flavor flavor, struct cil_symtab_datum *datum, struct cil_symtab_datum *orig)
+{
+ int rc = SEPOL_OK;
+
+ if (datum == orig) {
+ cil_tree_log(NODE(orig), CIL_ERR, "Self-reference found for %s", orig->name);
+ return SEPOL_ERR;
+ } else if (orig == NULL) {
+ orig = datum;
+ }
+
+ switch (flavor) {
+ case CIL_USERATTRIBUTE: {
+ struct cil_userattribute *attr = (struct cil_userattribute *)datum;
+ rc = __verify_no_self_reference_in_expr(attr->expr_list, orig);
+ break;
+ }
+ case CIL_ROLEATTRIBUTE: {
+ struct cil_roleattribute *attr = (struct cil_roleattribute *)datum;
+ rc = __verify_no_self_reference_in_expr(attr->expr_list, orig);
+ break;
+ }
+ case CIL_TYPEATTRIBUTE: {
+ struct cil_typeattribute *attr = (struct cil_typeattribute *)datum;
+ rc = __verify_no_self_reference_in_expr(attr->expr_list, orig);
+ break;
+ }
+ case CIL_CATSET: {
+ struct cil_catset *set = (struct cil_catset *)datum;
+ rc = __verify_no_self_reference_in_expr(set->cats->datum_expr, orig);
+ break;
+ }
+ default:
+ break;
+ }
+
+ return rc;
+}
+
int __cil_verify_ranges(struct cil_list *list)
{
int rc = SEPOL_ERR;
@@ -1757,27 +1800,22 @@ static int __cil_verify_map_class(struct cil_tree_node *node)
int __cil_pre_verify_helper(struct cil_tree_node *node, uint32_t *finished, __attribute__((unused)) void *extra_args)
{
- int rc = SEPOL_ERR;
+ int rc = SEPOL_OK;
- if (node->flavor == CIL_MACRO) {
+ switch (node->flavor) {
+ case CIL_MACRO: {
*finished = CIL_TREE_SKIP_HEAD;
- rc = SEPOL_OK;
- goto exit;
- } else if (node->flavor == CIL_BLOCK) {
+ break;
+ }
+ case CIL_BLOCK: {
struct cil_block *blk = node->data;
if (blk->is_abstract == CIL_TRUE) {
*finished = CIL_TREE_SKIP_HEAD;
}
- rc = SEPOL_OK;
- goto exit;
+ break;
}
-
- switch (node->flavor) {
case CIL_USER:
rc = __cil_verify_user_pre_eval(node);
- if (rc != SEPOL_OK) {
- goto exit;
- }
break;
case CIL_MAP_CLASS:
rc = __cil_verify_map_class(node);
@@ -1785,11 +1823,16 @@ int __cil_pre_verify_helper(struct cil_tree_node *node, uint32_t *finished, __at
case CIL_CLASSPERMISSION:
rc = __cil_verify_classpermission(node);
break;
+ case CIL_USERATTRIBUTE:
+ case CIL_ROLEATTRIBUTE:
+ case CIL_TYPEATTRIBUTE:
+ case CIL_CATSET:
+ rc = cil_verify_no_self_reference(node->flavor, node->data, NULL);
+ break;
default:
rc = SEPOL_OK;
break;
}
-exit:
return rc;
}
diff --git a/libsepol/cil/src/cil_verify.h b/libsepol/cil/src/cil_verify.h
index c497018f8a95..4ea14f5b0a9a 100644
--- a/libsepol/cil/src/cil_verify.h
+++ b/libsepol/cil/src/cil_verify.h
@@ -63,7 +63,6 @@ int cil_verify_constraint_leaf_expr_syntax(enum cil_flavor l_flavor, enum cil_fl
int cil_verify_constraint_expr_syntax(struct cil_tree_node *current, enum cil_flavor op);
int cil_verify_conditional_blocks(struct cil_tree_node *current);
int cil_verify_decl_does_not_shadow_macro_parameter(struct cil_macro *macro, struct cil_tree_node *node, const char *name);
-int cil_verify_no_self_reference(struct cil_symtab_datum *datum, struct cil_list *datum_list);
int __cil_verify_ranges(struct cil_list *list);
int __cil_verify_ordered_node_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args);
int __cil_verify_ordered(struct cil_tree_node *current, enum cil_flavor flavor);
--
2.32.0

View File

@ -1,74 +0,0 @@
From 0d6e95cfb24fd0bc5405ecea0b3ebac3462b5312 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Thu, 6 May 2021 13:05:36 -0400
Subject: [PATCH] libsepol/cil: Fix name resolution involving inherited blocks
When resolving a name in a block that has been inherited. First,
a search is done in the parent namespaces (if any) of the
blockinherit rule with the exception of the global namespace. If
the name is not found, then a search is done in the namespaces of
the original block (starting with that block's namespace) with
the exception of the global namespace. Finally, if it still has
not been found, the global namespace is searched.
This does not work if a declaration is in the block being
inherited.
For example:
(block b
(typeattribute a)
(allow a self (CLASS (PERM)))
)
(blockinherit b)
This will result in a policy with the following identical allow
rules:
(allow b.a self (CLASS (PERM)))
(allow b.a self (CLASS (PERM)))
rather than the expected:
(allow b.a self (CLASS (PERM)))
(allow a self (CLASS (PERM)))
This is because when the typeattribute is copied while resolving
the inheritance, the new datum is added to the global namespace
and, since that is searched last, the typeattribute in block b is
found first.
This behavior means that no declaration that is inherited into the
global namespace will actually be used.
Instead, if the name is not found in the parent namespaces (if any)
where the blockinherit is located with the exception of the global
namespace, start the next search in the namespace of the parent of
the original block (instead of the original block itself). Now if
a declaration is inherited from the original block, the new
declaration will be used. This behavior seems to be the originally
intended behavior because there is a comment in the code that says,
"Continue search in original block's parent".
This issue was found by secilc-fuzzer. If the original block
is made to be abstract, then the type attribute declaration
in the original block is not in the policy and a segfault
occurs when creating the binary because the copied allow rule
refers to a non-existent type attribute.
Signed-off-by: James Carter <jwcart2@gmail.com>
---
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 5368ae80ede9..5684b8da0f76 100644
--- a/libsepol/cil/src/cil_resolve_ast.c
+++ b/libsepol/cil/src/cil_resolve_ast.c
@@ -4182,7 +4182,7 @@ static int __cil_resolve_name_with_parents(struct cil_tree_node *node, char *nam
rc = __cil_resolve_name_with_parents(node->parent, name, sym_index, datum);
if (rc != SEPOL_OK) {
/* Continue search in original block's parent */
- rc = __cil_resolve_name_with_parents(NODE(inherit->block), name, sym_index, datum);
+ rc = __cil_resolve_name_with_parents(NODE(inherit->block)->parent, name, sym_index, datum);
goto exit;
}
}
--
2.32.0

View File

@ -1,75 +0,0 @@
From 788d40b0e61f352524660d0965d5e86f6e1e0718 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Tue, 11 May 2021 09:43:22 -0400
Subject: [PATCH] libsepol/cil: Make name resolution in macros work as
documented
The CIL Reference Guide specifies how name resolution is suppose
to work within an expanded macro.
1. Items defined inside the macro
2. Items passed into the macro as arguments
3. Items defined in the same namespace of the macro
4. Items defined in the caller's namespace
5. Items defined in the global namespace
But Lorenzo Ceragioli <lorenzo.ceragioli@phd.unipi.it> found
that the first step is not done.
So the following policy:
(block A
(type a)
(macro m ()
(type a)
(allow a self (CLASS (PERM)))
)
)
(block B
(call A.m)
)
will result in:
(allow A.a self (CLASS (PERM)))
instead of the expected:
(allow B.a self (CLASS (PERM)))
Now when an expanded call is found, the macro's namespace is
checked first. If the name is found, then the name was declared
in the macro and it is declared in the expanded call, so only the
namespace of the call up to and including the global namespace
will be searched. If the name is not found in the macro's namespace
then name resolution continues with steps 2-5 above.
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/cil/src/cil_resolve_ast.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
index 5684b8da0f76..ae6743f92f4c 100644
--- a/libsepol/cil/src/cil_resolve_ast.c
+++ b/libsepol/cil/src/cil_resolve_ast.c
@@ -4195,10 +4195,18 @@ static int __cil_resolve_name_with_parents(struct cil_tree_node *node, char *nam
break;
case CIL_CALL: {
struct cil_call *call = node->data;
- rc = cil_resolve_name_call_args(call, name, sym_index, datum);
- if (rc != SEPOL_OK) {
- /* Continue search in macro's parent */
- rc = __cil_resolve_name_with_parents(NODE(call->macro)->parent, name, sym_index, datum);
+ struct cil_macro *macro = call->macro;
+ symtab = &macro->symtab[sym_index];
+ rc = cil_symtab_get_datum(symtab, name, datum);
+ if (rc == SEPOL_OK) {
+ /* If the name was declared in the macro, just look on the call side */
+ rc = SEPOL_ERR;
+ } else {
+ rc = cil_resolve_name_call_args(call, name, sym_index, datum);
+ if (rc != SEPOL_OK) {
+ /* Continue search in macro's parent */
+ rc = __cil_resolve_name_with_parents(NODE(call->macro)->parent, name, sym_index, datum);
+ }
}
}
break;
--
2.32.0

View File

@ -1,45 +0,0 @@
From a1952af7c0346f3cd60a362e43fc90a7d799cffe Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Tue, 11 May 2021 09:43:43 -0400
Subject: [PATCH] libsepol/cil: Do not add NULL node when inserting key into
symtab
Allow inserting a key without providing a node.
This will make it easier to properly resolve call arguments where
a key might need to be temporarily removed to search for a datum
that is not declared within the call. Since the node is already
in the node list, re-inserting the key without this option would
add another link to the node and cause problems.
Also, do not add the node to the datum's node list if the result
of the call to hashtab_insert() is SEPOL_EEXIST because the datum
is a duplicate and will be destroyed.
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/cil/src/cil_symtab.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/libsepol/cil/src/cil_symtab.c b/libsepol/cil/src/cil_symtab.c
index 579a888e5785..c195156071e1 100644
--- a/libsepol/cil/src/cil_symtab.c
+++ b/libsepol/cil/src/cil_symtab.c
@@ -93,10 +93,10 @@ int cil_symtab_insert(symtab_t *symtab, hashtab_key_t key, struct cil_symtab_dat
datum->fqn = key;
datum->symtab = symtab;
symtab->nprim++;
- cil_list_append(datum->nodes, CIL_NODE, node);
- } else if (rc == SEPOL_EEXIST) {
- cil_list_append(datum->nodes, CIL_NODE, node);
- } else {
+ if (node) {
+ cil_list_append(datum->nodes, CIL_NODE, node);
+ }
+ } else if (rc != SEPOL_EEXIST) {
cil_symtab_error("Failed to insert datum into hashtab\n");
}
--
2.32.0

View File

@ -1,738 +0,0 @@
From bccec36a7694e8eee03ab0d592c3b0d8ddfff36e Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Tue, 11 May 2021 12:34:27 -0400
Subject: [PATCH] libsepo/cil: Refactor macro call resolution
Rename cil_resolve_call1() as cil resolve_call() and rename
cil_resolve_call2() as cil_resolve_call_args() to make it clearer
what is being done in each function.
Move code to build call arguments out of cil_resolve_call() and into
the new function called cil_build_call_args() so that the logic of
cil_resolve_call() can be seen.
Exit cil_resolve_call() immediately if the call has already been
copied.
In __cil_resolve_ast_node(), only resolve calls outside of macros.
This results in more calls to cil_copy_ast(), but slightly less
rules copied overall (since no rules are copied into a macro). This
also means that the CIL_PASS_MACRO pass is not needed and can be
eliminated.
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/cil/src/cil_internal.h | 1 -
libsepol/cil/src/cil_resolve_ast.c | 599 +++++++++++++++--------------
2 files changed, 303 insertions(+), 297 deletions(-)
diff --git a/libsepol/cil/src/cil_internal.h b/libsepol/cil/src/cil_internal.h
index 74e0b34d6cbd..a77c95201fb7 100644
--- a/libsepol/cil/src/cil_internal.h
+++ b/libsepol/cil/src/cil_internal.h
@@ -59,7 +59,6 @@ enum cil_pass {
CIL_PASS_BLKIN_LINK,
CIL_PASS_BLKIN_COPY,
CIL_PASS_BLKABS,
- CIL_PASS_MACRO,
CIL_PASS_CALL1,
CIL_PASS_CALL2,
CIL_PASS_ALIAS1,
diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
index ae6743f92f4c..258fdb1bb69f 100644
--- a/libsepol/cil/src/cil_resolve_ast.c
+++ b/libsepol/cil/src/cil_resolve_ast.c
@@ -2816,359 +2816,371 @@ exit:
return rc;
}
-int cil_resolve_call1(struct cil_tree_node *current, void *extra_args)
+static int cil_build_call_args(struct cil_tree_node *call_node, struct cil_call *call, struct cil_macro *macro, void *extra_args)
{
- struct cil_call *new_call = current->data;
struct cil_args_resolve *args = extra_args;
- struct cil_db *db = NULL;
- struct cil_tree_node *macro_node = NULL;
- struct cil_symtab_datum *macro_datum = NULL;
+ struct cil_list_item *item;
+ struct cil_args *arg = NULL;
+ struct cil_tree_node *arg_node = NULL;
int rc = SEPOL_ERR;
- if (args != NULL) {
- db = args->db;
+ if (macro->params == NULL) {
+ if (call->args_tree == NULL) {
+ return SEPOL_OK;
+ } else {
+ cil_tree_log(call_node, CIL_ERR, "Unexpected arguments");
+ return SEPOL_ERR;;
+ }
}
-
- rc = cil_resolve_name(current, new_call->macro_str, CIL_SYM_BLOCKS, extra_args, &macro_datum);
- if (rc != SEPOL_OK) {
- goto exit;
+ if (call->args_tree == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Missing arguments");
+ return SEPOL_ERR;
}
- macro_node = NODE(macro_datum);
+ arg_node = call->args_tree->root->cl_head;
- if (macro_node->flavor != CIL_MACRO) {
- cil_tree_log(current, CIL_ERR, "Failed to resolve %s to a macro", new_call->macro_str);
- rc = SEPOL_ERR;
- goto exit;
- }
- new_call->macro = (struct cil_macro*)macro_datum;
+ cil_list_init(&call->args, CIL_LIST_ITEM);
- if (new_call->macro->params != NULL ) {
+ cil_list_for_each(item, macro->params) {
+ enum cil_flavor flavor = ((struct cil_param*)item->data)->flavor;
- struct cil_list_item *item;
- struct cil_args *new_arg = NULL;
- struct cil_tree_node *pc = NULL;
-
- if (new_call->args_tree == NULL) {
- cil_tree_log(current, CIL_ERR, "Missing arguments");
+ if (arg_node == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Missing arguments");
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ if (item->flavor != CIL_PARAM) {
rc = SEPOL_ERR;
goto exit;
}
- pc = new_call->args_tree->root->cl_head;
-
- cil_list_init(&new_call->args, CIL_LIST_ITEM);
-
- cil_list_for_each(item, new_call->macro->params) {
- enum cil_flavor flavor = ((struct cil_param*)item->data)->flavor;
+ cil_args_init(&arg);
- if (pc == NULL) {
- cil_tree_log(current, CIL_ERR, "Missing arguments");
+ switch (flavor) {
+ case CIL_NAME: {
+ struct cil_name *name;
+ if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
rc = SEPOL_ERR;
goto exit;
}
- if (item->flavor != CIL_PARAM) {
+ name = __cil_insert_name(args->db, arg_node->data, call_node);
+ if (name != NULL) {
+ arg->arg = (struct cil_symtab_datum *)name;
+ } else {
+ arg->arg_str = arg_node->data;
+ }
+ }
+ break;
+ case CIL_TYPE:
+ if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
rc = SEPOL_ERR;
goto exit;
}
-
- cil_args_init(&new_arg);
-
- switch (flavor) {
- case CIL_NAME: {
- struct cil_name *name;
- if (pc->data == NULL) {
- cil_tree_log(current, CIL_ERR, "Invalid macro parameter");
- cil_destroy_args(new_arg);
- rc = SEPOL_ERR;
- goto exit;
- }
- name = __cil_insert_name(args->db, pc->data, current);
- if (name != NULL) {
- new_arg->arg = (struct cil_symtab_datum *)name;
- } else {
- new_arg->arg_str = pc->data;
- }
+ arg->arg_str = arg_node->data;
+ break;
+ case CIL_ROLE:
+ if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
+ rc = SEPOL_ERR;
+ goto exit;
}
- break;
- case CIL_TYPE:
- if (pc->data == NULL) {
- cil_tree_log(current, CIL_ERR, "Invalid macro parameter");
- cil_destroy_args(new_arg);
- rc = SEPOL_ERR;
- goto exit;
- }
- new_arg->arg_str = pc->data;
- break;
- case CIL_ROLE:
- if (pc->data == NULL) {
- cil_tree_log(current, CIL_ERR, "Invalid macro parameter");
- cil_destroy_args(new_arg);
- rc = SEPOL_ERR;
- goto exit;
- }
- new_arg->arg_str = pc->data;
- break;
- case CIL_USER:
- if (pc->data == NULL) {
- cil_tree_log(current, CIL_ERR, "Invalid macro parameter");
- cil_destroy_args(new_arg);
- rc = SEPOL_ERR;
- goto exit;
- }
- new_arg->arg_str = pc->data;
- break;
- case CIL_SENS:
- if (pc->data == NULL) {
- cil_tree_log(current, CIL_ERR, "Invalid macro parameter");
- cil_destroy_args(new_arg);
- rc = SEPOL_ERR;
- goto exit;
- }
- new_arg->arg_str = pc->data;
- break;
- case CIL_CAT:
- if (pc->data == NULL) {
- cil_tree_log(current, CIL_ERR, "Invalid macro parameter");
- cil_destroy_args(new_arg);
- rc = SEPOL_ERR;
- goto exit;
- }
- new_arg->arg_str = pc->data;
- break;
- case CIL_BOOL:
- if (pc->data == NULL) {
- cil_tree_log(current, CIL_ERR, "Invalid macro parameter");
- cil_destroy_args(new_arg);
- rc = SEPOL_ERR;
- goto exit;
- }
- new_arg->arg_str = pc->data;
- break;
- case CIL_CATSET: {
- if (pc->cl_head != NULL) {
- struct cil_catset *catset = NULL;
- struct cil_tree_node *cat_node = NULL;
- cil_catset_init(&catset);
- rc = cil_fill_cats(pc, &catset->cats);
- if (rc != SEPOL_OK) {
- cil_destroy_catset(catset);
- cil_destroy_args(new_arg);
- goto exit;
- }
- cil_tree_node_init(&cat_node);
- cat_node->flavor = CIL_CATSET;
- cat_node->data = catset;
- cil_list_append(((struct cil_symtab_datum*)catset)->nodes,
- CIL_LIST_ITEM, cat_node);
- new_arg->arg = (struct cil_symtab_datum*)catset;
- } else if (pc->data == NULL) {
- cil_tree_log(current, CIL_ERR, "Invalid macro parameter");
- cil_destroy_args(new_arg);
- rc = SEPOL_ERR;
+ arg->arg_str = arg_node->data;
+ break;
+ case CIL_USER:
+ if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ arg->arg_str = arg_node->data;
+ break;
+ case CIL_SENS:
+ if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ arg->arg_str = arg_node->data;
+ break;
+ case CIL_CAT:
+ if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ arg->arg_str = arg_node->data;
+ break;
+ case CIL_BOOL:
+ if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ arg->arg_str = arg_node->data;
+ break;
+ case CIL_CATSET: {
+ if (arg_node->cl_head != NULL) {
+ struct cil_catset *catset = NULL;
+ struct cil_tree_node *cat_node = NULL;
+ cil_catset_init(&catset);
+ rc = cil_fill_cats(arg_node, &catset->cats);
+ if (rc != SEPOL_OK) {
+ cil_destroy_catset(catset);
+ cil_destroy_args(arg);
goto exit;
- } else {
- new_arg->arg_str = pc->data;
}
-
- break;
+ cil_tree_node_init(&cat_node);
+ cat_node->flavor = CIL_CATSET;
+ cat_node->data = catset;
+ cil_list_append(((struct cil_symtab_datum*)catset)->nodes,
+ CIL_LIST_ITEM, cat_node);
+ arg->arg = (struct cil_symtab_datum*)catset;
+ } else if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
+ rc = SEPOL_ERR;
+ goto exit;
+ } else {
+ arg->arg_str = arg_node->data;
}
- case CIL_LEVEL: {
- if (pc->cl_head != NULL) {
- struct cil_level *level = NULL;
- struct cil_tree_node *lvl_node = NULL;
- cil_level_init(&level);
-
- rc = cil_fill_level(pc->cl_head, level);
- if (rc != SEPOL_OK) {
- cil_log(CIL_ERR, "Failed to create anonymous level, rc: %d\n", rc);
- cil_destroy_level(level);
- cil_destroy_args(new_arg);
- goto exit;
- }
- cil_tree_node_init(&lvl_node);
- lvl_node->flavor = CIL_LEVEL;
- lvl_node->data = level;
- cil_list_append(((struct cil_symtab_datum*)level)->nodes,
- CIL_LIST_ITEM, lvl_node);
- new_arg->arg = (struct cil_symtab_datum*)level;
- } else if (pc->data == NULL) {
- cil_tree_log(current, CIL_ERR, "Invalid macro parameter");
- cil_destroy_args(new_arg);
- rc = SEPOL_ERR;
+
+ break;
+ }
+ case CIL_LEVEL: {
+ if (arg_node->cl_head != NULL) {
+ struct cil_level *level = NULL;
+ struct cil_tree_node *lvl_node = NULL;
+ cil_level_init(&level);
+
+ rc = cil_fill_level(arg_node->cl_head, level);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to create anonymous level, rc: %d\n", rc);
+ cil_destroy_level(level);
+ cil_destroy_args(arg);
goto exit;
- } else {
- new_arg->arg_str = pc->data;
}
-
- break;
+ cil_tree_node_init(&lvl_node);
+ lvl_node->flavor = CIL_LEVEL;
+ lvl_node->data = level;
+ cil_list_append(((struct cil_symtab_datum*)level)->nodes,
+ CIL_LIST_ITEM, lvl_node);
+ arg->arg = (struct cil_symtab_datum*)level;
+ } else if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
+ rc = SEPOL_ERR;
+ goto exit;
+ } else {
+ arg->arg_str = arg_node->data;
}
- case CIL_LEVELRANGE: {
- if (pc->cl_head != NULL) {
- struct cil_levelrange *range = NULL;
- struct cil_tree_node *range_node = NULL;
- cil_levelrange_init(&range);
-
- rc = cil_fill_levelrange(pc->cl_head, range);
- if (rc != SEPOL_OK) {
- cil_log(CIL_ERR, "Failed to create anonymous levelrange, rc: %d\n", rc);
- cil_destroy_levelrange(range);
- cil_destroy_args(new_arg);
- goto exit;
- }
- cil_tree_node_init(&range_node);
- range_node->flavor = CIL_LEVELRANGE;
- range_node->data = range;
- cil_list_append(((struct cil_symtab_datum*)range)->nodes,
- CIL_LIST_ITEM, range_node);
- new_arg->arg = (struct cil_symtab_datum*)range;
- } else if (pc->data == NULL) {
- cil_tree_log(current, CIL_ERR, "Invalid macro parameter");
- cil_destroy_args(new_arg);
- rc = SEPOL_ERR;
+
+ break;
+ }
+ case CIL_LEVELRANGE: {
+ if (arg_node->cl_head != NULL) {
+ struct cil_levelrange *range = NULL;
+ struct cil_tree_node *range_node = NULL;
+ cil_levelrange_init(&range);
+
+ rc = cil_fill_levelrange(arg_node->cl_head, range);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to create anonymous levelrange, rc: %d\n", rc);
+ cil_destroy_levelrange(range);
+ cil_destroy_args(arg);
goto exit;
- } else {
- new_arg->arg_str = pc->data;
}
-
- break;
+ cil_tree_node_init(&range_node);
+ range_node->flavor = CIL_LEVELRANGE;
+ range_node->data = range;
+ cil_list_append(((struct cil_symtab_datum*)range)->nodes,
+ CIL_LIST_ITEM, range_node);
+ arg->arg = (struct cil_symtab_datum*)range;
+ } else if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
+ rc = SEPOL_ERR;
+ goto exit;
+ } else {
+ arg->arg_str = arg_node->data;
}
- case CIL_IPADDR: {
- if (pc->cl_head != NULL) {
- struct cil_ipaddr *ipaddr = NULL;
- struct cil_tree_node *addr_node = NULL;
- cil_ipaddr_init(&ipaddr);
-
- rc = cil_fill_ipaddr(pc->cl_head, ipaddr);
- if (rc != SEPOL_OK) {
- cil_log(CIL_ERR, "Failed to create anonymous ip address, rc: %d\n", rc);
- cil_destroy_ipaddr(ipaddr);
- cil_destroy_args(new_arg);
- goto exit;
- }
- cil_tree_node_init(&addr_node);
- addr_node->flavor = CIL_IPADDR;
- addr_node->data = ipaddr;
- cil_list_append(((struct cil_symtab_datum*)ipaddr)->nodes,
- CIL_LIST_ITEM, addr_node);
- new_arg->arg = (struct cil_symtab_datum*)ipaddr;
- } else if (pc->data == NULL) {
- cil_tree_log(current, CIL_ERR, "Invalid macro parameter");
- cil_destroy_args(new_arg);
- rc = SEPOL_ERR;
+
+ break;
+ }
+ case CIL_IPADDR: {
+ if (arg_node->cl_head != NULL) {
+ struct cil_ipaddr *ipaddr = NULL;
+ struct cil_tree_node *addr_node = NULL;
+ cil_ipaddr_init(&ipaddr);
+
+ rc = cil_fill_ipaddr(arg_node->cl_head, ipaddr);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to create anonymous ip address, rc: %d\n", rc);
+ cil_destroy_ipaddr(ipaddr);
+ cil_destroy_args(arg);
goto exit;
- } else {
- new_arg->arg_str = pc->data;
}
+ cil_tree_node_init(&addr_node);
+ addr_node->flavor = CIL_IPADDR;
+ addr_node->data = ipaddr;
+ cil_list_append(((struct cil_symtab_datum*)ipaddr)->nodes,
+ CIL_LIST_ITEM, addr_node);
+ arg->arg = (struct cil_symtab_datum*)ipaddr;
+ } else if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
+ rc = SEPOL_ERR;
+ goto exit;
+ } else {
+ arg->arg_str = arg_node->data;
+ }
- break;
+ break;
+ }
+ case CIL_CLASS:
+ if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
+ rc = SEPOL_ERR;
+ goto exit;
}
- case CIL_CLASS:
- if (pc->data == NULL) {
- cil_tree_log(current, CIL_ERR, "Invalid macro parameter");
- cil_destroy_args(new_arg);
- rc = SEPOL_ERR;
- goto exit;
- }
- new_arg->arg_str = pc->data;
- break;
- case CIL_MAP_CLASS:
- if (pc->data == NULL) {
- cil_tree_log(current, CIL_ERR, "Invalid macro parameter");
- cil_destroy_args(new_arg);
- rc = SEPOL_ERR;
- goto exit;
- }
- new_arg->arg_str = pc->data;
- break;
- case CIL_CLASSPERMISSION: {
- if (pc->cl_head != NULL) {
- struct cil_classpermission *cp = NULL;
- struct cil_tree_node *cp_node = NULL;
-
- cil_classpermission_init(&cp);
- rc = cil_fill_classperms_list(pc, &cp->classperms);
- if (rc != SEPOL_OK) {
- cil_log(CIL_ERR, "Failed to create anonymous classpermission\n");
- cil_destroy_classpermission(cp);
- cil_destroy_args(new_arg);
- goto exit;
- }
- cil_tree_node_init(&cp_node);
- cp_node->flavor = CIL_CLASSPERMISSION;
- cp_node->data = cp;
- cil_list_append(cp->datum.nodes, CIL_LIST_ITEM, cp_node);
- new_arg->arg = (struct cil_symtab_datum*)cp;
- } else if (pc->data == NULL) {
- cil_tree_log(current, CIL_ERR, "Invalid macro parameter");
- cil_destroy_args(new_arg);
- rc = SEPOL_ERR;
+ arg->arg_str = arg_node->data;
+ break;
+ case CIL_MAP_CLASS:
+ if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ arg->arg_str = arg_node->data;
+ break;
+ case CIL_CLASSPERMISSION: {
+ if (arg_node->cl_head != NULL) {
+ struct cil_classpermission *cp = NULL;
+ struct cil_tree_node *cp_node = NULL;
+
+ cil_classpermission_init(&cp);
+ rc = cil_fill_classperms_list(arg_node, &cp->classperms);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to create anonymous classpermission\n");
+ cil_destroy_classpermission(cp);
+ cil_destroy_args(arg);
goto exit;
- } else {
- new_arg->arg_str = pc->data;
}
- break;
- }
- default:
- cil_log(CIL_ERR, "Unexpected flavor: %d\n",
- (((struct cil_param*)item->data)->flavor));
- cil_destroy_args(new_arg);
+ cil_tree_node_init(&cp_node);
+ cp_node->flavor = CIL_CLASSPERMISSION;
+ cp_node->data = cp;
+ cil_list_append(cp->datum.nodes, CIL_LIST_ITEM, cp_node);
+ arg->arg = (struct cil_symtab_datum*)cp;
+ } else if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
rc = SEPOL_ERR;
goto exit;
+ } else {
+ arg->arg_str = arg_node->data;
}
- new_arg->param_str = ((struct cil_param*)item->data)->str;
- new_arg->flavor = flavor;
-
- cil_list_append(new_call->args, CIL_ARGS, new_arg);
-
- pc = pc->next;
+ break;
}
-
- if (pc != NULL) {
- cil_tree_log(current, CIL_ERR, "Unexpected arguments");
+ default:
+ cil_log(CIL_ERR, "Unexpected flavor: %d\n",
+ (((struct cil_param*)item->data)->flavor));
+ cil_destroy_args(arg);
rc = SEPOL_ERR;
goto exit;
}
- } else if (new_call->args_tree != NULL) {
- cil_tree_log(current, CIL_ERR, "Unexpected arguments");
+ arg->param_str = ((struct cil_param*)item->data)->str;
+ arg->flavor = flavor;
+
+ cil_list_append(call->args, CIL_ARGS, arg);
+
+ arg_node = arg_node->next;
+ }
+
+ if (arg_node != NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Unexpected arguments");
rc = SEPOL_ERR;
goto exit;
}
- if (new_call->copied == 0) {
- new_call->copied = 1;
+ return SEPOL_OK;
- rc = cil_check_recursive_call(current, macro_node);
- if (rc != SEPOL_OK) {
- goto exit;
- }
+exit:
+ return rc;
+}
- rc = cil_copy_ast(db, macro_node, current);
- if (rc != SEPOL_OK) {
- cil_log(CIL_ERR, "Failed to copy macro, rc: %d\n", rc);
- goto exit;
- }
+int cil_resolve_call(struct cil_tree_node *current, void *extra_args)
+{
+ struct cil_call *call = current->data;
+ struct cil_args_resolve *args = extra_args;
+ struct cil_tree_node *macro_node = NULL;
+ struct cil_symtab_datum *macro_datum = NULL;
+ int rc = SEPOL_ERR;
+
+ if (call->copied) {
+ return SEPOL_OK;
+ }
+
+ rc = cil_resolve_name(current, call->macro_str, CIL_SYM_BLOCKS, extra_args, &macro_datum);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
+
+ macro_node = NODE(macro_datum);
+
+ if (macro_node->flavor != CIL_MACRO) {
+ cil_tree_log(current, CIL_ERR, "Failed to resolve %s to a macro", call->macro_str);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ call->macro = (struct cil_macro*)macro_datum;
+
+ rc = cil_build_call_args(current, call, call->macro, extra_args);
+ if (rc != SEPOL_OK) {
+ goto exit;
}
+ rc = cil_check_recursive_call(current, macro_node);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
+
+ rc = cil_copy_ast(args->db, macro_node, current);
+ if (rc != SEPOL_OK) {
+ cil_tree_log(current, CIL_ERR, "Failed to copy macro %s to call", macro_datum->name);
+ goto exit;
+ }
+
+ call->copied = 1;
+
return SEPOL_OK;
exit:
return rc;
}
-int cil_resolve_call2(struct cil_tree_node *current, void *extra_args)
+int cil_resolve_call_args(struct cil_tree_node *current, void *extra_args)
{
- struct cil_call *new_call = current->data;
+ struct cil_call *call = current->data;
int rc = SEPOL_ERR;
enum cil_sym_index sym_index = CIL_SYM_UNKNOWN;
struct cil_list_item *item;
- if (new_call->args == NULL) {
+ if (call->args == NULL) {
rc = SEPOL_OK;
goto exit;
}
- cil_list_for_each(item, new_call->args) {
+ cil_list_for_each(item, call->args) {
struct cil_args *arg = item->data;
if (arg->arg == NULL && arg->arg_str == NULL) {
cil_log(CIL_ERR, "Arguments not created correctly\n");
@@ -3574,19 +3586,14 @@ int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args)
rc = cil_resolve_blockabstract(node, args);
}
break;
- case CIL_PASS_MACRO:
- if (node->flavor == CIL_CALL && args->macro != NULL) {
- rc = cil_resolve_call1(node, args);
- }
- break;
case CIL_PASS_CALL1:
- if (node->flavor == CIL_CALL) {
- rc = cil_resolve_call1(node, args);
+ if (node->flavor == CIL_CALL && args->macro == NULL) {
+ rc = cil_resolve_call(node, args);
}
break;
case CIL_PASS_CALL2:
- if (node->flavor == CIL_CALL) {
- rc = cil_resolve_call2(node, args);
+ if (node->flavor == CIL_CALL && args->macro == NULL) {
+ rc = cil_resolve_call_args(node, args);
}
break;
case CIL_PASS_ALIAS1:
@@ -3890,7 +3897,7 @@ int __cil_resolve_ast_node_helper(struct cil_tree_node *node, uint32_t *finished
}
if (node->flavor == CIL_MACRO) {
- if (pass != CIL_PASS_TIF && pass != CIL_PASS_MACRO) {
+ if (pass != CIL_PASS_TIF) {
*finished = CIL_TREE_SKIP_HEAD;
rc = SEPOL_OK;
goto exit;
--
2.32.0

View File

@ -1,83 +0,0 @@
From aa8ac8ffafb9e4121b95a721341371042a3b2994 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Tue, 11 May 2021 14:22:53 -0400
Subject: [PATCH] libsepol/cil: Do not resolve arguments to declarations in the
call
Lorenzo Ceragioli <lorenzo.ceragioli@phd.unipi.it> noted that the
following policy:
(type a)
(block A
(macro m ((type x))
(type a)
(allow x x (file (read))))
)
(block B
(call A.m(a))
)
results in the allow rule (allow B.a B.a (file(read))). This makes
no sense because the "a" being passed as an argument has to be the
global "a" and not the "a" defined in the macro.
This behavior occurs because the call arguments are resolved AFTER
the macro body has been copied and the declaration of "a" in the
macro has been added to block B's namespace, so this is the "a"
that the call argument resolves to, rather than the one in the
global namespace.
When resolving call arguments, check if the datum found belongs to
a declaration in the call. If it does, then remove the datum from
the symbol table, re-resolve the argument, and add the datum back
into the symbol table.
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/cil/src/cil_resolve_ast.c | 28 +++++++++++++++++++++++++++-
1 file changed, 27 insertions(+), 1 deletion(-)
diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
index 258fdb1bb69f..74e5b78f9325 100644
--- a/libsepol/cil/src/cil_resolve_ast.c
+++ b/libsepol/cil/src/cil_resolve_ast.c
@@ -3263,11 +3263,37 @@ int cil_resolve_call_args(struct cil_tree_node *current, void *extra_args)
}
if (sym_index != CIL_SYM_UNKNOWN) {
- rc = cil_resolve_name(current, arg->arg_str, sym_index, extra_args, &(arg->arg));
+ struct cil_symtab_datum *datum;
+ struct cil_tree_node *n;
+ rc = cil_resolve_name(current, arg->arg_str, sym_index, extra_args, &datum);
if (rc != SEPOL_OK) {
cil_tree_log(current, CIL_ERR, "Failed to resolve %s in call argument list", arg->arg_str);
goto exit;
}
+ arg->arg = datum;
+ n = NODE(datum);
+ while (n && n->flavor != CIL_ROOT) {
+ if (n == current) {
+ symtab_t *s = datum->symtab;
+ /* Call arg should not resolve to declaration in the call
+ * Need to remove datum temporarily to resolve to a datum outside
+ * the call.
+ */
+ cil_symtab_remove_datum(datum);
+ rc = cil_resolve_name(current, arg->arg_str, sym_index, extra_args, &(arg->arg));
+ if (rc != SEPOL_OK) {
+ cil_tree_log(current, CIL_ERR, "Failed to resolve %s in call argument list", arg->arg_str);
+ goto exit;
+ }
+ rc = cil_symtab_insert(s, datum->name, datum, NULL);
+ if (rc != SEPOL_OK) {
+ cil_tree_log(current, CIL_ERR, "Failed to re-insert datum while resolving %s in call argument list", arg->arg_str);
+ goto exit;
+ }
+ break;
+ }
+ n = n->parent;
+ }
}
}
--
2.32.0

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 74e5b78f9325..328add0421c5 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);
--
2.32.0

View File

@ -1,39 +0,0 @@
From 29d6a3ee4a958607fdf7c01a78b6d389ba6e8612 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Thu, 13 May 2021 12:36:44 -0400
Subject: [PATCH] libsepol/cil: Destroy the permission nodes when exiting with
an error
When exiting with an error because a class or common has too many
permissions, destroy the permission nodes.
This bug was found by the secilc-fuzzer.
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/cil/src/cil_build_ast.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c
index 87043a8fa183..71f14e20e25e 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);
+ cil_tree_children_destroy(ast_node);
rc = SEPOL_ERR;
goto exit;
}
@@ -1019,6 +1020,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);
+ cil_tree_children_destroy(ast_node);
rc = SEPOL_ERR;
goto exit;
}
--
2.32.0

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 a93062180ff8..fb95f401f1c7 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;
--
2.32.0

View File

@ -1,44 +0,0 @@
From a8dcf4d57bad3e531e44855ccfa22d234a2a7e56 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Thu, 13 May 2021 12:51:44 -0400
Subject: [PATCH] libsepol/cil: Resolve anonymous class permission sets only
once
Anonymous class permission sets can be passed as call arguments.
Anonymous call arguments are resolved when they are used in a
rule. [This is because all the information might not be present
(like common permissions being added to a class) when the call
itself is resolved.] If there is more than one rule using an
anonymous class permission set, then a memory leak will occur
when a new list for the permission datum expression is created
without destroying the old one.
When resolving the class and permissions, check if the class has
already been resolved. If it has, then the permissions have been
as well.
This bug was found by the secilc-fuzzer.
Signed-off-by: James Carter <jwcart2@gmail.com>
---
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 328add0421c5..c504e60b7c58 100644
--- a/libsepol/cil/src/cil_resolve_ast.c
+++ b/libsepol/cil/src/cil_resolve_ast.c
@@ -158,6 +158,10 @@ int cil_resolve_classperms(struct cil_tree_node *current, struct cil_classperms
symtab_t *common_symtab = NULL;
struct cil_class *class;
+ if (cp->class) {
+ return SEPOL_OK;
+ }
+
rc = cil_resolve_name(current, cp->class_str, CIL_SYM_CLASSES, extra_args, &datum);
if (rc != SEPOL_OK) {
goto exit;
--
2.32.0

View File

@ -1,232 +0,0 @@
From 73d991abdc41b8e1380bfe05f031c822bfa0b515 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Thu, 13 May 2021 12:53:54 -0400
Subject: [PATCH] libsepol/cil: Pointers to datums should be set to NULL when
resetting
Set the pointer to the sensitivity in levels, the pointers to the low
and high levels in levelranges, the pointer to the level in userlevels,
the pointer to the range in userranges, and the pointers to contexts
in ocontexts to NULL.
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/cil/src/cil_reset_ast.c | 56 ++++++++++++++++++++++++++++++--
1 file changed, 53 insertions(+), 3 deletions(-)
diff --git a/libsepol/cil/src/cil_reset_ast.c b/libsepol/cil/src/cil_reset_ast.c
index d24d4f8159a3..6d1d2da77c89 100644
--- a/libsepol/cil/src/cil_reset_ast.c
+++ b/libsepol/cil/src/cil_reset_ast.c
@@ -140,8 +140,11 @@ static void cil_reset_userattributeset(struct cil_userattributeset *uas)
static void cil_reset_selinuxuser(struct cil_selinuxuser *selinuxuser)
{
+ selinuxuser->user = NULL;
if (selinuxuser->range_str == NULL) {
cil_reset_levelrange(selinuxuser->range);
+ } else {
+ selinuxuser->range = NULL;
}
}
@@ -214,6 +217,8 @@ static void cil_reset_rangetransition(struct cil_rangetransition *rangetrans)
{
if (rangetrans->range_str == NULL) {
cil_reset_levelrange(rangetrans->range);
+ } else {
+ rangetrans->range = NULL;
}
}
@@ -251,6 +256,7 @@ static void cil_reset_catset(struct cil_catset *catset)
static inline void cil_reset_level(struct cil_level *level)
{
+ level->sens = NULL;
cil_reset_cats(level->cats);
}
@@ -258,10 +264,14 @@ static inline void cil_reset_levelrange(struct cil_levelrange *levelrange)
{
if (levelrange->low_str == NULL) {
cil_reset_level(levelrange->low);
+ } else {
+ levelrange->low = NULL;
}
if (levelrange->high_str == NULL) {
cil_reset_level(levelrange->high);
+ } else {
+ levelrange->high = NULL;
}
}
@@ -269,6 +279,8 @@ static inline void cil_reset_userlevel(struct cil_userlevel *userlevel)
{
if (userlevel->level_str == NULL) {
cil_reset_level(userlevel->level);
+ } else {
+ userlevel->level = NULL;
}
}
@@ -276,13 +288,20 @@ static inline void cil_reset_userrange(struct cil_userrange *userrange)
{
if (userrange->range_str == NULL) {
cil_reset_levelrange(userrange->range);
+ } else {
+ userrange->range = NULL;
}
}
static inline void cil_reset_context(struct cil_context *context)
{
+ if (!context) {
+ return;
+ }
if (context->range_str == NULL) {
cil_reset_levelrange(context->range);
+ } else {
+ context->range = NULL;
}
}
@@ -290,26 +309,35 @@ static void cil_reset_sidcontext(struct cil_sidcontext *sidcontext)
{
if (sidcontext->context_str == NULL) {
cil_reset_context(sidcontext->context);
+ } else {
+ sidcontext->context = NULL;
}
}
static void cil_reset_filecon(struct cil_filecon *filecon)
{
- if (filecon->context_str == NULL && filecon->context != NULL) {
+ if (filecon->context_str == NULL) {
cil_reset_context(filecon->context);
+ } else {
+ filecon->context = NULL;
}
}
static void cil_reset_ibpkeycon(struct cil_ibpkeycon *ibpkeycon)
{
- if (!ibpkeycon->context_str)
+ if (ibpkeycon->context_str == NULL) {
cil_reset_context(ibpkeycon->context);
+ } else {
+ ibpkeycon->context = NULL;
+ }
}
static void cil_reset_portcon(struct cil_portcon *portcon)
{
if (portcon->context_str == NULL) {
cil_reset_context(portcon->context);
+ } else {
+ portcon->context = NULL;
}
}
@@ -317,6 +345,8 @@ static void cil_reset_nodecon(struct cil_nodecon *nodecon)
{
if (nodecon->context_str == NULL) {
cil_reset_context(nodecon->context);
+ } else {
+ nodecon->context = NULL;
}
}
@@ -324,6 +354,8 @@ static void cil_reset_genfscon(struct cil_genfscon *genfscon)
{
if (genfscon->context_str == NULL) {
cil_reset_context(genfscon->context);
+ } else {
+ genfscon->context = NULL;
}
}
@@ -331,17 +363,23 @@ static void cil_reset_netifcon(struct cil_netifcon *netifcon)
{
if (netifcon->if_context_str == NULL) {
cil_reset_context(netifcon->if_context);
+ } else {
+ netifcon->if_context = NULL;
}
if (netifcon->packet_context_str == NULL) {
cil_reset_context(netifcon->packet_context);
+ } else {
+ netifcon->packet_context = NULL;
}
}
static void cil_reset_ibendportcon(struct cil_ibendportcon *ibendportcon)
{
- if (!ibendportcon->context_str) {
+ if (ibendportcon->context_str == NULL) {
cil_reset_context(ibendportcon->context);
+ } else {
+ ibendportcon->context = NULL;
}
}
@@ -349,6 +387,8 @@ static void cil_reset_pirqcon(struct cil_pirqcon *pirqcon)
{
if (pirqcon->context_str == NULL) {
cil_reset_context(pirqcon->context);
+ } else {
+ pirqcon->context = NULL;
}
}
@@ -356,6 +396,8 @@ static void cil_reset_iomemcon(struct cil_iomemcon *iomemcon)
{
if (iomemcon->context_str == NULL) {
cil_reset_context(iomemcon->context);
+ } else {
+ iomemcon->context = NULL;
}
}
@@ -363,6 +405,8 @@ static void cil_reset_ioportcon(struct cil_ioportcon *ioportcon)
{
if (ioportcon->context_str == NULL) {
cil_reset_context(ioportcon->context);
+ } else {
+ ioportcon->context = NULL;
}
}
@@ -370,6 +414,8 @@ static void cil_reset_pcidevicecon(struct cil_pcidevicecon *pcidevicecon)
{
if (pcidevicecon->context_str == NULL) {
cil_reset_context(pcidevicecon->context);
+ } else {
+ pcidevicecon->context = NULL;
}
}
@@ -377,6 +423,8 @@ static void cil_reset_devicetreecon(struct cil_devicetreecon *devicetreecon)
{
if (devicetreecon->context_str == NULL) {
cil_reset_context(devicetreecon->context);
+ } else {
+ devicetreecon->context = NULL;
}
}
@@ -384,6 +432,8 @@ static void cil_reset_fsuse(struct cil_fsuse *fsuse)
{
if (fsuse->context_str == NULL) {
cil_reset_context(fsuse->context);
+ } else {
+ fsuse->context = NULL;
}
}
--
2.32.0

View File

@ -1,39 +0,0 @@
From d8b90f8ad1bc9dbff09312e628b48ac439ef4ef0 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Thu, 13 May 2021 13:23:57 -0400
Subject: [PATCH] libsepol/cil: Resolve anonymous levels only once
Anonymous levels can be passed as call arguments and they can
appear in anonymous levelranges as well.
Anonymous call arguments are resolved when they are used in a rule.
If more than one rule uses the anonymous level, then a memory leak
will occur when a new list for the category datum expression is
created without destroying the old one.
When resolving a level, check if the sensitivity datum has already
been resolved. If it has, then the categories have been as well.
Signed-off-by: James Carter <jwcart2@gmail.com>
---
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 c504e60b7c58..77ffe0ffd22b 100644
--- a/libsepol/cil/src/cil_resolve_ast.c
+++ b/libsepol/cil/src/cil_resolve_ast.c
@@ -1700,6 +1700,10 @@ int cil_resolve_level(struct cil_tree_node *current, struct cil_level *level, vo
struct cil_symtab_datum *sens_datum = NULL;
int rc = SEPOL_ERR;
+ if (level->sens) {
+ return SEPOL_OK;
+ }
+
rc = cil_resolve_name(current, (char*)level->sens_str, CIL_SYM_SENS, extra_args, &sens_datum);
if (rc != SEPOL_OK) {
cil_log(CIL_ERR, "Failed to find sensitivity\n");
--
2.32.0

View File

@ -1,58 +0,0 @@
From 644c5bbbc4c71f6636c939cb7748dd2dfa50e638 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Tue, 8 Jun 2021 21:39:02 +0200
Subject: [PATCH] libsepol: quote paths in CIL conversion
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
When generating CIL policy from kernel or module policy quote paths,
which are allowed to contain spaces, in the statements `genfscon` and
`devicetreecon`.
Reported by LuK1337 while building policy for Android via IRC.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
libsepol/src/kernel_to_cil.c | 4 ++--
libsepol/src/module_to_cil.c | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/libsepol/src/kernel_to_cil.c b/libsepol/src/kernel_to_cil.c
index 989aacde8a12..30a27bf527d5 100644
--- a/libsepol/src/kernel_to_cil.c
+++ b/libsepol/src/kernel_to_cil.c
@@ -2654,7 +2654,7 @@ static int write_genfscon_rules_to_cil(FILE *out, struct policydb *pdb)
goto exit;
}
- rc = strs_create_and_add(strs, "(genfscon %s %s %s)", 3,
+ rc = strs_create_and_add(strs, "(genfscon %s \"%s\" %s)", 3,
fstype, name, ctx);
free(ctx);
if (rc != 0) {
@@ -3115,7 +3115,7 @@ static int write_xen_devicetree_rules_to_cil(FILE *out, struct policydb *pdb)
goto exit;
}
- sepol_printf(out, "(devicetreecon %s %s)\n", name, ctx);
+ sepol_printf(out, "(devicetreecon \"%s\" %s)\n", name, ctx);
free(ctx);
}
diff --git a/libsepol/src/module_to_cil.c b/libsepol/src/module_to_cil.c
index 496693f4616e..19c7c65c6382 100644
--- a/libsepol/src/module_to_cil.c
+++ b/libsepol/src/module_to_cil.c
@@ -2963,7 +2963,7 @@ static int genfscon_to_cil(struct policydb *pdb)
for (genfs = pdb->genfs; genfs != NULL; genfs = genfs->next) {
for (ocon = genfs->head; ocon != NULL; ocon = ocon->next) {
- cil_printf("(genfscon %s %s ", genfs->fstype, ocon->u.name);
+ cil_printf("(genfscon %s \"%s\" ", genfs->fstype, ocon->u.name);
context_to_cil(pdb, &ocon->context[0]);
cil_printf(")\n");
}
--
2.32.0

View File

@ -1,93 +0,0 @@
From 9ac9d2dab40826abe049fd07d21a20386fe5b38b Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Mon, 14 Jun 2021 12:53:25 -0400
Subject: [PATCH] libsepol/cil: Fix anonymous IP address call arguments
A named IP address (using an ipaddr rule) could be passed as an
argument, but trying to pass an actual IP address caused an error.
As an exmample, consider the following portion of a policy.
(macro m4 ((ipaddr ip)(ipaddr nm))
(nodecon ip nm (USER ROLE TYPE ((s0) (s0))))
)
(ipaddr nm1 255.255.255.0)
(ipaddr ip1 1.2.3.4)
(call m4 (ip1 nm1)) ; This works
(call m4 (1.2.3.4 255.255.255.0)) ; This doesn't
Allow actual IP addresses to be passed as a call argument. Now the
second call works as well.
Signed-off-by: James Carter <jwcart2@gmail.com>
Acked-by: Nicolas Iooss <nicolas.iooss@m4x.org>
---
libsepol/cil/src/cil_build_ast.c | 4 ----
libsepol/cil/src/cil_resolve_ast.c | 23 ++++++++++-------------
2 files changed, 10 insertions(+), 17 deletions(-)
diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c
index 71f14e20e25e..538df2794ade 100644
--- a/libsepol/cil/src/cil_build_ast.c
+++ b/libsepol/cil/src/cil_build_ast.c
@@ -5642,10 +5642,6 @@ int cil_fill_ipaddr(struct cil_tree_node *addr_node, struct cil_ipaddr *addr)
goto exit;
}
- if (addr_node->cl_head != NULL || addr_node->next != NULL) {
- goto exit;
- }
-
if (strchr(addr_node->data, '.') != NULL) {
addr->family = AF_INET;
} else {
diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
index 77ffe0ffd22b..16c8c7533ce3 100644
--- a/libsepol/cil/src/cil_resolve_ast.c
+++ b/libsepol/cil/src/cil_resolve_ast.c
@@ -3024,14 +3024,18 @@ static int cil_build_call_args(struct cil_tree_node *call_node, struct cil_call
break;
}
case CIL_IPADDR: {
- if (arg_node->cl_head != NULL) {
+ if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
+ rc = SEPOL_ERR;
+ goto exit;
+ } else if (strchr(arg_node->data, '.') || strchr(arg_node->data, ':')) {
struct cil_ipaddr *ipaddr = NULL;
struct cil_tree_node *addr_node = NULL;
cil_ipaddr_init(&ipaddr);
-
- rc = cil_fill_ipaddr(arg_node->cl_head, ipaddr);
+ rc = cil_fill_ipaddr(arg_node, ipaddr);
if (rc != SEPOL_OK) {
- cil_log(CIL_ERR, "Failed to create anonymous ip address, rc: %d\n", rc);
+ cil_tree_log(call_node, CIL_ERR, "Failed to create anonymous ip address");
cil_destroy_ipaddr(ipaddr);
cil_destroy_args(arg);
goto exit;
@@ -3039,18 +3043,11 @@ static int cil_build_call_args(struct cil_tree_node *call_node, struct cil_call
cil_tree_node_init(&addr_node);
addr_node->flavor = CIL_IPADDR;
addr_node->data = ipaddr;
- cil_list_append(((struct cil_symtab_datum*)ipaddr)->nodes,
- CIL_LIST_ITEM, addr_node);
- arg->arg = (struct cil_symtab_datum*)ipaddr;
- } else if (arg_node->data == NULL) {
- cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
- cil_destroy_args(arg);
- rc = SEPOL_ERR;
- goto exit;
+ cil_list_append(DATUM(ipaddr)->nodes, CIL_LIST_ITEM, addr_node);
+ arg->arg = DATUM(ipaddr);
} else {
arg->arg_str = arg_node->data;
}
-
break;
}
case CIL_CLASS:
--
2.32.0

View File

@ -1,90 +0,0 @@
From 982ec302b67f3c7f8df667dadb67352b1e4a6d18 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Tue, 15 Jun 2021 10:40:20 -0400
Subject: [PATCH] libsepol/cil: Account for anonymous category sets in an
expression
It is possible for anonymous category sets to be in a category
expression if the expression has a macro parameter in it.
Unfortunately, anonymous category sets are not looked for when
resolving category expressions and a segfault will occur during
later processing if there was one.
As an example, consider the following portion of a policy.
(macro m1 ((categoryset cs))
(userlevel USER (s0 (cs)))
)
(call m1 ((c0 c1)))
This policy will cause a segault, because the categoryset datum
for the parameter cs is not seen as a categoryset and is treated
as a plain category.
When resolving an expression, check whether or not the datum that
is found is actually an anonymous category set associated with a
macro parameter. If it is, then resolve the category set if it
has not already been resolved and treat its categories as a sub
expression.
Signed-off-by: James Carter <jwcart2@gmail.com>
Acked-by: Nicolas Iooss <nicolas.iooss@m4x.org>
---
libsepol/cil/src/cil_resolve_ast.c | 24 +++++++++++++++++-------
1 file changed, 17 insertions(+), 7 deletions(-)
diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
index 16c8c7533ce3..42a58468ed36 100644
--- a/libsepol/cil/src/cil_resolve_ast.c
+++ b/libsepol/cil/src/cil_resolve_ast.c
@@ -3346,6 +3346,7 @@ int cil_resolve_expr(enum cil_flavor expr_type, struct cil_list *str_expr, struc
struct cil_list_item *curr;
struct cil_symtab_datum *res_datum = NULL;
enum cil_sym_index sym_index = CIL_SYM_UNKNOWN;
+ struct cil_list *datum_sub_expr;
switch (str_expr->flavor) {
case CIL_BOOL:
@@ -3379,18 +3380,26 @@ int cil_resolve_expr(enum cil_flavor expr_type, struct cil_list *str_expr, struc
if (rc != SEPOL_OK) {
goto exit;
}
-
- if (sym_index == CIL_SYM_TYPES && (expr_type == CIL_CONSTRAIN || expr_type == CIL_VALIDATETRANS)) {
- cil_type_used(res_datum, CIL_ATTR_CONSTRAINT);
+ if (sym_index == CIL_SYM_CATS && NODE(res_datum)->flavor == CIL_CATSET) {
+ struct cil_catset *catset = (struct cil_catset *)res_datum;
+ if (!catset->cats->datum_expr) {
+ rc = cil_resolve_expr(expr_type, catset->cats->str_expr, &catset->cats->datum_expr, parent, extra_args);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
+ }
+ cil_copy_list(catset->cats->datum_expr, &datum_sub_expr);
+ cil_list_append(*datum_expr, CIL_LIST, datum_sub_expr);
+ } else {
+ if (sym_index == CIL_SYM_TYPES && (expr_type == CIL_CONSTRAIN || expr_type == CIL_VALIDATETRANS)) {
+ cil_type_used(res_datum, CIL_ATTR_CONSTRAINT);
+ }
+ cil_list_append(*datum_expr, CIL_DATUM, res_datum);
}
-
- cil_list_append(*datum_expr, CIL_DATUM, res_datum);
break;
case CIL_LIST: {
- struct cil_list *datum_sub_expr;
rc = cil_resolve_expr(expr_type, curr->data, &datum_sub_expr, parent, extra_args);
if (rc != SEPOL_OK) {
- cil_list_destroy(&datum_sub_expr, CIL_TRUE);
goto exit;
}
cil_list_append(*datum_expr, CIL_LIST, datum_sub_expr);
@@ -3404,6 +3413,7 @@ int cil_resolve_expr(enum cil_flavor expr_type, struct cil_list *str_expr, struc
return SEPOL_OK;
exit:
+ cil_list_destroy(datum_expr, CIL_FALSE);
return rc;
}
--
2.32.0

View File

@ -1,46 +0,0 @@
From ce1025bf9ccd2e34a0c12d9a1d8eee19eb415573 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Tue, 15 Jun 2021 16:31:01 -0400
Subject: [PATCH] libsepol: Quote paths when generating policy.conf from binary
policy
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Christian Göttsche <cgzones@googlemail.com> submitted a similar patch
to quote paths when generating CIL policy from a binary policy.
Since genfscon and devicetreecon rules have paths which are allowed
to contain spaces, always quote the path when writing out these rules.
Signed-off-by: James Carter <jwcart2@gmail.com>
Acked-by: Petr Lautrbach <plautrba@redhat.com>
---
libsepol/src/kernel_to_conf.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libsepol/src/kernel_to_conf.c b/libsepol/src/kernel_to_conf.c
index 5db47fe4f567..ffdf179a71f3 100644
--- a/libsepol/src/kernel_to_conf.c
+++ b/libsepol/src/kernel_to_conf.c
@@ -2527,7 +2527,7 @@ static int write_genfscon_rules_to_conf(FILE *out, struct policydb *pdb)
goto exit;
}
- rc = strs_create_and_add(strs, "genfscon %s %s %s", 3,
+ rc = strs_create_and_add(strs, "genfscon %s \"%s\" %s", 3,
fstype, name, ctx);
free(ctx);
if (rc != 0) {
@@ -2992,7 +2992,7 @@ static int write_xen_devicetree_rules_to_conf(FILE *out, struct policydb *pdb)
goto exit;
}
- sepol_printf(out, "devicetreecon %s %s\n", name, ctx);
+ sepol_printf(out, "devicetreecon \"%s\" %s\n", name, ctx);
free(ctx);
}
--
2.32.0

View File

@ -1,72 +0,0 @@
From 2cb6bacddcd6957a8f28ce51a089e8514af3d574 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:50 +0200
Subject: [PATCH] libsepol: fix typos
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
---
libsepol/cil/src/cil_build_ast.c | 2 +-
libsepol/cil/src/cil_resolve_ast.c | 2 +-
libsepol/src/module_to_cil.c | 2 +-
libsepol/src/policydb_validate.c | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c
index 538df2794ade..96c97263d8c8 100644
--- a/libsepol/cil/src/cil_build_ast.c
+++ b/libsepol/cil/src/cil_build_ast.c
@@ -3692,7 +3692,7 @@ int cil_gen_sensitivityorder(struct cil_db *db, struct cil_tree_node *parse_curr
cil_list_for_each(curr, sensorder->sens_list_str) {
if (curr->data == CIL_KEY_UNORDERED) {
- cil_log(CIL_ERR, "Sensitivy order cannot be unordered.\n");
+ cil_log(CIL_ERR, "Sensitivity order cannot be unordered.\n");
rc = SEPOL_ERR;
goto exit;
}
diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
index 42a58468ed36..92a4d29700e9 100644
--- a/libsepol/cil/src/cil_resolve_ast.c
+++ b/libsepol/cil/src/cil_resolve_ast.c
@@ -1619,7 +1619,7 @@ int cil_resolve_sensitivityorder(struct cil_tree_node *current, void *extra_args
cil_list_for_each(curr, sensorder->sens_list_str) {
rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_SENS, extra_args, &datum);
if (rc != SEPOL_OK) {
- cil_log(CIL_ERR, "Failed to resolve sensitivty %s in sensitivityorder\n", (char *)curr->data);
+ cil_log(CIL_ERR, "Failed to resolve sensitivity %s in sensitivityorder\n", (char *)curr->data);
goto exit;
}
if (FLAVOR(datum) != CIL_SENS) {
diff --git a/libsepol/src/module_to_cil.c b/libsepol/src/module_to_cil.c
index 19c7c65c6382..60290da2a75f 100644
--- a/libsepol/src/module_to_cil.c
+++ b/libsepol/src/module_to_cil.c
@@ -3972,7 +3972,7 @@ int sepol_module_policydb_to_cil(FILE *fp, struct policydb *pdb, int linked)
if (pdb->policy_type != SEPOL_POLICY_BASE &&
pdb->policy_type != SEPOL_POLICY_MOD) {
- log_err("Policy pakcage is not a base or module");
+ log_err("Policy package is not a base or module");
rc = -1;
goto exit;
}
diff --git a/libsepol/src/policydb_validate.c b/libsepol/src/policydb_validate.c
index b2891ddd64f3..246aa6e398f3 100644
--- a/libsepol/src/policydb_validate.c
+++ b/libsepol/src/policydb_validate.c
@@ -641,7 +641,7 @@ static int validate_scope_index(sepol_handle_t *handle, scope_index_t *scope_ind
return 0;
bad:
- ERR(handle, "Invalide scope");
+ ERR(handle, "Invalid scope");
return -1;
}
--
2.32.0

View File

@ -1,203 +0,0 @@
From 9ec061b61c97878ac4d2626803dfbdd3fcbe0c87 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:51 +0200
Subject: [PATCH] libsepol: resolve missing prototypes
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Declare the functions as static or include the corresponding header
file.
assertion.c:294:5: error: no previous prototype for function 'report_assertion_failures' [-Werror,-Wmissing-prototypes]
int report_assertion_failures(sepol_handle_t *handle, policydb_t *p, avrule_t *avrule)
^
context.c:23:5: error: no previous prototype for function 'sepol_check_context' [-Werror,-Wmissing-prototypes]
int sepol_check_context(const char *context)
^
expand.c:3377:5: error: no previous prototype for function 'expand_cond_av_node' [-Werror,-Wmissing-prototypes]
int expand_cond_av_node(policydb_t * p,
^
policydb.c:638:6: error: no previous prototype for function 'role_trans_rule_destroy' [-Werror,-Wmissing-prototypes]
void role_trans_rule_destroy(role_trans_rule_t * x)
^
policydb.c:1169:5: error: no previous prototype for function 'policydb_index_decls' [-Werror,-Wmissing-prototypes]
int policydb_index_decls(sepol_handle_t * handle, policydb_t * p)
^
policydb.c:1429:6: error: no previous prototype for function 'ocontext_selinux_free' [-Werror,-Wmissing-prototypes]
void ocontext_selinux_free(ocontext_t **ocontexts)
^
policydb.c:1451:6: error: no previous prototype for function 'ocontext_xen_free' [-Werror,-Wmissing-prototypes]
void ocontext_xen_free(ocontext_t **ocontexts)
^
policydb.c:1750:5: error: no previous prototype for function 'type_set_or' [-Werror,-Wmissing-prototypes]
int type_set_or(type_set_t * dst, type_set_t * a, type_set_t * b)
^
policydb.c:2524:5: error: no previous prototype for function 'role_trans_read' [-Werror,-Wmissing-prototypes]
int role_trans_read(policydb_t *p, struct policy_file *fp)
^
policydb.c:2567:5: error: no previous prototype for function 'role_allow_read' [-Werror,-Wmissing-prototypes]
int role_allow_read(role_allow_t ** r, struct policy_file *fp)
^
policydb.c:2842:5: error: no previous prototype for function 'filename_trans_read' [-Werror,-Wmissing-prototypes]
int filename_trans_read(policydb_t *p, struct policy_file *fp)
^
services.c:1027:5: error: no previous prototype for function 'sepol_validate_transition' [-Werror,-Wmissing-prototypes]
int sepol_validate_transition(sepol_security_id_t oldsid,
^
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
---
libsepol/src/assertion.c | 2 +-
libsepol/src/context_internal.h | 1 +
libsepol/src/expand.c | 6 +++---
libsepol/src/policydb.c | 16 ++++++++--------
libsepol/src/services.c | 2 +-
5 files changed, 14 insertions(+), 13 deletions(-)
diff --git a/libsepol/src/assertion.c b/libsepol/src/assertion.c
index 266f67d74c56..dd2749a09dc0 100644
--- a/libsepol/src/assertion.c
+++ b/libsepol/src/assertion.c
@@ -291,7 +291,7 @@ exit:
return rc;
}
-int report_assertion_failures(sepol_handle_t *handle, policydb_t *p, avrule_t *avrule)
+static int report_assertion_failures(sepol_handle_t *handle, policydb_t *p, avrule_t *avrule)
{
int rc;
struct avtab_match_args args;
diff --git a/libsepol/src/context_internal.h b/libsepol/src/context_internal.h
index 3cae28cc1c67..3dc9cd156a9c 100644
--- a/libsepol/src/context_internal.h
+++ b/libsepol/src/context_internal.h
@@ -1,6 +1,7 @@
#ifndef _SEPOL_CONTEXT_INTERNAL_H_
#define _SEPOL_CONTEXT_INTERNAL_H_
+#include <sepol/context.h>
#include <sepol/context_record.h>
#endif
diff --git a/libsepol/src/expand.c b/libsepol/src/expand.c
index a656ffad3a71..84bfcfa36d0a 100644
--- a/libsepol/src/expand.c
+++ b/libsepol/src/expand.c
@@ -3374,9 +3374,9 @@ static int expand_cond_insert(cond_av_list_t ** l,
return 0;
}
-int expand_cond_av_node(policydb_t * p,
- avtab_ptr_t node,
- cond_av_list_t ** newl, avtab_t * expa)
+static int expand_cond_av_node(policydb_t * p,
+ avtab_ptr_t node,
+ cond_av_list_t ** newl, avtab_t * expa)
{
avtab_key_t *k = &node->key;
avtab_datum_t *d = &node->datum;
diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c
index ffa279715686..3f7ddb11a236 100644
--- a/libsepol/src/policydb.c
+++ b/libsepol/src/policydb.c
@@ -635,7 +635,7 @@ void role_trans_rule_init(role_trans_rule_t * x)
ebitmap_init(&x->classes);
}
-void role_trans_rule_destroy(role_trans_rule_t * x)
+static void role_trans_rule_destroy(role_trans_rule_t * x)
{
if (x != NULL) {
role_set_destroy(&x->roles);
@@ -1166,7 +1166,7 @@ int policydb_index_bools(policydb_t * p)
return 0;
}
-int policydb_index_decls(sepol_handle_t * handle, policydb_t * p)
+static int policydb_index_decls(sepol_handle_t * handle, policydb_t * p)
{
avrule_block_t *curblock;
avrule_decl_t *decl;
@@ -1426,7 +1426,7 @@ static int range_tr_destroy(hashtab_key_t key, hashtab_datum_t datum,
return 0;
}
-void ocontext_selinux_free(ocontext_t **ocontexts)
+static void ocontext_selinux_free(ocontext_t **ocontexts)
{
ocontext_t *c, *ctmp;
int i;
@@ -1448,7 +1448,7 @@ void ocontext_selinux_free(ocontext_t **ocontexts)
}
}
-void ocontext_xen_free(ocontext_t **ocontexts)
+static void ocontext_xen_free(ocontext_t **ocontexts)
{
ocontext_t *c, *ctmp;
int i;
@@ -1747,7 +1747,7 @@ int symtab_insert(policydb_t * pol, uint32_t sym,
return retval;
}
-int type_set_or(type_set_t * dst, type_set_t * a, type_set_t * b)
+static int type_set_or(type_set_t * dst, type_set_t * a, type_set_t * b)
{
type_set_init(dst);
@@ -2521,7 +2521,7 @@ static int type_read(policydb_t * p, hashtab_t h, struct policy_file *fp)
return -1;
}
-int role_trans_read(policydb_t *p, struct policy_file *fp)
+static int role_trans_read(policydb_t *p, struct policy_file *fp)
{
role_trans_t **t = &p->role_tr;
unsigned int i;
@@ -2564,7 +2564,7 @@ int role_trans_read(policydb_t *p, struct policy_file *fp)
return 0;
}
-int role_allow_read(role_allow_t ** r, struct policy_file *fp)
+static int role_allow_read(role_allow_t ** r, struct policy_file *fp)
{
unsigned int i;
uint32_t buf[2], nel;
@@ -2839,7 +2839,7 @@ err:
return -1;
}
-int filename_trans_read(policydb_t *p, struct policy_file *fp)
+static int filename_trans_read(policydb_t *p, struct policy_file *fp)
{
unsigned int i;
uint32_t buf[1], nel;
diff --git a/libsepol/src/services.c b/libsepol/src/services.c
index 6596431c38e2..39fbd979b095 100644
--- a/libsepol/src/services.c
+++ b/libsepol/src/services.c
@@ -1024,7 +1024,7 @@ static int context_struct_compute_av(context_struct_t * scontext,
return 0;
}
-int sepol_validate_transition(sepol_security_id_t oldsid,
+static int sepol_validate_transition(sepol_security_id_t oldsid,
sepol_security_id_t newsid,
sepol_security_id_t tasksid,
sepol_security_class_t tclass)
--
2.32.0

View File

@ -1,151 +0,0 @@
From 42f3d7cceb1e15f10eb8e886e6f07ee3c3c6130f 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:52 +0200
Subject: [PATCH] libsepol: remove unused functions
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The functions `role_set_get_role`, `sepol_validate_transition` and
`sepol_sidtab_remove` seem to be unused since the initial import.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
---
libsepol/src/policydb.c | 18 ----------------
libsepol/src/services.c | 47 -----------------------------------------
libsepol/src/sidtab.c | 31 ---------------------------
3 files changed, 96 deletions(-)
diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c
index 3f7ddb11a236..fc1d07112efb 100644
--- a/libsepol/src/policydb.c
+++ b/libsepol/src/policydb.c
@@ -1791,24 +1791,6 @@ int type_set_or_eq(type_set_t * dst, type_set_t * other)
return ret;
}
-int role_set_get_role(role_set_t * x, uint32_t role)
-{
- if (x->flags & ROLE_STAR)
- return 1;
-
- if (ebitmap_get_bit(&x->roles, role - 1)) {
- if (x->flags & ROLE_COMP)
- return 0;
- else
- return 1;
- } else {
- if (x->flags & ROLE_COMP)
- return 1;
- else
- return 0;
- }
-}
-
/***********************************************************************/
/* everything below is for policy reads */
diff --git a/libsepol/src/services.c b/libsepol/src/services.c
index 39fbd979b095..ff91f7d2fdfc 100644
--- a/libsepol/src/services.c
+++ b/libsepol/src/services.c
@@ -1024,53 +1024,6 @@ static int context_struct_compute_av(context_struct_t * scontext,
return 0;
}
-static int sepol_validate_transition(sepol_security_id_t oldsid,
- sepol_security_id_t newsid,
- sepol_security_id_t tasksid,
- sepol_security_class_t tclass)
-{
- context_struct_t *ocontext;
- context_struct_t *ncontext;
- context_struct_t *tcontext;
- class_datum_t *tclass_datum;
- constraint_node_t *constraint;
-
- if (!tclass || tclass > policydb->p_classes.nprim) {
- ERR(NULL, "unrecognized class %d", tclass);
- return -EINVAL;
- }
- tclass_datum = policydb->class_val_to_struct[tclass - 1];
-
- ocontext = sepol_sidtab_search(sidtab, oldsid);
- if (!ocontext) {
- ERR(NULL, "unrecognized SID %d", oldsid);
- return -EINVAL;
- }
-
- ncontext = sepol_sidtab_search(sidtab, newsid);
- if (!ncontext) {
- ERR(NULL, "unrecognized SID %d", newsid);
- return -EINVAL;
- }
-
- tcontext = sepol_sidtab_search(sidtab, tasksid);
- if (!tcontext) {
- ERR(NULL, "unrecognized SID %d", tasksid);
- return -EINVAL;
- }
-
- constraint = tclass_datum->validatetrans;
- while (constraint) {
- if (!constraint_expr_eval_reason(ocontext, ncontext, tcontext,
- 0, constraint, NULL, 0)) {
- return -EPERM;
- }
- constraint = constraint->next;
- }
-
- return 0;
-}
-
/*
* sepol_validate_transition_reason_buffer - the reason buffer is realloc'd
* in the constraint_expr_eval_reason() function.
diff --git a/libsepol/src/sidtab.c b/libsepol/src/sidtab.c
index e6bf57161e52..255e07252412 100644
--- a/libsepol/src/sidtab.c
+++ b/libsepol/src/sidtab.c
@@ -84,37 +84,6 @@ int sepol_sidtab_insert(sidtab_t * s, sepol_security_id_t sid,
return 0;
}
-int sepol_sidtab_remove(sidtab_t * s, sepol_security_id_t sid)
-{
- int hvalue;
- sidtab_node_t *cur, *last;
-
- if (!s || !s->htable)
- return -ENOENT;
-
- hvalue = SIDTAB_HASH(sid);
- last = NULL;
- cur = s->htable[hvalue];
- while (cur != NULL && sid > cur->sid) {
- last = cur;
- cur = cur->next;
- }
-
- if (cur == NULL || sid != cur->sid)
- return -ENOENT;
-
- if (last == NULL)
- s->htable[hvalue] = cur->next;
- else
- last->next = cur->next;
-
- context_destroy(&cur->context);
-
- free(cur);
- s->nel--;
- return 0;
-}
-
context_struct_t *sepol_sidtab_search(sidtab_t * s, sepol_security_id_t sid)
{
int hvalue;
--
2.32.0

View File

@ -1,47 +0,0 @@
From 1537ea8412e4af832b53ac48b7d85eac00426a92 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:55 +0200
Subject: [PATCH] libsepol: avoid unsigned integer overflow
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Unsigned integer overflow is well-defined and not undefined behavior.
But it is still useful to enable undefined behavior sanitizer checks on
unsigned arithmetic to detect possible issues on counters or variables
with similar purpose.
Use a spaceship operator like comparison instead of subtraction.
Modern compilers will generate a single comparison instruction instead
of actually perform the subtraction.
policydb.c:826:17: runtime error: unsigned integer overflow: 24 - 1699 cannot be represented in type 'unsigned int'
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
---
libsepol/src/policydb.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c
index fc1d07112efb..e0b072e1938f 100644
--- a/libsepol/src/policydb.c
+++ b/libsepol/src/policydb.c
@@ -817,11 +817,11 @@ static int filenametr_cmp(hashtab_t h __attribute__ ((unused)),
const filename_trans_key_t *ft2 = (const filename_trans_key_t *)k2;
int v;
- v = ft1->ttype - ft2->ttype;
+ v = (ft1->ttype > ft2->ttype) - (ft1->ttype < ft2->ttype);
if (v)
return v;
- v = ft1->tclass - ft2->tclass;
+ v = (ft1->tclass > ft2->tclass) - (ft1->tclass < ft2->tclass);
if (v)
return v;
--
2.32.0

View File

@ -1,335 +0,0 @@
From 8f50b45320f715aa7ab883fe3540017bdc097e20 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:56 +0200
Subject: [PATCH] libsepol: 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/src/booleans.c | 6 ++--
libsepol/src/debug.c | 2 +-
libsepol/src/ebitmap.c | 11 ++++---
libsepol/src/module_to_cil.c | 10 +++---
libsepol/src/nodes.c | 6 ++--
libsepol/src/services.c | 59 ++++++++++++++++++------------------
libsepol/src/util.c | 2 +-
7 files changed, 50 insertions(+), 46 deletions(-)
diff --git a/libsepol/src/booleans.c b/libsepol/src/booleans.c
index 30fcf29d892b..716da6b487a9 100644
--- a/libsepol/src/booleans.c
+++ b/libsepol/src/booleans.c
@@ -19,6 +19,7 @@ static int bool_update(sepol_handle_t * handle,
const char *cname;
char *name;
int value;
+ cond_bool_datum_t *datum;
sepol_bool_key_unpack(key, &cname);
name = strdup(cname);
@@ -27,8 +28,7 @@ static int bool_update(sepol_handle_t * handle,
if (!name)
goto omem;
- cond_bool_datum_t *datum =
- hashtab_search(policydb->p_bools.table, name);
+ datum = hashtab_search(policydb->p_bools.table, name);
if (!datum) {
ERR(handle, "boolean %s no longer in policy", name);
goto err;
@@ -84,10 +84,10 @@ int sepol_bool_set(sepol_handle_t * handle,
const sepol_bool_key_t * key, const sepol_bool_t * data)
{
+ policydb_t *policydb = &p->p;
const char *name;
sepol_bool_key_unpack(key, &name);
- policydb_t *policydb = &p->p;
if (bool_update(handle, policydb, key, data) < 0)
goto err;
diff --git a/libsepol/src/debug.c b/libsepol/src/debug.c
index 0458e3538884..f6a59ae701ed 100644
--- a/libsepol/src/debug.c
+++ b/libsepol/src/debug.c
@@ -44,6 +44,7 @@ void sepol_msg_default_handler(void *varg __attribute__ ((unused)),
{
FILE *stream = NULL;
+ va_list ap;
switch (sepol_msg_get_level(handle)) {
@@ -60,7 +61,6 @@ void sepol_msg_default_handler(void *varg __attribute__ ((unused)),
fprintf(stream, "%s.%s: ",
sepol_msg_get_channel(handle), sepol_msg_get_fname(handle));
- va_list ap;
va_start(ap, fmt);
vfprintf(stream, fmt, ap);
va_end(ap);
diff --git a/libsepol/src/ebitmap.c b/libsepol/src/ebitmap.c
index 7f425349c229..522e14a68a94 100644
--- a/libsepol/src/ebitmap.c
+++ b/libsepol/src/ebitmap.c
@@ -113,9 +113,10 @@ int ebitmap_not(ebitmap_t *dst, ebitmap_t *e1, unsigned int maxbit)
int ebitmap_andnot(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2, unsigned int maxbit)
{
+ int rc;
ebitmap_t e3;
ebitmap_init(dst);
- int rc = ebitmap_not(&e3, e2, maxbit);
+ rc = ebitmap_not(&e3, e2, maxbit);
if (rc < 0)
return rc;
rc = ebitmap_and(dst, e1, &e3);
@@ -138,13 +139,15 @@ unsigned int ebitmap_cardinality(ebitmap_t *e1)
int ebitmap_hamming_distance(ebitmap_t * e1, ebitmap_t * e2)
{
+ int rc;
+ ebitmap_t tmp;
+ int distance;
if (ebitmap_cmp(e1, e2))
return 0;
- ebitmap_t tmp;
- int rc = ebitmap_xor(&tmp, e1, e2);
+ rc = ebitmap_xor(&tmp, e1, e2);
if (rc < 0)
return -1;
- int distance = ebitmap_cardinality(&tmp);
+ distance = ebitmap_cardinality(&tmp);
ebitmap_destroy(&tmp);
return distance;
}
diff --git a/libsepol/src/module_to_cil.c b/libsepol/src/module_to_cil.c
index 60290da2a75f..580ba06a95b0 100644
--- a/libsepol/src/module_to_cil.c
+++ b/libsepol/src/module_to_cil.c
@@ -107,8 +107,8 @@ static void cil_printf(const char *fmt, ...) {
__attribute__ ((format(printf, 2, 3)))
static void cil_println(int indent, const char *fmt, ...)
{
- cil_indent(indent);
va_list argptr;
+ cil_indent(indent);
va_start(argptr, fmt);
if (vfprintf(out_file, fmt, argptr) < 0) {
log_err("Failed to write to output");
@@ -235,12 +235,14 @@ static void role_list_destroy(void)
static void attr_list_destroy(struct list **attr_list)
{
+ struct list_node *curr;
+ struct attr_list_node *attr;
+
if (attr_list == NULL || *attr_list == NULL) {
return;
}
- struct list_node *curr = (*attr_list)->head;
- struct attr_list_node *attr;
+ curr = (*attr_list)->head;
while (curr != NULL) {
attr = curr->data;
@@ -3525,12 +3527,12 @@ exit:
static int additive_scopes_to_cil(int indent, struct policydb *pdb, struct avrule_block *block, struct stack *decl_stack)
{
int rc = -1;
+ struct avrule_decl *decl = stack_peek(decl_stack);
struct map_args args;
args.pdb = pdb;
args.block = block;
args.decl_stack = decl_stack;
args.indent = indent;
- struct avrule_decl *decl = stack_peek(decl_stack);
for (args.sym_index = 0; args.sym_index < SYM_NUM; args.sym_index++) {
if (func_to_cil[args.sym_index] == NULL) {
diff --git a/libsepol/src/nodes.c b/libsepol/src/nodes.c
index 820346d0f5df..97a0f959c7ca 100644
--- a/libsepol/src/nodes.c
+++ b/libsepol/src/nodes.c
@@ -19,20 +19,20 @@ static int node_from_record(sepol_handle_t * handle,
ocontext_t *tmp_node = NULL;
context_struct_t *tmp_con = NULL;
char *addr_buf = NULL, *mask_buf = NULL;
+ size_t addr_bsize, mask_bsize;
+ int proto;
tmp_node = (ocontext_t *) calloc(1, sizeof(ocontext_t));
if (!tmp_node)
goto omem;
- size_t addr_bsize, mask_bsize;
-
/* Address and netmask */
if (sepol_node_get_addr_bytes(handle, data, &addr_buf, &addr_bsize) < 0)
goto err;
if (sepol_node_get_mask_bytes(handle, data, &mask_buf, &mask_bsize) < 0)
goto err;
- int proto = sepol_node_get_proto(data);
+ proto = sepol_node_get_proto(data);
switch (proto) {
case SEPOL_PROTO_IP4:
diff --git a/libsepol/src/services.c b/libsepol/src/services.c
index ff91f7d2fdfc..d647c8f57300 100644
--- a/libsepol/src/services.c
+++ b/libsepol/src/services.c
@@ -290,6 +290,19 @@ static char *get_class_info(sepol_security_class_t tclass,
{
constraint_expr_t *e;
int mls, state_num;
+ /* Determine statement type */
+ const char *statements[] = {
+ "constrain ", /* 0 */
+ "mlsconstrain ", /* 1 */
+ "validatetrans ", /* 2 */
+ "mlsvalidatetrans ", /* 3 */
+ 0 };
+ size_t class_buf_len = 0;
+ size_t new_class_buf_len;
+ size_t buf_used;
+ int len;
+ char *class_buf = NULL, *p;
+ char *new_class_buf = NULL;
/* Find if MLS statement or not */
mls = 0;
@@ -300,26 +313,11 @@ static char *get_class_info(sepol_security_class_t tclass,
}
}
- /* Determine statement type */
- const char *statements[] = {
- "constrain ", /* 0 */
- "mlsconstrain ", /* 1 */
- "validatetrans ", /* 2 */
- "mlsvalidatetrans ", /* 3 */
- 0 };
-
if (xcontext == NULL)
state_num = mls + 0;
else
state_num = mls + 2;
- size_t class_buf_len = 0;
- size_t new_class_buf_len;
- size_t buf_used;
- int len;
- char *class_buf = NULL, *p;
- char *new_class_buf = NULL;
-
while (1) {
new_class_buf_len = class_buf_len + EXPR_BUF_SIZE;
new_class_buf = realloc(class_buf, new_class_buf_len);
@@ -417,6 +415,8 @@ static int constraint_expr_eval_reason(context_struct_t *scontext,
char *tgt = NULL;
int rc = 0, x;
char *class_buf = NULL;
+ int expr_list_len = 0;
+ int expr_count;
/*
* The array of expression answer buffer pointers and counter.
@@ -424,6 +424,11 @@ static int constraint_expr_eval_reason(context_struct_t *scontext,
char **answer_list = NULL;
int answer_counter = 0;
+ /* The pop operands */
+ char *a;
+ char *b;
+ int a_len, b_len;
+
class_buf = get_class_info(tclass, constraint, xcontext);
if (!class_buf) {
ERR(NULL, "failed to allocate class buffer");
@@ -431,7 +436,6 @@ static int constraint_expr_eval_reason(context_struct_t *scontext,
}
/* Original function but with buffer support */
- int expr_list_len = 0;
expr_counter = 0;
expr_list = NULL;
for (e = constraint->expr; e; e = e->next) {
@@ -701,7 +705,7 @@ mls_ops:
* expr_list malloc's. Normally they are released by the RPN to
* infix code.
*/
- int expr_count = expr_counter;
+ expr_count = expr_counter;
expr_counter = 0;
/*
@@ -715,11 +719,6 @@ mls_ops:
goto out;
}
- /* The pop operands */
- char *a;
- char *b;
- int a_len, b_len;
-
/* Convert constraint from RPN to infix notation. */
for (x = 0; x != expr_count; x++) {
if (strncmp(expr_list[x], "and", 3) == 0 || strncmp(expr_list[x],
@@ -778,14 +777,6 @@ mls_ops:
xcontext ? "Validatetrans" : "Constraint",
s[0] ? "GRANTED" : "DENIED");
- int len, new_buf_len;
- char *p, **new_buf = r_buf;
- /*
- * These contain the constraint components that are added to the
- * callers reason buffer.
- */
- const char *buffers[] = { class_buf, a, "); ", tmp_buf, 0 };
-
/*
* This will add the constraints to the callers reason buffer (who is
* responsible for freeing the memory). It will handle any realloc's
@@ -796,6 +787,14 @@ mls_ops:
if (r_buf && ((s[0] == 0) || ((s[0] == 1 &&
(flags & SHOW_GRANTED) == SHOW_GRANTED)))) {
+ int len, new_buf_len;
+ char *p, **new_buf = r_buf;
+ /*
+ * These contain the constraint components that are added to the
+ * callers reason buffer.
+ */
+ const char *buffers[] = { class_buf, a, "); ", tmp_buf, 0 };
+
for (x = 0; buffers[x] != NULL; x++) {
while (1) {
p = *r_buf + reason_buf_used;
diff --git a/libsepol/src/util.c b/libsepol/src/util.c
index d51750af3fa1..a47cae87bfed 100644
--- a/libsepol/src/util.c
+++ b/libsepol/src/util.c
@@ -129,9 +129,9 @@ char *sepol_extended_perms_to_string(avtab_extended_perms_t *xperms)
unsigned int bit;
unsigned int in_range = 0;
static char xpermsbuf[2048];
- xpermsbuf[0] = '\0';
char *p;
int len, xpermslen = 0;
+ xpermsbuf[0] = '\0';
p = xpermsbuf;
if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION)
--
2.32.0

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 18532aad9801..85094b01ef9d 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 96c97263d8c8..908b0336d1dd 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 097222a83da9..46db069b254a 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 4e7843cb01ef..8a426f1f5950 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 05842b644807..7bca0834ad39 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 92a4d29700e9..b5199bad35e2 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 2598bbf3d80e..70bca3630220 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");
--
2.32.0

View File

@ -1,92 +0,0 @@
From a53a845b76f674f2a11cd178222042bc9c3fdae6 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:58 +0200
Subject: [PATCH] libsepol: remove dead stores
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
conditional.c:391:4: warning: Value stored to 'i' is never read [deadcode.DeadStores]
i = 0;
^ ~
conditional.c:718:2: warning: Value stored to 'len' is never read [deadcode.DeadStores]
len = 0;
^ ~
conditional.c:772:2: warning: Value stored to 'len' is never read [deadcode.DeadStores]
len = 0;
^ ~
services.c:89:10: warning: Value stored to 'new_stack' during its initialization is never read [deadcode.DeadStores]
char **new_stack = stack;
^~~~~~~~~ ~~~~~
services.c:440:11: warning: Value stored to 'new_expr_list' during its initialization is never read [deadcode.DeadStores]
char **new_expr_list = expr_list;
^~~~~~~~~~~~~ ~~~~~~~~~
../cil/src/cil_binary.c:2230:24: warning: Value stored to 'cb_node' during its initialization is never read [deadcode.DeadStores]
struct cil_tree_node *cb_node = node->cl_head;
^~~~~~~ ~~~~~~~~~~~~~
Found by clang-analyzer
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
---
libsepol/src/conditional.c | 3 ---
libsepol/src/services.c | 4 ++--
2 files changed, 2 insertions(+), 5 deletions(-)
diff --git a/libsepol/src/conditional.c b/libsepol/src/conditional.c
index 823b649a9163..e3ede694e59f 100644
--- a/libsepol/src/conditional.c
+++ b/libsepol/src/conditional.c
@@ -388,7 +388,6 @@ int cond_normalize_expr(policydb_t * p, cond_node_t * cn)
for (e = cn->expr; e != NULL; e = e->next) {
switch (e->expr_type) {
case COND_BOOL:
- i = 0;
/* see if we've already seen this bool */
if (!bool_present(e->bool, cn->bool_ids, cn->nbools)) {
/* count em all but only record up to COND_MAX_BOOLS */
@@ -715,7 +714,6 @@ static int cond_read_av_list(policydb_t * p, void *fp,
*ret_list = NULL;
- len = 0;
rc = next_entry(buf, fp, sizeof(uint32_t));
if (rc < 0)
return -1;
@@ -769,7 +767,6 @@ static int cond_read_node(policydb_t * p, cond_node_t * node, void *fp)
node->cur_state = le32_to_cpu(buf[0]);
- len = 0;
rc = next_entry(buf, fp, sizeof(uint32_t));
if (rc < 0)
goto err;
diff --git a/libsepol/src/services.c b/libsepol/src/services.c
index d647c8f57300..c34bb9667fbc 100644
--- a/libsepol/src/services.c
+++ b/libsepol/src/services.c
@@ -86,7 +86,7 @@ static int next_stack_entry;
static void push(char *expr_ptr)
{
if (next_stack_entry >= stack_len) {
- char **new_stack = stack;
+ char **new_stack;
int new_stack_len;
if (stack_len == 0)
@@ -441,7 +441,7 @@ static int constraint_expr_eval_reason(context_struct_t *scontext,
for (e = constraint->expr; e; e = e->next) {
/* Allocate a stack to hold expression buffer entries */
if (expr_counter >= expr_list_len) {
- char **new_expr_list = expr_list;
+ char **new_expr_list;
int new_expr_list_len;
if (expr_list_len == 0)
--
2.32.0

View File

@ -1,135 +0,0 @@
From 390ec54d278a14d9c29b80cc4fc5cb9ba504ed13 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:59 +0200
Subject: [PATCH] libsepol: mark read-only parameters of ebitmap interfaces
const
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Make it more obvious which parameters are read-only and not being
modified and allow callers to pass const pointers.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
---
libsepol/include/sepol/policydb/ebitmap.h | 16 ++++++++--------
libsepol/src/ebitmap.c | 18 +++++++++---------
2 files changed, 17 insertions(+), 17 deletions(-)
diff --git a/libsepol/include/sepol/policydb/ebitmap.h b/libsepol/include/sepol/policydb/ebitmap.h
index 634436f6c30b..81d0c7a67347 100644
--- a/libsepol/include/sepol/policydb/ebitmap.h
+++ b/libsepol/include/sepol/policydb/ebitmap.h
@@ -67,7 +67,7 @@ static inline unsigned int ebitmap_next(ebitmap_node_t ** n, unsigned int bit)
return (bit + 1);
}
-static inline int ebitmap_node_get_bit(ebitmap_node_t * n, unsigned int bit)
+static inline int ebitmap_node_get_bit(const ebitmap_node_t * n, unsigned int bit)
{
if (n->map & (MAPBIT << (bit - n->startbit)))
return 1;
@@ -83,18 +83,18 @@ static inline int ebitmap_node_get_bit(ebitmap_node_t * n, unsigned int bit)
extern int ebitmap_cmp(const ebitmap_t * e1, const ebitmap_t * e2);
extern int ebitmap_or(ebitmap_t * dst, const ebitmap_t * e1, const ebitmap_t * e2);
extern int ebitmap_union(ebitmap_t * dst, const ebitmap_t * e1);
-extern int ebitmap_and(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2);
-extern int ebitmap_xor(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2);
-extern int ebitmap_not(ebitmap_t *dst, ebitmap_t *e1, unsigned int maxbit);
-extern int ebitmap_andnot(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2, unsigned int maxbit);
-extern unsigned int ebitmap_cardinality(ebitmap_t *e1);
-extern int ebitmap_hamming_distance(ebitmap_t * e1, ebitmap_t * e2);
+extern int ebitmap_and(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2);
+extern int ebitmap_xor(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2);
+extern int ebitmap_not(ebitmap_t *dst, const ebitmap_t *e1, unsigned int maxbit);
+extern int ebitmap_andnot(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2, unsigned int maxbit);
+extern unsigned int ebitmap_cardinality(const ebitmap_t *e1);
+extern int ebitmap_hamming_distance(const ebitmap_t * e1, const ebitmap_t * e2);
extern int ebitmap_cpy(ebitmap_t * dst, const ebitmap_t * src);
extern int ebitmap_contains(const ebitmap_t * e1, const ebitmap_t * e2);
extern int ebitmap_match_any(const ebitmap_t *e1, const ebitmap_t *e2);
extern int ebitmap_get_bit(const ebitmap_t * e, unsigned int bit);
extern int ebitmap_set_bit(ebitmap_t * e, unsigned int bit, int value);
-extern unsigned int ebitmap_highest_set_bit(ebitmap_t * e);
+extern unsigned int ebitmap_highest_set_bit(const ebitmap_t * e);
extern void ebitmap_destroy(ebitmap_t * e);
extern int ebitmap_read(ebitmap_t * e, void *fp);
diff --git a/libsepol/src/ebitmap.c b/libsepol/src/ebitmap.c
index 522e14a68a94..4e9acdf868a2 100644
--- a/libsepol/src/ebitmap.c
+++ b/libsepol/src/ebitmap.c
@@ -71,7 +71,7 @@ int ebitmap_union(ebitmap_t * dst, const ebitmap_t * e1)
return 0;
}
-int ebitmap_and(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2)
+int ebitmap_and(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2)
{
unsigned int i, length = min(ebitmap_length(e1), ebitmap_length(e2));
ebitmap_init(dst);
@@ -85,7 +85,7 @@ int ebitmap_and(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2)
return 0;
}
-int ebitmap_xor(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2)
+int ebitmap_xor(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2)
{
unsigned int i, length = max(ebitmap_length(e1), ebitmap_length(e2));
ebitmap_init(dst);
@@ -98,7 +98,7 @@ int ebitmap_xor(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2)
return 0;
}
-int ebitmap_not(ebitmap_t *dst, ebitmap_t *e1, unsigned int maxbit)
+int ebitmap_not(ebitmap_t *dst, const ebitmap_t *e1, unsigned int maxbit)
{
unsigned int i;
ebitmap_init(dst);
@@ -111,7 +111,7 @@ int ebitmap_not(ebitmap_t *dst, ebitmap_t *e1, unsigned int maxbit)
return 0;
}
-int ebitmap_andnot(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2, unsigned int maxbit)
+int ebitmap_andnot(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2, unsigned int maxbit)
{
int rc;
ebitmap_t e3;
@@ -126,10 +126,10 @@ int ebitmap_andnot(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2, unsigned int ma
return 0;
}
-unsigned int ebitmap_cardinality(ebitmap_t *e1)
+unsigned int ebitmap_cardinality(const ebitmap_t *e1)
{
unsigned int count = 0;
- ebitmap_node_t *n;
+ const ebitmap_node_t *n;
for (n = e1->node; n; n = n->next) {
count += __builtin_popcountll(n->map);
@@ -137,7 +137,7 @@ unsigned int ebitmap_cardinality(ebitmap_t *e1)
return count;
}
-int ebitmap_hamming_distance(ebitmap_t * e1, ebitmap_t * e2)
+int ebitmap_hamming_distance(const ebitmap_t * e1, const ebitmap_t * e2)
{
int rc;
ebitmap_t tmp;
@@ -347,9 +347,9 @@ int ebitmap_set_bit(ebitmap_t * e, unsigned int bit, int value)
return 0;
}
-unsigned int ebitmap_highest_set_bit(ebitmap_t * e)
+unsigned int ebitmap_highest_set_bit(const ebitmap_t * e)
{
- ebitmap_node_t *n;
+ const ebitmap_node_t *n;
MAPTYPE map;
unsigned int pos = 0;
--
2.32.0

View File

@ -1,68 +0,0 @@
From 8eec1bb50230c78faaeb9ccc0decb83cad205bf2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Tue, 8 Jun 2021 17:59:00 +0200
Subject: [PATCH] libsepol: mark read-only parameters of type_set_ interfaces
const
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Make it more obvious which parameters are read-only and not being
modified and allow callers to pass const pointers.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
---
libsepol/include/sepol/policydb/policydb.h | 4 ++--
libsepol/src/policydb.c | 6 +++---
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/libsepol/include/sepol/policydb/policydb.h b/libsepol/include/sepol/policydb/policydb.h
index 9ef43abc2f12..6976ef4831ef 100644
--- a/libsepol/include/sepol/policydb/policydb.h
+++ b/libsepol/include/sepol/policydb/policydb.h
@@ -667,8 +667,8 @@ extern int scope_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p);
extern void class_perm_node_init(class_perm_node_t * x);
extern void type_set_init(type_set_t * x);
extern void type_set_destroy(type_set_t * x);
-extern int type_set_cpy(type_set_t * dst, type_set_t * src);
-extern int type_set_or_eq(type_set_t * dst, type_set_t * other);
+extern int type_set_cpy(type_set_t * dst, const type_set_t * src);
+extern int type_set_or_eq(type_set_t * dst, const type_set_t * other);
extern void role_set_init(role_set_t * x);
extern void role_set_destroy(role_set_t * x);
extern void avrule_init(avrule_t * x);
diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c
index e0b072e1938f..b4e427af05c8 100644
--- a/libsepol/src/policydb.c
+++ b/libsepol/src/policydb.c
@@ -1747,7 +1747,7 @@ int symtab_insert(policydb_t * pol, uint32_t sym,
return retval;
}
-static int type_set_or(type_set_t * dst, type_set_t * a, type_set_t * b)
+static int type_set_or(type_set_t * dst, const type_set_t * a, const type_set_t * b)
{
type_set_init(dst);
@@ -1764,7 +1764,7 @@ static int type_set_or(type_set_t * dst, type_set_t * a, type_set_t * b)
return 0;
}
-int type_set_cpy(type_set_t * dst, type_set_t * src)
+int type_set_cpy(type_set_t * dst, const type_set_t * src)
{
type_set_init(dst);
@@ -1777,7 +1777,7 @@ int type_set_cpy(type_set_t * dst, type_set_t * src)
return 0;
}
-int type_set_or_eq(type_set_t * dst, type_set_t * other)
+int type_set_or_eq(type_set_t * dst, const type_set_t * other)
{
int ret;
type_set_t tmp;
--
2.32.0

View File

@ -1,63 +0,0 @@
From 19a6ebfa895ce3baa6bd07cb5227556c82f20cb6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Tue, 8 Jun 2021 17:59:01 +0200
Subject: [PATCH] libsepol: do not allocate memory of size 0
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
In case cats_ebitmap_len() returns 0, do not allocate but quit.
Found by clang-analyzer
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
---
libsepol/src/kernel_to_cil.c | 5 ++++-
libsepol/src/kernel_to_conf.c | 5 ++++-
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/libsepol/src/kernel_to_cil.c b/libsepol/src/kernel_to_cil.c
index 30a27bf527d5..5aaee6288565 100644
--- a/libsepol/src/kernel_to_cil.c
+++ b/libsepol/src/kernel_to_cil.c
@@ -1034,11 +1034,14 @@ static char *cats_ebitmap_to_str(struct ebitmap *cats, char **val_to_name)
{
struct ebitmap_node *node;
uint32_t i, start, range;
- char *catsbuf, *p;
+ char *catsbuf = NULL, *p;
const char *fmt;
int len, remaining;
remaining = (int)cats_ebitmap_len(cats, val_to_name);
+ if (remaining == 0) {
+ goto exit;
+ }
catsbuf = malloc(remaining);
if (!catsbuf) {
goto exit;
diff --git a/libsepol/src/kernel_to_conf.c b/libsepol/src/kernel_to_conf.c
index ffdf179a71f3..cb8e13809d52 100644
--- a/libsepol/src/kernel_to_conf.c
+++ b/libsepol/src/kernel_to_conf.c
@@ -1025,12 +1025,15 @@ static char *cats_ebitmap_to_str(struct ebitmap *cats, char **val_to_name)
{
struct ebitmap_node *node;
uint32_t i, start, range, first;
- char *catsbuf, *p;
+ char *catsbuf = NULL, *p;
const char *fmt;
char sep;
int len, remaining;
remaining = (int)cats_ebitmap_len(cats, val_to_name);
+ if (remaining == 0) {
+ goto exit;
+ }
catsbuf = malloc(remaining);
if (!catsbuf) {
goto exit;
--
2.32.0

View File

@ -1,41 +0,0 @@
From 1076a07288f527ac64dcd421ec01e424ee85474d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Tue, 8 Jun 2021 17:59:03 +0200
Subject: [PATCH] libsepol: remove dead stores
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Found by Infer
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
---
libsepol/src/services.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libsepol/src/services.c b/libsepol/src/services.c
index c34bb9667fbc..f7c31d80f954 100644
--- a/libsepol/src/services.c
+++ b/libsepol/src/services.c
@@ -175,7 +175,7 @@ static int expr_buf_len;
static void cat_expr_buf(char *e_buf, const char *string)
{
int len, new_buf_len;
- char *p, *new_buf = e_buf;
+ char *p, *new_buf;
while (1) {
p = e_buf + expr_buf_used;
@@ -406,7 +406,7 @@ static int constraint_expr_eval_reason(context_struct_t *scontext,
#define TARGET 2
#define XTARGET 3
- int s_t_x_num = SOURCE;
+ int s_t_x_num;
/* Set 0 = fail, u = CEXPR_USER, r = CEXPR_ROLE, t = CEXPR_TYPE */
int u_r_t = 0;
--
2.32.0

View File

@ -1,51 +0,0 @@
From de3b96a158c60147703dc5d49c227a596d4ae165 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Tue, 8 Jun 2021 17:59:04 +0200
Subject: [PATCH] libsepol/cil: silence cast warning
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
../cil/src/cil_write_ast.c:86:32: error: cast to smaller integer type 'enum cil_flavor' from 'void *' [-Werror,-Wvoid-pointer-to-enum-cast]
enum cil_flavor op_flavor = (enum cil_flavor)curr->data;
^~~~~~~~~~~~~~~~~~~~~~~~~~~
../cil/src/cil_write_ast.c:130:37: error: cast to smaller integer type 'enum cil_flavor' from 'void *' [-Werror,-Wvoid-pointer-to-enum-cast]
enum cil_flavor operand_flavor = (enum cil_flavor)curr->data;
^~~~~~~~~~~~~~~~~~~~~~~~~~~
Silence this warning by casting the pointer to an integer the cast to
enum cil_flavor.
See 32f8ed3d6b0b ("libsepol/cil: introduce intermediate cast to silence -Wvoid-pointer-to-enum-cast")
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
---
libsepol/cil/src/cil_write_ast.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libsepol/cil/src/cil_write_ast.c b/libsepol/cil/src/cil_write_ast.c
index 4871f7045e19..186070c1783a 100644
--- a/libsepol/cil/src/cil_write_ast.c
+++ b/libsepol/cil/src/cil_write_ast.c
@@ -83,7 +83,7 @@ static void write_expr(FILE *out, struct cil_list *expr)
break;
case CIL_OP: {
const char *op_str;
- enum cil_flavor op_flavor = (enum cil_flavor)curr->data;
+ enum cil_flavor op_flavor = (enum cil_flavor)(uintptr_t)curr->data;
switch (op_flavor) {
case CIL_AND:
op_str = CIL_KEY_AND;
@@ -127,7 +127,7 @@ static void write_expr(FILE *out, struct cil_list *expr)
}
case CIL_CONS_OPERAND: {
const char *operand_str;
- enum cil_flavor operand_flavor = (enum cil_flavor)curr->data;
+ enum cil_flavor operand_flavor = (enum cil_flavor)(uintptr_t)curr->data;
switch (operand_flavor) {
case CIL_CONS_U1:
operand_str = CIL_KEY_CONS_U1;
--
2.32.0

View File

@ -1,30 +0,0 @@
From 261b655ac20e8a4d21cd420ef70468309dedb097 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Tue, 8 Jun 2021 17:59:05 +0200
Subject: [PATCH] libsepol/cil: drop extra semicolon
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.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 908b0336d1dd..71ddada226df 100644
--- a/libsepol/cil/src/cil_build_ast.c
+++ b/libsepol/cil/src/cil_build_ast.c
@@ -4153,7 +4153,7 @@ void cil_destroy_context(struct cil_context *context)
return;
}
- cil_symtab_datum_destroy(&context->datum);;
+ cil_symtab_datum_destroy(&context->datum);
if (context->range_str == NULL && context->range != NULL) {
cil_destroy_levelrange(context->range);
--
2.32.0

View File

@ -1,36 +0,0 @@
From 0bb89514eba0f34685c87278d600b152b28ea76e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Tue, 8 Jun 2021 17:59:06 +0200
Subject: [PATCH] libsepol/cil: drop dead store
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
../cil/src/cil_binary.c:2230:24: warning: Value stored to 'cb_node' during its initialization is never read [deadcode.DeadStores]
struct cil_tree_node *cb_node = node->cl_head;
^~~~~~~ ~~~~~~~~~~~~~
Found by clang-analyzer
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
---
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 85094b01ef9d..601fe8d10ab1 100644
--- a/libsepol/cil/src/cil_binary.c
+++ b/libsepol/cil/src/cil_binary.c
@@ -2227,7 +2227,7 @@ int cil_booleanif_to_policydb(policydb_t *pdb, const struct cil_db *db, struct c
int rc = SEPOL_ERR;
struct cil_args_booleanif bool_args;
struct cil_booleanif *cil_boolif = (struct cil_booleanif*)node->data;
- struct cil_tree_node *cb_node = node->cl_head;
+ struct cil_tree_node *cb_node;
struct cil_tree_node *true_node = NULL;
struct cil_tree_node *false_node = NULL;
struct cil_tree_node *tmp_node = NULL;
--
2.32.0

View File

@ -1,68 +0,0 @@
From 2723b8ec2a84488f00199687d27d1aae5a76c33b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Tue, 8 Jun 2021 17:59:07 +0200
Subject: [PATCH] libsepol/cil: drop unnecessary casts
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
`const_hashtab_key_t` is a typedef of `const char *`, so these casts are
not needed.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
---
libsepol/cil/src/cil_strpool.c | 15 ++++++---------
1 file changed, 6 insertions(+), 9 deletions(-)
diff --git a/libsepol/cil/src/cil_strpool.c b/libsepol/cil/src/cil_strpool.c
index 70bca3630220..e32ee4e90f34 100644
--- a/libsepol/cil/src/cil_strpool.c
+++ b/libsepol/cil/src/cil_strpool.c
@@ -47,14 +47,13 @@ static hashtab_t cil_strpool_tab = NULL;
static unsigned int cil_strpool_hash(hashtab_t h, const_hashtab_key_t key)
{
- const char *p, *keyp;
+ const char *p;
size_t size;
unsigned int val;
val = 0;
- keyp = (const char*)key;
- size = strlen(keyp);
- for (p = keyp; ((size_t) (p - keyp)) < size; p++)
+ size = strlen(key);
+ for (p = key; ((size_t) (p - key)) < size; p++)
val =
(val << 4 | (val >> (8 * sizeof(unsigned int) - 4))) ^ (*p);
return val & (h->size - 1);
@@ -62,9 +61,7 @@ static unsigned int cil_strpool_hash(hashtab_t h, const_hashtab_key_t key)
static int cil_strpool_compare(hashtab_t h __attribute__ ((unused)), const_hashtab_key_t key1, const_hashtab_key_t key2)
{
- const char *keyp1 = (const char*)key1;
- const char *keyp2 = (const char*)key2;
- return strcmp(keyp1, keyp2);
+ return strcmp(key1, key2);
}
char *cil_strpool_add(const char *str)
@@ -73,12 +70,12 @@ char *cil_strpool_add(const char *str)
pthread_mutex_lock(&cil_strpool_mutex);
- strpool_ref = hashtab_search(cil_strpool_tab, (hashtab_key_t)str);
+ strpool_ref = hashtab_search(cil_strpool_tab, str);
if (strpool_ref == NULL) {
int rc;
strpool_ref = cil_malloc(sizeof(*strpool_ref));
strpool_ref->str = cil_strdup(str);
- rc = hashtab_insert(cil_strpool_tab, (hashtab_key_t)strpool_ref->str, strpool_ref);
+ rc = hashtab_insert(cil_strpool_tab, strpool_ref->str, strpool_ref);
if (rc != SEPOL_OK) {
pthread_mutex_unlock(&cil_strpool_mutex);
cil_log(CIL_ERR, "Failed to allocate memory\n");
--
2.32.0

View File

@ -1,78 +0,0 @@
From 5324a9ab1bf5e6d0dd931ee2342f32193341c601 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Tue, 8 Jun 2021 17:59:08 +0200
Subject: [PATCH] libsepol/cil: avoid using maybe uninitialized variables
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Initialize variables, as they are set after goto statements, which jump
to cleanup code using them.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
---
libsepol/cil/src/cil_binary.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c
index 601fe8d10ab1..54d13f2f3945 100644
--- a/libsepol/cil/src/cil_binary.c
+++ b/libsepol/cil/src/cil_binary.c
@@ -1073,7 +1073,7 @@ int __cil_type_rule_to_avtab(policydb_t *pdb, const struct cil_db *db, struct ci
type_datum_t *sepol_src = NULL;
type_datum_t *sepol_tgt = NULL;
class_datum_t *sepol_obj = NULL;
- struct cil_list *class_list;
+ struct cil_list *class_list = NULL;
type_datum_t *sepol_result = NULL;
ebitmap_t src_bitmap, tgt_bitmap;
ebitmap_node_t *node1, *node2;
@@ -1129,7 +1129,7 @@ int __cil_typetransition_to_avtab(policydb_t *pdb, const struct cil_db *db, stru
type_datum_t *sepol_src = NULL;
type_datum_t *sepol_tgt = NULL;
class_datum_t *sepol_obj = NULL;
- struct cil_list *class_list;
+ struct cil_list *class_list = NULL;
type_datum_t *sepol_result = NULL;
ebitmap_t src_bitmap, tgt_bitmap;
ebitmap_node_t *node1, *node2;
@@ -2338,7 +2338,7 @@ int cil_roletrans_to_policydb(policydb_t *pdb, const struct cil_db *db, struct c
role_datum_t *sepol_src = NULL;
type_datum_t *sepol_tgt = NULL;
class_datum_t *sepol_obj = NULL;
- struct cil_list *class_list;
+ struct cil_list *class_list = NULL;
role_datum_t *sepol_result = NULL;
role_trans_t *new = NULL;
uint32_t *new_role = NULL;
@@ -3166,7 +3166,7 @@ int cil_rangetransition_to_policydb(policydb_t *pdb, const struct cil_db *db, st
type_datum_t *sepol_src = NULL;
type_datum_t *sepol_tgt = NULL;
class_datum_t *sepol_class = NULL;
- struct cil_list *class_list;
+ struct cil_list *class_list = NULL;
range_trans_t *newkey = NULL;
struct mls_range *newdatum = NULL;
ebitmap_t src_bitmap, tgt_bitmap;
@@ -3603,7 +3603,7 @@ int cil_default_to_policydb(policydb_t *pdb, struct cil_default *def)
{
struct cil_list_item *curr;
class_datum_t *sepol_class;
- struct cil_list *class_list;
+ struct cil_list *class_list = NULL;
cil_list_for_each(curr, def->class_datums) {
struct cil_list_item *c;
@@ -3658,7 +3658,7 @@ int cil_defaultrange_to_policydb(policydb_t *pdb, struct cil_defaultrange *def)
{
struct cil_list_item *curr;
class_datum_t *sepol_class;
- struct cil_list *class_list;
+ struct cil_list *class_list = NULL;
cil_list_for_each(curr, def->class_datums) {
struct cil_list_item *c;
--
2.32.0

View File

@ -1,44 +0,0 @@
From 811185648af2ec8a6b11b54484cbe9d19ba452fa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Tue, 8 Jun 2021 17:59:09 +0200
Subject: [PATCH] libsepol: drop repeated semicolons
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
---
libsepol/src/kernel_to_cil.c | 2 +-
libsepol/src/module.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/libsepol/src/kernel_to_cil.c b/libsepol/src/kernel_to_cil.c
index 5aaee6288565..336d53b09ff9 100644
--- a/libsepol/src/kernel_to_cil.c
+++ b/libsepol/src/kernel_to_cil.c
@@ -1050,7 +1050,7 @@ static char *cats_ebitmap_to_str(struct ebitmap *cats, char **val_to_name)
p = catsbuf;
*p++ = '(';
- remaining--;;
+ remaining--;
range = 0;
ebitmap_for_each_positive_bit(cats, node, i) {
diff --git a/libsepol/src/module.c b/libsepol/src/module.c
index 836da308f8d3..9b53bc470952 100644
--- a/libsepol/src/module.c
+++ b/libsepol/src/module.c
@@ -82,7 +82,7 @@ static int policy_file_length(struct policy_file *fp, size_t *out)
break;
case PF_USE_MEMORY:
*out = fp->size;
- break;;
+ break;
default:
*out = 0;
break;
--
2.32.0

View File

@ -1,52 +0,0 @@
From 4fbc018a279a39160f17e257017b503194a7f44d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Tue, 8 Jun 2021 17:59:10 +0200
Subject: [PATCH] libsepol: drop unnecessary casts
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
`hashtab_search()` does take `const_hashtab_key_t` as second parameter,
which is a typedef for `const char *`.
Drop the unnecessary and const-violating cast.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
---
libsepol/src/services.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/libsepol/src/services.c b/libsepol/src/services.c
index f7c31d80f954..47a3dc1419db 100644
--- a/libsepol/src/services.c
+++ b/libsepol/src/services.c
@@ -1182,7 +1182,7 @@ int sepol_string_to_security_class(const char *class_name,
class_datum_t *tclass_datum;
tclass_datum = hashtab_search(policydb->p_classes.table,
- (hashtab_key_t) class_name);
+ class_name);
if (!tclass_datum) {
ERR(NULL, "unrecognized class %s", class_name);
return STATUS_ERR;
@@ -1211,7 +1211,7 @@ int sepol_string_to_av_perm(sepol_security_class_t tclass,
/* Check for unique perms then the common ones (if any) */
perm_datum = (perm_datum_t *)
hashtab_search(tclass_datum->permissions.table,
- (hashtab_key_t)perm_name);
+ perm_name);
if (perm_datum != NULL) {
*av = 0x1 << (perm_datum->s.value - 1);
return STATUS_SUCCESS;
@@ -1222,7 +1222,7 @@ int sepol_string_to_av_perm(sepol_security_class_t tclass,
perm_datum = (perm_datum_t *)
hashtab_search(tclass_datum->comdatum->permissions.table,
- (hashtab_key_t)perm_name);
+ perm_name);
if (perm_datum != NULL) {
*av = 0x1 << (perm_datum->s.value - 1);
--
2.32.0

View File

@ -1,36 +0,0 @@
From 4572bf254a8242898467a41811c8e235209ebdfa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Tue, 8 Jun 2021 17:59:11 +0200
Subject: [PATCH] libsepol: declare file local variable static
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Clang issues:
module_to_cil.c:65:7: warning: no previous extern declaration for non-static variable 'out_file' [-Wmissing-variable-declarations]
FILE *out_file;
^
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
---
libsepol/src/module_to_cil.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libsepol/src/module_to_cil.c b/libsepol/src/module_to_cil.c
index 580ba06a95b0..21d8e5dbcc39 100644
--- a/libsepol/src/module_to_cil.c
+++ b/libsepol/src/module_to_cil.c
@@ -62,7 +62,7 @@
# define UNUSED(x) UNUSED_ ## x
#endif
-FILE *out_file;
+static FILE *out_file;
#define STACK_SIZE 16
#define DEFAULT_LEVEL "systemlow"
--
2.32.0

View File

@ -1,225 +0,0 @@
From 9fb8df7f1675cef89f32e3dd1a187cc5d53e08e4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Tue, 8 Jun 2021 17:59:12 +0200
Subject: [PATCH] libsepol: declare read-only arrays const
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Make it more apparent that those data does not change and enforce it.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
---
libsepol/src/avrule_block.c | 2 +-
libsepol/src/avtab.c | 2 +-
libsepol/src/link.c | 2 +-
libsepol/src/polcaps.c | 2 +-
libsepol/src/policydb.c | 22 +++++++++++-----------
libsepol/src/policydb_internal.h | 2 +-
libsepol/src/private.h | 6 +++---
libsepol/src/write.c | 8 ++++----
8 files changed, 23 insertions(+), 23 deletions(-)
diff --git a/libsepol/src/avrule_block.c b/libsepol/src/avrule_block.c
index a9832d0d118f..dcfce8b8492c 100644
--- a/libsepol/src/avrule_block.c
+++ b/libsepol/src/avrule_block.c
@@ -30,7 +30,7 @@
/* It is anticipated that there be less declarations within an avrule
* block than the global policy. Thus the symbol table sizes are
* smaller than those listed in policydb.c */
-static unsigned int symtab_sizes[SYM_NUM] = {
+static const unsigned int symtab_sizes[SYM_NUM] = {
2,
4,
8,
diff --git a/libsepol/src/avtab.c b/libsepol/src/avtab.c
index 257f051a86ec..88e9d510f981 100644
--- a/libsepol/src/avtab.c
+++ b/libsepol/src/avtab.c
@@ -418,7 +418,7 @@ void avtab_hash_eval(avtab_t * h, char *tag)
}
/* Ordering of datums in the original avtab format in the policy file. */
-static uint16_t spec_order[] = {
+static const uint16_t spec_order[] = {
AVTAB_ALLOWED,
AVTAB_AUDITDENY,
AVTAB_AUDITALLOW,
diff --git a/libsepol/src/link.c b/libsepol/src/link.c
index bdc1fcbf59d3..461d2feb8190 100644
--- a/libsepol/src/link.c
+++ b/libsepol/src/link.c
@@ -78,7 +78,7 @@ typedef struct missing_requirement {
uint32_t perm_value;
} missing_requirement_t;
-static const char *symtab_names[SYM_NUM] = {
+static const char * const symtab_names[SYM_NUM] = {
"common", "class", "role", "type/attribute", "user",
"bool", "level", "category"
};
diff --git a/libsepol/src/polcaps.c b/libsepol/src/polcaps.c
index 67ed5786db16..6a74ec7d3c3a 100644
--- a/libsepol/src/polcaps.c
+++ b/libsepol/src/polcaps.c
@@ -5,7 +5,7 @@
#include <string.h>
#include <sepol/policydb/polcaps.h>
-static const char *polcap_names[] = {
+static const char * const polcap_names[] = {
"network_peer_controls", /* POLICYDB_CAPABILITY_NETPEER */
"open_perms", /* POLICYDB_CAPABILITY_OPENPERM */
"extended_socket_class", /* POLICYDB_CAPABILITY_EXTSOCKCLASS */
diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c
index b4e427af05c8..ef2217c28c91 100644
--- a/libsepol/src/policydb.c
+++ b/libsepol/src/policydb.c
@@ -57,10 +57,10 @@
#include "policydb_validate.h"
#define POLICYDB_TARGET_SZ ARRAY_SIZE(policydb_target_strings)
-const char *policydb_target_strings[] = { POLICYDB_STRING, POLICYDB_XEN_STRING };
+const char * const policydb_target_strings[] = { POLICYDB_STRING, POLICYDB_XEN_STRING };
/* These need to be updated if SYM_NUM or OCON_NUM changes */
-static struct policydb_compat_info policydb_compat[] = {
+static const struct policydb_compat_info policydb_compat[] = {
{
.type = POLICY_KERN,
.version = POLICYDB_VERSION_BOUNDARY,
@@ -460,7 +460,7 @@ static char *symtab_name[SYM_NUM] = {
};
#endif
-static unsigned int symtab_sizes[SYM_NUM] = {
+static const unsigned int symtab_sizes[SYM_NUM] = {
2,
32,
16,
@@ -471,12 +471,12 @@ static unsigned int symtab_sizes[SYM_NUM] = {
16,
};
-struct policydb_compat_info *policydb_lookup_compat(unsigned int version,
- unsigned int type,
- unsigned int target_platform)
+const struct policydb_compat_info *policydb_lookup_compat(unsigned int version,
+ unsigned int type,
+ unsigned int target_platform)
{
unsigned int i;
- struct policydb_compat_info *info = NULL;
+ const struct policydb_compat_info *info = NULL;
for (i = 0; i < sizeof(policydb_compat) / sizeof(*info); i++) {
if (policydb_compat[i].version == version &&
@@ -2848,7 +2848,7 @@ static int filename_trans_read(policydb_t *p, struct policy_file *fp)
return 0;
}
-static int ocontext_read_xen(struct policydb_compat_info *info,
+static int ocontext_read_xen(const struct policydb_compat_info *info,
policydb_t *p, struct policy_file *fp)
{
unsigned int i, j;
@@ -2957,7 +2957,7 @@ static int ocontext_read_xen(struct policydb_compat_info *info,
}
return 0;
}
-static int ocontext_read_selinux(struct policydb_compat_info *info,
+static int ocontext_read_selinux(const struct policydb_compat_info *info,
policydb_t * p, struct policy_file *fp)
{
unsigned int i, j;
@@ -3135,7 +3135,7 @@ static int ocontext_read_selinux(struct policydb_compat_info *info,
return 0;
}
-static int ocontext_read(struct policydb_compat_info *info,
+static int ocontext_read(const struct policydb_compat_info *info,
policydb_t *p, struct policy_file *fp)
{
int rc = -1;
@@ -4192,7 +4192,7 @@ int policydb_read(policydb_t * p, struct policy_file *fp, unsigned verbose)
uint32_t buf[5];
size_t len, nprim, nel;
char *policydb_str;
- struct policydb_compat_info *info;
+ const struct policydb_compat_info *info;
unsigned int policy_type, bufindex;
ebitmap_node_t *tnode;
int rc;
diff --git a/libsepol/src/policydb_internal.h b/libsepol/src/policydb_internal.h
index 06ba5c8be144..dd8f25d0fc74 100644
--- a/libsepol/src/policydb_internal.h
+++ b/libsepol/src/policydb_internal.h
@@ -3,5 +3,5 @@
#include <sepol/policydb.h>
-extern const char *policydb_target_strings[];
+extern const char * const policydb_target_strings[];
#endif
diff --git a/libsepol/src/private.h b/libsepol/src/private.h
index f5b5277f183a..72f212628314 100644
--- a/libsepol/src/private.h
+++ b/libsepol/src/private.h
@@ -56,9 +56,9 @@ struct policydb_compat_info {
unsigned int target_platform;
};
-extern struct policydb_compat_info *policydb_lookup_compat(unsigned int version,
- unsigned int type,
- unsigned int target_platform);
+extern const struct policydb_compat_info *policydb_lookup_compat(unsigned int version,
+ unsigned int type,
+ unsigned int target_platform);
/* Reading from a policy "file". */
extern int next_entry(void *buf, struct policy_file *fp, size_t bytes);
diff --git a/libsepol/src/write.c b/libsepol/src/write.c
index 84bcaf3f57ca..3bd034d65cb1 100644
--- a/libsepol/src/write.c
+++ b/libsepol/src/write.c
@@ -1345,7 +1345,7 @@ static int (*write_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum,
common_write, class_write, role_write, type_write, user_write,
cond_write_bool, sens_write, cat_write,};
-static int ocontext_write_xen(struct policydb_compat_info *info, policydb_t *p,
+static int ocontext_write_xen(const struct policydb_compat_info *info, policydb_t *p,
struct policy_file *fp)
{
unsigned int i, j;
@@ -1453,7 +1453,7 @@ static int ocontext_write_xen(struct policydb_compat_info *info, policydb_t *p,
return POLICYDB_SUCCESS;
}
-static int ocontext_write_selinux(struct policydb_compat_info *info,
+static int ocontext_write_selinux(const struct policydb_compat_info *info,
policydb_t *p, struct policy_file *fp)
{
unsigned int i, j;
@@ -1583,7 +1583,7 @@ static int ocontext_write_selinux(struct policydb_compat_info *info,
return POLICYDB_SUCCESS;
}
-static int ocontext_write(struct policydb_compat_info *info, policydb_t * p,
+static int ocontext_write(const struct policydb_compat_info *info, policydb_t * p,
struct policy_file *fp)
{
int rc = POLICYDB_ERROR;
@@ -2179,7 +2179,7 @@ int policydb_write(policydb_t * p, struct policy_file *fp)
unsigned int i, num_syms;
uint32_t buf[32], config;
size_t items, items2, len;
- struct policydb_compat_info *info;
+ const struct policydb_compat_info *info;
struct policy_data pd;
const char *policydb_str;
--
2.32.0

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 0d351b491c2c..671b5ec6e183 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 71ddada226df..ea665a323f78 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 954eab330340..9c0231f294e3 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 a77c95201fb7..24be09aa33d8 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 b5199bad35e2..6d13544c80f7 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;
}
--
2.32.0

View File

@ -1,136 +0,0 @@
From c28525a26fa145cb5fd911fd2a3b9125a275677f Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Mon, 21 Jun 2021 10:34:30 -0400
Subject: [PATCH] libsepol/cil: Properly check for loops in sets
Commit 61fbdce666f24c4a118b249ece6b014d54b65074 (ibsepol/cil: Check
for self-referential loops in sets) added checks for self-referential
loops in user, role, type, and category sets. Unfortunately, this
check ends up in an infinite loop if the set with the self-referential
loop is used in a different set that is checked before the bad set.
The problem with the old check is that only the initial datum is used
for the check. Instead, use a stack to track all of the set datums
that are currently involved as the check is made. A self-referential
loop occurs if a duplicate datum is found for any of the datums in the
stack.
Signed-off-by: James Carter <jwcart2@gmail.com>
Acked-by: Nicolas Iooss <nicolas.iooss@m4x.org>
---
libsepol/cil/src/cil_verify.c | 48 +++++++++++++++++++++++------------
1 file changed, 32 insertions(+), 16 deletions(-)
diff --git a/libsepol/cil/src/cil_verify.c b/libsepol/cil/src/cil_verify.c
index 8e15a0e68a69..59397f70f2ea 100644
--- a/libsepol/cil/src/cil_verify.c
+++ b/libsepol/cil/src/cil_verify.c
@@ -44,6 +44,7 @@
#include "cil_tree.h"
#include "cil_list.h"
#include "cil_find.h"
+#include "cil_stack.h"
#include "cil_verify.h"
@@ -430,9 +431,9 @@ int cil_verify_decl_does_not_shadow_macro_parameter(struct cil_macro *macro, str
return SEPOL_OK;
}
-static int cil_verify_no_self_reference(enum cil_flavor flavor, struct cil_symtab_datum *datum, struct cil_symtab_datum *orig);
+static int cil_verify_no_self_reference(enum cil_flavor flavor, struct cil_symtab_datum *datum, struct cil_stack *stack);
-static int __verify_no_self_reference_in_expr(struct cil_list *expr, struct cil_symtab_datum *orig)
+static int __verify_no_self_reference_in_expr(struct cil_list *expr, struct cil_stack *stack)
{
struct cil_list_item *item;
int rc = SEPOL_OK;
@@ -444,9 +445,9 @@ static int __verify_no_self_reference_in_expr(struct cil_list *expr, struct cil_
cil_list_for_each(item, expr) {
if (item->flavor == CIL_DATUM) {
struct cil_symtab_datum* datum = item->data;
- rc = cil_verify_no_self_reference(FLAVOR(datum), datum, orig);
+ rc = cil_verify_no_self_reference(FLAVOR(datum), datum, stack);
} else if (item->flavor == CIL_LIST) {
- rc = __verify_no_self_reference_in_expr(item->data, orig);
+ rc = __verify_no_self_reference_in_expr(item->data, stack);
}
if (rc != SEPOL_OK) {
return SEPOL_ERR;
@@ -456,36 +457,47 @@ static int __verify_no_self_reference_in_expr(struct cil_list *expr, struct cil_
return SEPOL_OK;
}
-static int cil_verify_no_self_reference(enum cil_flavor flavor, struct cil_symtab_datum *datum, struct cil_symtab_datum *orig)
+static int cil_verify_no_self_reference(enum cil_flavor flavor, struct cil_symtab_datum *datum, struct cil_stack *stack)
{
+ struct cil_stack_item *item;
+ int i = 0;
int rc = SEPOL_OK;
- if (datum == orig) {
- cil_tree_log(NODE(orig), CIL_ERR, "Self-reference found for %s", orig->name);
- return SEPOL_ERR;
- } else if (orig == NULL) {
- orig = datum;
+ cil_stack_for_each(stack, i, item) {
+ struct cil_symtab_datum *prev = item->data;
+ if (datum == prev) {
+ cil_tree_log(NODE(datum), CIL_ERR, "Self-reference found for %s", datum->name);
+ return SEPOL_ERR;
+ }
}
switch (flavor) {
case CIL_USERATTRIBUTE: {
struct cil_userattribute *attr = (struct cil_userattribute *)datum;
- rc = __verify_no_self_reference_in_expr(attr->expr_list, orig);
+ cil_stack_push(stack, CIL_DATUM, datum);
+ rc = __verify_no_self_reference_in_expr(attr->expr_list, stack);
+ cil_stack_pop(stack);
break;
}
case CIL_ROLEATTRIBUTE: {
struct cil_roleattribute *attr = (struct cil_roleattribute *)datum;
- rc = __verify_no_self_reference_in_expr(attr->expr_list, orig);
+ cil_stack_push(stack, CIL_DATUM, datum);
+ rc = __verify_no_self_reference_in_expr(attr->expr_list, stack);
+ cil_stack_pop(stack);
break;
}
case CIL_TYPEATTRIBUTE: {
struct cil_typeattribute *attr = (struct cil_typeattribute *)datum;
- rc = __verify_no_self_reference_in_expr(attr->expr_list, orig);
+ cil_stack_push(stack, CIL_DATUM, datum);
+ rc = __verify_no_self_reference_in_expr(attr->expr_list, stack);
+ cil_stack_pop(stack);
break;
}
case CIL_CATSET: {
struct cil_catset *set = (struct cil_catset *)datum;
- rc = __verify_no_self_reference_in_expr(set->cats->datum_expr, orig);
+ cil_stack_push(stack, CIL_DATUM, datum);
+ rc = __verify_no_self_reference_in_expr(set->cats->datum_expr, stack);
+ cil_stack_pop(stack);
break;
}
default:
@@ -1826,9 +1838,13 @@ int __cil_pre_verify_helper(struct cil_tree_node *node, uint32_t *finished, __at
case CIL_USERATTRIBUTE:
case CIL_ROLEATTRIBUTE:
case CIL_TYPEATTRIBUTE:
- case CIL_CATSET:
- rc = cil_verify_no_self_reference(node->flavor, node->data, NULL);
+ case CIL_CATSET: {
+ struct cil_stack *stack;
+ cil_stack_init(&stack);
+ rc = cil_verify_no_self_reference(node->flavor, node->data, stack);
+ cil_stack_destroy(&stack);
break;
+ }
default:
rc = SEPOL_OK;
break;
--
2.32.0

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 ea665a323f78..baed3e581be4 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;
--
2.32.0

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 7bca0834ad39..7e2c2b9a85c3 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) {
--
2.32.0

View File

@ -1,36 +0,0 @@
From 36e494573d7071f9b56670b4777ed14637025d9e Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Mon, 21 Jun 2021 10:56:49 -0400
Subject: [PATCH] libsepol/cil: Reduce the initial symtab sizes for blocks
It is possible to create bad behaving policy that can consume all
of a system's memory (one way is through the use of inheritance).
Analyzing these policies shows that most of the memory usage is for
the block symtabs.
Most of the nineteen symtabs will most likely never be used, so give
these symtabs an initial size of 1. The others are given more
appropriate sizes.
Signed-off-by: James Carter <jwcart2@gmail.com>
Acked-by: Nicolas Iooss <nicolas.iooss@m4x.org>
---
libsepol/cil/src/cil.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libsepol/cil/src/cil.c b/libsepol/cil/src/cil.c
index 671b5ec6e183..9d5038d91add 100644
--- a/libsepol/cil/src/cil.c
+++ b/libsepol/cil/src/cil.c
@@ -54,7 +54,7 @@
int cil_sym_sizes[CIL_SYM_ARRAY_NUM][CIL_SYM_NUM] = {
{64, 64, 64, 1 << 13, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64},
- {64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64},
+ {8, 8, 8, 32, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
--
2.32.0

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 24be09aa33d8..8b9aeabf66e4 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 6d13544c80f7..5245cc1556bd 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) {
--
2.32.0

View File

@ -1,58 +0,0 @@
From 20271849d5e16fd3a3dd9c0db7d19fae18cf1f4c Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Thu, 24 Jun 2021 15:58:14 -0400
Subject: [PATCH] libsepol/cil: Add function to determine if a subtree has a
declaration
Create the function cil_tree_subtree_has_decl() that returns CIL_TRUE
if the subtree has a declaration in it and CIL_FALSE otherwise.
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/cil/src/cil_tree.c | 16 ++++++++++++++++
libsepol/cil/src/cil_tree.h | 2 ++
2 files changed, 18 insertions(+)
diff --git a/libsepol/cil/src/cil_tree.c b/libsepol/cil/src/cil_tree.c
index 067268eb897c..4cf8dcc8b280 100644
--- a/libsepol/cil/src/cil_tree.c
+++ b/libsepol/cil/src/cil_tree.c
@@ -136,6 +136,22 @@ __attribute__((format (printf, 3, 4))) void cil_tree_log(struct cil_tree_node *n
cil_log(lvl,"\n");
}
+int cil_tree_subtree_has_decl(struct cil_tree_node *node)
+{
+ while (node) {
+ if (node->flavor >= CIL_MIN_DECLARATIVE) {
+ return CIL_TRUE;
+ }
+ if (node->cl_head != NULL) {
+ if (cil_tree_subtree_has_decl(node->cl_head))
+ return CIL_TRUE;
+ }
+ node = node->next;
+ }
+
+ return CIL_FALSE;
+}
+
int cil_tree_init(struct cil_tree **tree)
{
struct cil_tree *new_tree = cil_malloc(sizeof(*new_tree));
diff --git a/libsepol/cil/src/cil_tree.h b/libsepol/cil/src/cil_tree.h
index bac9f1e47f2c..f4d2207153ce 100644
--- a/libsepol/cil/src/cil_tree.h
+++ b/libsepol/cil/src/cil_tree.h
@@ -54,6 +54,8 @@ struct cil_tree_node *cil_tree_get_next_path(struct cil_tree_node *node, char **
char *cil_tree_get_cil_path(struct cil_tree_node *node);
__attribute__((format (printf, 3, 4))) void cil_tree_log(struct cil_tree_node *node, enum cil_log_level lvl, const char* msg, ...);
+int cil_tree_subtree_has_decl(struct cil_tree_node *node);
+
int cil_tree_init(struct cil_tree **tree);
void cil_tree_destroy(struct cil_tree **tree);
void cil_tree_subtree_destroy(struct cil_tree_node *node);
--
2.32.0

View File

@ -1,92 +0,0 @@
From 4ff514a33e2442ba7dac7e96fc7e371898eed316 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Thu, 24 Jun 2021 15:58:15 -0400
Subject: [PATCH] libsepol/cil: Only reset AST if optional has a declaration
When disabling optionals, the AST needs to be reset only if one
of the optional blocks being disabled contains a declaration.
Call the function cil_tree_subtree_has_decl() for each optional
block being disabled and only reset the AST if one of them has
a declaration in it.
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/cil/src/cil_resolve_ast.c | 58 +++++++++++++++++-------------
1 file changed, 34 insertions(+), 24 deletions(-)
diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
index 5245cc1556bd..0ea5b1697dd2 100644
--- a/libsepol/cil/src/cil_resolve_ast.c
+++ b/libsepol/cil/src/cil_resolve_ast.c
@@ -4230,33 +4230,43 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current)
if (changed) {
struct cil_list_item *item;
if (pass > CIL_PASS_CALL1) {
- /* Need to re-resolve because an optional was disabled that contained
- * one or more declarations. We only need to reset to the call1 pass
- * because things done in the preceding passes aren't allowed in
- * optionals, and thus can't be disabled.
- * Note: set pass to CIL_PASS_CALL1 because the pass++ will increment
- * it to CIL_PASS_CALL2
- */
- cil_log(CIL_INFO, "Resetting declarations\n");
-
- 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);
+ int has_decls = CIL_FALSE;
+
+ cil_list_for_each(item, extra_args.to_destroy) {
+ has_decls = cil_tree_subtree_has_decl(item->data);
+ if (has_decls) {
+ break;
+ }
}
- pass = CIL_PASS_CALL1;
+ if (has_decls) {
+ /* Need to re-resolve because an optional was disabled that
+ * contained one or more declarations.
+ * Everything that needs to be reset comes after the
+ * CIL_PASS_CALL2 pass. We set pass to CIL_PASS_CALL1 because
+ * the pass++ will increment it to CIL_PASS_CALL2
+ */
+ cil_log(CIL_INFO, "Resetting declarations\n");
+
+ 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);
+ }
- rc = cil_reset_ast(current);
- if (rc != SEPOL_OK) {
- cil_log(CIL_ERR, "Failed to reset declarations\n");
- goto exit;
+ pass = CIL_PASS_CALL1;
+
+ rc = cil_reset_ast(current);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to reset declarations\n");
+ goto exit;
+ }
}
}
cil_list_for_each(item, extra_args.to_destroy) {
--
2.32.0

View File

@ -1,60 +0,0 @@
From af75f64194c0f81c61f84305ddc8eb494de30e95 Mon Sep 17 00:00:00 2001
From: Nicolas Iooss <nicolas.iooss@m4x.org>
Date: Sat, 26 Jun 2021 14:34:43 +0200
Subject: [PATCH] libsepol/cil: make array cil_sym_sizes const
The values of this table are never modified.
Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
---
libsepol/cil/src/cil.c | 4 ++--
libsepol/cil/src/cil_internal.h | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/libsepol/cil/src/cil.c b/libsepol/cil/src/cil.c
index 9d5038d91add..32e8b3cf419e 100644
--- a/libsepol/cil/src/cil.c
+++ b/libsepol/cil/src/cil.c
@@ -52,7 +52,7 @@
#include "cil_strpool.h"
#include "cil_write_ast.h"
-int cil_sym_sizes[CIL_SYM_ARRAY_NUM][CIL_SYM_NUM] = {
+const int cil_sym_sizes[CIL_SYM_ARRAY_NUM][CIL_SYM_NUM] = {
{64, 64, 64, 1 << 13, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64},
{8, 8, 8, 32, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
@@ -1882,7 +1882,7 @@ void cil_set_policy_version(struct cil_db *db, int policy_version)
db->policy_version = policy_version;
}
-void cil_symtab_array_init(symtab_t symtab[], int symtab_sizes[CIL_SYM_NUM])
+void cil_symtab_array_init(symtab_t symtab[], const int symtab_sizes[CIL_SYM_NUM])
{
uint32_t i = 0;
for (i = 0; i < CIL_SYM_NUM; i++) {
diff --git a/libsepol/cil/src/cil_internal.h b/libsepol/cil/src/cil_internal.h
index 8b9aeabf66e4..3211fc355ec9 100644
--- a/libsepol/cil/src/cil_internal.h
+++ b/libsepol/cil/src/cil_internal.h
@@ -275,7 +275,7 @@ enum cil_sym_array {
CIL_SYM_ARRAY_NUM
};
-extern int cil_sym_sizes[CIL_SYM_ARRAY_NUM][CIL_SYM_NUM];
+extern const int cil_sym_sizes[CIL_SYM_ARRAY_NUM][CIL_SYM_NUM];
#define CIL_CLASS_SYM_SIZE 256
#define CIL_PERMS_PER_CLASS (sizeof(sepol_access_vector_t) * 8)
@@ -981,7 +981,7 @@ int cil_userprefixes_to_string(struct cil_db *db, char **out, size_t *size);
int cil_selinuxusers_to_string(struct cil_db *db, char **out, size_t *size);
int cil_filecons_to_string(struct cil_db *db, char **out, size_t *size);
-void cil_symtab_array_init(symtab_t symtab[], int symtab_sizes[CIL_SYM_NUM]);
+void cil_symtab_array_init(symtab_t symtab[], const int symtab_sizes[CIL_SYM_NUM]);
void cil_symtab_array_destroy(symtab_t symtab[]);
void cil_destroy_ast_symtabs(struct cil_tree_node *root);
int cil_get_symtab(struct cil_tree_node *ast_node, symtab_t **symtab, enum cil_sym_index sym_index);
--
2.32.0

View File

@ -1,244 +0,0 @@
From a0914acf2a128bdfd30ca0ee964a1e88ddb6439e Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@gmail.com>
Date: Tue, 29 Jun 2021 11:13:59 -0400
Subject: [PATCH] libsepol/cil: Provide option to allow qualified names in
declarations
Qualified names have "dots" in them. They are generated when a CIL
policy is compiled and come from declarations in blocks. If a kernel
policy is decompiled into a CIL policy, the resulting policy could
have declarations that use qualified names. Compiling this policy would
result in an error because "dots" in declarations are not allowed.
Qualified names in a policy are normally used to refer to the name of
identifiers, blocks, macros, or optionals that are declared in a
different block (that is not a parent). Name resolution is based on
splitting a name based on the "dots", searching the parents up to the
global namespace for the first block using the first part of the name,
using the second part of the name to lookup the next block using the
first block's symbol tables, looking up the third block in the second's
symbol tables, and so on.
To allow the option of using qualified names in declarations:
1) Create a field in the struct cil_db called "qualified_names" which
is set to CIL_TRUE when qualified names are to be used. This field is
checked in cil_verify_name() and "dots" are allowed if qualified names
are being allowed.
2) Only allow the direct lookup of the whole name in the global symbol
table. This means that blocks, blockinherits, blockabstracts, and in-
statements cannot be allowed. Use the "qualified_names" field of the
cil_db to know when using one of these should result in an error.
3) Create the function cil_set_qualified_names() that is used to set
the "qualified_names" field. Export the function in libsepol.
Signed-off-by: James Carter <jwcart2@gmail.com>
---
libsepol/cil/include/cil/cil.h | 1 +
libsepol/cil/src/cil.c | 6 ++++++
libsepol/cil/src/cil_build_ast.c | 24 ++++++++++++++++++++++--
libsepol/cil/src/cil_internal.h | 1 +
libsepol/cil/src/cil_resolve_ast.c | 4 ++--
libsepol/cil/src/cil_verify.c | 19 ++++++++++++++-----
libsepol/cil/src/cil_verify.h | 2 +-
libsepol/src/libsepol.map.in | 1 +
8 files changed, 48 insertions(+), 10 deletions(-)
diff --git a/libsepol/cil/include/cil/cil.h b/libsepol/cil/include/cil/cil.h
index 92fac6e1619a..482ca522277b 100644
--- a/libsepol/cil/include/cil/cil.h
+++ b/libsepol/cil/include/cil/cil.h
@@ -51,6 +51,7 @@ extern int cil_selinuxusers_to_string(cil_db_t *db, char **out, size_t *size);
extern int cil_filecons_to_string(cil_db_t *db, char **out, size_t *size);
extern void cil_set_disable_dontaudit(cil_db_t *db, int disable_dontaudit);
extern void cil_set_multiple_decls(cil_db_t *db, int multiple_decls);
+extern void cil_set_qualified_names(struct cil_db *db, int qualified_names);
extern void cil_set_disable_neverallow(cil_db_t *db, int disable_neverallow);
extern void cil_set_preserve_tunables(cil_db_t *db, int preserve_tunables);
extern int cil_set_handle_unknown(cil_db_t *db, int handle_unknown);
diff --git a/libsepol/cil/src/cil.c b/libsepol/cil/src/cil.c
index 32e8b3cf419e..d24c81c89337 100644
--- a/libsepol/cil/src/cil.c
+++ b/libsepol/cil/src/cil.c
@@ -440,6 +440,7 @@ void cil_db_init(struct cil_db **db)
(*db)->handle_unknown = -1;
(*db)->mls = -1;
(*db)->multiple_decls = CIL_FALSE;
+ (*db)->qualified_names = CIL_FALSE;
(*db)->target_platform = SEPOL_TARGET_SELINUX;
(*db)->policy_version = POLICYDB_VERSION_MAX;
}
@@ -1872,6 +1873,11 @@ void cil_set_multiple_decls(struct cil_db *db, int multiple_decls)
db->multiple_decls = multiple_decls;
}
+void cil_set_qualified_names(struct cil_db *db, int qualified_names)
+{
+ db->qualified_names = qualified_names;
+}
+
void cil_set_target_platform(struct cil_db *db, int target_platform)
{
db->target_platform = target_platform;
diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c
index baed3e581be4..9da90883e85a 100644
--- a/libsepol/cil/src/cil_build_ast.c
+++ b/libsepol/cil/src/cil_build_ast.c
@@ -146,7 +146,7 @@ int cil_gen_node(struct cil_db *db, struct cil_tree_node *ast_node, struct cil_s
int rc = SEPOL_ERR;
symtab_t *symtab = NULL;
- rc = cil_verify_name((const char*)key, nflavor);
+ rc = cil_verify_name(db, (const char*)key, nflavor);
if (rc != SEPOL_OK) {
goto exit;
}
@@ -204,6 +204,11 @@ int cil_gen_block(struct cil_db *db, struct cil_tree_node *parse_current, struct
goto exit;
}
+ if (db->qualified_names) {
+ cil_log(CIL_ERR, "Blocks are not allowed when the option for qualified names is used\n");
+ goto exit;
+ }
+
rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
if (rc != SEPOL_OK) {
goto exit;
@@ -274,6 +279,11 @@ int cil_gen_blockinherit(struct cil_db *db, struct cil_tree_node *parse_current,
goto exit;
}
+ if (db->qualified_names) {
+ cil_log(CIL_ERR, "Block inherit rules are not allowed when the option for qualified names is used\n");
+ goto exit;
+ }
+
rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
if (rc != SEPOL_OK) {
goto exit;
@@ -331,6 +341,11 @@ int cil_gen_blockabstract(struct cil_db *db, struct cil_tree_node *parse_current
goto exit;
}
+ if (db->qualified_names) {
+ cil_log(CIL_ERR, "Block abstract rules are not allowed when the option for qualified names is used\n");
+ goto exit;
+ }
+
rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
if (rc != SEPOL_OK) {
goto exit;
@@ -376,6 +391,11 @@ int cil_gen_in(struct cil_db *db, struct cil_tree_node *parse_current, struct ci
goto exit;
}
+ if (db->qualified_names) {
+ cil_log(CIL_ERR, "In-statements are not allowed when the option for qualified names is used\n");
+ goto exit;
+ }
+
rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
if (rc != SEPOL_OK) {
goto exit;
@@ -5261,7 +5281,7 @@ int cil_gen_macro(struct cil_db *db, struct cil_tree_node *parse_current, struct
param->str = current_item->cl_head->next->data;
- rc = cil_verify_name(param->str, param->flavor);
+ rc = cil_verify_name(db, param->str, param->flavor);
if (rc != SEPOL_OK) {
cil_destroy_param(param);
goto exit;
diff --git a/libsepol/cil/src/cil_internal.h b/libsepol/cil/src/cil_internal.h
index 3211fc355ec9..98e303d14e84 100644
--- a/libsepol/cil/src/cil_internal.h
+++ b/libsepol/cil/src/cil_internal.h
@@ -321,6 +321,7 @@ struct cil_db {
int handle_unknown;
int mls;
int multiple_decls;
+ int qualified_names;
int target_platform;
int policy_version;
};
diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
index 0ea5b1697dd2..32ea64e39b21 100644
--- a/libsepol/cil/src/cil_resolve_ast.c
+++ b/libsepol/cil/src/cil_resolve_ast.c
@@ -4419,8 +4419,8 @@ int cil_resolve_name_keep_aliases(struct cil_tree_node *ast_node, char *name, en
*datum = NULL;
- if (strchr(name,'.') == NULL) {
- /* No '.' in name */
+ if (db->qualified_names || strchr(name,'.') == NULL) {
+ /* Using qualified names or No '.' in name */
rc = __cil_resolve_name_helper(db, ast_node->parent, name, sym_index, datum);
if (rc != SEPOL_OK) {
goto exit;
diff --git a/libsepol/cil/src/cil_verify.c b/libsepol/cil/src/cil_verify.c
index 59397f70f2ea..ce3fcd8c81c9 100644
--- a/libsepol/cil/src/cil_verify.c
+++ b/libsepol/cil/src/cil_verify.c
@@ -92,7 +92,7 @@ static int __cil_is_reserved_name(const char *name, enum cil_flavor flavor)
return CIL_FALSE;
}
-int cil_verify_name(const char *name, enum cil_flavor flavor)
+int cil_verify_name(const struct cil_db *db, const char *name, enum cil_flavor flavor)
{
int rc = SEPOL_ERR;
int len;
@@ -116,10 +116,19 @@ int cil_verify_name(const char *name, enum cil_flavor flavor)
goto exit;
}
- for (i = 1; i < len; i++) {
- if (!isalnum(name[i]) && name[i] != '_' && name[i] != '-') {
- cil_log(CIL_ERR, "Invalid character \"%c\" in %s\n", name[i], name);
- goto exit;
+ if (db->qualified_names == CIL_FALSE) {
+ for (i = 1; i < len; i++) {
+ if (!isalnum(name[i]) && name[i] != '_' && name[i] != '-') {
+ cil_log(CIL_ERR, "Invalid character \"%c\" in %s\n", name[i], name);
+ goto exit;
+ }
+ }
+ } else {
+ for (i = 1; i < len; i++) {
+ if (!isalnum(name[i]) && name[i] != '_' && name[i] != '-' && name[i] != '.') {
+ cil_log(CIL_ERR, "Invalid character \"%c\" in %s\n", name[i], name);
+ goto exit;
+ }
}
}
diff --git a/libsepol/cil/src/cil_verify.h b/libsepol/cil/src/cil_verify.h
index 4ea14f5b0a9a..26e195a94c7e 100644
--- a/libsepol/cil/src/cil_verify.h
+++ b/libsepol/cil/src/cil_verify.h
@@ -56,7 +56,7 @@ struct cil_args_verify {
int *pass;
};
-int cil_verify_name(const char *name, enum cil_flavor flavor);
+int cil_verify_name(const struct cil_db *db, const char *name, enum cil_flavor flavor);
int __cil_verify_syntax(struct cil_tree_node *parse_current, enum cil_syntax s[], int len);
int cil_verify_expr_syntax(struct cil_tree_node *current, enum cil_flavor op, enum cil_flavor expr_flavor);
int cil_verify_constraint_leaf_expr_syntax(enum cil_flavor l_flavor, enum cil_flavor r_flavor, enum cil_flavor op, enum cil_flavor expr_flavor);
diff --git a/libsepol/src/libsepol.map.in b/libsepol/src/libsepol.map.in
index 2e503bd1b453..0e05d6064789 100644
--- a/libsepol/src/libsepol.map.in
+++ b/libsepol/src/libsepol.map.in
@@ -272,4 +272,5 @@ LIBSEPOL_3.0 {
cil_write_parse_ast;
cil_write_build_ast;
cil_write_resolve_ast;
+ cil_set_qualified_names;
} LIBSEPOL_1.1;
--
2.32.0

View File

@ -1,51 +0,0 @@
From fd705df050f916add396954218a67fb8a4fd7cad Mon Sep 17 00:00:00 2001
From: Nicolas Iooss <nicolas.iooss@m4x.org>
Date: Fri, 2 Jul 2021 13:07:05 +0200
Subject: [PATCH] libsepol/cil: do not override previous results of
__cil_verify_classperms
When __cil_verify_map_class() verifies a classpermission, it calls
__verify_map_perm_classperms() on each item. If the first item reports a
failure and the next one succeeds, the failure is overwritten in
map_args->rc. This is a bug which causes a NULL pointer dereference in
the CIL compiler when compiling the following policy:
(sid SID)
(sidorder (SID))
(class CLASS (PERM1))
(classorder (CLASS))
(classpermission CLSPERM)
(classpermissionset CLSPERM (CLASS (PERM1)))
(classmap files (CLAMAPxx x))
(classmapping files CLAMAPxx CLSPERM)
Fixes: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=30286
Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
---
libsepol/cil/src/cil_verify.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/libsepol/cil/src/cil_verify.c b/libsepol/cil/src/cil_verify.c
index ce3fcd8c81c9..fc8a8a406a15 100644
--- a/libsepol/cil/src/cil_verify.c
+++ b/libsepol/cil/src/cil_verify.c
@@ -1795,8 +1795,12 @@ static int __verify_map_perm_classperms(__attribute__((unused)) hashtab_key_t k,
{
struct cil_verify_map_args *map_args = args;
struct cil_perm *cmp = (struct cil_perm *)d;
+ int rc;
- map_args->rc = __cil_verify_classperms(cmp->classperms, &cmp->datum, &map_args->class->datum, &cmp->datum, CIL_MAP_PERM, 0, 2);
+ rc = __cil_verify_classperms(cmp->classperms, &cmp->datum, &map_args->class->datum, &cmp->datum, CIL_MAP_PERM, 0, 2);
+ if (rc != SEPOL_OK) {
+ map_args->rc = rc;
+ }
return SEPOL_OK;
}
--
2.32.0

View File

@ -1,132 +0,0 @@
From 9d85aa60d12e468e7fd510c2b5475b5299b71622 Mon Sep 17 00:00:00 2001
From: Nicolas Iooss <nicolas.iooss@m4x.org>
Date: Sat, 3 Jul 2021 16:31:17 +0200
Subject: [PATCH] libsepol: silence -Wextra-semi-stmt warning
On Ubuntu 20.04, when building with clang -Werror -Wextra-semi-stmt
(which is not the default build configuration), the compiler reports:
../cil/src/cil_binary.c:4293:22: error: empty expression statement
has no effect; remove unnecessary ';' to silence this warning
[-Werror,-Wextra-semi-stmt]
mix(k->target_class);
^
../cil/src/cil_binary.c:4294:21: error: empty expression statement
has no effect; remove unnecessary ';' to silence this warning
[-Werror,-Wextra-semi-stmt]
mix(k->target_type);
^
../cil/src/cil_binary.c:4295:21: error: empty expression statement
has no effect; remove unnecessary ';' to silence this warning
[-Werror,-Wextra-semi-stmt]
mix(k->source_type);
^
../cil/src/cil_binary.c:4296:19: error: empty expression statement
has no effect; remove unnecessary ';' to silence this warning
[-Werror,-Wextra-semi-stmt]
mix(k->specified);
^
Use a do { ... } while (0) construction to silence this warning.
Moreover the same warning appears when using two semicolons to end a
statement. Remove such occurrences, like what was already done in commit
811185648af2 ("libsepol: drop repeated semicolons").
Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
---
libsepol/cil/src/cil_binary.c | 4 ++--
libsepol/cil/src/cil_resolve_ast.c | 2 +-
libsepol/src/avtab.c | 4 ++--
libsepol/tests/libsepol-tests.c | 18 +++++++++++-------
4 files changed, 16 insertions(+), 12 deletions(-)
diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c
index 54d13f2f3945..41105c122bc3 100644
--- a/libsepol/cil/src/cil_binary.c
+++ b/libsepol/cil/src/cil_binary.c
@@ -4277,7 +4277,7 @@ static unsigned int avrulex_hash(__attribute__((unused)) hashtab_t h, const_hash
uint32_t hash = 0;
-#define mix(input) { \
+#define mix(input) do { \
uint32_t v = input; \
v *= c1; \
v = (v << r1) | (v >> (32 - r1)); \
@@ -4285,7 +4285,7 @@ static unsigned int avrulex_hash(__attribute__((unused)) hashtab_t h, const_hash
hash ^= v; \
hash = (hash << r2) | (hash >> (32 - r2)); \
hash = hash * m + n; \
-}
+} while (0)
mix(k->target_class);
mix(k->target_type);
diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
index 32ea64e39b21..9a02e3867659 100644
--- a/libsepol/cil/src/cil_resolve_ast.c
+++ b/libsepol/cil/src/cil_resolve_ast.c
@@ -2825,7 +2825,7 @@ static int cil_build_call_args(struct cil_tree_node *call_node, struct cil_call
return SEPOL_OK;
} else {
cil_tree_log(call_node, CIL_ERR, "Unexpected arguments");
- return SEPOL_ERR;;
+ return SEPOL_ERR;
}
}
if (call->args_tree == NULL) {
diff --git a/libsepol/src/avtab.c b/libsepol/src/avtab.c
index 88e9d510f981..5e16a0e9899e 100644
--- a/libsepol/src/avtab.c
+++ b/libsepol/src/avtab.c
@@ -63,7 +63,7 @@ static inline int avtab_hash(struct avtab_key *keyp, uint32_t mask)
uint32_t hash = 0;
-#define mix(input) { \
+#define mix(input) do { \
uint32_t v = input; \
v *= c1; \
v = (v << r1) | (v >> (32 - r1)); \
@@ -71,7 +71,7 @@ static inline int avtab_hash(struct avtab_key *keyp, uint32_t mask)
hash ^= v; \
hash = (hash << r2) | (hash >> (32 - r2)); \
hash = hash * m + n; \
-}
+} while (0)
mix(keyp->target_class);
mix(keyp->target_type);
diff --git a/libsepol/tests/libsepol-tests.c b/libsepol/tests/libsepol-tests.c
index 544c792d2ab5..dc8fd5ce5f6c 100644
--- a/libsepol/tests/libsepol-tests.c
+++ b/libsepol/tests/libsepol-tests.c
@@ -36,13 +36,17 @@
int mls;
#define DECLARE_SUITE(name) \
- suite = CU_add_suite(#name, name##_test_init, name##_test_cleanup); \
- if (NULL == suite) { \
- CU_cleanup_registry(); \
- return CU_get_error(); } \
- if (name##_add_tests(suite)) { \
- CU_cleanup_registry(); \
- return CU_get_error(); }
+ do { \
+ suite = CU_add_suite(#name, name##_test_init, name##_test_cleanup); \
+ if (NULL == suite) { \
+ CU_cleanup_registry(); \
+ return CU_get_error(); \
+ } \
+ if (name##_add_tests(suite)) { \
+ CU_cleanup_registry(); \
+ return CU_get_error(); \
+ } \
+ } while (0)
static void usage(char *progname)
{
--
2.32.0

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 9a02e3867659..145d4e7452dd 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;
}
--
2.32.0

View File

@ -1,79 +0,0 @@
From 44d56761bed0a394cceb4b0c57fee4fc0e4d9a85 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Tue, 6 Jul 2021 19:36:29 +0200
Subject: [PATCH] libsepol: avoid unsigned integer overflow
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Unsigned integer overflow is well-defined and not undefined behavior.
It is commonly used for hashing or pseudo random number generation.
But it is still useful to enable undefined behavior sanitizer checks on
unsigned arithmetic to detect possible issues on counters or variables
with similar purpose or missed overflow checks on user input.
Use a spaceship operator like comparison instead of subtraction.
policydb.c:851:24: runtime error: unsigned integer overflow: 801 - 929 cannot be represented in type 'unsigned int'
Follow-up of: 1537ea8412e4 ("libsepol: avoid unsigned integer overflow")
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
libsepol/src/policydb.c | 10 +++++-----
libsepol/src/private.h | 2 ++
2 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c
index ef2217c28c91..0398ceed2574 100644
--- a/libsepol/src/policydb.c
+++ b/libsepol/src/policydb.c
@@ -817,11 +817,11 @@ static int filenametr_cmp(hashtab_t h __attribute__ ((unused)),
const filename_trans_key_t *ft2 = (const filename_trans_key_t *)k2;
int v;
- v = (ft1->ttype > ft2->ttype) - (ft1->ttype < ft2->ttype);
+ v = spaceship_cmp(ft1->ttype, ft2->ttype);
if (v)
return v;
- v = (ft1->tclass > ft2->tclass) - (ft1->tclass < ft2->tclass);
+ v = spaceship_cmp(ft1->tclass, ft2->tclass);
if (v)
return v;
@@ -843,15 +843,15 @@ static int rangetr_cmp(hashtab_t h __attribute__ ((unused)),
const struct range_trans *key2 = (const struct range_trans *)k2;
int v;
- v = key1->source_type - key2->source_type;
+ v = spaceship_cmp(key1->source_type, key2->source_type);
if (v)
return v;
- v = key1->target_type - key2->target_type;
+ v = spaceship_cmp(key1->target_type, key2->target_type);
if (v)
return v;
- v = key1->target_class - key2->target_class;
+ v = spaceship_cmp(key1->target_class, key2->target_class);
return v;
}
diff --git a/libsepol/src/private.h b/libsepol/src/private.h
index 72f212628314..c63238abe5f3 100644
--- a/libsepol/src/private.h
+++ b/libsepol/src/private.h
@@ -47,6 +47,8 @@
#define is_saturated(x) (x == (typeof(x))-1)
#define zero_or_saturated(x) ((x == 0) || is_saturated(x))
+#define spaceship_cmp(a, b) (((a) > (b)) - ((a) < (b)))
+
/* Policy compatibility information. */
struct policydb_compat_info {
unsigned int type;
--
2.32.0

View File

@ -1,99 +0,0 @@
From 09405ba91c40e4e08f2212c946a432fa001d04bb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Thu, 1 Jul 2021 20:06:22 +0200
Subject: [PATCH] libsepol: ignore UBSAN false-positives
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Unsigned integer overflow is well-defined and not undefined behavior.
But it is still useful to enable undefined behavior sanitizer checks on
unsigned arithmetic to detect possible issues on counters or variables
with similar purpose.
Annotate functions, in which unsigned overflows are expected to happen,
with the respective Clang function attribute[1].
GCC does not support sanitizing unsigned integer arithmetic[2].
avtab.c:76:2: runtime error: unsigned integer overflow: 6 * 3432918353 cannot be represented in type 'unsigned int'
policydb.c:795:42: runtime error: unsigned integer overflow: 8160943042179512010 * 11 cannot be represented in type 'unsigned long'
symtab.c:25:12: runtime error: left shift of 1766601759 by 4 places cannot be represented in type 'unsigned int'
[1]: https://clang.llvm.org/docs/AttributeReference.html#no-sanitize
[2]: https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
libsepol/src/avtab.c | 1 +
libsepol/src/policydb.c | 1 +
libsepol/src/private.h | 11 +++++++++++
libsepol/src/symtab.c | 4 ++++
4 files changed, 17 insertions(+)
diff --git a/libsepol/src/avtab.c b/libsepol/src/avtab.c
index 5e16a0e9899e..93505b20e4c0 100644
--- a/libsepol/src/avtab.c
+++ b/libsepol/src/avtab.c
@@ -52,6 +52,7 @@
/* Based on MurmurHash3, written by Austin Appleby and placed in the
* public domain.
*/
+ignore_unsigned_overflow_
static inline int avtab_hash(struct avtab_key *keyp, uint32_t mask)
{
static const uint32_t c1 = 0xcc9e2d51;
diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c
index 0398ceed2574..7093d9b7028a 100644
--- a/libsepol/src/policydb.c
+++ b/libsepol/src/policydb.c
@@ -789,6 +789,7 @@ static int roles_init(policydb_t * p)
goto out;
}
+ignore_unsigned_overflow_
static inline unsigned long
partial_name_hash(unsigned long c, unsigned long prevhash)
{
diff --git a/libsepol/src/private.h b/libsepol/src/private.h
index c63238abe5f3..71287282fbc0 100644
--- a/libsepol/src/private.h
+++ b/libsepol/src/private.h
@@ -49,6 +49,17 @@
#define spaceship_cmp(a, b) (((a) > (b)) - ((a) < (b)))
+/* Use to ignore intentional unsigned under- and overflows while running under UBSAN. */
+#if defined(__clang__) && defined(__clang_major__) && (__clang_major__ >= 4)
+#if (__clang_major__ >= 12)
+#define ignore_unsigned_overflow_ __attribute__((no_sanitize("unsigned-integer-overflow", "unsigned-shift-base")))
+#else
+#define ignore_unsigned_overflow_ __attribute__((no_sanitize("unsigned-integer-overflow")))
+#endif
+#else
+#define ignore_unsigned_overflow_
+#endif
+
/* Policy compatibility information. */
struct policydb_compat_info {
unsigned int type;
diff --git a/libsepol/src/symtab.c b/libsepol/src/symtab.c
index 9a417ca24b53..a60618510bd3 100644
--- a/libsepol/src/symtab.c
+++ b/libsepol/src/symtab.c
@@ -8,9 +8,13 @@
*/
#include <string.h>
+
+#include "private.h"
+
#include <sepol/policydb/hashtab.h>
#include <sepol/policydb/symtab.h>
+ignore_unsigned_overflow_
static unsigned int symhash(hashtab_t h, const_hashtab_key_t key)
{
const char *p, *keyp;
--
2.32.0

View File

@ -1,70 +0,0 @@
From e1491388d570a83f6b005d7dc1906765a02b922e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Thu, 1 Jul 2021 20:06:45 +0200
Subject: [PATCH] libsepol: avoid implicit conversions
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Avoid implicit conversions from signed to unsigned values, found by
UB sanitizers, by using unsigned values in the first place.
expand.c:1644:18: runtime error: implicit conversion from type 'int' of value -1 (32-bit, signed) to type 'uint32_t' (aka 'unsigned int') changed the value to 4294967295 (32-bit, unsigned)
expand.c:2892:24: runtime error: implicit conversion from type 'int' of value -2 (32-bit, signed) to type 'unsigned int' changed the value to 4294967294 (32-bit, unsigned)
policy_define.c:2344:4: runtime error: implicit conversion from type 'int' of value -1048577 (32-bit, signed) to type 'unsigned int' changed the value to 4293918719 (32-bit, unsigned)
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
libsepol/include/sepol/policydb/conditional.h | 2 +-
libsepol/include/sepol/policydb/policydb.h | 6 +++---
libsepol/src/expand.c | 2 +-
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/libsepol/include/sepol/policydb/conditional.h b/libsepol/include/sepol/policydb/conditional.h
index 9c3df3ef488e..49c0d76631c4 100644
--- a/libsepol/include/sepol/policydb/conditional.h
+++ b/libsepol/include/sepol/policydb/conditional.h
@@ -90,7 +90,7 @@ typedef struct cond_node {
uint32_t expr_pre_comp;
struct cond_node *next;
/* a tunable conditional, calculated and used at expansion */
-#define COND_NODE_FLAGS_TUNABLE 0x01
+#define COND_NODE_FLAGS_TUNABLE UINT32_C(0x01)
uint32_t flags;
} cond_node_t;
diff --git a/libsepol/include/sepol/policydb/policydb.h b/libsepol/include/sepol/policydb/policydb.h
index 6976ef4831ef..4bf9f05ddd0a 100644
--- a/libsepol/include/sepol/policydb/policydb.h
+++ b/libsepol/include/sepol/policydb/policydb.h
@@ -251,9 +251,9 @@ typedef struct class_perm_node {
struct class_perm_node *next;
} class_perm_node_t;
-#define xperm_test(x, p) (1 & (p[x >> 5] >> (x & 0x1f)))
-#define xperm_set(x, p) (p[x >> 5] |= (1 << (x & 0x1f)))
-#define xperm_clear(x, p) (p[x >> 5] &= ~(1 << (x & 0x1f)))
+#define xperm_test(x, p) (UINT32_C(1) & (p[x >> 5] >> (x & 0x1f)))
+#define xperm_set(x, p) (p[x >> 5] |= (UINT32_C(1) << (x & 0x1f)))
+#define xperm_clear(x, p) (p[x >> 5] &= ~(UINT32_C(1) << (x & 0x1f)))
#define EXTENDED_PERMS_LEN 8
typedef struct av_extended_perms {
diff --git a/libsepol/src/expand.c b/libsepol/src/expand.c
index 84bfcfa36d0a..aac5b35f7bd1 100644
--- a/libsepol/src/expand.c
+++ b/libsepol/src/expand.c
@@ -1641,7 +1641,7 @@ static avtab_ptr_t find_avtab_node(sepol_handle_t * handle,
* AUDITDENY, aka DONTAUDIT, are &= assigned, versus |= for
* others. Initialize the data accordingly.
*/
- avdatum.data = key->specified == AVTAB_AUDITDENY ? ~0 : 0;
+ avdatum.data = key->specified == AVTAB_AUDITDENY ? ~UINT32_C(0) : UINT32_C(0);
/* this is used to get the node - insertion is actually unique */
node = avtab_insert_nonunique(avtab, key, &avdatum);
if (!node) {
--
2.32.0

View File

@ -1,89 +0,0 @@
From 07d6f1cea5a8ec0251606636189bc519d80b0729 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Thu, 1 Jul 2021 20:07:07 +0200
Subject: [PATCH] libsepol: assure string NUL-termination of ibdev_name
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Clang complains:
ibendport_record.c: In function sepol_ibendport_get_ibdev_name:
ibendport_record.c:169:2: error: strncpy specified bound 64 equals destination size [-Werror=stringop-truncation]
169 | strncpy(tmp_ibdev_name, ibendport->ibdev_name, IB_DEVICE_NAME_MAX);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ibendport_record.c: In function sepol_ibendport_set_ibdev_name:
ibendport_record.c:189:2: error: strncpy specified bound 64 equals destination size [-Werror=stringop-truncation]
189 | strncpy(tmp, ibdev_name, IB_DEVICE_NAME_MAX);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
strncpy(3) does not NUL-terminate the destination if the source is of
the same length or longer then the specified size.
The source of these copies are retrieved from
sepol_ibendport_alloc_ibdev_name(), which allocates a fixed amount of
IB_DEVICE_NAME_MAX bytes.
Reduce the size to copy by 1 of all memory regions allocated by
sepol_ibendport_alloc_ibdev_name().
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
libsepol/src/ibendport_record.c | 8 ++++----
libsepol/src/ibendports.c | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/libsepol/src/ibendport_record.c b/libsepol/src/ibendport_record.c
index adf671615e5c..1eb50914b8c0 100644
--- a/libsepol/src/ibendport_record.c
+++ b/libsepol/src/ibendport_record.c
@@ -62,7 +62,7 @@ int sepol_ibendport_key_create(sepol_handle_t *handle,
if (sepol_ibendport_alloc_ibdev_name(handle, &tmp_key->ibdev_name) < 0)
goto err;
- strncpy(tmp_key->ibdev_name, ibdev_name, IB_DEVICE_NAME_MAX);
+ strncpy(tmp_key->ibdev_name, ibdev_name, IB_DEVICE_NAME_MAX - 1);
tmp_key->port = port;
*key_ptr = tmp_key;
@@ -166,7 +166,7 @@ int sepol_ibendport_get_ibdev_name(sepol_handle_t *handle,
if (sepol_ibendport_alloc_ibdev_name(handle, &tmp_ibdev_name) < 0)
goto err;
- strncpy(tmp_ibdev_name, ibendport->ibdev_name, IB_DEVICE_NAME_MAX);
+ strncpy(tmp_ibdev_name, ibendport->ibdev_name, IB_DEVICE_NAME_MAX - 1);
*ibdev_name = tmp_ibdev_name;
return STATUS_SUCCESS;
@@ -186,7 +186,7 @@ int sepol_ibendport_set_ibdev_name(sepol_handle_t *handle,
if (sepol_ibendport_alloc_ibdev_name(handle, &tmp) < 0)
goto err;
- strncpy(tmp, ibdev_name, IB_DEVICE_NAME_MAX);
+ strncpy(tmp, ibdev_name, IB_DEVICE_NAME_MAX - 1);
free(ibendport->ibdev_name);
ibendport->ibdev_name = tmp;
return STATUS_SUCCESS;
@@ -230,7 +230,7 @@ int sepol_ibendport_clone(sepol_handle_t *handle,
if (sepol_ibendport_alloc_ibdev_name(handle, &new_ibendport->ibdev_name) < 0)
goto omem;
- strncpy(new_ibendport->ibdev_name, ibendport->ibdev_name, IB_DEVICE_NAME_MAX);
+ strncpy(new_ibendport->ibdev_name, ibendport->ibdev_name, IB_DEVICE_NAME_MAX - 1);
new_ibendport->port = ibendport->port;
if (ibendport->con &&
diff --git a/libsepol/src/ibendports.c b/libsepol/src/ibendports.c
index 6d56c9a1793f..ee5cb1930f31 100644
--- a/libsepol/src/ibendports.c
+++ b/libsepol/src/ibendports.c
@@ -34,7 +34,7 @@ static int ibendport_from_record(sepol_handle_t *handle,
&ibdev_name) < 0)
goto err;
- strncpy(tmp_ibendport->u.ibendport.dev_name, ibdev_name, IB_DEVICE_NAME_MAX);
+ strncpy(tmp_ibendport->u.ibendport.dev_name, ibdev_name, IB_DEVICE_NAME_MAX - 1);
free(ibdev_name);
ibdev_name = NULL;
--
2.32.0

Some files were not shown because too many files have changed in this diff Show More