[prev in list] [next in list] [prev in thread] [next in thread] 

List:       busybox
Subject:    Re: [PATCH] tsort: avoid use-after-free
From:       Denys Vlasenko <vda.linux () googlemail ! com>
Date:       2023-08-31 7:48:14
Message-ID: CAK1hOcO3BZ=38C-B57pTrdkpuFwcPRRtdaJp+TG6_hsn0f4nUQ () mail ! gmail ! com
[Download RAW message or body]

Applied, thank you.

On Tue, Aug 22, 2023 at 10:38 AM Ron Yorston <rmy@pobox.com> wrote:
>
> When the input data contained a cycle it was possible for tsort to
> attempt to access freed nodes.  This sometimes resulted in the
> test case 'echo a b b a | tsort' crashing.
>
> Don't free nodes when they're removed from the graph.
>
> function                                             old     new   delta
> tsort_main                                           621     596     -25
> ------------------------------------------------------------------------------
> (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-25)             Total: -25 bytes
>
> Signed-off-by: Ron Yorston <rmy@pobox.com>
> ---
>  coreutils/tsort.c | 20 +++++++++++++++++---
>  1 file changed, 17 insertions(+), 3 deletions(-)
>
> diff --git a/coreutils/tsort.c b/coreutils/tsort.c
> index a451ed2ff..3e7aa48f4 100644
> --- a/coreutils/tsort.c
> +++ b/coreutils/tsort.c
> @@ -101,6 +101,10 @@ int tsort_main(int argc UNUSED_PARAM, char **argv)
>         ssize_t len;
>         struct node *a;
>         int cycles;
> +       unsigned i;
> +#if ENABLE_FEATURE_CLEAN_UP
> +       unsigned max_len;
> +#endif
>
>         INIT_G();
>
> @@ -152,9 +156,11 @@ int tsort_main(int argc UNUSED_PARAM, char **argv)
>          *   - if any nodes are left, they form cycles.
>          */
>         cycles = 0;
> +#if ENABLE_FEATURE_CLEAN_UP
> +       max_len = G.nodes_len;
> +#endif
>         while (G.nodes_len) {
>                 struct node *n;
> -               unsigned i;
>
>                 /* Search for first node with no incoming edges */
>                 for (i = 0; i < G.nodes_len; i++) {
> @@ -173,16 +179,24 @@ int tsort_main(int argc UNUSED_PARAM, char **argv)
>                 /* Remove the node (need no longer maintain sort) */
>                 n = G.nodes[i];
>                 G.nodes[i] = G.nodes[--G.nodes_len];
> +#if ENABLE_FEATURE_CLEAN_UP
> +               /* Keep reference to removed node so it can be freed */
> +               G.nodes[G.nodes_len] = n;
> +#endif
>
>                 /* And remove its outgoing edges */
>                 for (i = 0; i < n->out_count; i++)
>                         n->out[i]->in_count--;
> -               free(n->out);
>
>                 puts(n->name);
> -               free(n);
> +       }
> +#if ENABLE_FEATURE_CLEAN_UP
> +       for (i = 0; i < max_len; i++)
> +               free(G.nodes[i].out);
> +               free(G.nodes[i]);
>         }
>         free(G.nodes);
> +#endif
>
>         fflush_stdout_and_exit(cycles ? 1 : 0);
>  }
> --
> 2.41.0
>
> _______________________________________________
> busybox mailing list
> busybox@busybox.net
> http://lists.busybox.net/mailman/listinfo/busybox
_______________________________________________
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic