James Carter <jwcart2@xxxxxxxxx> writes: > When checking for circular class permission declarations and a class > mapping is encountered, the class permissions for each map permission > must be checked. An assumption was made that there were no operators > in the class permissions. An operator in the class permissions would > cause a segfault. > > Example causing segault: > (classmap cm1 (mp1)) > (classmapping cm1 mp1 (CLASS (PERM))) > (classpermission cp1) > (classpermissionset cp1 (cm1 (all))) > > For map class permissions, check each item in the permission list to > see if it is an operator. If it is not, then verify the class > permissions associated with the map permission. If it is an operator > and the operator is "all", then create a list of all permissions for > that map class and verify the class permissions associated with each > map permission. If it is a different operator, then it can be skipped. > > This bug was found by the secilc-fuzzer. > > Signed-off-by: James Carter <jwcart2@xxxxxxxxx> Acked-by: Petr Lautrbach <plautrba@xxxxxxxxxx> Thanks! > --- > libsepol/cil/src/cil_verify.c | 40 ++++++++++++++++++++++++++++++----- > 1 file changed, 35 insertions(+), 5 deletions(-) > > diff --git a/libsepol/cil/src/cil_verify.c b/libsepol/cil/src/cil_verify.c > index 5502c4d5..dc29ea66 100644 > --- a/libsepol/cil/src/cil_verify.c > +++ b/libsepol/cil/src/cil_verify.c > @@ -1689,6 +1689,15 @@ exit: > return rc; > } > > +static int __add_perm_to_list(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) > +{ > + struct cil_list *perm_list = (struct cil_list *)args; > + > + cil_list_append(perm_list, CIL_DATUM, d); > + > + return SEPOL_OK; > +} > + > static int __cil_verify_classperms(struct cil_list *classperms, > struct cil_symtab_datum *orig, > struct cil_symtab_datum *parent, > @@ -1730,13 +1739,34 @@ static int __cil_verify_classperms(struct cil_list *classperms, > if (FLAVOR(cp->class) != CIL_CLASS) { /* MAP */ > struct cil_list_item *i = NULL; > cil_list_for_each(i, cp->perms) { > - struct cil_perm *cmp = i->data; > - rc = __cil_verify_classperms(cmp->classperms, orig, &cp->class->datum, &cmp->datum, CIL_MAP_PERM, steps, limit); > - if (rc != SEPOL_OK) { > - goto exit; > + if (i->flavor != CIL_OP) { > + struct cil_perm *cmp = i->data; > + rc = __cil_verify_classperms(cmp->classperms, orig, &cp->class->datum, &cmp->datum, CIL_MAP_PERM, steps, limit); > + if (rc != SEPOL_OK) { > + goto exit; > + } > + } else { > + enum cil_flavor op = (enum cil_flavor)i->data; > + if (op == CIL_ALL) { > + struct cil_class *mc = cp->class; > + struct cil_list *perm_list; > + struct cil_list_item *j = NULL; > + > + cil_list_init(&perm_list, CIL_MAP_PERM); > + cil_symtab_map(&mc->perms, __add_perm_to_list, perm_list); > + cil_list_for_each(j, perm_list) { > + struct cil_perm *cmp = j->data; > + rc = __cil_verify_classperms(cmp->classperms, orig, &cp->class->datum, &cmp->datum, CIL_MAP_PERM, steps, limit); > + if (rc != SEPOL_OK) { > + cil_list_destroy(&perm_list, CIL_FALSE); > + goto exit; > + } > + } > + cil_list_destroy(&perm_list, CIL_FALSE); > + } > } > } > - } > + } > } else { /* SET */ > struct cil_classperms_set *cp_set = curr->data; > struct cil_classpermission *cp = cp_set->set; > -- > 2.31.1