@@ -257,7 +257,7 @@ pub fn sv_loop(
257257 let mut curr_pid = init_pid;
258258
259259 // There's an initial sigstop we need to deal with.
260- wait_for_signal ( Some ( curr_pid) , signal:: SIGSTOP , InitialCont :: No ) ?;
260+ wait_for_signal ( Some ( curr_pid) , signal:: SIGSTOP , InitialCont :: No , None ) ?;
261261 ptrace:: cont ( curr_pid, None ) . unwrap ( ) ;
262262
263263 for evt in listener {
@@ -276,7 +276,7 @@ pub fn sv_loop(
276276 confirm_tx. send ( Confirmation ) . unwrap ( ) ;
277277 // We can't trust simply calling `Pid::this()` in the child process to give the right
278278 // PID for us, so we get it this way.
279- curr_pid = wait_for_signal ( None , signal:: SIGSTOP , InitialCont :: No ) . unwrap ( ) ;
279+ curr_pid = wait_for_signal ( None , signal:: SIGSTOP , InitialCont :: No , None ) . unwrap ( ) ;
280280 // Intercept libc events we care about.
281281 trap_libc ( curr_pid) ;
282282 // Continue until next syscall.
@@ -301,16 +301,16 @@ pub fn sv_loop(
301301 // If it was a segfault, check if it was an artificial one
302302 // caused by it trying to access the MiriMachine memory.
303303 signal:: SIGSEGV =>
304- handle_segfault (
304+ handle_segfault ( pid, & ch_pages, ch_stack. unwrap ( ) , & cs, & mut acc_events) ?,
305+ signal:: SIGTRAP =>
306+ handle_sigtrap (
305307 pid,
306- & ch_pages,
308+ & mut ch_pages,
309+ & event_tx,
310+ & mut acc_events,
307311 ch_stack. unwrap ( ) ,
308- page_size,
309312 & cs,
310- & mut acc_events,
311313 ) ?,
312- signal:: SIGTRAP =>
313- handle_sigtrap ( pid, page_size, & mut ch_pages, & event_tx, & mut acc_events) ?,
314314 // Something weird happened.
315315 _ => {
316316 eprintln ! ( "Process unexpectedly got {signal}; continuing..." ) ;
@@ -399,6 +399,13 @@ fn get_disasm() -> capstone::Capstone {
399399 . unwrap ( )
400400}
401401
402+ struct SegfaultCatchingStuff < ' a , ' b , ' c > {
403+ ch_pages : & ' a [ usize ] ,
404+ ch_stack : usize ,
405+ cs : & ' b capstone:: Capstone ,
406+ acc_events : & ' c mut Vec < AccessEvent > ,
407+ }
408+
402409/// Waits for `wait_signal`. If `init_cont`, it will first do a `ptrace::cont`.
403410/// We want to avoid that in some cases, like at the beginning of FFI.
404411///
@@ -407,6 +414,7 @@ fn wait_for_signal(
407414 pid : Option < unistd:: Pid > ,
408415 wait_signal : signal:: Signal ,
409416 init_cont : InitialCont ,
417+ mut catch_segfaults : Option < SegfaultCatchingStuff < ' _ , ' _ , ' _ > > ,
410418) -> Result < unistd:: Pid , ExecEnd > {
411419 if matches ! ( init_cont, InitialCont :: Yes ) {
412420 ptrace:: cont ( pid. unwrap ( ) , None ) . unwrap ( ) ;
@@ -435,6 +443,11 @@ fn wait_for_signal(
435443 } ;
436444 if signal == wait_signal {
437445 return Ok ( pid) ;
446+ } else if let Some ( ref mut sf) = catch_segfaults
447+ && signal == signal:: SIGSEGV
448+ {
449+ // Segfaults occuring during a wait should still be logged.
450+ handle_segfault ( pid, sf. ch_pages , sf. ch_stack , sf. cs , sf. acc_events ) ?;
438451 } else {
439452 ptrace:: cont ( pid, signal) . map_err ( |_| ExecEnd ( None ) ) ?;
440453 }
@@ -519,16 +532,19 @@ fn capstone_disassemble(
519532 Ok ( ( ) )
520533}
521534
535+ // THIS NEEDS TO SOMEHOW CATCH SEGFAULTS INSIDE IT!!!! AND ALSO IN THE FULL ONE IT
536+ // NEEDS TO GET THEM TO LOG THOSE ACCESSES AAAAAAAAAAAAAAAAA
537+
522538/// Grabs the access that caused a segfault and logs it down if it's to our memory,
523539/// or kills the child and returns the appropriate error otherwise.
524540fn handle_segfault (
525541 pid : unistd:: Pid ,
526542 ch_pages : & [ usize ] ,
527543 ch_stack : usize ,
528- page_size : usize ,
529544 cs : & capstone:: Capstone ,
530545 acc_events : & mut Vec < AccessEvent > ,
531546) -> Result < ( ) , ExecEnd > {
547+ let page_size = PAGE_SIZE . load ( Ordering :: Relaxed ) ;
532548 // Get information on what caused the segfault. This contains the address
533549 // that triggered it.
534550 let siginfo = ptrace:: getsiginfo ( pid) . unwrap ( ) ;
@@ -611,7 +627,7 @@ fn handle_segfault(
611627 ptrace:: setregs ( pid, new_regs) . unwrap ( ) ;
612628
613629 // Our mempr_* functions end with a raise(SIGSTOP).
614- wait_for_signal ( Some ( pid) , signal:: SIGSTOP , InitialCont :: Yes ) ?;
630+ wait_for_signal ( Some ( pid) , signal:: SIGSTOP , InitialCont :: Yes , None ) ?;
615631
616632 // Step 1 instruction.
617633 ptrace:: setregs ( pid, regs_bak) . unwrap ( ) ;
@@ -645,7 +661,7 @@ fn handle_segfault(
645661 new_regs. set_ip ( super :: child:: mempr_on as * const ( ) as usize ) ;
646662 new_regs. set_sp ( stack_ptr) ;
647663 ptrace:: setregs ( pid, new_regs) . unwrap ( ) ;
648- wait_for_signal ( Some ( pid) , signal:: SIGSTOP , InitialCont :: Yes ) ?;
664+ wait_for_signal ( Some ( pid) , signal:: SIGSTOP , InitialCont :: Yes , None ) ?;
649665
650666 ptrace:: setregs ( pid, regs_bak) . unwrap ( ) ;
651667 ptrace:: syscall ( pid, None ) . unwrap ( ) ;
@@ -656,10 +672,11 @@ fn handle_segfault(
656672/// to our shims to handle it instead.
657673fn handle_sigtrap (
658674 pid : unistd:: Pid ,
659- page_size : usize ,
660675 pages : & mut Vec < usize > ,
661676 _event_tx : & ipc:: IpcSender < MemEvents > ,
662- _acc_events : & mut Vec < AccessEvent > ,
677+ acc_events : & mut Vec < AccessEvent > ,
678+ ch_stack : usize ,
679+ cs : & capstone:: Capstone ,
663680) -> Result < ( ) , ExecEnd > {
664681 /// The libc functions we shim.
665682 enum LibcFn {
@@ -686,6 +703,7 @@ fn handle_sigtrap(
686703 }
687704 }
688705
706+ let page_size = PAGE_SIZE . load ( Ordering :: Relaxed ) ;
689707 let regs = ptrace:: getregs ( pid) . unwrap ( ) ;
690708 match get_libc_fn ( regs. ip ( ) ) {
691709 Some ( _) => {
@@ -734,7 +752,10 @@ fn handle_sigtrap(
734752 ptrace:: read ( pid, std:: ptr:: without_provenance_mut ( ret_addr) ) . unwrap ( ) ;
735753 ptrace:: write ( pid, std:: ptr:: without_provenance_mut ( ret_addr) , BREAKPT_INSTR . into ( ) )
736754 . unwrap ( ) ;
737- wait_for_signal ( Some ( pid) , signal:: SIGTRAP , InitialCont :: Yes ) . unwrap ( ) ;
755+ let catch_segfaults =
756+ SegfaultCatchingStuff { ch_pages : & * pages, ch_stack, cs, acc_events } ;
757+ wait_for_signal ( Some ( pid) , signal:: SIGTRAP , InitialCont :: Yes , Some ( catch_segfaults) )
758+ . unwrap ( ) ;
738759
739760 // Unset the breakpoint stuff and move the ip back an instruction to compensate.
740761 ptrace:: write ( pid, std:: ptr:: without_provenance_mut ( ret_addr) , ret_addr_bytes) . unwrap ( ) ;
0 commit comments