Skip to content

fix(cmux-wg-tun): a socketpair is never read as a utun (the name query is LOCAL_PEERPID on a local socket) - #34248

Merged
lawrencecchen merged 3 commits into
feat-cmux-nextfrom
base-red-wg-tun-utun-probe
Nov 3, 2026
Merged

lawrencecchen merged 3 commits into
feat-cmux-nextfrom
base-red-wg-tun-utun-probe

Conversation

@lawrencecchen

@lawrencecchen lawrencecchen commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

Summary

cmux-wg-tun's test engine::tests::a_socketpair_is_not_mistaken_for_utun failed in a full run and passed alone (fleet step f74200465feb95b217cf67d8). The cause is not test order and not shared state.

Cause: utun::interface_name asks getsockopt(fd, 2, 2) (SYSPROTO_CONTROL, UTUN_OPT_IFNAME). On a local (AF_UNIX) socket, macOS reads the same level and option as LOCAL_PEERPID; its handler ignores the level. So a socketpair answers the query with this process's pid as 4 bytes, and those bytes read as a "name" whenever they are ASCII. nextest runs each test in its own process, so the pid, and the result, changed from run to run.

Fix: a utun is found by its peer address family. is_kernel_control accepts only an AF_SYSTEM peer (getpeername), which is what WireGuard's Apple client checks. Only then does interface_name ask for the name.

The crate came in lawrencecchen's direct push ad2c76731f28..cc33e089376e and stays on the tip after the revert #34198, so this is a tip defect. This PR does not depend on #34220 (they change different lines of utun.rs).

Testing

Red first: e61e5a7a04e3 adds the tests, and is_kernel_control keeps the old rule (the fd answers the name query).

  • the_utun_name_query_answers_a_local_socket_with_its_peer_pid (macOS) pins the cause: the query succeeds on a socketpair, and the 4 reply bytes are this process's pid.
  • a_socketpair_is_not_a_kernel_control_socket is red on macOS at the red commit in every process, whatever the pid.
  • Fleet, macOS, cmux-tui-rust-check.sh test engine::tests::: red commit, step 140d2532959adadca832e04c; fix 792a09aec9e3, step 6b8d0dc2737388103d413953. Linux panic ratchet at the fix: step 307697ab0db2034d5f06fccc. Results in a comment.

Observed / Not run

  • Observed: the prepush gate; the fleet results in the comment.
  • Not run: find_utun_fd inside a real NetworkExtension provider (needs a signed system extension). getpeername with an AF_SYSTEM check is the method WireGuard's Apple client uses on the same fd.

Changelog

none


Autofix with [code]smith
Open in [code]smith · Need help on this PR? Tag @codesmith-bot with what you need.


Summary by cubic

Fixes a macOS test flake in cmux-wg-tun where a socketpair could be mistaken for a utun interface. The utun name query (level SYSPROTO_CONTROL, option UTUN_OPT_IFNAME) is also LOCAL_PEERPID on a local socket, so a socketpair answered it with this process's pid as 4 bytes, which read as an ASCII "name" roughly half the time — making the result pid-dependent and flaky between runs.

Now a kernel control socket is identified by its peer address family (AF_SYSTEM via getpeername), the same check WireGuard's Apple client uses, before the interface name is queried. Adds regression tests pinning the root cause and the corrected rule.

Written for commit 9b59b8c. Summary will update on new commits.

View guided diff Turn on auto-fix

…e utun name query is LOCAL_PEERPID there)

a_socketpair_is_not_mistaken_for_utun failed in some full runs and passed alone. The
cause is not test order: on macOS, getsockopt(level 2, option 2) on a local socket
is LOCAL_PEERPID (its handler ignores the level), so a socketpair answers the utun
name query with this process's pid. nextest runs each test in its own process, so
the 4 pid bytes read as a name in about half the runs.

the_utun_name_query_answers_a_local_socket_with_its_peer_pid pins the cause (green).
is_kernel_control keeps the current rule (the fd answers the name query), so
a_socketpair_is_not_a_kernel_control_socket is red on macOS in every process. The
next commit fixes the rule.
…by the name query alone

is_kernel_control now asks getpeername for the fd's peer address family and accepts
only AF_SYSTEM (kernel control sockets), as WireGuard's Apple client does. A local
socket, which answers the utun name query with its peer pid (LOCAL_PEERPID), is no
longer read as an interface. a_socketpair_is_not_a_kernel_control_socket and
a_socketpair_is_not_mistaken_for_utun are now green in every process.
@lawrencecchen lawrencecchen added the risk:normal Risk tier (docs/ci/risk-tiers.md) label Nov 3, 2026
@github-actions

github-actions Bot commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

cmux status (one comment, edited in place; each line is updated by the job that owns it)

Review 792a09a: HQ feed card · gallery before/after runs · checks

App of this head (app.zip, kept 1 day)

gh workflow run reload-build.yml -R manaflow-ai/cmux --ref feat-cmux-next -f tag=pr34248 -f ref=base-red-wg-tun-utun-probe -f platform=macos -f backend_mode=local

red: cmux-next checks (god files, concurrency, crash safety, l10n); base red: the same failure on the base cf0fdde; does not block

Shipped in:

@lawrencecchen

Copy link
Copy Markdown
Contributor Author

Review (claude-opus-reviewer): SHIP at 792a09a

Independent review (read-only). The cause is correct: XNU's uipc_ctloutput switches on the option name only, so (2, 2) is LOCAL_PEERPID on an AF_UNIX socket, and a datagram socketpair is connected. The premise test matches the pid bytes as a 4-byte pid_t. The fix compiles on macOS and Linux (ss_family is u8 or u16, and c_int::from accepts both). A real utun answers getpeername with AF_SYSTEM, the same check WireGuard-apple makes. The red commit is red on macOS for any pid and green on Linux. The PR adds no panic-ratchet site in non-test code. Non-blocking wording note: the bytes read as a name when they are valid UTF-8 up to the first NUL, not only when they are ASCII.

@blacksmith-sh

blacksmith-sh Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Found 3 test failures on Blacksmith runners:

Failures

Test View Logs
test_every_compile_job_names_its_warm_sources (main.ThisTree.test_every_compile_job
_names_its_warm_sources)/
test_every_compile_job_names_its_warm_sources (main.ThisTree.test_every_compile_job
_names_its_warm_sources)
View Logs
test_every_listed_hook_is_one_glaeda_released_with_the_check (main.SigningHooksInSt
epWithGlaedaTests.test_every_listed_hook_is_one_glaeda_released_with_the_check)/
test_every_listed_hook_is_one_glaeda_released_with_the_check (main.SigningHooksInSt
epWithGlaedaTests.test_every_listed_hook_is_one_glaeda_released_with_the_check)
View Logs
test_the_attestation_reserves_budget_and_its_retry_shares_the_ledger (main.Workflow
Tests.test_the_attestation_reserves_budget_and_its_retry_shares_the_ledger)/
test_the_attestation_reserves_budget_and_its_retry_shares_the_ledger (main.Workflow
Tests.test_the_attestation_reserves_budget_and_its_retry_shares_the_ledger)
View Logs

Fix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

@lawrencecchen

Copy link
Copy Markdown
Contributor Author

Red and green proof at e61e5a7 (red) and 792a09a (head). Command: cmux-tui-rust-check.sh test engine::tests:: (37 tests, including a_socketpair_is_not_a_kernel_control_socket and the macOS-only the_utun_name_query_answers_a_local_socket_with_its_peer_pid).

Owned Macs (aws-m4pro):

  • RED e61e5a7 failed 5 of 5, each with FAIL engine::tests::a_socketpair_is_not_a_kernel_control_socket: 140d2532959a (m4pro-5), 0554c61d3ce7 (m4pro-5), 5bc325e4874a (m4pro-4), cb9a68a86281 (m4pro-6), a7bff49d441f (m4pro-9).
  • GREEN 792a09a passed 5 of 5 (37/37): 6b8d0dc27373 (m4pro-4), 7fe449c28fa3 (m4pro-4), e68bfb4be77e (m4pro-4), 9656273a6bb7 (m4pro-4), 30571950163a (m4pro-3).

Also on Blacksmith macOS 26.3 (not counted above): red failed 2 of 2, green passed 3 of 3.

@lawrencecchen lawrencecchen added the ready-to-land Reviewed at this head; next-autoland merges it into feat-cmux-next when its only reds are base reds label Nov 3, 2026
@cmux-bot
cmux-bot Bot temporarily deployed to ci-routing-agent November 3, 2026 23:16 Inactive
@lawrencecchen
lawrencecchen merged commit f18c96c into feat-cmux-next Nov 3, 2026
160 of 165 checks passed
@lawrencecchen
lawrencecchen deleted the base-red-wg-tun-utun-probe branch November 3, 2026 23:32
lawrencecchen added a commit that referenced this pull request Nov 4, 2026
…tions) and acpmux repo_sync_tests.rs (field_reassign_with_default) (#34733)

Both are red at the feat-cmux-next tip and hold every Rust PR's --arg all
step (for example R-INPUT's #34641, green step 5a79450ad2d0, whose own tests
passed 57 of 57):
- cmux-tui/crates/cmux-wg-tun/src/utun.rs:32: `std::mem::size_of` is in
  the prelude (unused_qualifications under -D warnings), from f18c96c
  (#34248).
- cmux-tui/crates/acpmux/src/hub/permissions/repo_sync_tests.rs:11: a field
  set right after Config::default() (clippy field_reassign_with_default),
  from bf98a75 (#34491). The fixture now builds Config with
  `..Default::default()`, as folder_profiles_tests.rs does.
No behavior change.

This branch was previously deployed

3 inactive deployments
artifacts — 9b59b8c2 Deployed Nov 3, 2026 by cmux-bot[bot] via publish tree-addressed cmux-tui #107970
sentry-dsyms — 9b59b8c2 Deployed Nov 3, 2026 by cmux-bot[bot] via upload cmux-tui dSYMs to Sentry #107970
ci-routing-agent — 9b59b8c2 Deployed Nov 3, 2026 by cmux-bot[bot] via cmux-tui tree preflight #107970
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-to-land Reviewed at this head; next-autoland merges it into feat-cmux-next when its only reds are base reds risk:normal Risk tier (docs/ci/risk-tiers.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant