b9874d0941
Add redbear-usb-storage-check in-guest binary that validates USB mass storage read and write I/O: discovers /scheme/disk/ devices, writes a test pattern to sector 2048, reads it back, verifies match, restores original content. Updates test-usb-storage-qemu.sh with write-proof verification step. Includes all accumulated Red Bear OS work: kernel patches, relibc patches, driver infrastructure, DRM/GPU, KDE recipes, firmware, validation tooling, build system hardening, and documentation.
189 lines
5.5 KiB
Diff
189 lines
5.5 KiB
Diff
diff --git a/src/lib.rs b/src/lib.rs
|
|
--- a/src/lib.rs
|
|
+++ b/src/lib.rs
|
|
@@ -57,61 +57,201 @@ pub mod start;
|
|
pub mod sync;
|
|
|
|
-use crate::platform::{Allocator, NEWALLOCATOR};
|
|
+use crate::platform::{Allocator, NEWALLOCATOR, Pal, Sys};
|
|
|
|
#[global_allocator]
|
|
static ALLOCATOR: Allocator = NEWALLOCATOR;
|
|
+
|
|
+const MAX_FATAL_BACKTRACE_FRAMES: usize = 16;
|
|
+const MAX_FATAL_FRAME_STRIDE: usize = 1024 * 1024;
|
|
+
|
|
+#[inline(never)]
|
|
+fn write_process_thread_identity(w: &mut platform::FileWriter) {
|
|
+ use core::fmt::Write;
|
|
+
|
|
+ let pid = Sys::getpid();
|
|
+ let tid = Sys::gettid();
|
|
+
|
|
+ match crate::pthread::current_thread() {
|
|
+ Some(thread) => {
|
|
+ let _ = w.write_fmt(format_args!(
|
|
+ "RELIBC CONTEXT: pid={} tid={} pthread={:#x}\n",
|
|
+ pid,
|
|
+ tid,
|
|
+ thread as *const _ as usize,
|
|
+ ));
|
|
+ }
|
|
+ None => {
|
|
+ let _ = w.write_fmt(format_args!(
|
|
+ "RELIBC CONTEXT: pid={} tid={} pthread=<unavailable>\n",
|
|
+ pid, tid,
|
|
+ ));
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+#[cfg(any(target_arch = "x86_64", target_arch = "x86", target_arch = "aarch64"))]
|
|
+#[inline(never)]
|
|
+fn current_frame_pointer() -> *const usize {
|
|
+ let frame: *const usize;
|
|
+
|
|
+ #[cfg(target_arch = "x86_64")]
|
|
+ unsafe {
|
|
+ core::arch::asm!("mov {}, rbp", out(reg) frame, options(nomem, nostack, preserves_flags));
|
|
+ }
|
|
+
|
|
+ #[cfg(target_arch = "x86")]
|
|
+ unsafe {
|
|
+ core::arch::asm!("mov {}, ebp", out(reg) frame, options(nomem, nostack, preserves_flags));
|
|
+ }
|
|
+
|
|
+ #[cfg(target_arch = "aarch64")]
|
|
+ unsafe {
|
|
+ core::arch::asm!("mov {}, x29", out(reg) frame, options(nomem, nostack, preserves_flags));
|
|
+ }
|
|
+
|
|
+ frame
|
|
+}
|
|
+
|
|
+#[cfg(any(target_arch = "x86_64", target_arch = "x86", target_arch = "aarch64"))]
|
|
+fn read_backtrace_frame(frame: *const usize) -> Option<(*const usize, usize)> {
|
|
+ let align = core::mem::align_of::<usize>();
|
|
+ let frame_addr = frame as usize;
|
|
+
|
|
+ if frame.is_null() || frame_addr % align != 0 {
|
|
+ return None;
|
|
+ }
|
|
+
|
|
+ let next_frame = unsafe { frame.read() } as *const usize;
|
|
+ let return_address = unsafe { frame.add(1).read() };
|
|
+
|
|
+ if return_address == 0 {
|
|
+ return None;
|
|
+ }
|
|
+
|
|
+ Some((next_frame, return_address))
|
|
+}
|
|
+
|
|
+#[cfg(any(target_arch = "x86_64", target_arch = "x86", target_arch = "aarch64"))]
|
|
+fn is_sane_next_backtrace_frame(current: *const usize, next: *const usize) -> bool {
|
|
+ let align = core::mem::align_of::<usize>();
|
|
+ let current_addr = current as usize;
|
|
+ let next_addr = next as usize;
|
|
+
|
|
+ !next.is_null()
|
|
+ && next_addr % align == 0
|
|
+ && next_addr > current_addr
|
|
+ && next_addr - current_addr <= MAX_FATAL_FRAME_STRIDE
|
|
+}
|
|
+
|
|
+#[inline(never)]
|
|
+fn write_best_effort_backtrace(w: &mut platform::FileWriter) {
|
|
+ use core::fmt::Write;
|
|
+
|
|
+ let _ = w.write_str("RELIBC: attempting best-effort backtrace\n");
|
|
+
|
|
+ #[cfg(any(target_arch = "x86_64", target_arch = "x86", target_arch = "aarch64"))]
|
|
+ {
|
|
+ let mut frame = current_frame_pointer();
|
|
+ let mut wrote_frame = false;
|
|
+
|
|
+ for frame_index in 0..MAX_FATAL_BACKTRACE_FRAMES {
|
|
+ let Some((next_frame, return_address)) = read_backtrace_frame(frame) else {
|
|
+ break;
|
|
+ };
|
|
+
|
|
+ wrote_frame = true;
|
|
+ let _ = w.write_fmt(format_args!(
|
|
+ "RELIBC BACKTRACE[{frame_index:02}]: {:#x}\n",
|
|
+ return_address,
|
|
+ ));
|
|
+
|
|
+ if !is_sane_next_backtrace_frame(frame, next_frame) {
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ frame = next_frame;
|
|
+ }
|
|
+
|
|
+ if !wrote_frame {
|
|
+ let _ = w.write_str("RELIBC: backtrace attempt produced no frames\n");
|
|
+ }
|
|
+ }
|
|
+
|
|
+ #[cfg(not(any(target_arch = "x86_64", target_arch = "x86", target_arch = "aarch64")))]
|
|
+ {
|
|
+ let _ = w.write_str("RELIBC: backtrace unavailable on this architecture\n");
|
|
+ }
|
|
+}
|
|
|
|
#[unsafe(no_mangle)]
|
|
pub extern "C" fn relibc_panic(pi: &::core::panic::PanicInfo) -> ! {
|
|
use core::fmt::Write;
|
|
|
|
let mut w = platform::FileWriter::new(2);
|
|
- let _ = w.write_fmt(format_args!("RELIBC PANIC: {}\n", pi));
|
|
+
|
|
+ if let Some(location) = pi.location() {
|
|
+ let _ = w.write_fmt(format_args!(
|
|
+ "RELIBC PANIC LOCATION: {}:{}:{}\n",
|
|
+ location.file(),
|
|
+ location.line(),
|
|
+ location.column(),
|
|
+ ));
|
|
+ } else {
|
|
+ let _ = w.write_str("RELIBC PANIC LOCATION: <unavailable>\n");
|
|
+ }
|
|
+
|
|
+ write_process_thread_identity(&mut w);
|
|
+ let _ = w.write_fmt(format_args!("RELIBC PANIC: {}\n", pi));
|
|
|
|
core::intrinsics::abort();
|
|
}
|
|
@@ -95,23 +235,27 @@ pub extern "C" fn rust_oom(layout: ::core::alloc::Layout) -> ! {
|
|
|
|
let mut w = platform::FileWriter::new(2);
|
|
let _ = w.write_fmt(format_args!(
|
|
- "RELIBC OOM: {} bytes aligned to {} bytes\n",
|
|
+ "RELIBC OOM: {} bytes aligned to {} bytes - process will abort\n",
|
|
layout.size(),
|
|
layout.align()
|
|
));
|
|
+ write_process_thread_identity(&mut w);
|
|
+ write_best_effort_backtrace(&mut w);
|
|
|
|
core::intrinsics::abort();
|
|
}
|
|
|
|
#[cfg(not(test))]
|
|
#[allow(non_snake_case)]
|
|
#[linkage = "weak"]
|
|
#[unsafe(no_mangle)]
|
|
pub extern "C" fn _Unwind_Resume() -> ! {
|
|
use core::fmt::Write;
|
|
|
|
let mut w = platform::FileWriter::new(2);
|
|
- let _ = w.write_str("_Unwind_Resume\n");
|
|
+ let _ = w.write_str(
|
|
+ "RELIBC: _Unwind_Resume called - exception propagation failed, aborting\n",
|
|
+ );
|
|
+ write_process_thread_identity(&mut w);
|
|
|
|
core::intrinsics::abort();
|
|
}
|