docs: the security-track execution plan — path flag-day, namespace phases, kernel hardening

The /loop work list for the committed design set: Phase 0 baseline, PM
(unix-path flag-day), H1 copy discipline, P1 envelope + Channel, P2
registry + ServiceId retirement, P3 open grants, P4a-c protocol rebase,
H2 SMEP, HS sysret guard, H3 SMAP. Ten settled decisions from the
2026-07-31 grounding pass, two corrected on review: every packet carries
the envelope header folded (headerless events rejected), and bind/open
authorization is chain-attested identity (name alone rejected — ungated
spawn makes it a confused deputy). smep-smap.md gains the verified
straggler table: nine syscalls, klog_status the ninth, with the
callee-writer restructuring notes.
This commit is contained in:
Daniel Samson
2026-07-31 19:10:23 +01:00
parent c96ef87714
commit 9a3238025d
2 changed files with 422 additions and 16 deletions
+28 -16
View File
@@ -52,26 +52,38 @@ The design is closer than it looks, because the IPC layer was built right:
- **CR4 today:** the BSP inherits firmware CR4 (no kernel write anywhere);
APs set PAE/OSFXSR/OSXMMEXCPT in `trampoline.s:62-68`. Neither path sets
SMEP/SMAP yet, and both must.
- **The stragglers.** A handful of syscalls still dereference user pointers
raw after a bounds check — every one is a SMAP #PF waiting to happen, and
- **The stragglers.** Nine syscalls still dereference user pointers raw
after a bounds check — every one is a SMAP #PF waiting to happen, and
every one is *already* a latent kernel fault today (an unmapped-but-in-
range user page oopses the kernel instead of failing the call). The audit
list, from the 2026-07-31 survey of `system/kernel/process.zig`:
range user page oopses the kernel instead of failing the call). The
verified sweep of `system/kernel/process.zig` (2026-07-31; a
whole-kernel `@ptrFromInt` audit found no user-address dereference
outside this file):
| Syscall | Raw access |
|---|---|
| `system_spawn` | name + argument blob (`:972`, `:980`) |
| `fs_resolve` | path in, result out (`:1780`, `:1797`) |
| `fs_mount` / `fs_unmount` | prefix + rewrite strings (`:1864`) |
| `fs_node` | read buffer out (`:1820`) |
| `debug_write` | message bytes (`:1700`) |
| `klog_read` | log bytes out (`:1740`) |
| `process_enumerate` | descriptor array out (`:1132`) |
| `device_enumerate` | descriptor array out (`:388`) |
| Syscall | Raw access | Direction |
|---|---|---|
| `system_spawn` | name + argument blob (`:972`, `:980`) | read |
| `fs_resolve` | path in (`:1780`), result out (`:1797`) | read + write |
| `fs_mount` | prefix + rewrite strings (`:1864`, `:1865`) | read |
| `fs_unmount` | prefix string (`:1883`) | read |
| `fs_node` | read buffer out (`:1820`) | write |
| `debug_write` | message bytes (`:1700`; read twice — memcpy `:1710` and `log.append` `:1717`) | read |
| `klog_read` | log bytes out (`:1741`) | write |
| `klog_status` | status struct out (`:1758`) | write |
| `process_enumerate` | descriptor array out (`:1132`) | write |
| `device_enumerate` | descriptor array out (`:388`) | write |
For the write-direction rows the `@ptrFromInt` is in process.zig but the
stores happen in callees (`scheduler.enumerate`
`system/kernel/scheduler.zig:1209`, `devices_broker.enumerate`
`devices-broker.zig:136`, `log.readAt` `log.zig:209`, the vfs node calls
`vfs.zig:257/269/289`) — converting them means bounce buffers plus
`copyToUser` around those calls, not just editing the process.zig lines.
(Some paths already do it right — the futex word and the device-register
descriptor go through `copyFromUser` (`:1087`, `:924`). The write
direction has no helper yet.)
direction has no public helper yet, but the mechanism exists:
`copyAcross` with a kernel source is exactly how IPC replies reach user
buffers, so `copyToUser` is a mechanical mirror.)
- **One known gap inside the copy layer itself:** the walk checks presence,
not the leaf U/S and writable bits (`ipc-synchronous.zig:20-22` flags
@@ -85,7 +97,7 @@ The design is closer than it looks, because the IPC layer was built right:
**H1 — copy discipline (the real work).** A `user-memory` kernel module:
`copyFromUser` / `copyToUser` (the missing write direction) via the physmap
walk, with U/S and writable leaf checks closing the in-tree TODO. Convert
the eight stragglers. This fixes the latent unmapped-page kernel fault on
the nine stragglers. This fixes the latent unmapped-page kernel fault on
its own — it is worth doing even if SMEP/SMAP never shipped. QEMU suite
green; no behavior change visible to correct programs.