Re: [PATCH] libsepol: Cap max depth and processed nodes for cil_tree_walk()
James Carter <[email protected]> Mon, 3 Aug 2026 11:12:39 -0400
| Newsgroups | org.kernel.vger.selinux |
|---|---|
| Message-ID | <CAP+JOzQ5n-5S4BpMfZD7d7jWQZw6fw4iON6oV+dboc==+mibCg@mail.gmail.com> |
On Mon, Aug 3, 2026 at 10:24=E2=80=AFAM Stephen Smalley <[email protected]> wrote: > > Cap the max tree depth and number of processed nodes for > cil_tree_walk() to avoid stack overflows and OOM conditions. > > Reported-by: oss-fuzz (issue 471608794) > Signed-off-by: Stephen Smalley <[email protected]> Acked-by: James Carter <[email protected]> > --- > libsepol/cil/src/cil_tree.c | 65 ++++++++++++++++++++++++++++++------- > 1 file changed, 53 insertions(+), 12 deletions(-) > > diff --git a/libsepol/cil/src/cil_tree.c b/libsepol/cil/src/cil_tree.c > index 63dd33dd..17f19256 100644 > --- a/libsepol/cil/src/cil_tree.c > +++ b/libsepol/cil/src/cil_tree.c > @@ -41,6 +41,9 @@ > #include "cil_parser.h" > #include "cil_strpool.h" > > +#define MAX_DEPTH (256) > +#define MAX_NODES (1U << 20) > + > struct cil_tree_node *cil_tree_get_next_path(struct cil_tree_node *node, > char **info_kind, > uint32_t *hll_line, char **p= ath) > @@ -311,25 +314,41 @@ void cil_tree_node_remove(struct cil_tree_node *nod= e) > extra_args: any additional data to be passed to the hel= per functions > */ > > +static int cil_tree_walk_helper( > + struct cil_tree_node *node, > + int (*process_node)(struct cil_tree_node *node, uint32_t *finishe= d, > + void *extra_args), > + int (*first_child)(struct cil_tree_node *node, void *extra_args), > + int (*last_child)(struct cil_tree_node *node, void *extra_args), > + void *extra_args, unsigned depth, unsigned *processed); > + > static int cil_tree_walk_core( > struct cil_tree_node *node, > int (*process_node)(struct cil_tree_node *node, uint32_t *finishe= d, > void *extra_args), > int (*first_child)(struct cil_tree_node *node, void *extra_args), > int (*last_child)(struct cil_tree_node *node, void *extra_args), > - void *extra_args) > + void *extra_args, unsigned depth, unsigned *processed) > { > int rc =3D SEPOL_ERR; > > while (node) { > uint32_t finished =3D CIL_TREE_SKIP_NOTHING; > > + if (*processed >=3D MAX_NODES) { > + cil_tree_log(node, CIL_ERR, > + "Exceeded max tree processed nodes (= %u)", > + MAX_NODES); > + return SEPOL_ERR; > + } > + > if (process_node !=3D NULL) { > rc =3D (*process_node)(node, &finished, extra_arg= s); > if (rc !=3D SEPOL_OK) { > cil_tree_log(node, CIL_INFO, "Problem"); > return rc; > } > + (*processed)++; > } > > if (finished & CIL_TREE_SKIP_NEXT) { > @@ -337,8 +356,10 @@ static int cil_tree_walk_core( > } > > if (node->cl_head !=3D NULL && !(finished & CIL_TREE_SKIP= _HEAD)) { > - rc =3D cil_tree_walk(node, process_node, first_ch= ild, > - last_child, extra_args); > + rc =3D cil_tree_walk_helper(node, process_node, > + first_child, last_child= , > + extra_args, depth + 1, > + processed); > if (rc !=3D SEPOL_OK) { > return rc; > } > @@ -350,17 +371,22 @@ static int cil_tree_walk_core( > return SEPOL_OK; > } > > -int cil_tree_walk(struct cil_tree_node *node, > - int (*process_node)(struct cil_tree_node *node, > - uint32_t *finished, void *extra_arg= s), > - int (*first_child)(struct cil_tree_node *node, > - void *extra_args), > - int (*last_child)(struct cil_tree_node *node, > - void *extra_args), > - void *extra_args) > +static int cil_tree_walk_helper( > + struct cil_tree_node *node, > + int (*process_node)(struct cil_tree_node *node, uint32_t *finishe= d, > + void *extra_args), > + int (*first_child)(struct cil_tree_node *node, void *extra_args), > + int (*last_child)(struct cil_tree_node *node, void *extra_args), > + void *extra_args, unsigned depth, unsigned *processed) > { > int rc =3D SEPOL_ERR; > > + if (depth >=3D MAX_DEPTH) { > + cil_tree_log(node, CIL_ERR, "Exceeded max tree depth (%u)= ", > + MAX_DEPTH); > + return SEPOL_ERR; > + } > + > if (!node || !node->cl_head) { > return SEPOL_OK; > } > @@ -374,7 +400,7 @@ int cil_tree_walk(struct cil_tree_node *node, > } > > rc =3D cil_tree_walk_core(node->cl_head, process_node, first_chil= d, > - last_child, extra_args); > + last_child, extra_args, depth, processed)= ; > if (rc !=3D SEPOL_OK) { > return rc; > } > @@ -389,3 +415,18 @@ int cil_tree_walk(struct cil_tree_node *node, > > return SEPOL_OK; > } > + > +int cil_tree_walk(struct cil_tree_node *node, > + int (*process_node)(struct cil_tree_node *node, > + uint32_t *finished, void *extra_arg= s), > + int (*first_child)(struct cil_tree_node *node, > + void *extra_args), > + int (*last_child)(struct cil_tree_node *node, > + void *extra_args), > + void *extra_args) > +{ > + unsigned processed =3D 0; > + > + return cil_tree_walk_helper(node, process_node, first_child, last= _child, > + extra_args, 0, &processed); > +} > -- > 2.55.0 >