Commit 6d9392a
riscv: stop teardown freeing shared kernel tables; wire kernel satp root
Two RISC-V process-exit memory-safety bugs surfaced by the 2026-06-03
kernel correctness review and confirmed against the code. Both are
independent of the page-table-root self-free common to x86_64 + riscv
(see "Out of scope").
What:
1. reclaim_process_page_tables (src/memory/mod.rs, the shared aarch64/
riscv arm) walked the full L0 range 0..512. On RISC-V there is no
TTBR split, so create_process_page_table copies the kernel-half
descriptors (L0[256..512]) into every user table; those point at the
shared *static* BOOT_L2_IDENTITY / BOOT_L2_KERNEL tables in
arch::riscv64::entry. Walking the upper half therefore reached those
shared tables and frame_alloc.free zero-filled them — destroying the
HHDM and kernel map that every CPU and every address space depend on
(global corruption, strictly worse than a single-process brick).
Fix: walk only the user half (0..256), matching x86_64's
paging::reclaim_process_page_tables. Harmless narrowing on AArch64
(user L0 upper half is always zero; kernel lives in TTBR1) and a
standing guard against a future kernel-half copy there.
2. kmain_riscv64 (src/microkernel/main.rs) never set the canonical
kernel page-table root, so kernel_cr3() stayed 0. The portable
scheduler substitutes kernel_cr3() as the switch hint for kernel/idle
tasks (cr3 == 0); the riscv satp reload gate skips when that hint is
0, so a kernel/idle task kept the previous user satp loaded after the
owning process exited — a use-after-free of a freed root. Fix: wire
set_kernel_cr3(boot_root_phys) from BOOT_SATP, mirroring the x86_64
(CR3) / aarch64 (TTBR1) wiring already in kmain.
Why: x86_64 and aarch64 already wire kernel_cr3() and already walk the
user half only; RISC-V was the lone gap on both. Found while
adversarially verifying the deferred-reclaim design across all three
arches.
Out of scope: the active-root self-free common to x86_64 and RISC-V (a
dying task frees + zeroes the page-table root still loaded in its own
CR3/satp before it yields). That is the deferred-reclaim mechanism,
landing next. After this commit RISC-V process exit still bricks on that
common path; what changes is that the catastrophic *global* HHDM
corruption (bug 1) and the satp UAF (bug 2) are gone.
Verification:
- make check-all: x86_64 + aarch64 + riscv64 build cleanly.
- check-assumptions / check-deferrals / check-unsafe-coverage: pass.
The two baseline files carry only line-number resyncs for the 3
(assumptions) + 8 (deferrals) pre-existing entries my added comments
shifted; no new bounds or deferrals introduced.
- Not boot-tested under QEMU: riscv boot-smoke is not yet in CI, and
riscv process exit still bricks on the common active-root self-free
above, so a boot would not yet demonstrate a clean exit. Verified by
code inspection + the tri-arch build.
Staged files:
src/memory/mod.rs
src/microkernel/main.rs
tools/check-assumptions-baseline.txt
tools/check-deferrals-baseline.txt
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>1 parent 514fad9 commit 6d9392a
4 files changed
Lines changed: 43 additions & 12 deletions
File tree
- src
- memory
- microkernel
- tools
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
419 | 419 | | |
420 | 420 | | |
421 | 421 | | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
422 | 437 | | |
423 | 438 | | |
424 | 439 | | |
| |||
435 | 450 | | |
436 | 451 | | |
437 | 452 | | |
438 | | - | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
439 | 457 | | |
440 | 458 | | |
441 | 459 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
681 | 681 | | |
682 | 682 | | |
683 | 683 | | |
| 684 | + | |
| 685 | + | |
| 686 | + | |
| 687 | + | |
| 688 | + | |
| 689 | + | |
| 690 | + | |
| 691 | + | |
| 692 | + | |
| 693 | + | |
| 694 | + | |
| 695 | + | |
| 696 | + | |
684 | 697 | | |
685 | 698 | | |
686 | 699 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
318 | 318 | | |
319 | 319 | | |
320 | 320 | | |
321 | | - | |
322 | | - | |
323 | | - | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
324 | 324 | | |
325 | 325 | | |
326 | 326 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
87 | 87 | | |
88 | 88 | | |
89 | 89 | | |
90 | | - | |
91 | | - | |
92 | | - | |
93 | | - | |
94 | | - | |
95 | | - | |
96 | | - | |
97 | | - | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
98 | 98 | | |
99 | 99 | | |
100 | 100 | | |
| |||
0 commit comments