Netdev List
 help / color / mirror / Atom feed
* [PATCH net v4 0/2] sctp: handle wrapped and duplicate RECONF responses
@ 2026-08-24  8:18 Jun Yang
  2026-08-24  8:18 ` [PATCH net v4 1/2] sctp: distinguish sequence zero from wildcard in reconf lookup Jun Yang
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Jun Yang @ 2026-08-24  8:18 UTC (permalink / raw)
  To: linux-sctp, netdev
  Cc: marcelo.leitner, lucien.xin, davem, edumazet, kuba, pabeni, horms,
	Jun Yang

From: Jun Yang <junvyyang@tencent.com>

Fix response sequence zero lookup first, then make RECONF response
handling idempotent with an outstanding-request bitmask.

Jun Yang (2):
  sctp: distinguish sequence zero from wildcard in reconf lookup
  sctp: fix stream->outcnt underflow on duplicate RECONF responses

 include/net/sctp/structs.h |  2 +-
 net/sctp/stream.c          | 46 ++++++++++++++++++++++++++------------
 2 files changed, 33 insertions(+), 15 deletions(-)

---
Changes since v3:
 - Restore the SCTP_STRRESET_SET/CLEAR/TEST() helpers.

v2: https://lore.kernel.org/netdev/20260804113100.37840-1-juny24602@gmail.com/
--
2.55.0

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH net v4 1/2] sctp: distinguish sequence zero from wildcard in reconf lookup
  2026-08-24  8:18 [PATCH net v4 0/2] sctp: handle wrapped and duplicate RECONF responses Jun Yang
@ 2026-08-24  8:18 ` Jun Yang
  2026-08-24  8:18 ` [PATCH net v4 2/2] sctp: fix stream->outcnt underflow on duplicate RECONF responses Jun Yang
  2026-08-25 12:30 ` [PATCH net v4 0/2] sctp: handle wrapped and " patchwork-bot+netdevbpf
  2 siblings, 0 replies; 4+ messages in thread
From: Jun Yang @ 2026-08-24  8:18 UTC (permalink / raw)
  To: linux-sctp, netdev
  Cc: marcelo.leitner, lucien.xin, davem, edumazet, kuba, pabeni, horms,
	Jun Yang, stable

From: Jun Yang <junvyyang@tencent.com>

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 <horms@kernel.org>
Acked-by: Xin Long <lucien.xin@gmail.com>
Signed-off-by: Jun Yang <junvyyang@tencent.com>
---
 net/sctp/stream.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/net/sctp/stream.c b/net/sctp/stream.c
index 34ffe6c945a4..cfca5aa28c1a 100644
--- a/net/sctp/stream.c
+++ b/net/sctp/stream.c
@@ -482,7 +482,7 @@ int sctp_send_add_streams(struct sctp_association *asoc,
 
 static struct sctp_paramhdr *sctp_chunk_lookup_strreset_param(
 			struct sctp_association *asoc, __be32 resp_seq,
-			__be16 type)
+			__be16 type, bool match_seq)
 {
 	struct sctp_chunk *chunk = asoc->strreset_chunk;
 	struct sctp_reconf_chunk *hdr;
@@ -499,7 +499,7 @@ static struct sctp_paramhdr *sctp_chunk_lookup_strreset_param(
 		 */
 		struct sctp_strreset_tsnreq *req = param.v;
 
-		if ((!resp_seq || req->request_seq == resp_seq) &&
+		if ((!match_seq || req->request_seq == resp_seq) &&
 		    (!type || type == req->param_hdr.type))
 			return param.v;
 	}
@@ -564,7 +564,7 @@ struct sctp_chunk *sctp_process_strreset_outreq(
 	if (asoc->strreset_chunk) {
 		if (!sctp_chunk_lookup_strreset_param(
 				asoc, outreq->response_seq,
-				SCTP_PARAM_RESET_IN_REQUEST)) {
+				SCTP_PARAM_RESET_IN_REQUEST, true)) {
 			/* same process with outstanding isn't 0 */
 			result = SCTP_STRRESET_ERR_IN_PROGRESS;
 			goto out;
@@ -816,7 +816,7 @@ struct sctp_chunk *sctp_process_strreset_addstrm_out(
 
 	if (asoc->strreset_chunk) {
 		if (!sctp_chunk_lookup_strreset_param(
-			asoc, 0, SCTP_PARAM_RESET_ADD_IN_STREAMS)) {
+			asoc, 0, SCTP_PARAM_RESET_ADD_IN_STREAMS, false)) {
 			/* same process with outstanding isn't 0 */
 			result = SCTP_STRRESET_ERR_IN_PROGRESS;
 			goto out;
@@ -927,7 +927,8 @@ struct sctp_chunk *sctp_process_strreset_resp(
 	struct sctp_paramhdr *req;
 	__u32 result;
 
-	req = sctp_chunk_lookup_strreset_param(asoc, resp->response_seq, 0);
+	req = sctp_chunk_lookup_strreset_param(asoc, resp->response_seq, 0,
+					       true);
 	if (!req)
 		return NULL;
 
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH net v4 2/2] sctp: fix stream->outcnt underflow on duplicate RECONF responses
  2026-08-24  8:18 [PATCH net v4 0/2] sctp: handle wrapped and duplicate RECONF responses Jun Yang
  2026-08-24  8:18 ` [PATCH net v4 1/2] sctp: distinguish sequence zero from wildcard in reconf lookup Jun Yang
@ 2026-08-24  8:18 ` Jun Yang
  2026-08-25 12:30 ` [PATCH net v4 0/2] sctp: handle wrapped and " patchwork-bot+netdevbpf
  2 siblings, 0 replies; 4+ messages in thread
From: Jun Yang @ 2026-08-24  8:18 UTC (permalink / raw)
  To: linux-sctp, netdev
  Cc: marcelo.leitner, lucien.xin, davem, edumazet, kuba, pabeni, horms,
	Jun Yang, stable, TencentOS Corvus AI

From: Jun Yang <junvyyang@tencent.com>

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 <corvus@tencent.com>
Link: https://lore.kernel.org/netdev/20260730110225.37371-1-juny24602@gmail.com/
Suggested-by: Xin Long <lucien.xin@gmail.com>
Assisted-by: tencentos-corvus-ai:kimi-k3
Signed-off-by: Jun Yang <junvyyang@tencent.com>
---
v4:
 - Restore the SCTP_STRRESET_SET/CLEAR/TEST() helpers, each of which is
   used more than once, so open-coding them only adds lines.

v3:
 - Split the response_seq == 0 lookup fix into patch 1 (Simon Horman).
 - Keep the request bit helper local to stream.c.

v2:
 - Track outstanding requests by type instead of sequence (Xin Long).
 - Drop the redundant arithmetic guard (Xin Long).

v1: https://lore.kernel.org/netdev/20260730110225.37371-1-juny24602@gmail.com/

 include/net/sctp/structs.h |  2 +-
 net/sctp/stream.c          | 39 +++++++++++++++++++++++++++-----------
 2 files changed, 29 insertions(+), 12 deletions(-)

diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index cccc662561aa..b21f23b736fd 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -2057,7 +2057,7 @@ struct sctp_association {
 	     force_delay:1;
 
 	__u8 strreset_enable;
-	__u8 strreset_outstanding; /* request param count on the fly */
+	__u8 strreset_outstanding; /* request param bitmask on the fly */
 
 	__u32 strreset_outseq; /* Update after receiving response */
 	__u32 strreset_inseq; /* Update after receiving request */
diff --git a/net/sctp/stream.c b/net/sctp/stream.c
index cfca5aa28c1a..9fee0da78845 100644
--- a/net/sctp/stream.c
+++ b/net/sctp/stream.c
@@ -22,6 +22,15 @@
 #include <net/sctp/sm.h>
 #include <net/sctp/stream_sched.h>
 
+#define SCTP_STRRESET_MASK(type) \
+	BIT(ntohs(type) - ntohs(SCTP_PARAM_RESET_OUT_REQUEST))
+#define SCTP_STRRESET_TEST(asoc, type) \
+	((asoc)->strreset_outstanding & SCTP_STRRESET_MASK(type))
+#define SCTP_STRRESET_SET(asoc, type) \
+	((asoc)->strreset_outstanding |= SCTP_STRRESET_MASK(type))
+#define SCTP_STRRESET_CLEAR(asoc, type) \
+	((asoc)->strreset_outstanding &= ~SCTP_STRRESET_MASK(type))
+
 static void sctp_stream_shrink_out(struct sctp_stream *stream, __u16 outcnt)
 {
 	struct sctp_association *asoc;
@@ -372,7 +381,10 @@ int sctp_send_reset_streams(struct sctp_association *asoc,
 		goto out;
 	}
 
-	asoc->strreset_outstanding = out + in;
+	if (out)
+		SCTP_STRRESET_SET(asoc, SCTP_PARAM_RESET_OUT_REQUEST);
+	if (in)
+		SCTP_STRRESET_SET(asoc, SCTP_PARAM_RESET_IN_REQUEST);
 
 out:
 	return retval;
@@ -417,7 +429,7 @@ int sctp_send_reset_assoc(struct sctp_association *asoc)
 		return retval;
 	}
 
-	asoc->strreset_outstanding = 1;
+	SCTP_STRRESET_SET(asoc, SCTP_PARAM_RESET_TSN_REQUEST);
 
 	return 0;
 }
@@ -474,7 +486,10 @@ int sctp_send_add_streams(struct sctp_association *asoc,
 		goto out;
 	}
 
-	asoc->strreset_outstanding = !!out + !!in;
+	if (out)
+		SCTP_STRRESET_SET(asoc, SCTP_PARAM_RESET_ADD_OUT_STREAMS);
+	if (in)
+		SCTP_STRRESET_SET(asoc, SCTP_PARAM_RESET_ADD_IN_STREAMS);
 
 out:
 	return retval;
@@ -564,13 +579,14 @@ struct sctp_chunk *sctp_process_strreset_outreq(
 	if (asoc->strreset_chunk) {
 		if (!sctp_chunk_lookup_strreset_param(
 				asoc, outreq->response_seq,
-				SCTP_PARAM_RESET_IN_REQUEST, true)) {
+				SCTP_PARAM_RESET_IN_REQUEST, true) ||
+		    !SCTP_STRRESET_TEST(asoc, SCTP_PARAM_RESET_IN_REQUEST)) {
 			/* same process with outstanding isn't 0 */
 			result = SCTP_STRRESET_ERR_IN_PROGRESS;
 			goto out;
 		}
 
-		asoc->strreset_outstanding--;
+		SCTP_STRRESET_CLEAR(asoc, SCTP_PARAM_RESET_IN_REQUEST);
 		asoc->strreset_outseq++;
 
 		if (!asoc->strreset_outstanding) {
@@ -669,7 +685,7 @@ struct sctp_chunk *sctp_process_strreset_inreq(
 			SCTP_SO(stream, i)->state = SCTP_STREAM_CLOSED;
 
 	asoc->strreset_chunk = chunk;
-	asoc->strreset_outstanding = 1;
+	SCTP_STRRESET_SET(asoc, SCTP_PARAM_RESET_OUT_REQUEST);
 	sctp_chunk_hold(asoc->strreset_chunk);
 
 	result = SCTP_STRRESET_PERFORMED;
@@ -816,13 +832,14 @@ struct sctp_chunk *sctp_process_strreset_addstrm_out(
 
 	if (asoc->strreset_chunk) {
 		if (!sctp_chunk_lookup_strreset_param(
-			asoc, 0, SCTP_PARAM_RESET_ADD_IN_STREAMS, false)) {
+			asoc, 0, SCTP_PARAM_RESET_ADD_IN_STREAMS, false) ||
+		    !SCTP_STRRESET_TEST(asoc, SCTP_PARAM_RESET_ADD_IN_STREAMS)) {
 			/* same process with outstanding isn't 0 */
 			result = SCTP_STRRESET_ERR_IN_PROGRESS;
 			goto out;
 		}
 
-		asoc->strreset_outstanding--;
+		SCTP_STRRESET_CLEAR(asoc, SCTP_PARAM_RESET_ADD_IN_STREAMS);
 		asoc->strreset_outseq++;
 
 		if (!asoc->strreset_outstanding) {
@@ -899,7 +916,7 @@ struct sctp_chunk *sctp_process_strreset_addstrm_in(
 		goto out;
 
 	asoc->strreset_chunk = chunk;
-	asoc->strreset_outstanding = 1;
+	SCTP_STRRESET_SET(asoc, SCTP_PARAM_RESET_ADD_OUT_STREAMS);
 	sctp_chunk_hold(asoc->strreset_chunk);
 
 	stream->outcnt = outcnt;
@@ -929,7 +946,7 @@ struct sctp_chunk *sctp_process_strreset_resp(
 
 	req = sctp_chunk_lookup_strreset_param(asoc, resp->response_seq, 0,
 					       true);
-	if (!req)
+	if (!req || !SCTP_STRRESET_TEST(asoc, req->type))
 		return NULL;
 
 	result = ntohl(resp->result);
@@ -1079,7 +1096,7 @@ struct sctp_chunk *sctp_process_strreset_resp(
 			nums, 0, GFP_ATOMIC);
 	}
 
-	asoc->strreset_outstanding--;
+	SCTP_STRRESET_CLEAR(asoc, req->type);
 	asoc->strreset_outseq++;
 
 	/* remove everything for this reconf request */
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH net v4 0/2] sctp: handle wrapped and duplicate RECONF responses
  2026-08-24  8:18 [PATCH net v4 0/2] sctp: handle wrapped and duplicate RECONF responses Jun Yang
  2026-08-24  8:18 ` [PATCH net v4 1/2] sctp: distinguish sequence zero from wildcard in reconf lookup Jun Yang
  2026-08-24  8:18 ` [PATCH net v4 2/2] sctp: fix stream->outcnt underflow on duplicate RECONF responses Jun Yang
@ 2026-08-25 12:30 ` patchwork-bot+netdevbpf
  2 siblings, 0 replies; 4+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-08-25 12:30 UTC (permalink / raw)
  To: Jun Yang
  Cc: linux-sctp, netdev, marcelo.leitner, lucien.xin, davem, edumazet,
	kuba, pabeni, horms, junvyyang

Hello:

This series was applied to netdev/net.git (main)
by Paolo Abeni <pabeni@redhat.com>:

On Mon, 24 Aug 2026 16:18:18 +0800 you wrote:
> From: Jun Yang <junvyyang@tencent.com>
> 
> Fix response sequence zero lookup first, then make RECONF response
> handling idempotent with an outstanding-request bitmask.
> 
> Jun Yang (2):
>   sctp: distinguish sequence zero from wildcard in reconf lookup
>   sctp: fix stream->outcnt underflow on duplicate RECONF responses
> 
> [...]

Here is the summary with links:
  - [net,v4,1/2] sctp: distinguish sequence zero from wildcard in reconf lookup
    https://git.kernel.org/netdev/net/c/63f44178f0a0
  - [net,v4,2/2] sctp: fix stream->outcnt underflow on duplicate RECONF responses
    https://git.kernel.org/netdev/net/c/3faf13aff243

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-08-25 12:31 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-24  8:18 [PATCH net v4 0/2] sctp: handle wrapped and duplicate RECONF responses Jun Yang
2026-08-24  8:18 ` [PATCH net v4 1/2] sctp: distinguish sequence zero from wildcard in reconf lookup Jun Yang
2026-08-24  8:18 ` [PATCH net v4 2/2] sctp: fix stream->outcnt underflow on duplicate RECONF responses Jun Yang
2026-08-25 12:30 ` [PATCH net v4 0/2] sctp: handle wrapped and " patchwork-bot+netdevbpf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox