Re: [PATCH] libsepol/cil: Fix double free in cil_deny.c
Stephen Smalley <[email protected]> Fri, 24 Jul 2026 12:07:05 -0400
| Newsgroups | org.kernel.vger.selinux |
|---|---|
| Message-ID | <CAEjxPJ6nvhWaWmXHW4O_kV+dSa0svnki6xh75qW_=9rH+9fLHw@mail.gmail.com> |
On Fri, Jul 24, 2026 at 11:09 AM James Carter <[email protected]> wrote: > > The function cil_create_attribute_d1_and_not_d2() (let's call this > f1) mallocs an ebitmap named types. This ebitmap is passed to the > function cil_create_and_insert_attribute_and_set() (let's call this > f2) which will create a new typeattribute which has its types field > point to the types ebitmap passed in by f1. If there is an error in > getting a symtab or inserting the new attribute into the symtab, > then cil_destroy_typeattribute() is called during cleanup. This will > free the ebitmap pointed to by the types field. After f2 exits with > an error, f1 will perform cleanup and try to free the types ebitmap > again. > > Move the calls to cil_get_symtab() and cil_symtab_insert() to > earlier in f2 to make it easier to clean up in the case of an error. > When cleaning up from an error do the cleanup manually instead of > calling cil_destroy_typeattribute() and do not free the passed in > types ebitmap. Function f1 needs to call ebitmap_destroy() (which > is safe to call more than once on a ebitmap) and free the ebitmap. > > Also add ebitmap_destroy() calls to > cil_create_attribute_all_and_not_d() and > cil_create_attribute_d1_and_d2() > > Reported-by: oss-fuzz (issue 500754862) > Signed-off-by: James Carter <[email protected]> Acked-by: Stephen Smalley <[email protected]> > --- > libsepol/cil/src/cil_deny.c | 44 ++++++++++++++++++------------------- > 1 file changed, 22 insertions(+), 22 deletions(-) > > diff --git a/libsepol/cil/src/cil_deny.c b/libsepol/cil/src/cil_deny.c > index c81b8beb..dc0f4ae9 100644 > --- a/libsepol/cil/src/cil_deny.c > +++ b/libsepol/cil/src/cil_deny.c > @@ -870,7 +870,6 @@ static int cil_create_and_insert_attribute_and_set(struct cil_db *db, > struct cil_tree_node *attr_node = NULL; > char *name; > struct cil_typeattribute *attr = NULL; > - struct cil_tree_node *attrset_node = NULL; > struct cil_typeattributeset *attrset = NULL; > symtab_t *symtab = NULL; > int rc = SEPOL_ERR; > @@ -880,12 +879,25 @@ static int cil_create_and_insert_attribute_and_set(struct cil_db *db, > goto exit; > } > > + rc = cil_get_symtab(prev->parent, &symtab, CIL_SYM_TYPES); > + if (rc != SEPOL_OK) { > + goto exit; > + } > + > + cil_typeattribute_init(&attr); > + attr_node = cil_create_and_insert_node(prev, CIL_TYPEATTRIBUTE, attr); > + > + rc = cil_symtab_insert(symtab, name, &attr->datum, attr_node); > + if (rc != SEPOL_OK) { > + goto exit; > + } > + > cil_typeattributeset_init(&attrset); > attrset->attr_str = name; > attrset->str_expr = str_expr; > attrset->datum_expr = datum_expr; > + cil_create_and_insert_node(attr_node, CIL_TYPEATTRIBUTESET, attrset); > > - cil_typeattribute_init(&attr); > cil_list_init(&attr->expr_list, CIL_TYPE); > cil_list_append(attr->expr_list, CIL_LIST, datum_expr); > attr->types = types; > @@ -894,20 +906,6 @@ static int cil_create_and_insert_attribute_and_set(struct cil_db *db, > CIL_FALSE : > CIL_TRUE; > > - attr_node = cil_create_and_insert_node(prev, CIL_TYPEATTRIBUTE, attr); > - attrset_node = cil_create_and_insert_node( > - attr_node, CIL_TYPEATTRIBUTESET, attrset); > - > - rc = cil_get_symtab(prev->parent, &symtab, CIL_SYM_TYPES); > - if (rc != SEPOL_OK) { > - goto exit; > - } > - > - rc = cil_symtab_insert(symtab, name, &attr->datum, attr_node); > - if (rc != SEPOL_OK) { > - goto exit; > - } > - > db->num_types_and_attrs++; > > *d = &attr->datum; > @@ -915,15 +913,14 @@ static int cil_create_and_insert_attribute_and_set(struct cil_db *db, > return SEPOL_OK; > > exit: > + if (attr) { > + cil_symtab_datum_destroy(&attr->datum); > + free(attr); > + } > if (attr_node) { > - cil_destroy_typeattribute( > - attr_node->data); // This will not destroy datum_expr > + prev->next = attr_node->next; > free(attr_node); > } > - if (attrset_node) { > - prev->next = attrset_node->next; > - free(attrset_node); > - } > return rc; > } > > @@ -1038,6 +1035,7 @@ static int cil_create_attribute_all_and_not_d(struct cil_db *db, > exit: > cil_list_destroy(&str_expr, CIL_FALSE); > cil_list_destroy(&datum_expr, CIL_FALSE); > + ebitmap_destroy(types); > free(types); > return rc; > } > @@ -1103,6 +1101,7 @@ static int cil_create_attribute_d1_and_not_d2(struct cil_db *db, > exit: > cil_list_destroy(&str_expr, CIL_FALSE); > cil_list_destroy(&datum_expr, CIL_FALSE); > + ebitmap_destroy(types); > free(types); > return rc; > } > @@ -1168,6 +1167,7 @@ static int cil_create_attribute_d1_and_d2(struct cil_db *db, > exit: > cil_list_destroy(&str_expr, CIL_FALSE); > cil_list_destroy(&datum_expr, CIL_FALSE); > + ebitmap_destroy(types); > free(types); > return rc; > } > -- > 2.55.0 >