QEMU: do not crash in helpers pre and post execs (#1065)
* QEMU: do not crash in helpers pre and post execs * comma
This commit is contained in:
parent
53dba5f49d
commit
f8a4a020e8
@ -6,7 +6,7 @@ use std::{
|
||||
sync::Mutex,
|
||||
};
|
||||
|
||||
use libafl::{inputs::UsesInput, state::HasMetadata};
|
||||
use libafl::{executors::ExitKind, inputs::UsesInput, state::HasMetadata};
|
||||
use libc::{
|
||||
c_void, MAP_ANON, MAP_FAILED, MAP_FIXED, MAP_NORESERVE, MAP_PRIVATE, PROT_READ, PROT_WRITE,
|
||||
};
|
||||
@ -53,7 +53,7 @@ pub enum QasanAction {
|
||||
SwapState,
|
||||
}
|
||||
|
||||
#[derive(IntoPrimitive, TryFromPrimitive, Debug, Clone, Copy)]
|
||||
#[derive(IntoPrimitive, TryFromPrimitive, Debug, Clone, Copy, PartialEq)]
|
||||
#[repr(i8)]
|
||||
pub enum PoisonKind {
|
||||
Valid = 0,
|
||||
@ -79,6 +79,13 @@ pub enum PoisonKind {
|
||||
HeapFreed = -3, // 0xfd
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum AsanRollback {
|
||||
Ok,
|
||||
HasLeaks,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum AsanError {
|
||||
Read(GuestAddr, usize),
|
||||
Write(GuestAddr, usize),
|
||||
@ -343,7 +350,7 @@ impl AsanGiovese {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn report_and_crash(&mut self, emu: &Emulator, error: AsanError) {
|
||||
pub fn report_or_crash(&mut self, emu: &Emulator, error: AsanError) {
|
||||
if let Some(cb) = self.error_callback.as_mut() {
|
||||
(cb)(emu, error);
|
||||
} else {
|
||||
@ -351,6 +358,12 @@ impl AsanGiovese {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn report(&mut self, emu: &Emulator, error: AsanError) {
|
||||
if let Some(cb) = self.error_callback.as_mut() {
|
||||
(cb)(emu, error);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn alloc_insert(&mut self, start: GuestAddr, end: GuestAddr) {
|
||||
self.alloc_tree.lock().unwrap().insert(start..end, ());
|
||||
}
|
||||
@ -390,7 +403,7 @@ impl AsanGiovese {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rollback(&mut self, emu: &Emulator, detect_leaks: bool) {
|
||||
pub fn rollback(&mut self, emu: &Emulator, detect_leaks: bool) -> AsanRollback {
|
||||
let mut leaks = vec![];
|
||||
|
||||
{
|
||||
@ -423,9 +436,17 @@ impl AsanGiovese {
|
||||
set.clear();
|
||||
}
|
||||
|
||||
let ret = if leaks.is_empty() {
|
||||
AsanRollback::Ok
|
||||
} else {
|
||||
AsanRollback::HasLeaks
|
||||
};
|
||||
|
||||
for interval in leaks {
|
||||
self.report_and_crash(emu, AsanError::MemLeak(interval));
|
||||
self.report(emu, AsanError::MemLeak(interval));
|
||||
}
|
||||
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
@ -563,12 +584,12 @@ impl QemuAsanHelper {
|
||||
if ck.start != addr {
|
||||
// Free not the start of the chunk
|
||||
self.rt
|
||||
.report_and_crash(emulator, AsanError::BadFree(addr, Some(ck)));
|
||||
.report_or_crash(emulator, AsanError::BadFree(addr, Some(ck)));
|
||||
}
|
||||
} else {
|
||||
// Free of wild ptr
|
||||
self.rt
|
||||
.report_and_crash(emulator, AsanError::BadFree(addr, None));
|
||||
.report_or_crash(emulator, AsanError::BadFree(addr, None));
|
||||
}
|
||||
}
|
||||
|
||||
@ -580,67 +601,63 @@ impl QemuAsanHelper {
|
||||
|
||||
pub fn read_1(&mut self, emulator: &Emulator, addr: GuestAddr) {
|
||||
if self.enabled() && AsanGiovese::is_invalid_access_1(emulator, addr) {
|
||||
self.rt.report_and_crash(emulator, AsanError::Read(addr, 1));
|
||||
self.rt.report_or_crash(emulator, AsanError::Read(addr, 1));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_2(&mut self, emulator: &Emulator, addr: GuestAddr) {
|
||||
if self.enabled() && AsanGiovese::is_invalid_access_2(emulator, addr) {
|
||||
self.rt.report_and_crash(emulator, AsanError::Read(addr, 2));
|
||||
self.rt.report_or_crash(emulator, AsanError::Read(addr, 2));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_4(&mut self, emulator: &Emulator, addr: GuestAddr) {
|
||||
if self.enabled() && AsanGiovese::is_invalid_access_4(emulator, addr) {
|
||||
self.rt.report_and_crash(emulator, AsanError::Read(addr, 4));
|
||||
self.rt.report_or_crash(emulator, AsanError::Read(addr, 4));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_8(&mut self, emulator: &Emulator, addr: GuestAddr) {
|
||||
if self.enabled() && AsanGiovese::is_invalid_access_8(emulator, addr) {
|
||||
self.rt.report_and_crash(emulator, AsanError::Read(addr, 8));
|
||||
self.rt.report_or_crash(emulator, AsanError::Read(addr, 8));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_n(&mut self, emulator: &Emulator, addr: GuestAddr, size: usize) {
|
||||
if self.enabled() && AsanGiovese::is_invalid_access(emulator, addr, size) {
|
||||
self.rt
|
||||
.report_and_crash(emulator, AsanError::Read(addr, size));
|
||||
.report_or_crash(emulator, AsanError::Read(addr, size));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_1(&mut self, emulator: &Emulator, addr: GuestAddr) {
|
||||
if self.enabled() && AsanGiovese::is_invalid_access_1(emulator, addr) {
|
||||
self.rt
|
||||
.report_and_crash(emulator, AsanError::Write(addr, 1));
|
||||
self.rt.report_or_crash(emulator, AsanError::Write(addr, 1));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_2(&mut self, emulator: &Emulator, addr: GuestAddr) {
|
||||
if self.enabled() && AsanGiovese::is_invalid_access_2(emulator, addr) {
|
||||
self.rt
|
||||
.report_and_crash(emulator, AsanError::Write(addr, 2));
|
||||
self.rt.report_or_crash(emulator, AsanError::Write(addr, 2));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_4(&mut self, emulator: &Emulator, addr: GuestAddr) {
|
||||
if self.enabled() && AsanGiovese::is_invalid_access_4(emulator, addr) {
|
||||
self.rt
|
||||
.report_and_crash(emulator, AsanError::Write(addr, 4));
|
||||
self.rt.report_or_crash(emulator, AsanError::Write(addr, 4));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_8(&mut self, emulator: &Emulator, addr: GuestAddr) {
|
||||
if self.enabled() && AsanGiovese::is_invalid_access_8(emulator, addr) {
|
||||
self.rt
|
||||
.report_and_crash(emulator, AsanError::Write(addr, 8));
|
||||
self.rt.report_or_crash(emulator, AsanError::Write(addr, 8));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_n(&mut self, emulator: &Emulator, addr: GuestAddr, size: usize) {
|
||||
if self.enabled() && AsanGiovese::is_invalid_access(emulator, addr, size) {
|
||||
self.rt
|
||||
.report_and_crash(emulator, AsanError::Write(addr, size));
|
||||
.report_or_crash(emulator, AsanError::Write(addr, size));
|
||||
}
|
||||
}
|
||||
|
||||
@ -659,8 +676,8 @@ impl QemuAsanHelper {
|
||||
AsanGiovese::unpoison(emulator, addr, size);
|
||||
}
|
||||
|
||||
pub fn reset(&mut self, emulator: &Emulator) {
|
||||
self.rt.rollback(emulator, self.detect_leaks);
|
||||
pub fn reset(&mut self, emulator: &Emulator) -> AsanRollback {
|
||||
self.rt.rollback(emulator, self.detect_leaks)
|
||||
}
|
||||
}
|
||||
|
||||
@ -713,8 +730,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn post_exec(&mut self, emulator: &Emulator, _input: &S::Input) {
|
||||
self.reset(emulator);
|
||||
fn post_exec(&mut self, emulator: &Emulator, _input: &S::Input, exit_kind: &mut ExitKind) {
|
||||
if self.reset(emulator) == AsanRollback::HasLeaks {
|
||||
*exit_kind = ExitKind::Crash;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
use std::{path::PathBuf, sync::Mutex};
|
||||
|
||||
use hashbrown::{hash_map::Entry, HashMap};
|
||||
use libafl::{inputs::UsesInput, state::HasMetadata};
|
||||
use libafl::{executors::ExitKind, inputs::UsesInput, state::HasMetadata};
|
||||
use libafl_targets::drcov::{DrCovBasicBlock, DrCovWriter};
|
||||
use rangemap::RangeMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -83,7 +83,7 @@ where
|
||||
|
||||
fn pre_exec(&mut self, _emulator: &Emulator, _input: &S::Input) {}
|
||||
|
||||
fn post_exec(&mut self, emulator: &Emulator, _input: &S::Input) {
|
||||
fn post_exec(&mut self, emulator: &Emulator, _input: &S::Input, _exit_kind: &mut ExitKind) {
|
||||
if self.full_trace {
|
||||
if DRCOV_IDS.lock().unwrap().as_ref().unwrap().len() > self.drcov_len {
|
||||
let mut drcov_vec = Vec::<DrCovBasicBlock>::new();
|
||||
|
@ -117,9 +117,11 @@ where
|
||||
self.first_exec = false;
|
||||
}
|
||||
self.hooks.helpers_mut().pre_exec_all(&emu, input);
|
||||
let r = self.inner.run_target(fuzzer, state, mgr, input);
|
||||
self.hooks.helpers_mut().post_exec_all(&emu, input);
|
||||
r
|
||||
let mut exit_kind = self.inner.run_target(fuzzer, state, mgr, input)?;
|
||||
self.hooks
|
||||
.helpers_mut()
|
||||
.post_exec_all(&emu, input, &mut exit_kind);
|
||||
Ok(exit_kind)
|
||||
}
|
||||
}
|
||||
|
||||
@ -277,9 +279,11 @@ where
|
||||
self.first_exec = false;
|
||||
}
|
||||
self.hooks.helpers_mut().pre_exec_all(&emu, input);
|
||||
let r = self.inner.run_target(fuzzer, state, mgr, input);
|
||||
self.hooks.helpers_mut().post_exec_all(&emu, input);
|
||||
r
|
||||
let mut exit_kind = self.inner.run_target(fuzzer, state, mgr, input)?;
|
||||
self.hooks
|
||||
.helpers_mut()
|
||||
.post_exec_all(&emu, input, &mut exit_kind);
|
||||
Ok(exit_kind)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
use core::{fmt::Debug, ops::Range};
|
||||
|
||||
use libafl::{bolts::tuples::MatchFirstType, inputs::UsesInput};
|
||||
use libafl::{bolts::tuples::MatchFirstType, executors::ExitKind, inputs::UsesInput};
|
||||
|
||||
use crate::{emu::Emulator, hooks::QemuHooks};
|
||||
|
||||
@ -26,7 +26,7 @@ where
|
||||
|
||||
fn pre_exec(&mut self, _emulator: &Emulator, _input: &S::Input) {}
|
||||
|
||||
fn post_exec(&mut self, _emulator: &Emulator, _input: &S::Input) {}
|
||||
fn post_exec(&mut self, _emulator: &Emulator, _input: &S::Input, _exit_kind: &mut ExitKind) {}
|
||||
}
|
||||
|
||||
pub trait QemuHelperTuple<S>: MatchFirstType + Debug
|
||||
@ -45,7 +45,7 @@ where
|
||||
|
||||
fn pre_exec_all(&mut self, _emulator: &Emulator, input: &S::Input);
|
||||
|
||||
fn post_exec_all(&mut self, _emulator: &Emulator, input: &S::Input);
|
||||
fn post_exec_all(&mut self, _emulator: &Emulator, input: &S::Input, _exit_kind: &mut ExitKind);
|
||||
}
|
||||
|
||||
impl<S> QemuHelperTuple<S> for ()
|
||||
@ -68,7 +68,13 @@ where
|
||||
|
||||
fn pre_exec_all(&mut self, _emulator: &Emulator, _input: &S::Input) {}
|
||||
|
||||
fn post_exec_all(&mut self, _emulator: &Emulator, _input: &S::Input) {}
|
||||
fn post_exec_all(
|
||||
&mut self,
|
||||
_emulator: &Emulator,
|
||||
_input: &S::Input,
|
||||
_exit_kind: &mut ExitKind,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
impl<Head, Tail, S> QemuHelperTuple<S> for (Head, Tail)
|
||||
@ -100,9 +106,9 @@ where
|
||||
self.1.pre_exec_all(emulator, input);
|
||||
}
|
||||
|
||||
fn post_exec_all(&mut self, emulator: &Emulator, input: &S::Input) {
|
||||
self.0.post_exec(emulator, input);
|
||||
self.1.post_exec_all(emulator, input);
|
||||
fn post_exec_all(&mut self, emulator: &Emulator, input: &S::Input, exit_kind: &mut ExitKind) {
|
||||
self.0.post_exec(emulator, input, exit_kind);
|
||||
self.1.post_exec_all(emulator, input, exit_kind);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user