diff options
| author | salmonik <salmonik@tuta.io> | 2026-08-02 23:28:29 +0200 |
|---|---|---|
| committer | salmonik <salmonik@tuta.io> | 2026-08-02 23:28:29 +0200 |
| commit | f846a9551bf30d61026fa9c9ccea78479ced321b (patch) | |
| tree | 10158ca300cc51f44fc9afee9c2b3092554d880b /rsdos/src | |
| parent | v0.5.7: guard reports the drop's size/align — identifies the clobbered struct (diff) | |
| download | rs-dos-f846a9551bf30d61026fa9c9ccea78479ced321b.tar.gz rs-dos-f846a9551bf30d61026fa9c9ccea78479ced321b.zip | |
v0.5.7: drop test-poison hooks; vt heap-struct verify at shell entry
The OptiPlex's first banner write #GPs when the vt cells VecData holds
firmware 0xAA fill instead of a real buffer pointer. The poison/fill
test hooks (stack + free-heap + free-page 0x00AAAAAA) were removed from
the release image — they changed boot behavior and may walk a corrupt
free list over live blocks. Added vt::debug_verify() (cells/rendered
ptr/cap/len + in-heap check) at shell entry: the next real-hardware
boot shows whether the corruption is present at shell entry or lands
during the banner write.
Diffstat (limited to 'rsdos/src')
| -rw-r--r-- | rsdos/src/main.rs | 40 |
1 files changed, 7 insertions, 33 deletions
diff --git a/rsdos/src/main.rs b/rsdos/src/main.rs index 52b37ec..42f95e5 100644 --- a/rsdos/src/main.rs +++ b/rsdos/src/main.rs | |||
| @@ -344,22 +344,13 @@ pub unsafe extern "efiapi" fn efi_main(image_handle: Handle, system_table: *mut | |||
| 344 | } else { | 344 | } else { |
| 345 | rsnix::serial_println!("cursor: no mouse — overlay disabled"); | 345 | rsnix::serial_println!("cursor: no mouse — overlay disabled"); |
| 346 | } | 346 | } |
| 347 | // TEST HOOK: reproduce the OptiPlex '0xaaaaaa' uninit-drop crash in | 347 | // Shell-entry self-check: verify the vt grid structs are sane right |
| 348 | // QEMU. The real hardware's stack carries 0xAA fill left by | 348 | // before the shell's first print. The OptiPlex crashes in the first |
| 349 | // firmware; any shell value that is dropped without being written | 349 | // banner write when the cells VecData (or the shadow) holds the |
| 350 | // then frees garbage and trips the dealloc guard. Filling the | 350 | // firmware's 0xAA fill instead of real values — this line shows |
| 351 | // shell's future stack region with 0xAA here makes the same bug | 351 | // whether the corruption is already present at shell entry or lands |
| 352 | // visible on QEMU (serial + gdb available) instead of only on the | 352 | // later, and prints the exact field values when it is. |
| 353 | // OptiPlex. | 353 | rsnix::vt::debug_verify(); |
| 354 | stack_fill_aa(); | ||
| 355 | // Poison the free heap AND the free pages with the OptiPlex's | ||
| 356 | // 0x00AAAAAA scrub pattern — the firmware's leftover fills both the | ||
| 357 | // heap (freed pool) and the pages the allocators hand out (heap | ||
| 358 | // growth, task stacks). Together with the stack fill this makes | ||
| 359 | // any uninitialized read reproduce the real machine's crashes in | ||
| 360 | // QEMU (garbage sizes → alloc panics, garbage ptrs → dealloc guard). | ||
| 361 | rsnix::memory::poison_free_blocks_aa(); | ||
| 362 | rsnix::memory::poison_free_pages_aa(); | ||
| 363 | shell::run(); | 354 | shell::run(); |
| 364 | } | 355 | } |
| 365 | 356 | ||
| @@ -368,23 +359,6 @@ pub unsafe extern "efiapi" fn efi_main(image_handle: Handle, system_table: *mut | |||
| 368 | /// headroom. 128 KiB covers the whole shell frame chain on QEMU and | 359 | /// headroom. 128 KiB covers the whole shell frame chain on QEMU and |
| 369 | /// the OptiPlex. Best-effort: the region is below rsp inside the boot | 360 | /// the OptiPlex. Best-effort: the region is below rsp inside the boot |
| 370 | /// stack mapping; the call into `shell::run` overwrites the top word. | 361 | /// stack mapping; the call into `shell::run` overwrites the top word. |
| 371 | fn stack_fill_aa() { | ||
| 372 | let rsp: usize; | ||
| 373 | unsafe { | ||
| 374 | core::arch::asm!("mov {}, rsp", out(reg) rsp); | ||
| 375 | } | ||
| 376 | let top = rsp - 0x100; | ||
| 377 | let bottom = rsp - 0x21100; | ||
| 378 | unsafe { | ||
| 379 | let mut p = bottom; | ||
| 380 | while p < top { | ||
| 381 | core::ptr::write_volatile(p as *mut u64, 0x00AAAAAA00AAAAAA); | ||
| 382 | p += 8; | ||
| 383 | } | ||
| 384 | } | ||
| 385 | rsnix::serial_println!("stack: 0x00AAAAAA-fill 0x{:x}..0x{:x}", bottom, top); | ||
| 386 | } | ||
| 387 | |||
| 388 | // --------------------------------------------------------------------------- | 362 | // --------------------------------------------------------------------------- |
| 389 | // Print a memory summary from the stashed memory map | 363 | // Print a memory summary from the stashed memory map |
| 390 | // --------------------------------------------------------------------------- | 364 | // --------------------------------------------------------------------------- |
