Raised by a V12 audit of the paired-serving activation and verified against the current tree. Pre-existing on main, byte-identical there.
What happens
add_peer removes the peer's session-gap claim after releasing the session-table lock, and without checking who owns the claim:
|
// The admitted session supersedes any gap claim left by its predecessor. |
The asymmetry is visible a few hundred lines below in the same file: remove_peer guards the same removal on the owning connection and does it while holding the peer-map lock, and finish_session inserts the claim under that lock. Only this one call site touches the claims map after releasing it.
So a superseded add_peer that is preempted between installing its session and removing the claim can delete a claim installed later by a different connection's teardown. That claim is what keeps the newer connection owned during ordered-stream reopen backoff, so an ownership sample can close a healthy connection.
Scope
Narrow and self-healing. add_peer is synchronous, so this needs genuine thread preemption across a window that must contain a full admit and teardown of the second connection, and the connection reconnects afterwards. Rated Low by the audit, and I agree.
Suggested fix
Move the claim removal inside the block that already holds the peer-map lock, so it matches the guarded, lock-ordered removal in remove_peer. The predicate in that function is the model to copy.
Raised by a V12 audit of the paired-serving activation and verified against the current tree. Pre-existing on
main, byte-identical there.What happens
add_peerremoves the peer's session-gap claim after releasing the session-table lock, and without checking who owns the claim:zakura/crates/zakura-network/src/zakura/block_sync/service.rs
Line 829 in f374d38
The asymmetry is visible a few hundred lines below in the same file:
remove_peerguards the same removal on the owning connection and does it while holding the peer-map lock, andfinish_sessioninserts the claim under that lock. Only this one call site touches the claims map after releasing it.So a superseded
add_peerthat is preempted between installing its session and removing the claim can delete a claim installed later by a different connection's teardown. That claim is what keeps the newer connection owned during ordered-stream reopen backoff, so an ownership sample can close a healthy connection.Scope
Narrow and self-healing.
add_peeris synchronous, so this needs genuine thread preemption across a window that must contain a full admit and teardown of the second connection, and the connection reconnects afterwards. Rated Low by the audit, and I agree.Suggested fix
Move the claim removal inside the block that already holds the peer-map lock, so it matches the guarded, lock-ordered removal in
remove_peer. The predicate in that function is the model to copy.