[PATCH net v2 1/1] sctp: stream: fully roll back denied add-stream state
Ren Wei <[email protected]> Fri, 5 Jun 2026 13:53:42 +0800
| Newsgroups | org.kernel.vger.linux-sctp,org.kernel.vger.netdev |
|---|---|
| Message-ID | <d78954ecd94954653ee299400e98d74a03a6f7d3.1780603399.git.bronzed_45_vested@icloud.com> |
From: Wyatt Feng <[email protected]> When ADD_OUT_STREAMS is denied, SCTP only shrinks the queued chunks and then lowers outcnt. That leaves removed stream metadata behind, so a later re-add can reuse a stale ext and hit a null-pointer dereference in the scheduler get path. Fix the rollback by tearing down the removed stream state the same way other stream resizes do. Unschedule the current scheduler state, drop the removed stream ext state with sctp_stream_outq_migrate(), and then reschedule the remaining streams. This keeps scheduler-private RR/FC/PRIO lists consistent while fully rolling back denied outgoing stream additions. Fixes: 637784ade221 ("sctp: introduce priority based stream scheduler") Cc: [email protected] Reported-by: Yuan Tan <[email protected]> Reported-by: Yifan Wu <[email protected]> Reported-by: Juefei Pu <[email protected]> Reported-by: Zhengchuan Liang <[email protected]> Reported-by: Xin Liu <[email protected]> Assisted-by: Codex:GPT-5.4 Signed-off-by: Wyatt Feng <[email protected]> Signed-off-by: Ren Wei <[email protected]> --- Changes in v2: - Moved the `sched` declaration below `addstrm` and dropped the `out_curr` handling. The rollback fix now only unschedules the current scheduler state, migrates/drops the removed stream ext state, and reschedules the remaining streams. - v1 Link: https://lore.kernel.org/all/345886be48a66f70bad26ddcea6defb38d1d0f72.1780439824.git.bronzed_45_vested@icloud.com/ net/sctp/stream.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/net/sctp/stream.c b/net/sctp/stream.c index c2247793c88b..5c2fdedea088 100644 --- a/net/sctp/stream.c +++ b/net/sctp/stream.c @@ -1038,6 +1038,7 @@ struct sctp_chunk *sctp_process_strreset_resp( stsn, rtsn, GFP_ATOMIC); } else if (req->type == SCTP_PARAM_RESET_ADD_OUT_STREAMS) { struct sctp_strreset_addstrm *addstrm; + const struct sctp_sched_ops *sched; __u16 number; addstrm = (struct sctp_strreset_addstrm *)req; @@ -1048,7 +1049,10 @@ struct sctp_chunk *sctp_process_strreset_resp( for (i = number; i < stream->outcnt; i++) SCTP_SO(stream, i)->state = SCTP_STREAM_OPEN; } else { - sctp_stream_shrink_out(stream, number); + sched = sctp_sched_ops_from_stream(stream); + sched->unsched_all(stream); + sctp_stream_outq_migrate(stream, NULL, number); + sched->sched_all(stream); stream->outcnt = number; } -- 2.43.7