RUSTSEC-2026-0386: tokio AsyncFd unsound; bump tokio and move to owned-fd constructors #255

Open
opened 2026-10-29 12:51:46 +00:00 by kayg · 16 comments
Owner

cargo deny check (part of scripts/verify fast) now fails on every branch: advisory RUSTSEC-2026-0386 (published after 2026-10-22) flags tokio 1.53.2 as unsound.

tokio::io::unix::AsyncFd provides safe constructors (new, with_interest, try_new, try_with_interest) that accept any T: AsRawFd rather than requiring proof of ownership or validity … Starting in Tokio 1.51.6, 1.53.3, and 1.54.0, these are deprecated in favor of the unsafe constructors.
Solution: upgrade to >=1.53.3.

Found by the release 9.4 → dev merge gate on the new build VM (#24, #254). It is independent of that merge: Cargo.lock is unchanged by it.

Scope

  • Bump tokio within its current minor line (1.53.2 → 1.53.3 or the latest 1.53.x patch); no other dependency moves unless the lockfile forces it.
  • Seven AsyncFd::new call sites become deprecated, and clippy runs with -D warnings:
    • crates/plugins/ssh/src/stdio.rs:38
    • crates/infraternal-agent/src/transport.rs:43
    • crates/infraternal-agent/src/sessions.rs:458, :494
    • crates/infraternal-agent/src/process_exits_linux.rs:55
    • crates/infraternal-agent/src/process_exits_macos.rs:62
    • crates/infraternal/tests/agent_sessions.rs:323
  • Move each one to the new constructor. Every unsafe block gets a // SAFETY: comment that names who owns the descriptor and why it outlives the registration. Where we can't prove ownership, restructure the type so we can (for example, hold an OwnedFd). No #[allow(deprecated)], and no ignore entry in deny.toml.
  • D243: measure both static images and ratchet the caps to the measured bytes. Growth must stay in the 16 KiB band.
  • Break-it review follows (I/O safety: descriptor reuse after close, double registration, macOS kqueue path).
`cargo deny check` (part of `scripts/verify fast`) now fails on every branch: advisory **RUSTSEC-2026-0386** (published after 2026-10-22) flags tokio 1.53.2 as unsound. > `tokio::io::unix::AsyncFd` provides safe constructors (`new`, `with_interest`, `try_new`, `try_with_interest`) that accept any `T: AsRawFd` rather than requiring proof of ownership or validity … Starting in Tokio 1.51.6, 1.53.3, and 1.54.0, these are deprecated in favor of the `unsafe` constructors. > Solution: upgrade to >=1.53.3. Found by the release 9.4 → dev merge gate on the new build VM (#24, #254). It is independent of that merge: `Cargo.lock` is unchanged by it. **Scope** - Bump tokio within its current minor line (1.53.2 → 1.53.3 or the latest 1.53.x patch); no other dependency moves unless the lockfile forces it. - Seven `AsyncFd::new` call sites become deprecated, and clippy runs with `-D warnings`: - `crates/plugins/ssh/src/stdio.rs:38` - `crates/infraternal-agent/src/transport.rs:43` - `crates/infraternal-agent/src/sessions.rs:458`, `:494` - `crates/infraternal-agent/src/process_exits_linux.rs:55` - `crates/infraternal-agent/src/process_exits_macos.rs:62` - `crates/infraternal/tests/agent_sessions.rs:323` - Move each one to the new constructor. Every `unsafe` block gets a `// SAFETY:` comment that names who owns the descriptor and why it outlives the registration. Where we can't prove ownership, restructure the type so we can (for example, hold an `OwnedFd`). No `#[allow(deprecated)]`, and no ignore entry in `deny.toml`. - D243: measure both static images and ratchet the caps to the measured bytes. Growth must stay in the 16 KiB band. - Break-it review follows (I/O safety: descriptor reuse after close, double registration, macOS kqueue path).
Author
Owner

Starting/resuming branch tokio-asyncfd-0386 at clean base f069bb2a9 (origin/merge-release94-dev). #255 and the referenced parent #254 have no comments; no previous implementation remains in this checkout.

Ownership audit: six registrations retain owned descriptors, but transport::Socket retains only a RawFd. Plan: retain a CLOEXEC duplicate for that socket and test replacement of the caller's descriptor. Keep D40's unsafe boundary in the shim: add a feature-gated, sealed registration wrapper accepting only audited owning descriptor types, with no mutable inner access; migrate the seven sites to it. This avoids weakening workspace unsafe/clippy lints and prevents safe replacement through AsyncFd::get_mut. Tokio 1.53.3 changes only its Cargo.lock entry. Dependency feature addition, registration/migration and size documentation will be separate logical commits. Known VM test exceptions remain unchanged.

Starting/resuming branch `tokio-asyncfd-0386` at clean base `f069bb2a9` (origin/merge-release94-dev). #255 and the referenced parent #254 have no comments; no previous implementation remains in this checkout. Ownership audit: six registrations retain owned descriptors, but transport::Socket retains only a RawFd. Plan: retain a CLOEXEC duplicate for that socket and test replacement of the caller's descriptor. Keep D40's unsafe boundary in the shim: add a feature-gated, sealed registration wrapper accepting only audited owning descriptor types, with no mutable inner access; migrate the seven sites to it. This avoids weakening workspace unsafe/clippy lints and prevents safe replacement through AsyncFd::get_mut. Tokio 1.53.3 changes only its Cargo.lock entry. Dependency feature addition, registration/migration and size documentation will be separate logical commits. Known VM test exceptions remain unchanged.
Author
Owner

Step 1 pushed: fc4b12c93, optional shim async-fd feature. No dependency versions moved; Tokio and nix event features already exist in the workspace. Standalone shim builds keep Tokio absent. cargo fmt --all --check and shim all-target clippy passed; shim library tests: 91 passed; 0 failed; 13 ignored. Feature tree: $HOME/.cache/codex-scratch/tokio-asyncfd-0386/evidence/shim-features.txt. Next: run the safe descriptor-replacement regression before changing transport.

Step 1 pushed: `fc4b12c93`, optional shim `async-fd` feature. No dependency versions moved; Tokio and nix event features already exist in the workspace. Standalone shim builds keep Tokio absent. `cargo fmt --all --check` and shim all-target clippy passed; shim library tests: `91 passed; 0 failed; 13 ignored`. Feature tree: `$HOME/.cache/codex-scratch/tokio-asyncfd-0386/evidence/shim-features.txt`. Next: run the safe descriptor-replacement regression before changing transport.
Author
Owner

Confirmed regression before the fix: replacing_the_callers_descriptor_cannot_redirect_registered_io fails on the old transport with BrokenPipe at transport.rs:125 after safe dup2 replaces the caller descriptor. This proves the reactor did not own the socket lifetime. The test uses no unsafe descriptor closing or guessed descriptor reuse.

The repair uses the patched unsafe constructor only inside the shim’s sealed owning wrapper. It also hides mutable access to prevent safe replacement through AsyncFd::get_mut. Socket retains a fresh CLOEXEC duplicate; existing read/write flags and wire framing stay the same. Tokio is the only version moved (1.53.2 → 1.53.3); unrelated Cargo updater rewrites of Windows dependency edges were reverted and --locked accepts the original edges.

Receipts:
red.log
dependency-gate.log
shim-features.txt

Confirmed regression before the fix: `replacing_the_callers_descriptor_cannot_redirect_registered_io` fails on the old transport with `BrokenPipe` at transport.rs:125 after safe dup2 replaces the caller descriptor. This proves the reactor did not own the socket lifetime. The test uses no unsafe descriptor closing or guessed descriptor reuse. The repair uses the patched unsafe constructor only inside the shim’s sealed owning wrapper. It also hides mutable access to prevent safe replacement through AsyncFd::get_mut. Socket retains a fresh CLOEXEC duplicate; existing read/write flags and wire framing stay the same. Tokio is the only version moved (1.53.2 → 1.53.3); unrelated Cargo updater rewrites of Windows dependency edges were reverted and --locked accepts the original edges. Receipts: [red.log](https://git.kayg.org/attachments/940e7062-09aa-4c27-8fc5-cb99d7697a6e) [dependency-gate.log](https://git.kayg.org/attachments/2e4ce8ec-d957-4fee-8e5d-b2956639f484) [shim-features.txt](https://git.kayg.org/attachments/9adf2f35-5961-4dc2-94f4-d9b05f507154)
Author
Owner

Migration validation: touched-crate all-target clippy passes with -D warnings; infraternal-agent library 69 passed; 0 failed; 7 ignored; transport integration 3 passed including the formerly failing descriptor-replacement case; real-binary agent_sessions 3 passed; shim library 91 passed; 0 failed; 13 ignored; both ownership compile-fail documentation tests pass. SSH plugin active suites passed in the targeted run.

One targeted native mouse probe failed because the ad-hoc runner lacked zig on PATH (FileNotFoundError, not a behavioral mismatch); scripts/verify sets its pinned Zig path and the probe will be rechecked there. No source or gate relaxation for this.

Read-only independent review found no concrete issues in lifetime, drop/error cleanup, descriptor replacement, or the macOS Kqueue source path. macOS execution was not performed. The safe API now prevents closing/replacing the actual registered owner; the regression replaces and then closes the caller's separate descriptor while the registered socket remains readable. No new task/timer/buffer; one CLOEXEC duplicate per inherited channel. Iteration gate running before the implementation and regression commits, then sequential static builds and exact D243 ratchet.

Migration validation: touched-crate all-target clippy passes with `-D warnings`; infraternal-agent library `69 passed; 0 failed; 7 ignored`; transport integration `3 passed` including the formerly failing descriptor-replacement case; real-binary agent_sessions `3 passed`; shim library `91 passed; 0 failed; 13 ignored`; both ownership compile-fail documentation tests pass. SSH plugin active suites passed in the targeted run. One targeted native mouse probe failed because the ad-hoc runner lacked `zig` on PATH (FileNotFoundError, not a behavioral mismatch); scripts/verify sets its pinned Zig path and the probe will be rechecked there. No source or gate relaxation for this. Read-only independent review found no concrete issues in lifetime, drop/error cleanup, descriptor replacement, or the macOS Kqueue source path. macOS execution was not performed. The safe API now prevents closing/replacing the actual registered owner; the regression replaces and then closes the caller's separate descriptor while the registered socket remains readable. No new task/timer/buffer; one CLOEXEC duplicate per inherited channel. Iteration gate running before the implementation and regression commits, then sequential static builds and exact D243 ratchet.
Author
Owner

Iteration interrupted deliberately before disk exhaustion: default workspace debug artifacts reached 34.4 GiB and free disk fell to about 8 GiB. Stopped only this run's process descendants (4035567, 4035571, 4035572, 4035573, 4078075, 4087519, 4087523); ps confirms all gone. cargo clean --profile dev under this job's CARGO_TARGET_DIR reported Removed 39323 files, 34.4GiB total; free disk recovered to 37 GiB. Evidence/logs retained.

Rerunning with CARGO_PROFILE_DEV_DEBUG=0 CARGO_PROFILE_TEST_DEBUG=0 CARGO_INCREMENTAL=0. These change only development/test debug artifacts; the tests, features, warning levels and pinned static release profile/recipe are unchanged. Final gate will use the same low-disk development/test settings. No other job's files or processes touched.

Iteration interrupted deliberately before disk exhaustion: default workspace debug artifacts reached 34.4 GiB and free disk fell to about 8 GiB. Stopped only this run's process descendants (4035567, 4035571, 4035572, 4035573, 4078075, 4087519, 4087523); ps confirms all gone. `cargo clean --profile dev` under this job's CARGO_TARGET_DIR reported `Removed 39323 files, 34.4GiB total`; free disk recovered to 37 GiB. Evidence/logs retained. Rerunning with `CARGO_PROFILE_DEV_DEBUG=0 CARGO_PROFILE_TEST_DEBUG=0 CARGO_INCREMENTAL=0`. These change only development/test debug artifacts; the tests, features, warning levels and pinned static release profile/recipe are unchanged. Final gate will use the same low-disk development/test settings. No other job's files or processes touched.
Author
Owner

Step 2 pushed: 1495c9480. Tokio 1.53.3 plus all seven constructor migrations, sealed owning registration boundary in the shim (D40), and independently owned CLOEXEC socket duplicate. No other dependency version changed; no weaker lint, deprecated allowance or advisory ignore. Bump and migration share a commit because old constructors fail clippy after the bump and the patched constructor does not exist before it.

Active requested crate suites, native mouse probe, both compile-fail ownership checks and real-binary agent_sessions (3/3) pass. A short live /proc directory handle keeps temporary test files inside this job’s scratch directory without exceeding Unix socket limits; no fixture/application changes.

Iteration result: only the two failures explicitly named in the brief (daemon timeout; process-per-user constructor SUN_LEN). Other Rust rows including cargo-deny PASS. Type/call-site inspection and read-only independent review found no additional issues; macOS execution remains untested.

iterate-lean.log
migration-gate-5.log

requested-tests-short.log

Step 2 pushed: `1495c9480`. Tokio 1.53.3 plus all seven constructor migrations, sealed owning registration boundary in the shim (D40), and independently owned CLOEXEC socket duplicate. No other dependency version changed; no weaker lint, deprecated allowance or advisory ignore. Bump and migration share a commit because old constructors fail clippy after the bump and the patched constructor does not exist before it. Active requested crate suites, native mouse probe, both compile-fail ownership checks and real-binary agent_sessions (3/3) pass. A short live /proc directory handle keeps temporary test files inside this job’s scratch directory without exceeding Unix socket limits; no fixture/application changes. Iteration result: only the two failures explicitly named in the brief (daemon timeout; process-per-user constructor SUN_LEN). Other Rust rows including cargo-deny PASS. Type/call-site inspection and read-only independent review found no additional issues; macOS execution remains untested. [iterate-lean.log](https://git.kayg.org/attachments/b757ac43-cbd1-4830-a3b2-36b109b51582) [migration-gate-5.log](https://git.kayg.org/attachments/c6abadc3-2895-4e19-bf6f-e256cbd0d347) [requested-tests-short.log](https://git.kayg.org/attachments/78525044-913d-4e5b-b648-5fa28241568e)
Author
Owner

Step 3 pushed: 371e8e81b, the separate regression-test commit. The test safely replaces the caller descriptor with dup2, supplies distinct bytes on both sockets, verifies the registration reads only the original, closes the caller, then verifies original IO again. Red receipt is above; green transport suite: 3 passed; 0 failed. Agent all-target clippy with warnings denied and fmt passed.

Both static builds are now running sequentially through the build slot with scripts/static-cargo. Original large debug outputs were removed before this phase; development/test builds use debug=0 and no incremental cache. Release settings remain pinned and unchanged.

regression-gate.log

Step 3 pushed: `371e8e81b`, the separate regression-test commit. The test safely replaces the caller descriptor with dup2, supplies distinct bytes on both sockets, verifies the registration reads only the original, closes the caller, then verifies original IO again. Red receipt is above; green transport suite: `3 passed; 0 failed`. Agent all-target clippy with warnings denied and fmt passed. Both static builds are now running sequentially through the build slot with scripts/static-cargo. Original large debug outputs were removed before this phase; development/test builds use debug=0 and no incremental cache. Release settings remain pinned and unchanged. [regression-gate.log](https://git.kayg.org/attachments/5f38b52e-4991-4f35-babc-f2d37d747464)
Author
Owner

First static image measured at head 371e8e81b: x86_64-unknown-linux-musl = 21,386,512 bytes, −2,912 bytes versus the supplied merged base f069bb2a9 (21,389,424). file reports static-pie linked and stripped. SHA-256 c3aba4dc538d0cba60df8dff605aa4c3133ba71b2501a9501836a8992cdfc447.

Recipe: scripts/static-cargo build --locked --release --package infraternal --target x86_64-unknown-linux-musl, through build-slot on 8by64-compute02; release profile unchanged. Receipt in $HOME/.cache/codex-scratch/tokio-asyncfd-0386/evidence/static-build.log. The aarch64 build began only after x86_64 completed. Both exact caps will be updated together once the second image is measured.

First static image measured at head `371e8e81b`: x86_64-unknown-linux-musl = **21,386,512 bytes**, **−2,912 bytes** versus the supplied merged base `f069bb2a9` (21,389,424). `file` reports static-pie linked and stripped. SHA-256 `c3aba4dc538d0cba60df8dff605aa4c3133ba71b2501a9501836a8992cdfc447`. Recipe: `scripts/static-cargo build --locked --release --package infraternal --target x86_64-unknown-linux-musl`, through build-slot on 8by64-compute02; release profile unchanged. Receipt in `$HOME/.cache/codex-scratch/tokio-asyncfd-0386/evidence/static-build.log`. The aarch64 build began only after x86_64 completed. Both exact caps will be updated together once the second image is measured.
Author
Owner

Step 4 pushed: 05a9d872db11234d54a95423f05d8169d818a29b. Both static ceilings and the PROCESS table now use the exact measured bytes, with a paragraph recording this repair (D243). Pinned recipe, sequential builds on 8by64-compute02; both images stripped and static.

Target Merged base f069bb2a9 Patched Delta
x86_64 musl 21,389,424 21,386,512 −2,912
aarch64 musl 19,562,168 19,563,608 +1,440

No increase above 16 KiB. Exact-cap acceptance, cap+1 rejection, shrink-ratchet rejection and unsupported-target rejection all pass. Final scripts/verify fast is running on this head through build-slot with the required CARGO_TARGET_DIR; no more source changes planned.

static-build.log
size-gate.log

Step 4 pushed: `05a9d872db11234d54a95423f05d8169d818a29b`. Both static ceilings and the PROCESS table now use the exact measured bytes, with a paragraph recording this repair (D243). Pinned recipe, sequential builds on 8by64-compute02; both images stripped and static. | Target | Merged base f069bb2a9 | Patched | Delta | | --- | ---: | ---: | ---: | | x86_64 musl | 21,389,424 | 21,386,512 | −2,912 | | aarch64 musl | 19,562,168 | 19,563,608 | +1,440 | No increase above 16 KiB. Exact-cap acceptance, cap+1 rejection, shrink-ratchet rejection and unsupported-target rejection all pass. Final `scripts/verify fast` is running on this head through build-slot with the required CARGO_TARGET_DIR; no more source changes planned. [static-build.log](https://git.kayg.org/attachments/a981fc26-8d9c-4f89-9b1c-35fc702a8089) [size-gate.log](https://git.kayg.org/attachments/13aaf678-037e-4373-9b6f-829b2f201e9f)
Author
Owner

Finished at pushed head 05a9d872db11234d54a95423f05d8169d818a29b on tokio-asyncfd-0386 (base f069bb2a9). Four atomic commits: optional dependency feature fc4b12c93, ownership repair and Tokio 1.53.3 1495c9480, red/green regression 371e8e81b, exact size ratchet/docs 05a9d872d. Worktree clean; no deployment.

Static target Merged base bytes Patched bytes / exact cap Delta bytes
x86_64 musl 21,389,424 21,386,512 −2,912
aarch64 musl 19,562,168 19,563,608 +1,440

Pinned sequential static recipe; both stripped, static, no PT_INTERP. Final artifact hashes equal the measurement receipts above. Native x86_64 key memory: Key memory initialization=1; locked pages and dump exclusion enabled. Aarch64 runtime and macOS execution were not performed.

Required head gate: scripts/verify fast, through /usr/local/bin/build-slot.sh, with CARGO_TARGET_DIR=$HOME/.cache/codex-scratch/tokio-asyncfd-0386/target. Development/test debug information and incremental caching disabled for disk usage; release recipe unchanged. A live directory handle supplied a short TMPDIR resolving into this job's scratch directory.

Exit 1 solely for the documented real_binary_preserves_input_and_output_across_24_abrupt_stops timeout. The other named VM test, session_constructor_retains_only_the_bound_socket_path, PASS in this final run (the earlier iteration hit SUN_LEN; its code is unchanged). Final shim process-per-user suite: 199 passed, 0 failed, 19 ignored.

The final inode-reuse fixture returned this documented skip; it executed and passed during the earlier iteration:

INODE_REUSE_SKIPPED: the filesystem did not reuse a released inode during 256 replacement attempts
test result: ok. 0 passed; 0 failed; 1 ignored

Verbatim final Rust gate output:

+---------------------------+--------------+
| Rust gate                 | Result       |
+---------------------------+--------------+
| fmt                       | PASS         |
| VT native fmt             | PASS         |
| CLI plugin compile-out    | PASS         |
| clippy                    | PASS         |
| SSH runtime test helper   | PASS         |
| test                      | FAIL (101)   |
| SSH inode reuse fixture   | PASS         |
| shim process-per-user     | PASS         |
| cargo-deny                | PASS         |
| static builds             | PASS         |
+---------------------------+--------------+

Because the Rust failure stops the dispatcher before TypeScript, ts_verify_fast was run separately on this same head through the build slot: exit 0. Metadata 2/2, tracer suites 356/356, connection suites 105/105, terminal-query suites 17/17, protocol suites 39/39; compiler, production build and transfer-size checks PASS.

Full unmodified gate transcripts:
final-fast.log
final-ts.log

Author checklist: all seven sites migrated; registered owners remain open/stable until deregistration; mutable owner and raw guard access hidden; inherited socket retains its own atomic CLOEXEC duplicate; unsafe blocks confined to the audited shim with SAFETY comments; other workspace unsafe/clippy settings unchanged; no deprecated allowances/advisory ignores; no other dependency version moved. Requested active agent/shim/SSH suites, both compile-fail ownership checks and real-binary session tests passed (receipts above). Independent read-only lifetime review found no concrete issues. No parser/auth/CLI/UI contract change.

Cleanup: no processes executing this job's target artifacts remained; cargo clean removed 7.9 GiB; target and temporary directory are gone; no baseline worktree was created. Evidence retained outside the checkout:
cleanup.log

Finished at pushed head `05a9d872db11234d54a95423f05d8169d818a29b` on `tokio-asyncfd-0386` (base `f069bb2a9`). Four atomic commits: optional dependency feature `fc4b12c93`, ownership repair and Tokio 1.53.3 `1495c9480`, red/green regression `371e8e81b`, exact size ratchet/docs `05a9d872d`. Worktree clean; no deployment. | Static target | Merged base bytes | Patched bytes / exact cap | Delta bytes | | --- | ---: | ---: | ---: | | x86_64 musl | 21,389,424 | 21,386,512 | −2,912 | | aarch64 musl | 19,562,168 | 19,563,608 | +1,440 | Pinned sequential static recipe; both stripped, static, no PT_INTERP. Final artifact hashes equal the measurement receipts above. Native x86_64 key memory: `Key memory initialization=1; locked pages and dump exclusion enabled`. Aarch64 runtime and macOS execution were not performed. Required head gate: `scripts/verify fast`, through `/usr/local/bin/build-slot.sh`, with `CARGO_TARGET_DIR=$HOME/.cache/codex-scratch/tokio-asyncfd-0386/target`. Development/test debug information and incremental caching disabled for disk usage; release recipe unchanged. A live directory handle supplied a short TMPDIR resolving into this job's scratch directory. Exit **1** solely for the documented `real_binary_preserves_input_and_output_across_24_abrupt_stops` timeout. The other named VM test, `session_constructor_retains_only_the_bound_socket_path`, **PASS** in this final run (the earlier iteration hit SUN_LEN; its code is unchanged). Final shim process-per-user suite: **199 passed, 0 failed, 19 ignored**. The final inode-reuse fixture returned this documented skip; it executed and passed during the earlier iteration: ``` INODE_REUSE_SKIPPED: the filesystem did not reuse a released inode during 256 replacement attempts test result: ok. 0 passed; 0 failed; 1 ignored ``` Verbatim final Rust gate output: ``` +---------------------------+--------------+ | Rust gate | Result | +---------------------------+--------------+ | fmt | PASS | | VT native fmt | PASS | | CLI plugin compile-out | PASS | | clippy | PASS | | SSH runtime test helper | PASS | | test | FAIL (101) | | SSH inode reuse fixture | PASS | | shim process-per-user | PASS | | cargo-deny | PASS | | static builds | PASS | +---------------------------+--------------+ ``` Because the Rust failure stops the dispatcher before TypeScript, `ts_verify_fast` was run separately on this same head through the build slot: **exit 0**. Metadata 2/2, tracer suites 356/356, connection suites 105/105, terminal-query suites 17/17, protocol suites 39/39; compiler, production build and transfer-size checks PASS. Full unmodified gate transcripts: [final-fast.log](https://git.kayg.org/attachments/065fc646-afd6-4f0b-9448-2626855f8315) [final-ts.log](https://git.kayg.org/attachments/983267f4-7427-4cbc-9966-1e352f5956cf) Author checklist: all seven sites migrated; registered owners remain open/stable until deregistration; mutable owner and raw guard access hidden; inherited socket retains its own atomic CLOEXEC duplicate; unsafe blocks confined to the audited shim with SAFETY comments; other workspace unsafe/clippy settings unchanged; no deprecated allowances/advisory ignores; no other dependency version moved. Requested active agent/shim/SSH suites, both compile-fail ownership checks and real-binary session tests passed (receipts above). Independent read-only lifetime review found no concrete issues. No parser/auth/CLI/UI contract change. Cleanup: no processes executing this job's target artifacts remained; `cargo clean` removed 7.9 GiB; target and temporary directory are gone; no baseline worktree was created. Evidence retained outside the checkout: [cleanup.log](https://git.kayg.org/attachments/55dddd82-7f57-4f13-980a-1a376d0f1c9b)
Author
Owner

Independent verification review started. Local branch review-tokio-asyncfd-0386, detached review target/base 05a9d872db11234d54a95423f05d8169d818a29b; merge base with origin/dev is 81962ab09a84384abcf1a58814e377ca71e781a4. The merge-base diff includes the release 9.4 integration at f069bb2a9; ownership review focuses on all seven #255 migrations and their surrounding lifecycle/error paths. No implementation changes. Logs and findings are under $HOME/.cache/codex-scratch/review-tokio-asyncfd-0386/.

Independent verification review started. Local branch `review-tokio-asyncfd-0386`, detached review target/base `05a9d872db11234d54a95423f05d8169d818a29b`; merge base with origin/dev is `81962ab09a84384abcf1a58814e377ca71e781a4`. The merge-base diff includes the release 9.4 integration at f069bb2a9; ownership review focuses on all seven #255 migrations and their surrounding lifecycle/error paths. No implementation changes. Logs and findings are under `$HOME/.cache/codex-scratch/review-tokio-asyncfd-0386/`.
Author
Owner

Source/dependency audit complete on unchanged target 05a9d872d: all seven migrations retain an owning Registration; pinned Tokio deregisters before dropping its source. Verified nix 0.30.1 Inotify/Epoll/Kqueue storage and shared-reference APIs, including macOS kqueue error/early-return and process-exit paths. No mutable owner or raw reactor guard is exposed. Socket duplication uses atomic F_DUPFD_CLOEXEC and failed registration drops its duplicate. Cargo.lock changes only Tokio version/checksum plus the shim dependency edge; deny.toml unchanged; no deprecated allowance added. No confirmed finding. macOS runtime remains unexecuted. Full head gate is running; five independent lifecycle scenarios are prepared for the review branch.

Source/dependency audit complete on unchanged target 05a9d872d: all seven migrations retain an owning Registration; pinned Tokio deregisters before dropping its source. Verified nix 0.30.1 Inotify/Epoll/Kqueue storage and shared-reference APIs, including macOS kqueue error/early-return and process-exit paths. No mutable owner or raw reactor guard is exposed. Socket duplication uses atomic F_DUPFD_CLOEXEC and failed registration drops its duplicate. Cargo.lock changes only Tokio version/checksum plus the shim dependency edge; deny.toml unchanged; no deprecated allowance added. No confirmed finding. macOS runtime remains unexecuted. Full head gate is running; five independent lifecycle scenarios are prepared for the review branch.
Author
Owner

Independent review evidence pushed on review-tokio-asyncfd-0386 at 5949b6b8b7c37bbbee9c4fbc2ff7aebe02eb9a6b. owned_readiness_lifecycle_review passes: 128 owner/error cycles with unchanged descriptor census, 64 explicit descriptor-number reuses while the old description remains open, CLOEXEC/invalid-fd checks, and real pidfd readiness after original-owner drop. Shim all-target clippy (async-fd, -D warnings), fmt and both ownership compile-fail documentation checks pass. No confirmed finding. Job-head static images independently reproduce exactly 21,386,512 / 19,563,608 bytes; static gate PASS.

Independent review evidence pushed on review-tokio-asyncfd-0386 at `5949b6b8b7c37bbbee9c4fbc2ff7aebe02eb9a6b`. `owned_readiness_lifecycle_review` passes: 128 owner/error cycles with unchanged descriptor census, 64 explicit descriptor-number reuses while the old description remains open, CLOEXEC/invalid-fd checks, and real pidfd readiness after original-owner drop. Shim all-target clippy (`async-fd`, `-D warnings`), fmt and both ownership compile-fail documentation checks pass. No confirmed finding. Job-head static images independently reproduce exactly 21,386,512 / 19,563,608 bytes; static gate PASS.
Author
Owner

Independent transport evidence pushed at a49eb72e316e1031d95f270dc64c51fb2b718c20 on review-tokio-asyncfd-0386. inherited_socket_lifecycle_review passes: two registrations of one caller socket retain separate owners; safe caller dup2/close cannot redirect reads or writes; dropping one registration preserves the other; final drop produces EOF; 128 failed registrations release duplicates and preserve the caller. Original transport suite 3/3, infraternal-agent library 69/69 active, SSH active suites, and real-binary agent_sessions 3/3 pass. Affected all-target clippy with warnings denied and fmt pass. No implementation changes or confirmed findings. Final review-branch fast gate running; baseline fixture/size comparison follows.

Independent transport evidence pushed at `a49eb72e316e1031d95f270dc64c51fb2b718c20` on review-tokio-asyncfd-0386. `inherited_socket_lifecycle_review` passes: two registrations of one caller socket retain separate owners; safe caller dup2/close cannot redirect reads or writes; dropping one registration preserves the other; final drop produces EOF; 128 failed registrations release duplicates and preserve the caller. Original transport suite 3/3, infraternal-agent library 69/69 active, SSH active suites, and real-binary agent_sessions 3/3 pass. Affected all-target clippy with warnings denied and fmt pass. No implementation changes or confirmed findings. Final review-branch fast gate running; baseline fixture/size comparison follows.
Author
Owner

Verdict: merge. Confirmed findings: P0=0, P1=0, P2=0, P3=0.

Reviewed target 05a9d872db11234d54a95423f05d8169d818a29b against merge base 81962ab09a84384abcf1a58814e377ca71e781a4 with origin/dev. That diff includes the prior release 9.4 integration at f069bb2a9; the four #255 commits follow it. Evidence is pushed only to review-tokio-asyncfd-0386, head a49eb72e31, in two test-only commits (5949b6b8b, a49eb72e3). No implementation changes.

All seven migrated sites were audited through normal, error, early-return and drop paths. Verified Tokio's deregister-before-owner-drop implementation and the pinned nix owners, including Kqueue and process-exit watching. Mutable owners and raw readiness guards do not escape. Only Tokio changes dependency version; the shim adds its existing dependency edge. No deprecated allowance, advisory ignore or contract change. The standalone shim tree contains no Tokio without async-fd.

Both new review tests pass across five scenarios: 128 owner/error cycles with zero descriptor growth; 64 reuses of a former registered number while the old description stays open; pidfd readiness after original-owner drop; independent registrations and bidirectional IO after caller dup2/close; and 128 failed inherited registrations without retained duplicates. Both compile-fail ownership checks pass. Affected all-target clippy with warnings denied, fmt, original transport 3/3, agent library 69 active, SSH active suites, and real-binary agent_sessions 3/3 pass. Separate ts_verify_fast: exit 0 (metadata 2, tracer 356, connection 105, terminal-query 17, protocol 39 tests; compiler/build/transfer checks pass).

Both static artifacts independently reproduce 21,386,512 / 19,563,608 bytes (x86_64 / aarch64), exactly matching both caps. Same-recipe stripped static x86_64 merge-base rebuild: 21,389,232 bytes, so the reviewed image is 2,720 bytes smaller. Recipe for both sources: scripts/static-cargo build --locked --release --package infraternal --target x86_64-unknown-linux-musl, through build-slot with the prescribed target directory and unchanged release settings. Static linkage/cap checks and native locked-key-memory check pass. macOS and aarch64 runtime execution were not performed; macOS ownership was source-audited.

Required scripts/verify fast on the untouched job head: exit 1. Repeated on the pushed review head with the same outcome. Both used build-slot, the prescribed target directory, development/test debug=0 and incremental=0; release settings unchanged. Verbatim Rust gate output from the job head:

+---------------------------+--------------+
| Rust gate                 | Result       |
+---------------------------+--------------+
| fmt                       | PASS         |
| VT native fmt             | PASS         |
| CLI plugin compile-out    | PASS         |
| clippy                    | PASS         |
| SSH runtime test helper   | PASS         |
| test                      | FAIL (101)   |
| SSH inode reuse fixture   | PASS         |
| shim process-per-user     | FAIL (101)   |
| cargo-deny                | PASS         |
| static builds             | PASS         |
+---------------------------+--------------+

The test row reproduces the daemon timeout explicitly excluded by the brief. Its captured argv uses the configured scratch target; this run does not establish the brief's suggested path explanation. The process-per-user row fails only session_constructor_retains_only_the_bound_socket_path with path must be shorter than SUN_LEN. Its source is byte-identical to the merge base, where the exact targeted test also exits 101 with that error: the fixture path reaches 108 bytes with seven-digit PIDs. Neither is counted as a #255 finding. Full transcripts are attached below; TypeScript ran separately because the Rust failure stops the dispatcher.

Cleanup verified: no live processes executing this review's target artifacts, target directory deleted, temporary baseline worktree removed, review worktree clean, local head equals pushed head. No deployment; issue remains open.

fast.log
review-fast.log
targeted.log
ts.log
audit-checklist.txt
baseline-constructor.log
baseline-classification.txt

baseline-static.log
size-summary.txt
cleanup.log
findings.md

Verdict: **merge**. Confirmed findings: **P0=0, P1=0, P2=0, P3=0**. Reviewed target `05a9d872db11234d54a95423f05d8169d818a29b` against merge base `81962ab09a84384abcf1a58814e377ca71e781a4` with origin/dev. That diff includes the prior release 9.4 integration at `f069bb2a9`; the four #255 commits follow it. Evidence is pushed only to `review-tokio-asyncfd-0386`, head **a49eb72e316e1031d95f270dc64c51fb2b718c20**, in two test-only commits (`5949b6b8b`, `a49eb72e3`). No implementation changes. All seven migrated sites were audited through normal, error, early-return and drop paths. Verified Tokio's deregister-before-owner-drop implementation and the pinned nix owners, including Kqueue and process-exit watching. Mutable owners and raw readiness guards do not escape. Only Tokio changes dependency version; the shim adds its existing dependency edge. No deprecated allowance, advisory ignore or contract change. The standalone shim tree contains no Tokio without async-fd. Both new review tests pass across five scenarios: 128 owner/error cycles with zero descriptor growth; 64 reuses of a former registered number while the old description stays open; pidfd readiness after original-owner drop; independent registrations and bidirectional IO after caller dup2/close; and 128 failed inherited registrations without retained duplicates. Both compile-fail ownership checks pass. Affected all-target clippy with warnings denied, fmt, original transport 3/3, agent library 69 active, SSH active suites, and real-binary agent_sessions 3/3 pass. Separate `ts_verify_fast`: exit 0 (metadata 2, tracer 356, connection 105, terminal-query 17, protocol 39 tests; compiler/build/transfer checks pass). Both static artifacts independently reproduce **21,386,512 / 19,563,608 bytes** (x86_64 / aarch64), exactly matching both caps. Same-recipe stripped static x86_64 merge-base rebuild: **21,389,232 bytes**, so the reviewed image is **2,720 bytes smaller**. Recipe for both sources: `scripts/static-cargo build --locked --release --package infraternal --target x86_64-unknown-linux-musl`, through build-slot with the prescribed target directory and unchanged release settings. Static linkage/cap checks and native locked-key-memory check pass. macOS and aarch64 runtime execution were not performed; macOS ownership was source-audited. Required `scripts/verify fast` on the untouched job head: **exit 1**. Repeated on the pushed review head with the same outcome. Both used build-slot, the prescribed target directory, development/test debug=0 and incremental=0; release settings unchanged. Verbatim Rust gate output from the job head: ``` +---------------------------+--------------+ | Rust gate | Result | +---------------------------+--------------+ | fmt | PASS | | VT native fmt | PASS | | CLI plugin compile-out | PASS | | clippy | PASS | | SSH runtime test helper | PASS | | test | FAIL (101) | | SSH inode reuse fixture | PASS | | shim process-per-user | FAIL (101) | | cargo-deny | PASS | | static builds | PASS | +---------------------------+--------------+ ``` The test row reproduces the daemon timeout explicitly excluded by the brief. Its captured argv uses the configured scratch target; this run does not establish the brief's suggested path explanation. The process-per-user row fails only `session_constructor_retains_only_the_bound_socket_path` with `path must be shorter than SUN_LEN`. Its source is byte-identical to the merge base, where the exact targeted test also exits 101 with that error: the fixture path reaches 108 bytes with seven-digit PIDs. Neither is counted as a #255 finding. Full transcripts are attached below; TypeScript ran separately because the Rust failure stops the dispatcher. Cleanup verified: no live processes executing this review's target artifacts, target directory deleted, temporary baseline worktree removed, review worktree clean, local head equals pushed head. No deployment; issue remains open. [fast.log](https://git.kayg.org/attachments/c8d1d24a-90e6-46ef-93e1-5ff2f304e282) [review-fast.log](https://git.kayg.org/attachments/891b7253-9888-4b3d-9351-fe51b00b373b) [targeted.log](https://git.kayg.org/attachments/afaf666d-dc79-4c9c-96c6-683fa8c99a15) [ts.log](https://git.kayg.org/attachments/99d8ca68-92af-4169-865b-39f7f82e68ec) [audit-checklist.txt](https://git.kayg.org/attachments/36f0a900-5edf-414b-9b16-6aec0bea7bbe) [baseline-constructor.log](https://git.kayg.org/attachments/f85dafa2-5182-4b55-80e2-a834df5c36f1) [baseline-classification.txt](https://git.kayg.org/attachments/a8c8cfbe-5c65-4788-8512-46f7e239ccc0) [baseline-static.log](https://git.kayg.org/attachments/e886e963-0ed9-4452-8e7f-c1fe08ceaf1a) [size-summary.txt](https://git.kayg.org/attachments/e007ef61-5691-4513-83d1-028579ab61de) [cleanup.log](https://git.kayg.org/attachments/54f133de-a35f-47d9-8f94-d9a3f76d3b2c) [findings.md](https://git.kayg.org/attachments/a3c05a99-e9da-430b-b241-f351a3df71fd)
Author
Owner

Landed on dev in 4a6202a52 (fast-forward, together with the release 9.4 back-merge and test-only fixes). Review verdict: merge, 0 findings. scripts/verify fast on dev: PASS, exit 0.

Landed on dev in `4a6202a52` (fast-forward, together with the release 9.4 back-merge and test-only fixes). Review verdict: merge, 0 findings. `scripts/verify fast` on dev: PASS, exit 0.
Sign in to join this conversation.
No labels
launch-qa
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kayg/infraternal#255
No description provided.