On Tue, Jan 25, 2022 at 4:17 PM James Carter <jwcart2@xxxxxxxxx> wrote: > > On Tue, Jan 25, 2022 at 2:43 PM Christian Göttsche > <cgzones@xxxxxxxxxxxxxx> wrote: > > > > 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> > > > > Acked-by: James Carter <jwcart2@xxxxxxxxx> > Merged. Thanks, Jim > > --- > > v3: > > - drop extra error blocks in kernel_to_(cil|conf).c in favor of a > > simple non-NULL check, as writing policies between version 20 and > > 23 is not supported and previously checked > > - refuse to optimize policies between version 20 and 23 altogether > > and simplify NULL checks > > > > Signed-off-by: Christian Göttsche <cgzones@xxxxxxxxxxxxxx> > > --- > > libsepol/src/kernel_to_cil.c | 10 +++++----- > > libsepol/src/kernel_to_conf.c | 8 ++++---- > > libsepol/src/optimize.c | 21 +++++++++++++++++++-- > > 3 files changed, 28 insertions(+), 11 deletions(-) > > > > diff --git a/libsepol/src/kernel_to_cil.c b/libsepol/src/kernel_to_cil.c > > index 18294a9a..693206d2 100644 > > --- a/libsepol/src/kernel_to_cil.c > > +++ b/libsepol/src/kernel_to_cil.c > > @@ -1227,7 +1227,7 @@ 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]; > > - if (type->flavor == TYPE_ATTRIB) { > > + if (type && type->flavor == TYPE_ATTRIB) { > > rc = strs_add(strs, pdb->p_type_val_to_name[i]); > > if (rc != 0) { > > goto exit; > > @@ -1357,7 +1357,7 @@ 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]; > > - if (type->flavor == TYPE_TYPE && type->primary) { > > + if (type && type->flavor == TYPE_TYPE && type->primary) { > > rc = strs_add(strs, pdb->p_type_val_to_name[i]); > > if (rc != 0) { > > goto exit; > > @@ -1486,7 +1486,7 @@ 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]; > > - if (type->flavor == TYPE_TYPE) { > > + if (type && type->flavor == TYPE_TYPE) { > > if (type->bounds > 0) { > > rc = strs_add(strs, pdb->p_type_val_to_name[i]); > > if (rc != 0) { > > @@ -1540,7 +1540,7 @@ 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]; > > - if (attr->flavor != TYPE_ATTRIB) continue; > > + if (!attr || attr->flavor != TYPE_ATTRIB) continue; > > name = pdb->p_type_val_to_name[i]; > > typemap = &pdb->attr_type_map[i]; > > if (ebitmap_is_empty(typemap)) continue; > > @@ -2273,7 +2273,7 @@ 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]; > > - if (type_datum->flavor == TYPE_TYPE && type_datum->primary) { > > + if (type_datum && type_datum->flavor == TYPE_TYPE && type_datum->primary) { > > rc = strs_add(strs, pdb->p_type_val_to_name[i]); > > if (rc != 0) { > > goto exit; > > diff --git a/libsepol/src/kernel_to_conf.c b/libsepol/src/kernel_to_conf.c > > index a92ba9fd..52b6c60f 100644 > > --- a/libsepol/src/kernel_to_conf.c > > +++ b/libsepol/src/kernel_to_conf.c > > @@ -1210,7 +1210,7 @@ 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]; > > - if (type->flavor == TYPE_ATTRIB) { > > + if (type && type->flavor == TYPE_ATTRIB) { > > rc = strs_add(strs, pdb->p_type_val_to_name[i]); > > if (rc != 0) { > > goto exit; > > @@ -1340,7 +1340,7 @@ 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]; > > - if (type->flavor == TYPE_TYPE && type->primary) { > > + if (type && type->flavor == TYPE_TYPE && type->primary) { > > rc = strs_add(strs, pdb->p_type_val_to_name[i]); > > if (rc != 0) { > > goto exit; > > @@ -1460,7 +1460,7 @@ 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]; > > - if (type->flavor == TYPE_TYPE) { > > + if (type && type->flavor == TYPE_TYPE) { > > if (type->bounds > 0) { > > rc = strs_add(strs, pdb->p_type_val_to_name[i]); > > if (rc != 0) { > > @@ -1583,7 +1583,7 @@ 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]; > > - if (type->flavor != TYPE_TYPE || !type->primary) continue; > > + if (!type || type->flavor != TYPE_TYPE || !type->primary) continue; > > if (ebitmap_cardinality(&pdb->type_attr_map[i]) == 1) continue; > > > > rc = ebitmap_cpy(&attrmap, &pdb->type_attr_map[i]); > > diff --git a/libsepol/src/optimize.c b/libsepol/src/optimize.c > > index 8a048702..93ff2116 100644 > > --- a/libsepol/src/optimize.c > > +++ b/libsepol/src/optimize.c > > @@ -31,6 +31,7 @@ > > #include <sepol/policydb/policydb.h> > > #include <sepol/policydb/conditional.h> > > > > +#include "debug.h" > > #include "private.h" > > > > #define TYPE_VEC_INIT_SIZE 16 > > @@ -104,6 +105,9 @@ static struct type_vec *build_type_map(const policydb_t *p) > > if (type_vec_init(&map[i])) > > goto err; > > > > + if (!p->type_val_to_struct[i]) > > + 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 +118,13 @@ 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]; > > + const ebitmap_t *types_k; > > > > - if (p->type_val_to_struct[k]->flavor != TYPE_ATTRIB) > > + if (!p->type_val_to_struct[k] || 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; > > @@ -438,6 +444,17 @@ int policydb_optimize(policydb_t *p) > > if (p->policy_type != POLICY_KERN) > > return -1; > > > > + if (p->policyvers >= POLICYDB_VERSION_AVTAB && p->policyvers <= POLICYDB_VERSION_PERMISSIVE) { > > + /* > > + * For policy versions between 20 and 23, attributes exist in the policy, > > + * but only in the type_attr_map. This means that there are gaps in both > > + * the type_val_to_struct and p_type_val_to_name arrays and policy rules > > + * can refer to those gaps. > > + */ > > + ERR(NULL, "Optimizing policy versions between 20 and 23 is not supported"); > > + return -1; > > + } > > + > > type_map = build_type_map(p); > > if (!type_map) > > return -1; > > -- > > 2.34.1 > >