Re: [PATCH net v3] sctp: fix use-after-free of cached ASCONF chunk

Xin Long <[email protected]>
Newsgroups org.kernel.vger.linux-sctp,org.kernel.vger.linux-kernel,org.kernel.vger.netdev,org.kernel.vger.stable
Message-ID <CADvbK_cv+Wkb5r-8_sGnKsuA5tfErvLoiPZYVN=yXALbWfBOGw@mail.gmail.com>
On Sun, Aug 9, 2026 at 12:38 AM Yuxiang Yang
<[email protected]> wrote:
>
> addip_last_asconf caches the outstanding outbound ASCONF chunk. The normal
> ASCONF-ACK completion path releases the chunk and clears the pointer.
>
> However, sctp_asconf_queue_teardown() releases the cached chunk without
> clearing addip_last_asconf. During peer restart handling,
> sctp_sf_do_dupcook_a() queues SCTP_CMD_PURGE_ASCONF_QUEUE, which invokes
> sctp_asconf_queue_teardown() while the association remains alive and leaves
> the pointer dangling.
>
> A delayed authenticated ASCONF-ACK can then reach sctp_sf_do_asconf_ack(),
> which accesses the stale chunk and passes it to sctp_process_asconf_ack(),
> causing a use-after-free and a second release.
>
> Clearing the pointer exposes a race with T4 expiry. Peer restart handling
> queues the timer stop before the purge, but SCTP_CMD_TIMER_STOP uses
> timer_delete(), which does not wait for a callback already running on
> another CPU. Such a callback can reach sctp_sf_t4_timer_expire() after
> the purge and dereference NULL.
>
> Clear addip_last_asconf after releasing the cached chunk, and make
> sctp_sf_t4_timer_expire() consume a stale T4 expiry if no outstanding
> ASCONF remains.
>
> Fixes: a000c01e60e4 ("sctp: stop pending timers and purge queues when peer restart asoc")
> Cc: [email protected]
> Suggested-by: Xin Long <[email protected]>
> Assisted-by: Claude-Code:GLM-5.2
> Signed-off-by: Yuxiang Yang <[email protected]>
> ---
> Changes in v3:
> - Resend as a new, independent thread as requested by pv-bot. No code
>   changes.
> - Link to v2:
>   https://lore.kernel.org/netdev/[email protected]/
>
> Changes in v2:
> - Guard sctp_sf_t4_timer_expire() against a cleared cached ASCONF pointer,
>   as requested by Xin Long.
> - Explain why the T4 callback may run after the restart purge.
>
>  net/sctp/associola.c    | 4 +++-
>  net/sctp/sm_statefuns.c | 6 +++++-
>  2 files changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/net/sctp/associola.c b/net/sctp/associola.c
> index 5b0ae61..737f8ea 100644
> --- a/net/sctp/associola.c
> +++ b/net/sctp/associola.c
> @@ -1713,6 +1713,8 @@ void sctp_asconf_queue_teardown(struct sctp_association *asoc)
>         sctp_assoc_free_asconf_queue(asoc);
>
>         /* Free any cached ASCONF chunk. */
> -       if (asoc->addip_last_asconf)
> +       if (asoc->addip_last_asconf) {
>                 sctp_chunk_free(asoc->addip_last_asconf);
> +               asoc->addip_last_asconf = NULL;
> +       }
>  }
> diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
> index 708fa07..3a8e16b 100644
> --- a/net/sctp/sm_statefuns.c
> +++ b/net/sctp/sm_statefuns.c
> @@ -6145,8 +6145,12 @@ enum sctp_disposition sctp_sf_t4_timer_expire(
>                                         struct sctp_cmd_seq *commands)
>  {
>         struct sctp_chunk *chunk = asoc->addip_last_asconf;
> -       struct sctp_transport *transport = chunk->transport;
> +       struct sctp_transport *transport;
> +
> +       if (!chunk)
> +               return SCTP_DISPOSITION_CONSUME;
>
> +       transport = chunk->transport;
>         SCTP_INC_STATS(net, SCTP_MIB_T4_RTO_EXPIREDS);
>
>         /* ADDIP 4.1 B1) Increment the error counters and perform path failure
> --
> 2.25.1
>

Acked-by: Xin Long <[email protected]>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.