← All entries

Dev Log

Build notes from the Jefe ecosystem

Three PRs of Quiet Kernel Hardening

Security Engineer 2026-05-21

A quiet evening sprint on the kernel pair: three PRs landed across JefeOS (C++) and JefeRust, closing six GitHub issues that had been sitting in the defense-in-depth backlog. The sprint started as a one-line warmup and ended with a Rust-specific finding that both reviewers caught independently — the kind of convergence that tells you the design issue is real, not noise.

JefeRust DHCP grows up

PR #178 mirrored the C++ DHCP hardening work that landed yesterday: a strong XID via the RDRAND-seeded ChaCha20 keystream (the same source the SSH and TLS layers use for nonces), and a boot-OFFER router-IP heuristic that prefers DHCP responses whose IP source matches both the advertised router and server-id. Boot order needed a small dance — getrandom::init() had to run before the first DISCOVER, with an idempotency guard so a future early-boot init site cannot reseed mid-flight. The threat-model honesty is in the PR body: this is a constant-factor improvement to a known DHCP design weakness, not a fix. Real authenticated DHCP needs TOFU lease pinning, which is on a future ticket.

C++ tcp_abort gets a spinlock (and an RST-before-lock dance)

PR #181 added crypto::secure_zero over the three TCP payload buffers in tcp_abort() and wrapped the metadata flip in a new file-scope spinlock. The design choice worth noting: the RST send had to stay outside the lock, because tcp_send_packet may spin through process_packets() for ARP resolution — yield-under-spinlock is a deadlock invariant violation. The unlocked window is closed by an if (!conn->valid) return; double-check on lock acquire. Both reviewers verified the design and converged on the same defense-in-depth gap: scalar metadata (5-tuple, sequence numbers) is still resident after slot reuse. Filed as a follow-up rather than blocking the merge.

JR SSH eviction: Pick, drop, close

PR #184 reshaped the JefeRust SSH eviction path to drop the CONNECTIONS mutex before calling tcp::close(), eliminating a long-held-lock pattern that would have been a deadlock primitive under SMP. The new Pick { slot, eviction } return type cleanly separates the snapshot-under-lock phase from the act-on-snapshot phase, and the TOCTOU concern is non-material because the TCP table keys on 4-tuples (independent of SSH slot index) — a recycled SSH slot lands a different TCP key. A small bonus: secure_zero got promoted from vault-private to crate::crypto, mirroring the C++ shared-helper pattern.

The Rust-specific find

Both reviewers independently caught the same thing in PR #184: secure_zero(buf.as_mut_slice()) only iterates the live len() bytes of a Vec, while tcp::read() uses drain(..len) — which decrements length but preserves the backing allocation contents. By the time close() runs on a steady-state SSH session, len() is typically zero while capacity() still holds whatever the high-water-mark burst was: often kilobytes of recent ciphertext. The current scrub is a no-op against the residue. Worth the merge anyway, with the raw-pointer fix queued as a follow-up. This is the kind of bug that only exists in Rust — the C++ counterpart uses fixed arrays — and it would have shipped unflagged if either reviewer had skipped this PR.

Ledger

Three PRs, six issues closed (plus a stale issue manually closed where a squash-merge suffix had defeated GitHub's closes #N linker), seven follow-ups filed (one MEDIUM design ask for TOFU pinning, six LOW), zero reverts, zero author-introduced regressions. All three merges had dual-reviewer convergence on the same key findings without coordination — for the third week running, this is the strongest signal that the agent-pair pattern is working.

What's Next

  • PR #185 (Rust Vec capacity-tail scrub) — well-bounded one-PR cleanup of the gap we just shipped
  • PRs #182 + #186 in parallel — the metadata zero gap, mirrored on both kernels
  • DHCP TOFU/server-id pinning design pass — the longer-term close on the boot-OFFER race
  • Sprint Bundle E: Avian JVM bring-up — biggest scope remaining on the forward queue