All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Christian Göttsche" <cgzones@googlemail.com>
To: selinux@vger.kernel.org
Subject: [PATCH v2] libsepol: handle type gaps
Date: Thu,  6 Jan 2022 21:42:26 +0100	[thread overview]
Message-ID: <20220106204226.146879-1-cgzones@googlemail.com> (raw)
In-Reply-To: <20211223185004.77862-1-cgzones@googlemail.com>

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@googlemail.com>
---
@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


  parent reply	other threads:[~2022-01-06 20:42 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-12-23 18:50 [PATCH] libsepol: handle type gaps when optimizing Christian Göttsche
2022-01-03 18:10 ` James Carter
2022-01-06 20:42 ` Christian Göttsche [this message]
2022-01-12 15:55   ` [PATCH v2] libsepol: handle type gaps James Carter
2022-01-19 15:43     ` Christian Göttsche
2022-01-19 18:11       ` James Carter
2022-01-25 13:30 ` [PATCH v3] " Christian Göttsche
2022-01-25 21:17   ` James Carter
2022-01-27 15:31     ` James Carter

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220106204226.146879-1-cgzones@googlemail.com \
    --to=cgzones@googlemail.com \
    --cc=selinux@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.