* [PATCH net] sctp: fix ASCONF address change on single-homed hosts
@ 2026-10-22 16:36 Andrey Misiurov
2026-10-22 16:43 ` netdev-bot+sinfo
2026-10-26 17:45 ` netdev-bot+sashiko
0 siblings, 2 replies; 4+ messages in thread
From: Andrey Misiurov @ 2026-10-22 16:36 UTC (permalink / raw)
To: Marcelo Ricardo Leitner, Xin Long
Cc: Jun Yang, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, linux-sctp, netdev, linux-kernel,
Andrey Misiurov, stable
Commit 9b2854f86f0b ("sctp: don't free the ASCONF's own transport in
DEL-IP processing") refuses a DEL-IP of the transport the ASCONF was
located by, so that a later wildcard DEL-IP cannot use it after free.
This also breaks the single-homed address change (RFC 5061 5.3.2). The
host sends [Address Parameter L] [ADD-IP S] [DEL-IP L], the association
is located by L, and DEL-IP L is now refused. The sender never gets an
all-success ASCONF-ACK, keeps src_out_of_asoc_ok set and stops sending
data, so the association stalls.
Fix the wildcard DEL-IP instead: look up the transport of the packet
source rather than reusing asconf->transport, and clear
asconf->transport when a plain DEL-IP removes it.
Fixes: 9b2854f86f0b ("sctp: don't free the ASCONF's own transport in DEL-IP processing")
Cc: stable@vger.kernel.org
Signed-off-by: Andrey Misiurov <andrey.misyrov@gmail.com>
---
net/sctp/sm_make_chunk.c | 15 ++++++++-------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -3150,9 +3150,11 @@
* packet MUST be deleted.
*/
if (af->is_any(&addr)) {
- sctp_assoc_set_primary(asoc, asconf->transport);
- sctp_assoc_del_nonprimary_peers(asoc,
- asconf->transport);
+ peer = sctp_assoc_lookup_paddr(asoc, &asconf->source);
+ if (!peer)
+ return SCTP_ERROR_REQ_REFUSED;
+ sctp_assoc_set_primary(asoc, peer);
+ sctp_assoc_del_nonprimary_peers(asoc, peer);
return SCTP_ERROR_NO_ERROR;
}
@@ -3165,13 +3167,9 @@
if (!peer)
return SCTP_ERROR_DNS_FAILED;
- /* Don't free asconf->transport; a later wildcard DEL-IP
- * parameter reuses it.
- */
- if (peer == asconf->transport)
- return SCTP_ERROR_REQ_REFUSED;
-
sctp_assoc_rm_peer(asoc, peer);
+ if (asconf->transport == peer)
+ asconf->transport = NULL;
break;
case SCTP_PARAM_SET_PRIMARY:
/* ADDIP Section 4.2.4
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH net] sctp: fix ASCONF address change on single-homed hosts 2026-10-22 16:36 [PATCH net] sctp: fix ASCONF address change on single-homed hosts Andrey Misiurov @ 2026-10-22 16:43 ` netdev-bot+sinfo 2026-10-26 17:45 ` netdev-bot+sashiko 1 sibling, 0 replies; 4+ messages in thread From: netdev-bot+sinfo @ 2026-10-22 16:43 UTC (permalink / raw) To: Andrey Misiurov Cc: Marcelo Ricardo Leitner, Xin Long, Jun Yang, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman, linux-sctp, netdev, linux-kernel, stable Hi! This is an automated message. This series looks like a fix, but its commit messages seem to be missing some information: - How the issue was discovered, e.g. hit in production, hit during development, syzbot report, manual code inspection, LLM or static analysis tool scan. Please do not repost the series just to address the above. Instead, reply to this email with the missing information, so that reviewers can take it into account. If the series needs another revision for other reasons, please include the information in the commit messages then. The evaluation is done by an LLM so it may be wrong, if you think that is the case please reply and explain. ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH net] sctp: fix ASCONF address change on single-homed hosts 2026-10-22 16:36 [PATCH net] sctp: fix ASCONF address change on single-homed hosts Andrey Misiurov 2026-10-22 16:43 ` netdev-bot+sinfo @ 2026-10-26 17:45 ` netdev-bot+sashiko 2026-10-26 22:38 ` Xin Long 1 sibling, 1 reply; 4+ messages in thread From: netdev-bot+sashiko @ 2026-10-26 17:45 UTC (permalink / raw) To: andrey.misyrov Cc: marcelo.leitner, lucien.xin, junvyyang, davem, edumazet, kuba, pabeni, horms, linux-sctp, netdev, linux-kernel, stable Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider. Critical: 1 · High: 0 · Medium: 0 · Low: 0 (1) If you believe none of the issues are legitimate, please reply to each issue of Medium severity or higher and explain why the AI is wrong. If any of them are legitimate and you plan to respin, please let patchwork know by including "pw-bot: cr" as a separate line at the end of your reply (one such reply per series is enough). - [Critical] The patch rewrites the wildcard DEL-IP (0.0.0.0) branch of sctp_process_asconf_param() (net/sctp/sm_make_chunk.c:3153-3159) to… Pre-existing issues: - [Low] The wildcard SET_PRIMARY branch of sctp_process_asconf_param() (net/sctp/sm_make_chunk.c:3182) takes the packet source address from… -- sctp: fix ASCONF address change on single-homed hosts This patch drops the refusal of a plain DEL-IP of asconf->transport that commit 9b2854f86f0b added, so the RFC 5061 5.3.2 single-homed address change works again. The wildcard DEL-IP branch now looks up the transport of the packet source instead of reusing asconf->transport. The plain DEL-IP branch now clears asconf->transport when it removes that peer. > diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c > index ddc31a5dbad32..2b76e451d5cb0 100644 > --- a/net/sctp/sm_make_chunk.c > +++ b/net/sctp/sm_make_chunk.c > @@ -3151,9 +3151,11 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, > * packet MUST be deleted. > */ > if (af->is_any(&addr)) { > - sctp_assoc_set_primary(asoc, asconf->transport); > - sctp_assoc_del_nonprimary_peers(asoc, > - asconf->transport); > + peer = sctp_assoc_lookup_paddr(asoc, &asconf->source); > + if (!peer) > + return SCTP_ERROR_REQ_REFUSED; > + sctp_assoc_set_primary(asoc, peer); > + sctp_assoc_del_nonprimary_peers(asoc, peer); > return SCTP_ERROR_NO_ERROR; > } [Severity: Critical] Can this leave asconf->transport pointing at a freed transport? Suppose __sctp_rcv_asconf_lookup() found the association through the ASCONF Address Parameter L. Then asconf->transport is T(L), while asconf->source is the packet source S. Take a packet from a new source S like this: [AUTH][ASCONF: AddrParam L, ADD-IP S (or ADD-IP 0.0.0.0), DEL-IP 0.0.0.0][DATA] ADD-IP S creates T(S). The wildcard DEL-IP then keeps T(S) and removes everything else, including T(L): sctp_assoc_del_nonprimary_peers(asoc, T(S)) sctp_assoc_rm_peer(asoc, T(L)) sctp_transport_free(T(L)) Nothing in this branch clears or retargets asconf->transport. Only the plain DEL-IP branch below does that. sctp_inq_pop() reuses the same chunk struct for the bundled DATA chunk. sctp_assoc_bh_rcv() then runs: if (sctp_chunk_is_data(chunk)) asoc->peer.last_data_from = chunk->transport; This stores the removed T(L). The last_data_from fixup in sctp_assoc_rm_peer() has already run, so it does not catch this. sctp_rcv() then drops its lookup reference, and T(L) is freed after the RCU grace period. When the delayed SACK timer fires: sctp_gen_sack() trans = asoc->peer.last_data_from sctp_make_sack() retval->transport = asoc->peer.last_data_from; ... sctp_outq_select_transport() reads new_transport->state list_add_tail(&ctx->transport->send_ready, &ctx->transport_list) Is that a use-after-free read and write of the transport? Before this patch, the wildcard branch always kept asconf->transport, and 9b2854f86f0b refused a plain DEL-IP of it. So asconf->transport could not be freed during ASCONF processing. Any peer of an association with ASCONF enabled appears able to reach this, including a well-behaved peer following the RFC 5061 wildcard procedure. Would it close this to set asconf->transport = peer after sctp_assoc_del_nonprimary_peers(), or to clear it whenever it is not the surviving transport? > @@ -3166,13 +3168,9 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, > if (!peer) > return SCTP_ERROR_DNS_FAILED; > > - /* Don't free asconf->transport; a later wildcard DEL-IP > - * parameter reuses it. > - */ > - if (peer == asconf->transport) > - return SCTP_ERROR_REQ_REFUSED; > - > sctp_assoc_rm_peer(asoc, peer); > + if (asconf->transport == peer) > + asconf->transport = NULL; > break; > case SCTP_PARAM_SET_PRIMARY: > /* ADDIP Section 4.2.4 [Severity: Low] This is a pre-existing issue and was not introduced by this patch. The wildcard SET_PRIMARY handling in sctp_process_asconf_param() uses sctp_source() instead of &asconf->source: if (af->is_any(&addr)) memcpy(&addr, sctp_source(asconf), sizeof(addr)); sctp_source() returns &chunk->transport->ipaddr whenever chunk->transport is set. When the association was located via the Address Parameter (transport T(L), source S), SET_PRIMARY 0.0.0.0 makes L primary instead of the packet source S. That doesn't match the comment. The ADD-IP and DEL-IP wildcard branches both use &asconf->source. With this patch the result also depends on parameter order: - After a plain DEL-IP L clears asconf->transport, sctp_source() returns S. - After a wildcard DEL-IP, it returns the ipaddr of the removed T(L), the dangling pointer described above. The lookup then fails and the parameter gets SCTP_ERROR_DNS_FAILED. Should this branch use &asconf->source like the other two? -- Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20261022163639.2566945-1-andrey.misyrov%40gmail.com ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH net] sctp: fix ASCONF address change on single-homed hosts 2026-10-26 17:45 ` netdev-bot+sashiko @ 2026-10-26 22:38 ` Xin Long 0 siblings, 0 replies; 4+ messages in thread From: Xin Long @ 2026-10-26 22:38 UTC (permalink / raw) To: netdev-bot+sashiko Cc: andrey.misyrov, marcelo.leitner, junvyyang, davem, edumazet, kuba, pabeni, horms, linux-sctp, netdev, linux-kernel, stable On Mon, Oct 26, 2026 at 1:45 PM <netdev-bot+sashiko@kernel.org> wrote: > > Thank you for your contribution! Sashiko AI review found 1 potential > issue(s) to consider. > > Critical: 1 · High: 0 · Medium: 0 · Low: 0 (1) > > If you believe none of the issues are legitimate, please reply to each > issue of Medium severity or higher and explain why the AI is wrong. > If any of them are legitimate and you plan to respin, please let patchwork > know by including "pw-bot: cr" as a separate line at the end of your reply > (one such reply per series is enough). > > - [Critical] The patch rewrites the wildcard DEL-IP (0.0.0.0) branch of > sctp_process_asconf_param() (net/sctp/sm_make_chunk.c:3153-3159) to… > > Pre-existing issues: > - [Low] The wildcard SET_PRIMARY branch of sctp_process_asconf_param() > (net/sctp/sm_make_chunk.c:3182) takes the packet source address from… > > -- > > sctp: fix ASCONF address change on single-homed hosts > > This patch drops the refusal of a plain DEL-IP of asconf->transport that > commit 9b2854f86f0b added, so the RFC 5061 5.3.2 single-homed address > change works again. The wildcard DEL-IP branch now looks up the > transport of the packet source instead of reusing asconf->transport. The > plain DEL-IP branch now clears asconf->transport when it removes that > peer. > > > diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c > > index ddc31a5dbad32..2b76e451d5cb0 100644 > > --- a/net/sctp/sm_make_chunk.c > > +++ b/net/sctp/sm_make_chunk.c > > @@ -3151,9 +3151,11 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, > > * packet MUST be deleted. > > */ > > if (af->is_any(&addr)) { > > - sctp_assoc_set_primary(asoc, asconf->transport); > > - sctp_assoc_del_nonprimary_peers(asoc, > > - asconf->transport); > > + peer = sctp_assoc_lookup_paddr(asoc, &asconf->source); > > + if (!peer) > > + return SCTP_ERROR_REQ_REFUSED; > > + sctp_assoc_set_primary(asoc, peer); > > + sctp_assoc_del_nonprimary_peers(asoc, peer); > > return SCTP_ERROR_NO_ERROR; > > } > > [Severity: Critical] > > Can this leave asconf->transport pointing at a freed transport? > > Suppose __sctp_rcv_asconf_lookup() found the association through the > ASCONF Address Parameter L. Then asconf->transport is T(L), while > asconf->source is the packet source S. Take a packet from a new source S > like this: > > [AUTH][ASCONF: AddrParam L, ADD-IP S (or ADD-IP 0.0.0.0), DEL-IP 0.0.0.0][DATA] > > ADD-IP S creates T(S). The wildcard DEL-IP then keeps T(S) and removes > everything else, including T(L): > > sctp_assoc_del_nonprimary_peers(asoc, T(S)) > sctp_assoc_rm_peer(asoc, T(L)) > sctp_transport_free(T(L)) > > Nothing in this branch clears or retargets asconf->transport. Only the > plain DEL-IP branch below does that. > > sctp_inq_pop() reuses the same chunk struct for the bundled DATA chunk. > sctp_assoc_bh_rcv() then runs: > > if (sctp_chunk_is_data(chunk)) > asoc->peer.last_data_from = chunk->transport; > > This stores the removed T(L). The last_data_from fixup in > sctp_assoc_rm_peer() has already run, so it does not catch this. > sctp_rcv() then drops its lookup reference, and T(L) is freed after the > RCU grace period. > > When the delayed SACK timer fires: > > sctp_gen_sack() > trans = asoc->peer.last_data_from > sctp_make_sack() > retval->transport = asoc->peer.last_data_from; > ... > sctp_outq_select_transport() > reads new_transport->state > list_add_tail(&ctx->transport->send_ready, &ctx->transport_list) > > Is that a use-after-free read and write of the transport? > > Before this patch, the wildcard branch always kept asconf->transport, and > 9b2854f86f0b refused a plain DEL-IP of it. So asconf->transport could not > be freed during ASCONF processing. > > Any peer of an association with ASCONF enabled appears able to reach > this, including a well-behaved peer following the RFC 5061 wildcard > procedure. > > Would it close this to set asconf->transport = peer after > sctp_assoc_del_nonprimary_peers(), or to clear it whenever it is not the > surviving transport? > This looks like a legit issue. Either way above works for me. Thanks. > > @@ -3166,13 +3168,9 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, > > if (!peer) > > return SCTP_ERROR_DNS_FAILED; > > > > - /* Don't free asconf->transport; a later wildcard DEL-IP > > - * parameter reuses it. > > - */ > > - if (peer == asconf->transport) > > - return SCTP_ERROR_REQ_REFUSED; > > - > > sctp_assoc_rm_peer(asoc, peer); > > + if (asconf->transport == peer) > > + asconf->transport = NULL; > > break; > > case SCTP_PARAM_SET_PRIMARY: > > /* ADDIP Section 4.2.4 > > [Severity: Low] > > This is a pre-existing issue and was not introduced by this patch. The > wildcard SET_PRIMARY handling in sctp_process_asconf_param() uses > sctp_source() instead of &asconf->source: > > if (af->is_any(&addr)) > memcpy(&addr, sctp_source(asconf), sizeof(addr)); > > sctp_source() returns &chunk->transport->ipaddr whenever chunk->transport > is set. When the association was located via the Address Parameter > (transport T(L), source S), SET_PRIMARY 0.0.0.0 makes L primary instead > of the packet source S. That doesn't match the comment. The ADD-IP and > DEL-IP wildcard branches both use &asconf->source. > > With this patch the result also depends on parameter order: > > - After a plain DEL-IP L clears asconf->transport, sctp_source() returns > S. > - After a wildcard DEL-IP, it returns the ipaddr of the removed T(L), the > dangling pointer described above. The lookup then fails and the > parameter gets SCTP_ERROR_DNS_FAILED. > > Should this branch use &asconf->source like the other two? > > -- > Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20261022163639.2566945-1-andrey.misyrov%40gmail.com ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-10-26 22:38 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-10-22 16:36 [PATCH net] sctp: fix ASCONF address change on single-homed hosts Andrey Misiurov 2026-10-22 16:43 ` netdev-bot+sinfo 2026-10-26 17:45 ` netdev-bot+sashiko 2026-10-26 22:38 ` Xin Long
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox