summaryrefslogtreecommitdiffstats
path: root/shell/src
diff options
context:
space:
mode:
authorsalmonik <salmonik@tuta.io>2026-08-02 21:47:18 +0200
committersalmonik <salmonik@tuta.io>2026-08-02 21:47:18 +0200
commit0187b802113a10a9ee99af48b811cd332c660a13 (patch)
treeb0873f7b2dcf6be1c575c8fe1919a72f041bba49 /shell/src
parentv0.5.6: fault dumps carry kernel image base + stack backtrace (diff)
downloadrs-dos-0187b802113a10a9ee99af48b811cd332c660a13.tar.gz
rs-dos-0187b802113a10a9ee99af48b811cd332c660a13.zip
v0.5.7: allocator corruption guard + full register dump for real-hardware repro
The OptiPlex #GP (vec=13 in __rust_dealloc) frees a garbage pointer: the back-pointer at [ptr-8] is clobbered by the time the shell drops its Parsed struct. A blind store to the bogus block header was an opaque #GP — now it is a readable report: - dealloc validates the back-pointer (in-heap block, sane size, in-use) before trusting it; on failure it prints ptr/block/heap range, the memory around the block header, and the live stack chain, writes the crash band + crash.log, and halts (memory.rs: heap_guard_report). - fault dumps now carry the full register set (rax..rdi, rbx, r8..r15) so the next repro shows the exact freed ptr and clobbered value. - new 'corrupt' shell hook deliberately clobbers a live block's back-pointer to prove the guard fires (test-fault-style halt). Verified: test-msg/test-disk/test-fault pass; corrupt hook reports ptr=.. block=0xdeedbeef... with mem dump instead of #GP. rs-dos.img rebuilt with the release kernel.
Diffstat (limited to 'shell/src')
-rw-r--r--shell/src/lib.rs16
1 files changed, 16 insertions, 0 deletions
diff --git a/shell/src/lib.rs b/shell/src/lib.rs
index a32d259..175a2c7 100644
--- a/shell/src/lib.rs
+++ b/shell/src/lib.rs
@@ -740,6 +740,7 @@ write `{} <path> TIL <marker>`",
740 "kill" => cmd_kill(&parsed), 740 "kill" => cmd_kill(&parsed),
741 "demo" => cmd_demo(&parsed), 741 "demo" => cmd_demo(&parsed),
742 "fault" => cmd_fault(), 742 "fault" => cmd_fault(),
743 "corrupt" => cmd_corrupt(),
743 "crashlog" => cmd_crashlog(), 744 "crashlog" => cmd_crashlog(),
744 "stall" => cmd_stall(&parsed), 745 "stall" => cmd_stall(&parsed),
745 _ => term_err(&alloc::format!("unknown command: {}", cmd)), 746 _ => term_err(&alloc::format!("unknown command: {}", cmd)),
@@ -839,6 +840,21 @@ fn cmd_fault() {
839 } 840 }
840} 841}
841 842
843/// Deliberately clobber a live heap block's back-pointer, then free it —
844/// test hook that proves the allocator's corruption guard fires with a
845/// readable report (instead of a #GP inside `__rust_dealloc`). The
846/// system stops; the log must show `!!! heap corruption in dealloc`.
847fn cmd_corrupt() {
848 term_println("corrupt: clobbering a live block's back-pointer...");
849 let s = String::from("hello heap guard");
850 let ptr = s.as_ptr() as usize;
851 unsafe {
852 *((ptr - 8) as *mut usize) = 0xdeed_beef_deed_beefusize;
853 }
854 drop(s);
855 term_println("corrupt: guard did NOT fire (unexpected)");
856}
857
842/// Debug hook: run the crash-log FAT write from the *shell* context (not 858/// Debug hook: run the crash-log FAT write from the *shell* context (not
843/// the fault ISR) to compare behaviour. 859/// the fault ISR) to compare behaviour.
844fn cmd_crashlog() { 860fn cmd_crashlog() {