refactor(control): remove two latent panics on control-supplied wire data#254
Merged
Merged
Conversation
…data An adversarial control-client audit flagged two panics reachable (today only in theory) from control-server-supplied data — a hostile or MITM control server could otherwise drop the node off its control connection: - control_dialer.rs: the `DialMode::Ace` arm of the dial-plan TcpDialer was `unimplemented!()`. `next_dialer` skips every Ace candidate before `dial` is called, so it's unreachable today — but `candidate.mode` is control-controlled, so a future change wiring Ace dialing without re-checking the skip could turn it into a remotely-triggerable panic in the reconnect path. Return a typed `io::ErrorKind::Unsupported` error instead; the dial loop then falls through to the next candidate / system DNS exactly as it does for any failed candidate. - ip_range.rs: `IpRange::iter_prefixes` had `_ => unreachable!()` for a mixed-family (one v4, one v6) Range. The deserialize path (`parse_range`) rejects mismatched families, so it's unreachable from the wire, but `IpRange::Range` is a public constructor — make the function total (empty iterator for the impossible case) so packet-filter compile can never panic the netmap-apply path even if a future internal caller builds one by hand. Both are defense-in-depth: no behavior change on any reachable path. The parser still rejects mismatched-family ranges (mismatched_ip_kinds test still should_panic), and Ace candidates are still skipped before dialing. The rest of the control client audited clean (Noise IK pinned-key handshake, bounded 16 MiB netmap frame + read watchdog, Result-based parsing, fail-closed filter compile, n²-backoff map-poll). Signed-off-by: Sergio <sergio@geiser.cloud>
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughTwo independent panic removal fixes across two crates: ChangesPanic-to-error conversions
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~4 minutes ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
GeiserX
pushed a commit
that referenced
this pull request
Jun 15, 2026
Release 0.39.0. Bundles the parity + anti-leak batch: magicsock CallMeMaybe immediate-ping (#246), peerless-STUN-stop (#247), STUN SOFTWARE+FINGERPRINT (#241); MagicDNS RD/RA+compression (#242) + SERVFAIL-not-NXDOMAIN (#248); DERP send rate-limit (#249); IPv4 fragment handling (#253); control Hostinfo/ProtoPortRange/NetInfo wire fixes (#244/#245); netcheck StunProber deletion (#250); forwarder subnet-SSRF doc+test (#252); control panic-hardening (#254).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
An adversarial control-client audit flagged two panics reachable (today only in theory) from control-server-supplied wire data. A hostile or MITM control server could otherwise drop the node off its control connection (DoS).
ts_control/src/control_dialer.rs— theDialMode::Acearm of the dial-planTcpDialer::dialwasunimplemented!().next_dialerskips everyAcecandidate beforedialis called, so it's unreachable today — butcandidate.modecomes from the control-suppliedMapResponse.control_dial_plan, so a future change that wires Ace dialing without re-checking the skip would turn it into a remotely-triggerable panic in the reconnect path. Return a typedio::ErrorKind::Unsupportederror instead; the dial loop falls through to the next candidate / system DNS exactly as for any failed candidate.ts_packetfilter_serde/src/ip_range.rs—IpRange::iter_prefixeshad_ => unreachable!()for a mixed-family (one v4, one v6)Range. The deserialize path (parse_range) rejects mismatched families so it's unreachable from the wire, butIpRange::Rangeis a public constructor — make the function total (empty iterator for the impossible case) so packet-filter compile can never panic the netmap-apply path even if a future internal caller builds one by hand.Why no behavior change
Ipdial arm is byte-identical (.await?preserved). TheAcearm is now a bare typedErr(...); both arms unify toio::Result<TcpStream>(the.timeout().await?foldsElapsedintoio::Error), so noreturnis needed (clippy-clean).mismatched_ip_kinds#[should_panic]test (which assertsIpRange::try_from("127.0.0.1-ffef::")errors) still passes.iter_prefixesis only ever called on parser-produced (same-family) ranges.The rest of the control client audited clean: Noise IK pinned-server-key handshake (no downgrade/MITM), bounded 16 MiB netmap frame + 120s read watchdog,
Result-based parsing with no production unwrap/index on wire data, fail-closed filter compile, n²-backoff map-poll reset only on substantive frames.Verification
cargo build -p geiserx_ts_control(0 errors),cargo test -p geiserx_ts_control(233) +geiserx_ts_packetfilter_serde(15, incl.mismatched_ip_kinds),clippy -D warnings(0),fmt,cargo run -p checks(anti-leak guard) all green.Created using Claude Code (Opus 4.8)
Summary by CodeRabbit