Fix SkHermesMessage payload-aliasing defect (task 3.8 findings log)

sk_hermes_send_one() -- the single funnel every sender, including
sk_hermes_publish(), already goes through -- used to store the
caller's own payload_addr pointer as-is. Two sends before either
drains meant both messages pointed at the same caller-owned buffer,
whichever send wrote last silently winning: real, confirmed live (a
second identity thumbdrive attached at boot alongside Zuse's own left
its WIREBIND pairing silently never happening).

SkHermesMessage gains an inline payload_buf[SK_HERMES_CHUNK_MAX_
PAYLOAD] field; sk_hermes_send_one() now memcpy()s the caller's
payload into it and points payload_addr at that copy instead. No
sender or reader call site needed to change -- every existing reader
already only ever reads through payload_addr, which still points at
valid bytes of the same length, now message-owned. g_kh_blk_attach_buf/
g_kh_console_cmd_buf (repl.c, tasks 3.8/3.9) no longer need to survive
past their own send call; their doc comments, which had claimed the
old aliasing shape was benign, are corrected.

Verified the original bug is actually gone: reproduced the exact
original scenario (a real, sequentially-minted rajames identity
attached at boot alongside Zuse's own, two simultaneous BLK-ATTACH-
EVENT sends in one idle-loop pass) -- WIREBIND pairing, USE, and the
Stage D relay all now work where WIREBIND previously silently failed.
Standard three-ISA acceptance also clean: zero UNKNOWN WORD, dict_hash
identical across all three and matching every prior acceptance run in
this document.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Robert Allan James
2026-09-22 14:16:29 -04:00
co-authored by Claude Sonnet 5
parent 21734b1a52
commit 5c07745c18
14 changed files with 46639 additions and 35 deletions
+37
View File
@@ -1323,6 +1323,43 @@ kept as the reproduction — a second identity drive attached at boot is what ex
default single-drive boot this whole document's other acceptance runs used never will. Task 3.9
is paused pending Captain Bob's decision on when this gets fixed.
**2026-09-22 — CLOSED.** Captain Bob's own instruction, after 3.9/prompt-format both landed:
"finish the work" before cleanup/3.10. Fixed exactly as scoped above — `SkHermesMessage`
(`kernel_hermes.h`) gained an inline `payload_buf[SK_HERMES_CHUNK_MAX_PAYLOAD]` field;
`sk_hermes_send_one()` (`kernel_hermes.c`, the single funnel every sender/`sk_hermes_publish()`
already goes through) now `memcpy()`s the caller's payload into it and points `payload_addr` at
that copy, instead of storing the caller's own pointer. No sender or reader call site needed to
change — every existing reader (`sk_hermes_drain_checkpoint()`, `sk_hermes_reassemble()`) already
only ever reads through `payload_addr`, which still points at valid bytes of the same length,
now message-owned. `g_kh_blk_attach_buf`/`g_kh_console_cmd_buf` (`repl.c`, tasks 3.8/3.9) no
longer need to survive past their own send call — their doc comments corrected accordingly;
left `static` as a harmless convenience, not changed to stack-local (out of this fix's own
scope).
**Verified the original bug is actually gone, not just no-longer-observed.** Reproduced the exact
original scenario — `S" Captain Bob"...MINT`'d a real `rajames` identity sequentially first
(so both devices are genuinely eligible, not one blank/one real), then rebooted with `rajames`'s
now-minted drive attached at launch alongside Zuse's own (`QEMU_EXTRA`, port 2), reproducing two
simultaneous `BLK-ATTACH-EVENT` sends in one idle-loop pass before either drains
(`logs/20260922-140405/amd64/`: `ledger held=4096`, the same two-admission signature the original
bug's own log showed). **Before this fix, that scenario left `rajames`'s own WIREBIND pairing
silently never happening** (`FABRIC-3.6.md`'s own earlier finding: `S" bob" USE` returned `USE:
bob not found`). **After this fix, in the identical scenario, `WIREBIND: rajames attached and
ready` fires, `USE rajames` succeeds, and the Stage D relay still works on top of it** — confirmed
live, interactively, in that same log. `dict_hash` for Artemis differs from this document's other
acceptance runs in that one log only, expected and already-documented (task 0.0's own finding:
`disk/artemis.img` was deliberately left unreset across the two boots this reproduction needed,
so Artemis took the `resuming` branch, not `blank -- formatting`) — not a cross-architecture
divergence, since this reproduction was amd64-only by design.
Standard three-ISA acceptance (single-drive boot, disks reset before each arch, matching every
other task in this document): `logs/20260922-140634/amd64/`, `logs/20260922-140908/aarch64/`,
`logs/20260922-141236/riscv64/` — all three reach `[zuse@Hera] ok>`, zero `UNKNOWN WORD`,
`dict_hash` identical across all three and matching every prior acceptance run in this document
exactly (unaffected — the fix changes message storage, not dictionary content). Both `USE
rajames` (task 3.9's earlier finding that the documented `FABRIC-3.md §XXX` USE/BINDSTEP crash
did not reproduce, confirmed again here) and the Stage D relay verified working on all three.
**2026-09-22, out-of-band request during task 3.9's own verification — console prompt format
changed on Captain Bob's direct instruction, not a reshuffle task, no task number.** The bracket
line prefix (`console.c`'s `emit_prefix()`, unchanged) used to read