Skip to content

Prevent stream ID reuse while outgoing RE-CONFIG is pending#37

Draft
timwu20 wants to merge 6 commits intoalgesten:mainfrom
ChainSafe:tim/prevent-stream-id-reuse-during-reconfig
Draft

Prevent stream ID reuse while outgoing RE-CONFIG is pending#37
timwu20 wants to merge 6 commits intoalgesten:mainfrom
ChainSafe:tim/prevent-stream-id-reuse-during-reconfig

Conversation

@timwu20
Copy link

@timwu20 timwu20 commented Mar 2, 2026

Problem

sctp-proto allows reusing an SCTP stream ID immediately after closing it, without waiting for the RE-CONFIG (RFC 6525) acknowledgment from the remote peer. This causes the remote's SCTP stack to silently drop or queue data sent on the reused stream, because from the remote's perspective the stream is still in a reset-pending state.

Reproduction sequence

  1. sctp-proto sends RE-CONFIG for stream 1 and removes stream 1 from its stream table
  2. 3ms later, open_stream is called and sctp-proto allocates stream 1 (it looks available — not in the table)
  3. sctp-proto sends a DCEP OPEN on stream 1
  4. The remote's SCTP stack receives data on stream 1, but stream 1 is still in reset-pending state (RE-CONFIG not yet acknowledged), so the data is silently dropped or queued
  5. The DCEP OPEN is never processed, the channel never opens

This is easy to trigger in practice when short-lived channels (identify, request-response) are closed quickly and new channels are opened immediately after, especially when there is significant data flowing on other streams which may delay the RE-CONFIG ACK.

Relevant RFC

RFC 6525, Section 5.1 (Outgoing SSN Reset Request):

After sending a RE-CONFIG chunk with an Outgoing SSN Reset Request, the sender MUST NOT send DATA chunks on the streams mentioned until the response has been received.

Impact

This bug causes WebRTC data channel failures in production when a data channel is opened shortly after another channel on the same SCTP stream ID is closed. In Polkadot light client WebRTC connections, it kills the block-announces notification protocol, leaving the peer permanently unable to sync.

Fix

  • Add a has_pending_reset_for_stream() helper that checks self.reconfigs (pending outgoing RE-CONFIGs awaiting acknowledgment) for any entry containing the requested stream ID
  • Guard open_stream() to return ErrStreamResetPending if the stream ID has an unacknowledged outgoing RE-CONFIG
  • No new data structures needed — self.reconfigs already tracks unacknowledged outgoing reconfigs and is typically 0-1 entries

Changes

  • src/association/mod.rs: Added has_pending_reset_for_stream() and guard in open_stream()
  • src/error.rs: Added ErrStreamResetPending error variant
  • src/endpoint/endpoint_test.rs: Added test_assoc_open_stream_rejects_pending_reset_id

Test plan

  • New test verifies open_stream rejects a stream ID mid-reset and allows it after the RE-CONFIG is acknowledged
  • All 110 existing tests pass
  • cargo clippy and cargo fmt clean

@timwu20 timwu20 marked this pull request as draft March 2, 2026 18:39
@timwu20
Copy link
Author

timwu20 commented Mar 2, 2026

Created this as draft for now since this is built on top of #30. I'll rebase after #30 gets merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant