Use AddVectoredExceptionHandler to register exception handlers (#403)

* add

* unix fix

* unsafe positions

* another unsafe!

* ignore

* ignore

* make changes back

* fix

* fix

* fmt

* exception fix

* fix

* bug fix

* fmt

* fix things messed up during merge

* stack overflow fix

* fix

* fix

* fix

Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>
Co-authored-by: Dominik Maier <domenukk@gmail.com>
This commit is contained in:
Dongjia Zhang 2021-12-16 19:15:24 +09:00 committed by GitHub
parent d93f97309a
commit 79f9bcd3e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 38 additions and 19 deletions

View File

@ -1,7 +1,7 @@
//! Exception handling for Windows //! Exception handling for Windows
pub use windows::Win32::System::Diagnostics::Debug::{ pub use windows::Win32::System::Diagnostics::Debug::{
SetUnhandledExceptionFilter, EXCEPTION_POINTERS, AddVectoredExceptionHandler, EXCEPTION_POINTERS,
}; };
pub use windows::Win32::Foundation::NTSTATUS; pub use windows::Win32::Foundation::NTSTATUS;
@ -309,8 +309,6 @@ unsafe fn internal_handle_exception(
} }
} }
type NativeHandlerType = extern "system" fn(*mut EXCEPTION_POINTERS) -> c_long;
/// Internal function that is being called whenever an exception arrives (stdcall). /// Internal function that is being called whenever an exception arrives (stdcall).
unsafe extern "system" fn handle_exception(exception_pointers: *mut EXCEPTION_POINTERS) -> c_long { unsafe extern "system" fn handle_exception(exception_pointers: *mut EXCEPTION_POINTERS) -> c_long {
let code = exception_pointers let code = exception_pointers
@ -361,8 +359,11 @@ pub unsafe fn setup_exception_handler<T: 'static + Handler>(handler: &mut T) ->
if catch_assertions { if catch_assertions {
signal(SIGABRT, handle_signal); signal(SIGABRT, handle_signal);
} }
if let Some(prev) = SetUnhandledExceptionFilter(Some(core::mem::transmute( // SetUnhandledFilter does not work with frida since the stack is changed and exception handler is lost with Stalker enabled.
handle_exception as *const c_void, // See https://github.com/AFLplusplus/LibAFL/pull/403
))) {} AddVectoredExceptionHandler(
1,
Some(core::mem::transmute(handle_exception as *const c_void)),
);
Ok(()) Ok(())
} }

View File

@ -25,6 +25,9 @@ use crate::bolts::os::unix_signals::setup_signal_handler;
#[cfg(all(windows, feature = "std"))] #[cfg(all(windows, feature = "std"))]
use crate::bolts::os::windows_exceptions::setup_exception_handler; use crate::bolts::os::windows_exceptions::setup_exception_handler;
#[cfg(windows)]
use windows::Win32::System::Threading::SetThreadStackGuarantee;
use crate::{ use crate::{
corpus::Corpus, corpus::Corpus,
events::{EventFirer, EventRestarter}, events::{EventFirer, EventRestarter},
@ -121,6 +124,21 @@ where
Z: HasObjective<I, OF, S>, Z: HasObjective<I, OF, S>,
{ {
let handlers = InProcessHandlers::new::<Self, EM, I, OC, OF, OT, S, Z>()?; let handlers = InProcessHandlers::new::<Self, EM, I, OC, OF, OT, S, Z>()?;
#[cfg(windows)]
unsafe {
/*
See https://github.com/AFLplusplus/LibAFL/pull/403
This one reserves certain amount of memory for the stack.
If stack overflow happens during fuzzing on windows, the program is transferred to our exception handler for windows.
However, if we run out of the stack memory again in this exception handler, we'll crash with STATUS_ACCESS_VIOLATION.
We need this API call because with the llmp_compression
feature enabled, the exception handler uses a lot of stack memory (in the compression lib code) on release build.
As far as I have observed, the compression uses around 0x10000 bytes, but for safety let's just reserve 0x20000 bytes for our exception handlers.
This number 0x20000 could vary depending on the compilers optimization for future compression library changes.
*/
let mut stack_reserved = 0x20000;
SetThreadStackGuarantee(&mut stack_reserved);
}
Ok(Self { Ok(Self {
harness_fn, harness_fn,
observers, observers,
@ -569,7 +587,7 @@ mod unix_signal_handler {
#[cfg(feature = "std")] #[cfg(feature = "std")]
{ {
println!("Type QUIT to restart the child"); eprintln!("Type QUIT to restart the child");
let mut line = String::new(); let mut line = String::new();
while line.trim() != "QUIT" { while line.trim() != "QUIT" {
std::io::stdin().read_line(&mut line).unwrap(); std::io::stdin().read_line(&mut line).unwrap();
@ -629,10 +647,10 @@ mod unix_signal_handler {
event_mgr.on_restart(state).unwrap(); event_mgr.on_restart(state).unwrap();
#[cfg(feature = "std")] #[cfg(feature = "std")]
println!("Waiting for broker..."); eprintln!("Waiting for broker...");
event_mgr.await_restart_safe(); event_mgr.await_restart_safe();
#[cfg(feature = "std")] #[cfg(feature = "std")]
println!("Bye!"); eprintln!("Bye!");
} }
libc::_exit(128 + (signal as i32)); libc::_exit(128 + (signal as i32));
@ -735,7 +753,7 @@ mod windows_exception_handler {
dbg!("TIMEOUT or SIGUSR2 happened, but currently not fuzzing. Exiting"); dbg!("TIMEOUT or SIGUSR2 happened, but currently not fuzzing. Exiting");
} else { } else {
#[cfg(feature = "std")] #[cfg(feature = "std")]
println!("Timeout in fuzz run."); eprintln!("Timeout in fuzz run.");
#[cfg(feature = "std")] #[cfg(feature = "std")]
let _res = stdout().flush(); let _res = stdout().flush();
@ -771,10 +789,10 @@ mod windows_exception_handler {
event_mgr.on_restart(state).unwrap(); event_mgr.on_restart(state).unwrap();
#[cfg(feature = "std")] #[cfg(feature = "std")]
println!("Waiting for broker..."); eprintln!("Waiting for broker...");
event_mgr.await_restart_safe(); event_mgr.await_restart_safe();
#[cfg(feature = "std")] #[cfg(feature = "std")]
println!("Bye!"); eprintln!("Bye!");
event_mgr.await_restart_safe(); event_mgr.await_restart_safe();
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
@ -834,11 +852,11 @@ mod windows_exception_handler {
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
println!("Crashed with {}", code); eprintln!("Crashed with {}", code);
if data.current_input_ptr.is_null() { if data.current_input_ptr.is_null() {
#[cfg(feature = "std")] #[cfg(feature = "std")]
{ {
println!("Double crash\n"); eprintln!("Double crash\n");
let crash_addr = exception_pointers let crash_addr = exception_pointers
.as_mut() .as_mut()
.unwrap() .unwrap()
@ -847,14 +865,14 @@ mod windows_exception_handler {
.unwrap() .unwrap()
.ExceptionAddress as usize; .ExceptionAddress as usize;
println!( eprintln!(
"We crashed at addr 0x{:x}, but are not in the target... Bug in the fuzzer? Exiting.", "We crashed at addr 0x{:x}, but are not in the target... Bug in the fuzzer? Exiting.",
crash_addr crash_addr
); );
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
{ {
println!("Type QUIT to restart the child"); eprintln!("Type QUIT to restart the child");
let mut line = String::new(); let mut line = String::new();
while line.trim() != "QUIT" { while line.trim() != "QUIT" {
std::io::stdin().read_line(&mut line).unwrap(); std::io::stdin().read_line(&mut line).unwrap();
@ -870,7 +888,7 @@ mod windows_exception_handler {
let observers = executor.observers(); let observers = executor.observers();
#[cfg(feature = "std")] #[cfg(feature = "std")]
println!("Child crashed!"); eprintln!("Child crashed!");
#[cfg(feature = "std")] #[cfg(feature = "std")]
drop(stdout().flush()); drop(stdout().flush());
@ -908,10 +926,10 @@ mod windows_exception_handler {
event_mgr.on_restart(state).unwrap(); event_mgr.on_restart(state).unwrap();
#[cfg(feature = "std")] #[cfg(feature = "std")]
println!("Waiting for broker..."); eprintln!("Waiting for broker...");
event_mgr.await_restart_safe(); event_mgr.await_restart_safe();
#[cfg(feature = "std")] #[cfg(feature = "std")]
println!("Bye!"); eprintln!("Bye!");
} }
ExitProcess(1); ExitProcess(1);
} }