Compare commits
No commits in common. 'c8' and 'c9' have entirely different histories.
@ -1 +1 @@
|
|||||||
SOURCES/libsepol-2.9.tar.gz
|
SOURCES/libsepol-3.5.tar.gz
|
||||||
|
@ -1 +1 @@
|
|||||||
b2447a0b2ea8dd45737535c3e407c950f16dcca5 SOURCES/libsepol-2.9.tar.gz
|
3089ffd091af5a284a230daf77192fccb0695c30 SOURCES/libsepol-3.5.tar.gz
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
From 923849fa1cc36580086be542036c4935d7cbfe1c Mon Sep 17 00:00:00 2001
|
||||||
|
From: Petr Lautrbach <plautrba@redhat.com>
|
||||||
|
Date: Mon, 23 May 2022 12:25:58 +0200
|
||||||
|
Subject: [PATCH] libsepol: Bring back POLICYDB_CAPABILITY_* constants
|
||||||
|
Content-type: text/plain
|
||||||
|
|
||||||
|
They were removed by the commit 0d84ebcbc475d ("libsepol: Shorten the
|
||||||
|
policy capability enum names") but they might be used somewhere in code
|
||||||
|
deployed on RHEL 9.0
|
||||||
|
|
||||||
|
Signed-off-by: Petr Lautrbach <plautrba@redhat.com>
|
||||||
|
---
|
||||||
|
libsepol/include/sepol/policydb/polcaps.h | 14 ++++++++++++++
|
||||||
|
1 file changed, 14 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/libsepol/include/sepol/policydb/polcaps.h b/libsepol/include/sepol/policydb/polcaps.h
|
||||||
|
index f5e32e60975d..e568733b3a33 100644
|
||||||
|
--- a/libsepol/include/sepol/policydb/polcaps.h
|
||||||
|
+++ b/libsepol/include/sepol/policydb/polcaps.h
|
||||||
|
@@ -19,6 +19,20 @@ enum {
|
||||||
|
};
|
||||||
|
#define POLICYDB_CAP_MAX (__POLICYDB_CAP_MAX - 1)
|
||||||
|
|
||||||
|
+/* legacy constants from past to preserve backward compatibility */
|
||||||
|
+enum {
|
||||||
|
+ POLICYDB_CAPABILITY_NETPEER = POLICYDB_CAP_NETPEER,
|
||||||
|
+ POLICYDB_CAPABILITY_OPENPERM = POLICYDB_CAP_OPENPERM,
|
||||||
|
+ POLICYDB_CAPABILITY_EXTSOCKCLASS = POLICYDB_CAP_EXTSOCKCLASS,
|
||||||
|
+ POLICYDB_CAPABILITY_ALWAYSNETWORK = POLICYDB_CAP_ALWAYSNETWORK,
|
||||||
|
+ POLICYDB_CAPABILITY_CGROUPSECLABEL = POLICYDB_CAP_CGROUPSECLABEL,
|
||||||
|
+ POLICYDB_CAPABILITY_NNP_NOSUID_TRANSITION = POLICYDB_CAP_NNP_NOSUID_TRANSITION,
|
||||||
|
+ POLICYDB_CAPABILITY_GENFS_SECLABEL_SYMLINKS = POLICYDB_CAP_GENFS_SECLABEL_SYMLINKS,
|
||||||
|
+ POLICYDB_CAPABILITY_IOCTL_SKIP_CLOEXEC = POLICYDB_CAP_IOCTL_SKIP_CLOEXEC,
|
||||||
|
+ __POLICYDB_CAPABILITY_MAX = __POLICYDB_CAP_MAX
|
||||||
|
+};
|
||||||
|
+#define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAP_MAX - 1)
|
||||||
|
+
|
||||||
|
/* Convert a capability name to number. */
|
||||||
|
extern int sepol_polcap_getnum(const char *name);
|
||||||
|
|
||||||
|
--
|
||||||
|
2.39.0
|
||||||
|
|
@ -1,50 +0,0 @@
|
|||||||
From 2b2f42f9311ede75c3fe61d356094999e8e161b9 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 0b09cecc..bdeaa7c6 100644
|
|
||||||
--- a/libsepol/cil/src/cil_post.c
|
|
||||||
+++ b/libsepol/cil/src/cil_post.c
|
|
||||||
@@ -179,6 +179,13 @@ void cil_post_fc_fill_data(struct fc_data *fc, 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.30.2
|
|
||||||
|
|
@ -1,100 +0,0 @@
|
|||||||
From 5012fee580f5e4744166462855767949311f9154 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>
|
|
||||||
|
|
||||||
(cherry-picked from SElinuxProject
|
|
||||||
commit: f34d3d30c8325e4847a6b696fe7a3936a8a361f3)
|
|
||||||
---
|
|
||||||
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 43e6b88e..73e1fcf0 100644
|
|
||||||
--- a/libsepol/cil/src/cil_reset_ast.c
|
|
||||||
+++ b/libsepol/cil/src/cil_reset_ast.c
|
|
||||||
@@ -52,7 +52,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.30.2
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
|||||||
From 8c8a21d4ca75e4b767d3dfaa181a83e4c0e1f3a1 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>
|
|
||||||
|
|
||||||
(cherry-picked from SElinuxProject
|
|
||||||
commit: 2d35fcc7e9e976a2346b1de20e54f8663e8a6cba)
|
|
||||||
---
|
|
||||||
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 73e1fcf0..f321b396 100644
|
|
||||||
--- a/libsepol/cil/src/cil_reset_ast.c
|
|
||||||
+++ b/libsepol/cil/src/cil_reset_ast.c
|
|
||||||
@@ -34,7 +34,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.30.2
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
|||||||
From 52bf0fe9ce922229e8bb3b99faa7c7dce2c3531f 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>
|
|
||||||
|
|
||||||
(cherry-picked from SElinuxProject
|
|
||||||
commit: c49a8ea09501ad66e799ea41b8154b6770fec2c8)
|
|
||||||
---
|
|
||||||
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 f321b396..7bf0391b 100644
|
|
||||||
--- a/libsepol/cil/src/cil_reset_ast.c
|
|
||||||
+++ b/libsepol/cil/src/cil_reset_ast.c
|
|
||||||
@@ -57,7 +57,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.30.2
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
|||||||
From 6beea9f422cb452c01a24619247b559b67a4aeec 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 7bf0391b..e86ee3b8 100644
|
|
||||||
--- a/libsepol/cil/src/cil_reset_ast.c
|
|
||||||
+++ b/libsepol/cil/src/cil_reset_ast.c
|
|
||||||
@@ -43,6 +43,7 @@ static inline void cil_reset_classperms(struct cil_classperms *cp)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ cp->class = NULL;
|
|
||||||
cil_list_destroy(&cp->perms, CIL_FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
2.30.2
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
|||||||
From e42e31d865be8dbb5ea1b99ffab434fcfec14df2 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 1036d73c..3972b1e9 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.30.2
|
|
||||||
|
|
@ -1,194 +0,0 @@
|
|||||||
From 5edd2126ad3dc30f75f0ec9f73cd609bbe432c29 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 b90b0f60..fe7b7777 100644
|
|
||||||
--- a/libsepol/cil/src/cil_build_ast.c
|
|
||||||
+++ b/libsepol/cil/src/cil_build_ast.c
|
|
||||||
@@ -110,7 +110,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;
|
|
||||||
}
|
|
||||||
@@ -1919,12 +1919,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;
|
|
||||||
@@ -2303,12 +2297,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;
|
|
||||||
@@ -2357,12 +2345,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;
|
|
||||||
@@ -3064,12 +3046,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;
|
|
||||||
@@ -5294,7 +5270,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 3972b1e9..ea95c2cb 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 bda1565f..e4b98919 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.30.2
|
|
||||||
|
|
@ -1,75 +0,0 @@
|
|||||||
From d6863cc6e4f472444a7944c9ea95333e587efd73 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 bdeaa7c6..a820d5ba 100644
|
|
||||||
--- a/libsepol/cil/src/cil_post.c
|
|
||||||
+++ b/libsepol/cil/src/cil_post.c
|
|
||||||
@@ -2138,6 +2138,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.30.2
|
|
||||||
|
|
@ -1,219 +0,0 @@
|
|||||||
From 6b6a787188804cad4f7f853e95eb0a58dea7ad62 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 fe7b7777..6d5a57fa 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)
|
|
||||||
@@ -6075,10 +6075,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) {
|
|
||||||
@@ -6088,10 +6088,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 */
|
|
||||||
@@ -6108,13 +6108,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;
|
|
||||||
@@ -6122,15 +6140,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) {
|
|
||||||
@@ -6144,24 +6162,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;
|
|
||||||
@@ -6447,14 +6447,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;
|
|
||||||
}
|
|
||||||
@@ -6463,6 +6455,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;
|
|
||||||
@@ -6498,14 +6498,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;
|
|
||||||
}
|
|
||||||
@@ -6514,6 +6506,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
|
|
||||||
@@ -6538,10 +6538,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.30.2
|
|
||||||
|
|
@ -1,91 +0,0 @@
|
|||||||
From 34f3ecbcffaa0ede0252d015d381cef847432fa0 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 6d5a57fa..b7245dbc 100644
|
|
||||||
--- a/libsepol/cil/src/cil_build_ast.c
|
|
||||||
+++ b/libsepol/cil/src/cil_build_ast.c
|
|
||||||
@@ -6071,28 +6071,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;
|
|
||||||
@@ -6480,20 +6468,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;
|
|
||||||
@@ -6522,9 +6501,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.30.2
|
|
||||||
|
|
@ -1,98 +0,0 @@
|
|||||||
From 3e82b1e527fab1fb1dbcad8c70bdb59810a98783 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 b7245dbc..ceb55324 100644
|
|
||||||
--- a/libsepol/cil/src/cil_build_ast.c
|
|
||||||
+++ b/libsepol/cil/src/cil_build_ast.c
|
|
||||||
@@ -6435,22 +6435,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;
|
|
||||||
@@ -6466,6 +6450,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;
|
|
||||||
@@ -6519,7 +6527,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.30.2
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
|||||||
From 628f0f60995c2ed6d2de72bda34e6a62668be74b Mon Sep 17 00:00:00 2001
|
|
||||||
From: James Carter <jwcart2@gmail.com>
|
|
||||||
Date: Mon, 16 Nov 2020 17:06:59 -0500
|
|
||||||
Subject: [PATCH] libsepol/cil: Remove unused field from struct
|
|
||||||
cil_args_resolve
|
|
||||||
|
|
||||||
When resolving names, the struct cil_args_resolve is passed to the
|
|
||||||
various resolve functions. The field last_resolved_name is not used.
|
|
||||||
|
|
||||||
Remove the last_resolved_name field from struct cil_args_resolve.
|
|
||||||
|
|
||||||
Signed-off-by: James Carter <jwcart2@gmail.com>
|
|
||||||
---
|
|
||||||
libsepol/cil/src/cil_resolve_ast.c | 4 ----
|
|
||||||
1 file changed, 4 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
|
|
||||||
index ea08087d..ed876260 100644
|
|
||||||
--- a/libsepol/cil/src/cil_resolve_ast.c
|
|
||||||
+++ b/libsepol/cil/src/cil_resolve_ast.c
|
|
||||||
@@ -51,7 +51,6 @@ struct cil_args_resolve {
|
|
||||||
struct cil_db *db;
|
|
||||||
enum cil_pass pass;
|
|
||||||
uint32_t *changed;
|
|
||||||
- char *last_resolved_name;
|
|
||||||
struct cil_tree_node *optstack;
|
|
||||||
struct cil_tree_node *boolif;
|
|
||||||
struct cil_tree_node *macro;
|
|
||||||
@@ -3907,7 +3906,6 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current)
|
|
||||||
extra_args.db = db;
|
|
||||||
extra_args.pass = pass;
|
|
||||||
extra_args.changed = &changed;
|
|
||||||
- extra_args.last_resolved_name = NULL;
|
|
||||||
extra_args.optstack = NULL;
|
|
||||||
extra_args.boolif= NULL;
|
|
||||||
extra_args.macro = NULL;
|
|
||||||
@@ -4236,7 +4234,5 @@ exit:
|
|
||||||
*datum = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
- args->last_resolved_name = name;
|
|
||||||
-
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
--
|
|
||||||
2.30.2
|
|
||||||
|
|
@ -1,115 +0,0 @@
|
|||||||
From d668f8e3a0a0361c03881ae3f00509196eaee064 Mon Sep 17 00:00:00 2001
|
|
||||||
From: James Carter <jwcart2@gmail.com>
|
|
||||||
Date: Mon, 8 Feb 2021 11:23:42 -0500
|
|
||||||
Subject: [PATCH] libsepol/cil: Destroy disabled optional blocks after pass is
|
|
||||||
complete
|
|
||||||
|
|
||||||
Nicolas Iooss reports:
|
|
||||||
I am continuing to investigate OSS-Fuzz crashes and the following one
|
|
||||||
is quite complex. Here is a CIL policy which triggers a
|
|
||||||
heap-use-after-free error in the CIL compiler:
|
|
||||||
|
|
||||||
(class CLASS (PERM2))
|
|
||||||
(classorder (CLASS))
|
|
||||||
(classpermission CLSPRM)
|
|
||||||
(optional o
|
|
||||||
(mlsvalidatetrans x (domby l1 h1))
|
|
||||||
(common CLSCOMMON (PERM1))
|
|
||||||
(classcommon CLASS CLSCOMMON)
|
|
||||||
)
|
|
||||||
(classpermissionset CLSPRM (CLASS (PERM1)))
|
|
||||||
|
|
||||||
The issue is that the mlsvalidatetrans fails to resolve in pass
|
|
||||||
CIL_PASS_MISC3, which comes after the resolution of classcommon (in
|
|
||||||
pass CIL_PASS_MISC2). So:
|
|
||||||
|
|
||||||
* In pass CIL_PASS_MISC2, the optional block still exists, the
|
|
||||||
classcommon is resolved and class CLASS is linked with common
|
|
||||||
CLSCOMMON.
|
|
||||||
* In pass CIL_PASS_MISC3, the optional block is destroyed, including
|
|
||||||
the common CLSCOMMON.
|
|
||||||
* When classpermissionset is resolved, function cil_resolve_classperms
|
|
||||||
uses "common_symtab = &class->common->perms;", which has been freed.
|
|
||||||
The use-after-free issue occurs in __cil_resolve_perms (in
|
|
||||||
libsepol/cil/src/cil_resolve_ast.c):
|
|
||||||
|
|
||||||
// common_symtab was freed
|
|
||||||
rc = cil_symtab_get_datum(common_symtab, curr->data, &perm_datum);
|
|
||||||
|
|
||||||
The fundamental problem here is that when the optional block is
|
|
||||||
disabled it is immediately destroyed in the middle of the pass, so
|
|
||||||
the class has not been reset and still refers to the now destroyed
|
|
||||||
common when the classpermissionset is resolved later in the same pass.
|
|
||||||
|
|
||||||
Added a list, disabled_optionals, to struct cil_args_resolve which is
|
|
||||||
passed when resolving the tree. When optionals are disabled, they are
|
|
||||||
now added to this list and then are destroyed after the tree has been
|
|
||||||
reset between passes.
|
|
||||||
|
|
||||||
Reported-by: Nicolas Iooss <nicolas.iooss@m4x.org>
|
|
||||||
Signed-off-by: James Carter <jwcart2@gmail.com>
|
|
||||||
Acked-by: Nicolas Iooss <nicolas.iooss@m4x.org>
|
|
||||||
---
|
|
||||||
libsepol/cil/src/cil_resolve_ast.c | 11 ++++++++++-
|
|
||||||
1 file changed, 10 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
|
|
||||||
index ed876260..979fa17d 100644
|
|
||||||
--- a/libsepol/cil/src/cil_resolve_ast.c
|
|
||||||
+++ b/libsepol/cil/src/cil_resolve_ast.c
|
|
||||||
@@ -51,6 +51,7 @@ struct cil_args_resolve {
|
|
||||||
struct cil_db *db;
|
|
||||||
enum cil_pass pass;
|
|
||||||
uint32_t *changed;
|
|
||||||
+ struct cil_list *disabled_optionals;
|
|
||||||
struct cil_tree_node *optstack;
|
|
||||||
struct cil_tree_node *boolif;
|
|
||||||
struct cil_tree_node *macro;
|
|
||||||
@@ -3854,7 +3855,7 @@ int __cil_resolve_ast_last_child_helper(struct cil_tree_node *current, void *ext
|
|
||||||
|
|
||||||
if (((struct cil_optional *)parent->data)->enabled == CIL_FALSE) {
|
|
||||||
*(args->changed) = CIL_TRUE;
|
|
||||||
- cil_tree_children_destroy(parent);
|
|
||||||
+ cil_list_append(args->disabled_optionals, CIL_NODE, parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* pop off the stack */
|
|
||||||
@@ -3917,6 +3918,7 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current)
|
|
||||||
extra_args.in_list = NULL;
|
|
||||||
extra_args.blockstack = NULL;
|
|
||||||
|
|
||||||
+ cil_list_init(&extra_args.disabled_optionals, CIL_NODE);
|
|
||||||
cil_list_init(&extra_args.sidorder_lists, CIL_LIST_ITEM);
|
|
||||||
cil_list_init(&extra_args.classorder_lists, CIL_LIST_ITEM);
|
|
||||||
cil_list_init(&extra_args.unordered_classorder_lists, CIL_LIST_ITEM);
|
|
||||||
@@ -3984,6 +3986,7 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changed && (pass > CIL_PASS_CALL1)) {
|
|
||||||
+ struct cil_list_item *item;
|
|
||||||
/* Need to re-resolve because an optional was disabled that contained
|
|
||||||
* one or more declarations. We only need to reset to the call1 pass
|
|
||||||
* because things done in the preceeding passes aren't allowed in
|
|
||||||
@@ -4012,6 +4015,11 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current)
|
|
||||||
cil_log(CIL_ERR, "Failed to reset declarations\n");
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
+ cil_list_for_each(item, extra_args.disabled_optionals) {
|
|
||||||
+ cil_tree_children_destroy(item->data);
|
|
||||||
+ }
|
|
||||||
+ cil_list_destroy(&extra_args.disabled_optionals, CIL_FALSE);
|
|
||||||
+ cil_list_init(&extra_args.disabled_optionals, CIL_NODE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* reset the arguments */
|
|
||||||
@@ -4040,6 +4048,7 @@ exit:
|
|
||||||
__cil_ordered_lists_destroy(&extra_args.catorder_lists);
|
|
||||||
__cil_ordered_lists_destroy(&extra_args.sensitivityorder_lists);
|
|
||||||
__cil_ordered_lists_destroy(&extra_args.unordered_classorder_lists);
|
|
||||||
+ cil_list_destroy(&extra_args.disabled_optionals, CIL_FALSE);
|
|
||||||
cil_list_destroy(&extra_args.in_list, CIL_FALSE);
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
--
|
|
||||||
2.30.2
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
|||||||
From 8d7ed6eb2c396d64b1a8f6d516cb9f6f86ba2ece Mon Sep 17 00:00:00 2001
|
|
||||||
From: James Carter <jwcart2@gmail.com>
|
|
||||||
Date: Wed, 4 Mar 2020 16:28:11 -0500
|
|
||||||
Subject: [PATCH] libsepol/cil: Check if name is a macro parameter first
|
|
||||||
|
|
||||||
Type transition file names are stored in a symbol table. Before the
|
|
||||||
name is added, the symbol table is searched to see if the name had
|
|
||||||
already been inserted. If it has, then the already existing datum is
|
|
||||||
returned. If it has not, then the name is added if either the
|
|
||||||
typetransition rule does not occur in a macro or the name is not one
|
|
||||||
of the macro parameters.
|
|
||||||
|
|
||||||
Checking for a previous insertion before checking if the name is a
|
|
||||||
macro parameter can cause a macro parameter to be treated as the
|
|
||||||
actual name if a previous type transition file name is the same as
|
|
||||||
the parameter.
|
|
||||||
|
|
||||||
Now check the name to see if it a macro paramter before checking for
|
|
||||||
its existence in the symbol table.
|
|
||||||
|
|
||||||
Signed-off-by: James Carter <jwcart2@gmail.com>
|
|
||||||
Acked-by: Ondrej Mosnacek <omosnace@redhat.com>
|
|
||||||
---
|
|
||||||
libsepol/cil/src/cil_resolve_ast.c | 16 ++++++++--------
|
|
||||||
1 file changed, 8 insertions(+), 8 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
|
|
||||||
index 979fa17d..ae334620 100644
|
|
||||||
--- a/libsepol/cil/src/cil_resolve_ast.c
|
|
||||||
+++ b/libsepol/cil/src/cil_resolve_ast.c
|
|
||||||
@@ -76,14 +76,6 @@ static struct cil_name * __cil_insert_name(struct cil_db *db, hashtab_key_t key,
|
|
||||||
enum cil_sym_index sym_index;
|
|
||||||
struct cil_symtab_datum *datum = NULL;
|
|
||||||
|
|
||||||
- cil_flavor_to_symtab_index(CIL_NAME, &sym_index);
|
|
||||||
- symtab = &((struct cil_root *)db->ast->root->data)->symtab[sym_index];
|
|
||||||
-
|
|
||||||
- cil_symtab_get_datum(symtab, key, &datum);
|
|
||||||
- if (datum != NULL) {
|
|
||||||
- return (struct cil_name *)datum;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
if (parent->flavor == CIL_CALL) {
|
|
||||||
struct cil_call *call = parent->data;
|
|
||||||
macro = call->macro;
|
|
||||||
@@ -99,6 +91,14 @@ static struct cil_name * __cil_insert_name(struct cil_db *db, hashtab_key_t key,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+ cil_flavor_to_symtab_index(CIL_NAME, &sym_index);
|
|
||||||
+ symtab = &((struct cil_root *)db->ast->root->data)->symtab[sym_index];
|
|
||||||
+
|
|
||||||
+ cil_symtab_get_datum(symtab, key, &datum);
|
|
||||||
+ if (datum != NULL) {
|
|
||||||
+ return (struct cil_name *)datum;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
cil_name_init(&name);
|
|
||||||
cil_symtab_insert(symtab, key, (struct cil_symtab_datum *)name, ast_node);
|
|
||||||
cil_list_append(db->names, CIL_NAME, name);
|
|
||||||
--
|
|
||||||
2.30.2
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
|||||||
From 7cb30b316eda0b2aa8adeaba28a8afe15fc58c28 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 ae334620..91e08633 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.30.2
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
|||||||
From 2f9ce13779d3b92198e60cdbd3d19e7c08b5457f Mon Sep 17 00:00:00 2001
|
|
||||||
From: James Carter <jwcart2@tycho.nsa.gov>
|
|
||||||
Date: Fri, 1 Nov 2019 09:50:53 -0400
|
|
||||||
Subject: [PATCH] libsepol/cil: Report disabling an optional block only at high
|
|
||||||
verbose levels
|
|
||||||
|
|
||||||
Since failing to resolve a statement in an optional block is normal,
|
|
||||||
only display messages about the statement failing to resolve and the
|
|
||||||
optional block being disabled at the highest verbosity level.
|
|
||||||
|
|
||||||
These messages are now only at log level CIL_INFO instead of CIL_WARN.
|
|
||||||
|
|
||||||
Signed-off-by: James Carter <jwcart2@tycho.nsa.gov>
|
|
||||||
---
|
|
||||||
libsepol/cil/src/cil_resolve_ast.c | 6 ++++--
|
|
||||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
|
|
||||||
index 91e08633..dab8b276 100644
|
|
||||||
--- a/libsepol/cil/src/cil_resolve_ast.c
|
|
||||||
+++ b/libsepol/cil/src/cil_resolve_ast.c
|
|
||||||
@@ -3765,14 +3765,16 @@ int __cil_resolve_ast_node_helper(struct cil_tree_node *node, uint32_t *finished
|
|
||||||
enum cil_log_level lvl = CIL_ERR;
|
|
||||||
|
|
||||||
if (optstack != NULL) {
|
|
||||||
- lvl = CIL_WARN;
|
|
||||||
+ lvl = CIL_INFO;
|
|
||||||
|
|
||||||
struct cil_optional *opt = (struct cil_optional *)optstack->data;
|
|
||||||
struct cil_tree_node *opt_node = opt->datum.nodes->head->data;
|
|
||||||
- cil_tree_log(opt_node, lvl, "Disabling optional '%s'", opt->datum.name);
|
|
||||||
/* 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);
|
|
||||||
rc = SEPOL_OK;
|
|
||||||
+ goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
cil_tree_log(node, lvl, "Failed to resolve %s statement", cil_node_to_string(node));
|
|
||||||
--
|
|
||||||
2.30.2
|
|
||||||
|
|
@ -1,249 +0,0 @@
|
|||||||
From 599c1422479ae9dd9501c43680bf4a1667e7c951 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 dab8b276..e0379782 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;
|
|
||||||
@@ -3692,16 +3692,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));
|
|
||||||
@@ -3710,7 +3710,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;
|
|
||||||
@@ -3764,11 +3764,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));
|
|
||||||
@@ -3791,39 +3791,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) {
|
|
||||||
@@ -3842,7 +3821,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;
|
|
||||||
@@ -3853,30 +3831,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;
|
|
||||||
@@ -3885,16 +3864,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;
|
|
||||||
@@ -3909,7 +3878,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;
|
|
||||||
@@ -3918,7 +3888,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);
|
|
||||||
@@ -4022,17 +3991,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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -4043,8 +4002,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.30.2
|
|
||||||
|
|
@ -1,175 +0,0 @@
|
|||||||
From 88f4d1c0b93d6a359d7fc7b2116de0da32c74ca5 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 e0379782..c520c44a 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;
|
|
||||||
@@ -3692,50 +3692,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 {
|
|
||||||
@@ -3801,12 +3803,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;
|
|
||||||
@@ -3828,7 +3830,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;
|
|
||||||
@@ -3846,16 +3858,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;
|
|
||||||
@@ -3879,9 +3881,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.30.2
|
|
||||||
|
|
@ -1,86 +0,0 @@
|
|||||||
From dadf1e9ad66318fdd814cf06af2b83741467a3d8 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 ceb55324..3a91be03 100644
|
|
||||||
--- a/libsepol/cil/src/cil_build_ast.c
|
|
||||||
+++ b/libsepol/cil/src/cil_build_ast.c
|
|
||||||
@@ -6136,7 +6136,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 c520c44a..06b6ab48 100644
|
|
||||||
--- a/libsepol/cil/src/cil_resolve_ast.c
|
|
||||||
+++ b/libsepol/cil/src/cil_resolve_ast.c
|
|
||||||
@@ -3689,7 +3689,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;
|
|
||||||
@@ -3732,18 +3732,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.30.2
|
|
||||||
|
|
@ -1,151 +0,0 @@
|
|||||||
From 0e420cc6f6debc2050229ea537b592c963b81a7c 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 3a91be03..4f72884c 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;
|
|
||||||
};
|
|
||||||
|
|
||||||
@@ -6077,6 +6078,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;
|
|
||||||
@@ -6127,6 +6129,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 &&
|
|
||||||
@@ -6468,6 +6482,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;
|
|
||||||
}
|
|
||||||
@@ -6498,6 +6516,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;
|
|
||||||
}
|
|
||||||
@@ -6526,6 +6557,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 06b6ab48..8ffab438 100644
|
|
||||||
--- a/libsepol/cil/src/cil_resolve_ast.c
|
|
||||||
+++ b/libsepol/cil/src/cil_resolve_ast.c
|
|
||||||
@@ -3723,8 +3723,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.30.2
|
|
||||||
|
|
Loading…
Reference in new issue