[PATCH v2] libsepol: handle type gaps

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



For policy versions between 20 and 23 the type_val_to_struct array might
contain gaps. Skip those gaps to avoid NULL pointer dereferences:

    ==1250==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000008 (pc 0x00000058560b bp 0x7ffdca60c110 sp 0x7ffdca60bfc0 T0)
    ==1250==The signal is caused by a READ memory access.
    ==1250==Hint: address points to the zero page.
        #0 0x58560b in build_type_map selinux/libsepol/src/optimize.c:107:33
        #1 0x58560b in policydb_optimize selinux/libsepol/src/optimize.c:441:13
        #2 0x55e63e in LLVMFuzzerTestOneInput selinux/libsepol/fuzz/binpolicy-fuzzer.c:42:10
        #3 0x455283 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) cxa_noexception.cpp:0
        #4 0x440ec2 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:324:6
        #5 0x44671c in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) cxa_noexception.cpp:0
        #6 0x46f522 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10
        #7 0x7f9c160d00b2 in __libc_start_main /build/glibc-eX1tMB/glibc-2.31/csu/libc-start.c:308:16
        #8 0x41f67d in _start

Found by oss-fuzz (#42697)

Signed-off-by: Christian Göttsche <cgzones@xxxxxxxxxxxxxx>
---
@Jim:
    I hope I have interpreted and implemented your feedback correctly, but I
    am not sure I have seen through the whole gaps logic yet.
---
 libsepol/src/kernel_to_cil.c  | 40 +++++++++++++++++++++++++++++++++++
 libsepol/src/kernel_to_conf.c | 32 ++++++++++++++++++++++++++++
 libsepol/src/optimize.c       | 18 +++++++++++++++-
 3 files changed, 89 insertions(+), 1 deletion(-)

diff --git a/libsepol/src/kernel_to_cil.c b/libsepol/src/kernel_to_cil.c
index 18294a9a..1353e77f 100644
--- a/libsepol/src/kernel_to_cil.c
+++ b/libsepol/src/kernel_to_cil.c
@@ -1227,6 +1227,14 @@ static int write_type_attributes_to_cil(FILE *out, struct policydb *pdb)
 
 	for (i=0; i < pdb->p_types.nprim; i++) {
 		type = pdb->type_val_to_struct[i];
+		/* Gap in types for policy versions between 20 and 23 */
+		if (!type) {
+			if (pdb->policyvers <= POLICYDB_VERSION_PERMISSIVE) {
+				rc = -1;
+				goto exit;
+			}
+			continue;
+		}
 		if (type->flavor == TYPE_ATTRIB) {
 			rc = strs_add(strs, pdb->p_type_val_to_name[i]);
 			if (rc != 0) {
@@ -1357,6 +1365,14 @@ static int write_type_decl_rules_to_cil(FILE *out, struct policydb *pdb)
 
 	for (i=0; i < pdb->p_types.nprim; i++) {
 		type = pdb->type_val_to_struct[i];
+		/* Gap in types for policy versions between 20 and 23 */
+		if (!type) {
+			if (pdb->policyvers <= POLICYDB_VERSION_PERMISSIVE) {
+				rc = -1;
+				goto exit;
+			}
+			continue;
+		}
 		if (type->flavor == TYPE_TYPE && type->primary) {
 			rc = strs_add(strs, pdb->p_type_val_to_name[i]);
 			if (rc != 0) {
@@ -1486,6 +1502,14 @@ static int write_type_bounds_rules_to_cil(FILE *out, struct policydb *pdb)
 
 	for (i=0; i < pdb->p_types.nprim; i++) {
 		type = pdb->type_val_to_struct[i];
+		/* Gap in types for policy versions between 20 and 23 */
+		if (!type) {
+			if (pdb->policyvers <= POLICYDB_VERSION_PERMISSIVE) {
+				rc = -1;
+				goto exit;
+			}
+			continue;
+		}
 		if (type->flavor == TYPE_TYPE) {
 			if (type->bounds > 0) {
 				rc = strs_add(strs, pdb->p_type_val_to_name[i]);
@@ -1540,6 +1564,14 @@ static int write_type_attribute_sets_to_cil(FILE *out, struct policydb *pdb)
 
 	for (i=0; i < pdb->p_types.nprim; i++) {
 		attr = pdb->type_val_to_struct[i];
+		/* Gap in types for policy versions between 20 and 23 */
+		if (!attr) {
+			if (pdb->policyvers <= POLICYDB_VERSION_PERMISSIVE) {
+				rc = -1;
+				goto exit;
+			}
+			continue;
+		}
 		if (attr->flavor != TYPE_ATTRIB) continue;
 		name = pdb->p_type_val_to_name[i];
 		typemap = &pdb->attr_type_map[i];
@@ -2273,6 +2305,14 @@ static int write_role_decl_rules_to_cil(FILE *out, struct policydb *pdb)
 
 	for (i=0; i < pdb->p_types.nprim; i++) {
 		type_datum = pdb->type_val_to_struct[i];
+		/* Gap in types for policy versions between 20 and 23 */
+		if (!type_datum) {
+			if (pdb->policyvers <= POLICYDB_VERSION_PERMISSIVE) {
+				rc = -1;
+				goto exit;
+			}
+			continue;
+		}
 		if (type_datum->flavor == TYPE_TYPE && type_datum->primary) {
 			rc = strs_add(strs, pdb->p_type_val_to_name[i]);
 			if (rc != 0) {
diff --git a/libsepol/src/kernel_to_conf.c b/libsepol/src/kernel_to_conf.c
index a92ba9fd..235b4556 100644
--- a/libsepol/src/kernel_to_conf.c
+++ b/libsepol/src/kernel_to_conf.c
@@ -1210,6 +1210,14 @@ static int write_type_attributes_to_conf(FILE *out, struct policydb *pdb)
 
 	for (i=0; i < pdb->p_types.nprim; i++) {
 		type = pdb->type_val_to_struct[i];
+		/* Gap in types for policy versions between 20 and 23 */
+		if (!type) {
+			if (pdb->policyvers <= POLICYDB_VERSION_PERMISSIVE) {
+				rc = -1;
+				goto exit;
+			}
+			continue;
+		}
 		if (type->flavor == TYPE_ATTRIB) {
 			rc = strs_add(strs, pdb->p_type_val_to_name[i]);
 			if (rc != 0) {
@@ -1340,6 +1348,14 @@ static int write_type_decl_rules_to_conf(FILE *out, struct policydb *pdb)
 
 	for (i=0; i < pdb->p_types.nprim; i++) {
 		type = pdb->type_val_to_struct[i];
+		/* Gap in types for policy versions between 20 and 23 */
+		if (!type) {
+			if (pdb->policyvers <= POLICYDB_VERSION_PERMISSIVE) {
+				rc = -1;
+				goto exit;
+			}
+			continue;
+		}
 		if (type->flavor == TYPE_TYPE && type->primary) {
 			rc = strs_add(strs, pdb->p_type_val_to_name[i]);
 			if (rc != 0) {
@@ -1460,6 +1476,14 @@ static int write_type_bounds_rules_to_conf(FILE *out, struct policydb *pdb)
 
 	for (i=0; i < pdb->p_types.nprim; i++) {
 		type = pdb->type_val_to_struct[i];
+		/* Gap in types for policy versions between 20 and 23 */
+		if (!type) {
+			if (pdb->policyvers <= POLICYDB_VERSION_PERMISSIVE) {
+				rc = -1;
+				goto exit;
+			}
+			continue;
+		}
 		if (type->flavor == TYPE_TYPE) {
 			if (type->bounds > 0) {
 				rc = strs_add(strs, pdb->p_type_val_to_name[i]);
@@ -1583,6 +1607,14 @@ static int write_type_attribute_sets_to_conf(FILE *out, struct policydb *pdb)
 
 	for (i=0; i < pdb->p_types.nprim; i++) {
 		type = pdb->type_val_to_struct[i];
+		/* Gap in types for policy versions between 20 and 23 */
+		if (!type) {
+			if (pdb->policyvers <= POLICYDB_VERSION_PERMISSIVE) {
+				rc = -1;
+				goto exit;
+			}
+			continue;
+		}
 		if (type->flavor != TYPE_TYPE || !type->primary) continue;
 		if (ebitmap_cardinality(&pdb->type_attr_map[i]) == 1) continue;
 
diff --git a/libsepol/src/optimize.c b/libsepol/src/optimize.c
index 8a048702..f8c28313 100644
--- a/libsepol/src/optimize.c
+++ b/libsepol/src/optimize.c
@@ -104,6 +104,13 @@ static struct type_vec *build_type_map(const policydb_t *p)
 		if (type_vec_init(&map[i]))
 			goto err;
 
+		/* Gap in types for policy versions between 20 and 23 */
+		if (!p->type_val_to_struct[i]) {
+			if (p->policyvers <= POLICYDB_VERSION_PERMISSIVE)
+				goto err;
+			continue;
+		}
+
 		if (p->type_val_to_struct[i]->flavor != TYPE_ATTRIB) {
 			ebitmap_for_each_positive_bit(&p->type_attr_map[i],
 						      n, k) {
@@ -114,11 +121,20 @@ static struct type_vec *build_type_map(const policydb_t *p)
 			ebitmap_t *types_i = &p->attr_type_map[i];
 
 			for (k = 0; k < p->p_types.nprim; k++) {
-				ebitmap_t *types_k = &p->attr_type_map[k];
+				ebitmap_t *types_k;
+
+				/* Gap in types for policy versions between 20 and 23 */
+				if (!p->type_val_to_struct[k]) {
+					if (p->policyvers <= POLICYDB_VERSION_PERMISSIVE)
+						goto err;
+					continue;
+				}
 
 				if (p->type_val_to_struct[k]->flavor != TYPE_ATTRIB)
 					continue;
 
+				types_k = &p->attr_type_map[k];
+
 				if (ebitmap_contains(types_k, types_i)) {
 					if (type_vec_append(&map[i], k))
 						goto err;
-- 
2.34.1




[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux