Skip to content

Commit 04bf16e

Browse files
committed
remove platform-specific ptrace code as it does not build on arm32
1 parent 3e7a12c commit 04bf16e

File tree

1 file changed

+3
-117
lines changed

1 file changed

+3
-117
lines changed

src/shims/native_lib/trace/parent.rs

Lines changed: 3 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#![allow(unused)]
12
use std::sync::atomic::{AtomicPtr, AtomicUsize};
23

34
use ipc_channel::ipc;
@@ -401,7 +402,7 @@ fn handle_segfault(
401402
ch_stack: usize,
402403
page_size: usize,
403404
cs: &capstone::Capstone,
404-
acc_events: &mut Vec<AccessEvent>,
405+
acc_events: &mut [AccessEvent],
405406
) -> Result<(), ExecEnd> {
406407
/// This is just here to not pollute the main namespace with `capstone::prelude::*`.
407408
#[inline]
@@ -520,122 +521,7 @@ fn handle_segfault(
520521
Ok(())
521522
}
522523

523-
// Get information on what caused the segfault. This contains the address
524-
// that triggered it.
525-
let siginfo = ptrace::getsiginfo(pid).unwrap();
526-
// All x86, ARM, etc. instructions only have at most one memory operand
527-
// (thankfully!)
528-
// SAFETY: si_addr is safe to call.
529-
let addr = unsafe { siginfo.si_addr().addr() };
530-
let page_addr = addr.strict_sub(addr.strict_rem(page_size));
531-
532-
if !ch_pages.iter().any(|pg| (*pg..pg.strict_add(page_size)).contains(&addr)) {
533-
// This was a real segfault (not one of the Miri memory pages), so print some debug info and
534-
// quit.
535-
let regs = ptrace::getregs(pid).unwrap();
536-
eprintln!("Segfault occurred during FFI at {addr:#018x}");
537-
eprintln!("Expected access on pages: {ch_pages:#018x?}");
538-
eprintln!("Register dump: {regs:#x?}");
539-
ptrace::kill(pid).unwrap();
540-
return Err(ExecEnd(None));
541-
}
542-
543-
// Overall structure:
544-
// - Get the address that caused the segfault
545-
// - Unprotect the memory: we force the child to execute `mempr_off`, passing parameters via
546-
// global atomic variables. This is what we use the temporary callback stack for.
547-
// - Step 1 instruction
548-
// - Parse executed code to estimate size & type of access
549-
// - Reprotect the memory by executing `mempr_on` in the child.
550-
// - Continue
551-
552-
// Ensure the stack is properly zeroed out!
553-
for a in (ch_stack..ch_stack.strict_add(CALLBACK_STACK_SIZE)).step_by(ARCH_WORD_SIZE) {
554-
ptrace::write(pid, std::ptr::with_exposed_provenance_mut(a), 0).unwrap();
555-
}
556-
557-
// Guard against both architectures with upwards and downwards-growing stacks.
558-
let stack_ptr = ch_stack.strict_add(CALLBACK_STACK_SIZE / 2);
559-
let regs_bak = ptrace::getregs(pid).unwrap();
560-
let mut new_regs = regs_bak;
561-
let ip_prestep = regs_bak.ip();
562-
563-
// Move the instr ptr into the deprotection code.
564-
#[expect(clippy::as_conversions)]
565-
new_regs.set_ip(mempr_off as usize);
566-
// Don't mess up the stack by accident!
567-
new_regs.set_sp(stack_ptr);
568-
569-
// Modify the PAGE_ADDR global on the child process to point to the page
570-
// that we want unprotected.
571-
ptrace::write(
572-
pid,
573-
(&raw const PAGE_ADDR).cast_mut().cast(),
574-
libc::c_long::try_from(page_addr).unwrap(),
575-
)
576-
.unwrap();
577-
578-
// Check if we also own the next page, and if so unprotect it in case
579-
// the access spans the page boundary.
580-
let flag = if ch_pages.contains(&page_addr.strict_add(page_size)) { 2 } else { 1 };
581-
ptrace::write(pid, (&raw const PAGE_COUNT).cast_mut().cast(), flag).unwrap();
582-
583-
ptrace::setregs(pid, new_regs).unwrap();
584-
585-
// Our mempr_* functions end with a raise(SIGSTOP).
586-
wait_for_signal(Some(pid), signal::SIGSTOP, true)?;
587-
588-
// Step 1 instruction.
589-
ptrace::setregs(pid, regs_bak).unwrap();
590-
ptrace::step(pid, None).unwrap();
591-
// Don't use wait_for_signal here since 1 instruction doesn't give room
592-
// for any uncertainty + we don't want it `cont()`ing randomly by accident
593-
// Also, don't let it continue with unprotected memory if something errors!
594-
let _ = wait::waitid(wait::Id::Pid(pid), WAIT_FLAGS).map_err(|_| ExecEnd(None))?;
595-
596-
// Zero out again to be safe
597-
for a in (ch_stack..ch_stack.strict_add(CALLBACK_STACK_SIZE)).step_by(ARCH_WORD_SIZE) {
598-
ptrace::write(pid, std::ptr::with_exposed_provenance_mut(a), 0).unwrap();
599-
}
600-
601-
// Save registers and grab the bytes that were executed. This would
602-
// be really nasty if it was a jump or similar but those thankfully
603-
// won't do memory accesses and so can't trigger this!
604-
let regs_bak = ptrace::getregs(pid).unwrap();
605-
new_regs = regs_bak;
606-
let ip_poststep = regs_bak.ip();
607-
// We need to do reads/writes in word-sized chunks.
608-
let diff = (ip_poststep.strict_sub(ip_prestep)).div_ceil(ARCH_WORD_SIZE);
609-
let instr = (ip_prestep..ip_prestep.strict_add(diff)).fold(vec![], |mut ret, ip| {
610-
// This only needs to be a valid pointer in the child process, not ours.
611-
ret.append(
612-
&mut ptrace::read(pid, std::ptr::without_provenance_mut(ip))
613-
.unwrap()
614-
.to_ne_bytes()
615-
.to_vec(),
616-
);
617-
ret
618-
});
619-
620-
// Now figure out the size + type of access and log it down.
621-
// This will mark down e.g. the same area being read multiple times,
622-
// since it's more efficient to compress the accesses at the end.
623-
if capstone_disassemble(&instr, addr, cs, acc_events).is_err() {
624-
// Read goes first because we need to be pessimistic.
625-
acc_events.push(AccessEvent::Read(addr..addr.strict_add(ARCH_MAX_ACCESS_SIZE)));
626-
acc_events.push(AccessEvent::Write(addr..addr.strict_add(ARCH_MAX_ACCESS_SIZE)));
627-
}
628-
629-
// Reprotect everything and continue.
630-
#[expect(clippy::as_conversions)]
631-
new_regs.set_ip(mempr_on as usize);
632-
new_regs.set_sp(stack_ptr);
633-
ptrace::setregs(pid, new_regs).unwrap();
634-
wait_for_signal(Some(pid), signal::SIGSTOP, true)?;
635-
636-
ptrace::setregs(pid, regs_bak).unwrap();
637-
ptrace::syscall(pid, None).unwrap();
638-
Ok(())
524+
todo!()
639525
}
640526

641527
// We only get dropped into these functions via offsetting the instr pointer

0 commit comments

Comments
 (0)