<feed xmlns='http://www.w3.org/2005/Atom'>
<title>wireguard-linux/net/sctp, branch stable</title>
<subtitle>WireGuard for the Linux kernel</subtitle>
<id>https://git.zx2c4.com/wireguard-linux/atom/net/sctp?h=stable</id>
<link rel='self' href='https://git.zx2c4.com/wireguard-linux/atom/net/sctp?h=stable'/>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/wireguard-linux/'/>
<updated>2026-09-30T23:55:47Z</updated>
<entry>
<title>sctp: check RCV_SHUTDOWN after the sendmsg connect wait</title>
<updated>2026-09-30T23:55:47Z</updated>
<author>
<name>Jun Yang</name>
<email>junvyyang@tencent.com</email>
</author>
<published>2026-09-26T09:55:15Z</published>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/wireguard-linux/commit/?id=4f1da630d13de0370e2f6361f961f1c8b384af1c'/>
<id>urn:sha1:4f1da630d13de0370e2f6361f961f1c8b384af1c</id>
<content type='text'>
sctp_wait_for_connect() drops the socket lock while it sleeps. An
out-of-the-blue ABORT can then be processed from the socket backlog and
unlink the association. If a concurrent shutdown(fd, SHUT_RD) sets
RCV_SHUTDOWN, the waiter breaks with err == 0 before checking
asoc-&gt;base.dead. Its final sctp_association_put() can then free the
association, leaving sctp_sendmsg_to_asoc() to continue with a dangling
pointer.

Check RCV_SHUTDOWN along with the wait error in sctp_sendmsg_to_asoc()
before using the association again. The check only accesses the socket,
so it needs no additional association reference. Return the existing
-ESRCH so that sctp_sendmsg() skips freeing a new association that may
already have been destroyed.

Keep sctp_wait_for_connect() unchanged to preserve its behavior for the
connect() caller.

Fixes: 668c9beb9020 ("sctp: implement assign_number for sctp_stream_interleave")
Cc: stable@vger.kernel.org
Reported-by: TencentOS Corvus AI &lt;corvus@tencent.com&gt;
Signed-off-by: Jun Yang &lt;junvyyang@tencent.com&gt;
Acked-by: Xin Long &lt;lucien.xin@gmail.com&gt;
Link: https://patch.msgid.link/20260926095606.68601-1-juny24602@gmail.com
Signed-off-by: Jakub Kicinski &lt;kuba@kernel.org&gt;
</content>
</entry>
<entry>
<title>sctp: hold asoc or transport before mod_timer() in timer handlers</title>
<updated>2026-09-23T01:36:36Z</updated>
<author>
<name>Xin Long</name>
<email>lucien.xin@gmail.com</email>
</author>
<published>2026-09-21T18:03:45Z</published>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/wireguard-linux/commit/?id=cae23ae3f7887a1cf8a75da38edcebeef695040f'/>
<id>urn:sha1:cae23ae3f7887a1cf8a75da38edcebeef695040f</id>
<content type='text'>
Take the association or transport reference before rearming a timer in the
timer handlers.

The existing code calls mod_timer() before taking the reference needed by
the rearmed timer without holding the sock lock. This creates a race with
timer cleanup: if the timer is deleted after mod_timer() returns but before
the reference is taken, the cleanup path can drop the timer's reference and
destroy the transport or association. The timer handler then takes a
reference on the already freed object and eventually drops it, causing a
refcount underflow.

Hold the object before mod_timer() and drop the reference if mod_timer()
reports that the timer was already pending in timer handlers. Apply the
same ordering to the proto-unreachable path, which can rearm a transport
timer outside the timer handlers without holding the sock lock.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Reported-by: Tangxin Xie &lt;xietangxin@h-partners.com&gt;
Signed-off-by: Xin Long &lt;lucien.xin@gmail.com&gt;
Link: https://patch.msgid.link/c31b5e3ee2b7274e804f5eba2f21e2412e7eef7a.1790013825.git.lucien.xin@gmail.com
Signed-off-by: Jakub Kicinski &lt;kuba@kernel.org&gt;
</content>
</entry>
<entry>
<title>sctp: discard the rest of the packet on a stale-cookie error</title>
<updated>2026-09-23T01:31:01Z</updated>
<author>
<name>Aohan Mei</name>
<email>henrymei@tencent.com</email>
</author>
<published>2026-09-21T09:37:04Z</published>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/wireguard-linux/commit/?id=4498467a8af06cfa3d71cb04bd7c4170dec8f449'/>
<id>urn:sha1:4498467a8af06cfa3d71cb04bd7c4170dec8f449</id>
<content type='text'>
When an association is in COOKIE-ECHOED state and the peer sends a
bundled [ERROR(Stale Cookie)][DATA] packet from one of its non-primary
addresses, processing the ERROR chunk takes the non-fatal stale-cookie
retry path sctp_sf_do_5_2_6_stale(), which queues
SCTP_CMD_DEL_NON_PRIMARY while keeping the association alive.
sctp_cmd_del_non_primary() removes every non-primary transport -
including the very transport this packet arrived on, which is still
referenced by the receive lookup and shared by all chunks of the
packet via chunk-&gt;transport.

sctp_assoc_rm_peer() does redirect asoc-&gt;peer.last_data_from away from
the removed transport, but right afterwards the bundled DATA chunk
makes sctp_assoc_bh_rcv() re-register
asoc-&gt;peer.last_data_from = chunk-&gt;transport unconditionally, undoing
the redirection with the just-removed transport.

Once the packet is done, the receive reference is dropped and the
transport is RCU-freed, while the surviving association keeps the
dangling last_data_from.  A later FWD-TSN (or the delayed SACK timer)
makes sctp_gen_sack() dereference it (-&gt;param_flags and friends), and
sctp_make_sack()/sctp_outq_select_transport() may write to the freed
object and link it into the live transport list.  This is a
use-after-free triggerable by any malicious SCTP peer (or a local
unprivileged user acting as one) with no capabilities required:

  BUG: KASAN: slab-use-after-free in sctp_do_sm+0x498a/0x5660
  Read of size 4 at addr ffff88800e1e356c by task poc/115
  Call Trace: sctp_do_sm &lt;- sctp_assoc_bh_rcv &lt;- sctp_inq_push &lt;-
              sctp_rcv &lt;- ip_protocol_deliver_rcu &lt;- ip_rcv
  Allocated: sctp_transport_new &lt;- sctp_assoc_add_peer &lt;-
             sctp_process_init (INIT-ACK processing)
  Freed: kfree &lt;- sctp_transport_destroy_rcu &lt;- rcu_core
         (call_rcu queued by sctp_transport_put at end of sctp_rcv)
  The buggy address is located 364 bytes inside of freed 1024-byte
  region [ffff88800e1e3400, ffff88800e1e3800), cache kmalloc-1k

Note that commit 03a9d10ecf71 ("sctp: drop a chunk if its transport
was removed") only covers the window between the receive lookup and
the chunk processing (e.g. an ASCONF DEL-IP racing the socket backlog);
here the transport is removed *while* the packet is being processed,
by an earlier chunk of the same packet, so the drop in sctp_inq_push()
does not reach this path.  Verified with the bundled [ERROR(Stale
Cookie)][DATA] + FWD-TSN reproducer: the KASAN report above still
fires with that commit applied, and is gone with this patch on top.

Fix it by discarding the rest of the packet on this path, as suggested
by Xin.  After the stale-cookie ERROR has sent the association back to
COOKIE-WAIT and removed the non-primary transports, the remaining
chunks of the packet can only run against the restarted handshake
while referencing the removed arrival transport through
chunk-&gt;transport: besides the last_data_from registration above,
sctp_cmd_setup_t2() and the sctp_make_*() reply builders would also
copy that pointer into association-lifetime state that
sctp_assoc_rm_peer() has already sanitized.  Let the peer retransmit
them, in line with what sctp_inq_push() does for chunks whose
transport was removed before processing.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Suggested-by: Xin Long &lt;lucien.xin@gmail.com&gt;
Reported-by: TencentOS Corvus AI &lt;corvus@tencent.com&gt;
Cc: stable@vger.kernel.org
Signed-off-by: Aohan Mei &lt;henrymei@tencent.com&gt;
Acked-by: Xin Long &lt;lucien.xin@gmail.com&gt;
Link: https://patch.msgid.link/20260921093707.1432184-1-ljp1205831794@gmail.com
Signed-off-by: Jakub Kicinski &lt;kuba@kernel.org&gt;
</content>
</entry>
<entry>
<title>sctp: avoid livelock while updating retransmit path</title>
<updated>2026-09-19T00:24:10Z</updated>
<author>
<name>Yiqi Sun</name>
<email>sunyiqixm@gmail.com</email>
</author>
<published>2026-09-15T09:50:17Z</published>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/wireguard-linux/commit/?id=d2c31b837406395e576afeb25958c98e9938f3f6'/>
<id>urn:sha1:d2c31b837406395e576afeb25958c98e9938f3f6</id>
<content type='text'>
sctp_assoc_update_retran_path() can loop forever when every remaining
transport, including retran_path, is SCTP_UNCONFIRMED: the state check
runs before the wraparound test, so the loop cannot observe that it has
completed a full pass.

Fix this by considering a transport only when it is not UNCONFIRMED,
then checking whether the walk has returned to retran_path. This makes
the full-pass termination independent of the transport state while
preserving the existing fallback selection semantics.

Also restore the NULL guard around the retran_path assignment. In the
all-UNCONFIRMED case there is no eligible replacement transport, and
installing NULL would leave later retransmit-path users and the debug
print with a NULL path.

Fixes: 4c47af4d5eb2 ("net: sctp: rework multihoming retransmission path selection to rfc4960")
Signed-off-by: Yiqi Sun &lt;sunyiqixm@gmail.com&gt;
Acked-by: Xin Long &lt;lucien.xin@gmail.com&gt;
Link: https://patch.msgid.link/20260915095017.942213-1-sunyiqixm@gmail.com
Signed-off-by: Jakub Kicinski &lt;kuba@kernel.org&gt;
</content>
</entry>
<entry>
<title>sctp: validate chunk length in the inqueue parser</title>
<updated>2026-08-30T21:17:53Z</updated>
<author>
<name>Charles Vosburgh</name>
<email>theminershive@gmail.com</email>
</author>
<published>2026-08-27T21:32:53Z</published>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/wireguard-linux/commit/?id=6cfc1b90cb86f4aabc69fb8e30128e07e2cdfa3a'/>
<id>urn:sha1:6cfc1b90cb86f4aabc69fb8e30128e07e2cdfa3a</id>
<content type='text'>
SCTP chunks always include a four-byte generic header, but
sctp_inq_pop() currently accepts shorter declared lengths. A zero-length
chunk leaves chunk_end at the current header.

When ASCONF is covered by the association's SCTP-AUTH policy,
sctp_assoc_bh_rcv() can continue before the state machine performs its
normal chunk-length check. sctp_inq_pop() then returns the same malformed
chunk repeatedly and the receive softirq can lock up.

A remote SCTP peer can trigger this after establishing an association on
a kernel built with CONFIG_IP_SCTP and configured with
net.sctp.addip_enable=1 and net.sctp.auth_enable=1. The reproducer did
not require application credentials, a shared SCTP AUTH key, or
net.sctp.addip_noauth_enable=1.

On commit f967455fb2a5 ("seg6: reset IP6CB after IPv6 decapsulation"),
one zero-length ASCONF caused repeated
watchdog soft-lockup reports in a two-vCPU KVM guest. All 3 pre-trigger
health probes succeeded, while 36 of 37 post-trigger probes failed. With
this change, all 37 post-trigger probes succeeded and no equivalent
soft-lockup signature appeared.

Reject chunks shorter than the generic SCTP header at the shared inqueue
parser boundary. Mark the packet for discard before either caller can
continue processing it, while preserving the four-byte generic minimum.
Declared-length 1 through 4 controls and kernel-generated ASCONF traffic
remained healthy. The patched sctp_hello selftest passed for IPv4 and
IPv6.

The complete private reproducer and validation evidence are available
directly to maintainers on request.

Fixes: bbd0d59809f9 ("[SCTP]: Implement the receive and verification of AUTH chunk")
Cc: stable@vger.kernel.org
Signed-off-by: Charles Vosburgh &lt;theminershive@gmail.com&gt;
Acked-by: Xin Long &lt;lucien.xin@gmail.com&gt;
Link: https://patch.msgid.link/20260827-sctp-zero-chunk-inqueue-v2-1-2e7669c6a6cb@gmail.com
Signed-off-by: Jakub Kicinski &lt;kuba@kernel.org&gt;
</content>
</entry>
<entry>
<title>sctp: fix soft lockup from unpadded ASCONF-ACK parameter iteration</title>
<updated>2026-08-30T21:14:09Z</updated>
<author>
<name>Henry Martin</name>
<email>bsdhenrymartin@gmail.com</email>
</author>
<published>2026-08-28T04:24:25Z</published>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/wireguard-linux/commit/?id=2cb0b0b1ed69430bf73740377ea0a1c44c50db63'/>
<id>urn:sha1:2cb0b0b1ed69430bf73740377ea0a1c44c50db63</id>
<content type='text'>
sctp_verify_asconf() walks ASCONF-ACK parameters with
sctp_walk_params(), which advances by SCTP_PAD4(length), while the
consumer sctp_get_asconf_response() iterates the same parameters
advancing by the raw length, without padding. A single odd-length
parameter desynchronises the two walks and makes the consumer
interpret attacker-controlled bytes at a misaligned offset.

When those bytes yield a length of zero, the while loop over
asconf_ack_len makes no progress, spinning forever in softirq
context, and the watchdog reports a soft lockup. All reads stay
within the received skb, so the lockup is a pure remote denial of
service. A remote peer can trigger it with a crafted ASCONF-ACK on
an ADD-IP enabled association with an outstanding ASCONF (RFC 5061
section 4.1.2 requires the chunk to be authenticated, but the
predefined empty key id 0 allows the peer to compute the same
association HMAC from publicly exchanged parameters, so the gate
does not help).

The SCTP_PARAM_ERR_CAUSE case of sctp_verify_asconf() also performs
no length check, letting a parameter without a complete error
header reach the consumer, which reads errhdr.cause past the end of
the parameter, an out-of-bounds read.

Reject SCTP_PARAM_ERR_CAUSE parameters shorter than
sizeof(struct sctp_addip_param) + sizeof(struct sctp_errhdr) at the
verifier, and advance the consumer iterator with the same padding
rule as the verifier to keep the two walks in lockstep. The verifier
change guarantees a complete error header in every ERR_CAUSE
parameter the consumer can see, so the consumer's asconf_ack_len
check is dropped and it returns err_param-&gt;cause directly. The
consumer padding fix is still required because odd lengths remain
valid for SCTP_PARAM_ERR_CAUSE per RFC 5061.

The issue was found by ZeroHive, a vulnerability hunting agent at
Tencent Yunding Lab.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Henry Martin &lt;bsdhenrymartin@gmail.com&gt;
Acked-by: Xin Long &lt;lucien.xin@gmail.com&gt;
Link: https://patch.msgid.link/20260828042431.3873725-1-bsdhenrymartin@gmail.com
Signed-off-by: Jakub Kicinski &lt;kuba@kernel.org&gt;
</content>
</entry>
<entry>
<title>sctp: fix a TOCTOU race in SCTP_CMD_TIMER_START</title>
<updated>2026-08-28T23:09:25Z</updated>
<author>
<name>Xin Long</name>
<email>lucien.xin@gmail.com</email>
</author>
<published>2026-08-26T19:49:04Z</published>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/wireguard-linux/commit/?id=2188569e7e1b0bc3f3b557dc97ab7a02befc11c8'/>
<id>urn:sha1:2188569e7e1b0bc3f3b557dc97ab7a02befc11c8</id>
<content type='text'>
The SCTP_CMD_TIMER_START handler checks timer_pending() before calling
timer_reduce(). The timer can expire and detach between these operations,
causing timer_reduce() to rearm the timer without taking the association
reference required for the newly armed timer.

The timer callback later unconditionally drops its association reference,
which can leave the association reference count unbalanced and result in
use-after-free during association teardown.

Use the return value of timer_reduce() to determine whether the timer was
actually armed. Take the association reference only when timer_reduce()
successfully starts a new timer, closing the race between checking the
timer state and rearming it.

This issue was reported by Nico Yip (@_cyeaa_) working with TrendAI Zero
Day Initiative.

Fixes: 20a785aa52c8 ("sctp: Don't add the shutdown timer if its already been added")
Reported-by: Zero Day Initiative &lt;zdi-disclosures@trendmicro.com&gt;
Signed-off-by: Xin Long &lt;lucien.xin@gmail.com&gt;
Link: https://patch.msgid.link/9d8f1b5c50329d5ea7c642128d35681abaa9ed20.1787773744.git.lucien.xin@gmail.com
Signed-off-by: Jakub Kicinski &lt;kuba@kernel.org&gt;
</content>
</entry>
<entry>
<title>sctp: fix stream-&gt;outcnt underflow on duplicate RECONF responses</title>
<updated>2026-08-25T11:33:08Z</updated>
<author>
<name>Jun Yang</name>
<email>junvyyang@tencent.com</email>
</author>
<published>2026-08-24T08:18:20Z</published>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/wireguard-linux/commit/?id=3faf13aff243ca9f78d08b1a2956ef5a6fc77b6e'/>
<id>urn:sha1:3faf13aff243ca9f78d08b1a2956ef5a6fc77b6e</id>
<content type='text'>
A cached RECONF chunk may contain more than one request parameter.  A
duplicate response can therefore find and process the same ADD_OUT request
again while another parameter is still outstanding, rolling back outcnt
twice and possibly underflowing it.

Track outstanding request types as bits and clear each bit after its first
response.  Later responses for the same request are then ignored.

Fixes: 11ae76e67a17 ("sctp: implement receiver-side procedures for the Reconf Response Parameter")
Cc: stable@kernel.org
Reported-by: TencentOS Corvus AI &lt;corvus@tencent.com&gt;
Link: https://lore.kernel.org/netdev/20260730110225.37371-1-juny24602@gmail.com/
Suggested-by: Xin Long &lt;lucien.xin@gmail.com&gt;
Assisted-by: tencentos-corvus-ai:kimi-k3
Signed-off-by: Jun Yang &lt;junvyyang@tencent.com&gt;
Link: https://patch.msgid.link/20260824081832.98717-3-juny24602@gmail.com
Signed-off-by: Paolo Abeni &lt;pabeni@redhat.com&gt;
</content>
</entry>
<entry>
<title>sctp: distinguish sequence zero from wildcard in reconf lookup</title>
<updated>2026-08-25T11:33:08Z</updated>
<author>
<name>Jun Yang</name>
<email>junvyyang@tencent.com</email>
</author>
<published>2026-08-24T08:18:19Z</published>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/wireguard-linux/commit/?id=63f44178f0a0f86060c9b576d6efab8a3ffa403e'/>
<id>urn:sha1:63f44178f0a0f86060c9b576d6efab8a3ffa403e</id>
<content type='text'>
Zero is a valid response sequence after strreset_outseq wraps, but
sctp_chunk_lookup_strreset_param() currently treats it as a wildcard.

Add match_seq so response lookups match zero exactly while the one
type-only lookup can still ignore the sequence.

Fixes: 50a41591f110 ("sctp: implement receiver-side procedures for the Add Outgoing Streams Request Parameter")
Cc: stable@kernel.org
Suggested-by: Simon Horman &lt;horms@kernel.org&gt;
Acked-by: Xin Long &lt;lucien.xin@gmail.com&gt;
Signed-off-by: Jun Yang &lt;junvyyang@tencent.com&gt;
Link: https://patch.msgid.link/20260824081832.98717-2-juny24602@gmail.com
Signed-off-by: Paolo Abeni &lt;pabeni@redhat.com&gt;
</content>
</entry>
<entry>
<title>sctp: fix NULL deref on untransmitted RECONF completion</title>
<updated>2026-08-25T09:06:46Z</updated>
<author>
<name>Weiming Shi</name>
<email>bestswngs@gmail.com</email>
</author>
<published>2026-08-23T17:28:58Z</published>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/wireguard-linux/commit/?id=2db9bfa3e27bdea15e05ea70b56bad3d21e570ec'/>
<id>urn:sha1:2db9bfa3e27bdea15e05ea70b56bad3d21e570ec</id>
<content type='text'>
sctp_process_strreset_outreq(), sctp_process_strreset_addstrm_out() and
sctp_process_strreset_resp() complete a pending stream reconfiguration
request by stopping the reconf timer on the transport it was sent on:

	t = asoc-&gt;strreset_chunk-&gt;transport;
	if (timer_delete(&amp;t-&gt;reconf_timer))
		sctp_transport_put(t);

chunk-&gt;transport is assigned by __sctp_packet_append_chunk() when the
chunk is appended to an outbound packet, and sctp_outq_flush_ctrl() arms
the reconf timer at that same point. A request already published in
asoc-&gt;strreset_chunk but not yet transmitted has neither, so completing
it dereferences NULL.

Two ways to get there. sctp_send_asconf_del_ip() sets
asoc-&gt;src_out_of_asoc_ok without sending anything when the address being
removed is the association's last one, and sctp_outq_flush_ctrl() then
leaves every non-ASCONF control chunk queued; as only
sctp_process_asconf_ack() clears that flag, it persists. An unprivileged
process that removes such an address and then asks for a stream reset
panics the kernel from softirq. A peer needs neither ASCONF nor local
help: sctp_cmd_interpreter() uncorks the outqueue only once the whole
packet has been processed, so a reply built while walking a RECONF chunk
stays untransmitted for the rest of that walk, and one RECONF chunk
carrying [Incoming SSN Reset Request, Outgoing SSN Reset Request,
Response] -- or two RECONF chunks in one packet -- reaches the same
dereference.

  KASAN: null-ptr-deref in range [0x00000000000001e8-0x00000000000001ef]
  RIP: 0010:timer_delete+0x67/0x110
  Call Trace:
   &lt;IRQ&gt;
   sctp_process_strreset_addstrm_out (net/sctp/stream.c:832)
   sctp_sf_do_reconf (net/sctp/sm_statefuns.c:4212)
   sctp_do_sm (net/sctp/sm_sideeffect.c:1172)
   sctp_assoc_bh_rcv (net/sctp/associola.c:1044)
   sctp_rcv (net/sctp/input.c:243)
   ip_local_deliver (net/ipv4/ip_input.c:262)
   process_backlog (net/core/dev.c:6680)
   &lt;/IRQ&gt;

A response can only acknowledge a request that was actually sent, so do
not match asoc-&gt;strreset_chunk while chunk-&gt;transport is NULL. Guarding
the lookup covers all three completion sites.

Fixes: 810544764536 ("sctp: implement receiver-side procedures for the Outgoing SSN Reset Request Parameter")
Cc: stable@vger.kernel.org
Reported-by: Xiang Mei &lt;xmei5@asu.edu&gt;
Suggested-by: Xin Long &lt;lucien.xin@gmail.com&gt;
Assisted-by: Claude:claude-opus-5
Signed-off-by: Weiming Shi &lt;bestswngs@gmail.com&gt;
Acked-by: Xin Long &lt;lucien.xin@gmail.com&gt;
Link: https://patch.msgid.link/20260823172857.896146-2-bestswngs@gmail.com
Signed-off-by: Paolo Abeni &lt;pabeni@redhat.com&gt;
</content>
</entry>
</feed>
