diff --git a/fuzzers/fuzzbench_qemu/Makefile b/fuzzers/fuzzbench_qemu/Makefile index 9f9e4b3037..7b63a820ce 100644 --- a/fuzzers/fuzzbench_qemu/Makefile +++ b/fuzzers/fuzzbench_qemu/Makefile @@ -33,7 +33,7 @@ target/$(BUILD_TARGET)/lib$(FUZZER_NAME).a: src/* qemu-libafl-bridge: git clone git@github.com:AFLplusplus/qemu-libafl-bridge.git - cd qemu-libafl-bridge && git checkout 03dfdbd7da90b2d3b9e4df1a52b5a48e8d453a84 + cd qemu-libafl-bridge && git checkout ae096f10cec9a0ac489cb6e6c9892bcbfaea159d build/config.status: qemu-libafl-bridge qemu-libafl-bridge/configure mkdir -p build diff --git a/fuzzers/fuzzbench_qemu/src/fuzzer.rs b/fuzzers/fuzzbench_qemu/src/fuzzer.rs index 9a2ff1918c..72c7e1ceb3 100644 --- a/fuzzers/fuzzbench_qemu/src/fuzzer.rs +++ b/fuzzers/fuzzbench_qemu/src/fuzzer.rs @@ -273,14 +273,16 @@ fn fuzz( let mut harness = |input: &BytesInput| { let target = input.target_bytes(); let mut buf = target.as_slice(); - if buf.len() > 4096 { + let mut len = buf.len(); + if len > 4096 { buf = &buf[0..4096]; + len = 4096; } emu::write_mem(input_addr, buf); emu::write_reg(Amd64Regs::Rdi, input_addr).unwrap(); - emu::write_reg(Amd64Regs::Rsi, buf.len()).unwrap(); + emu::write_reg(Amd64Regs::Rsi, len).unwrap(); emu::write_reg(Amd64Regs::Rip, test_one_input_ptr).unwrap(); emu::write_reg(Amd64Regs::Rsp, stack_ptr).unwrap(); diff --git a/libafl/src/bolts/cpu.rs b/libafl/src/bolts/cpu.rs index a0773c3cf3..c9f23058dd 100644 --- a/libafl/src/bolts/cpu.rs +++ b/libafl/src/bolts/cpu.rs @@ -16,7 +16,14 @@ use crate::bolts::current_nanos; #[cfg(any(target_arch = "x86_64", target_arch = "x86"))] #[must_use] pub fn read_time_counter() -> u64 { - unsafe { core::arch::x86_64::_rdtsc() } + #[cfg(target_arch = "x86_64")] + unsafe { + core::arch::x86_64::_rdtsc() + } + #[cfg(target_arch = "x86")] + unsafe { + core::arch::x86::_rdtsc() + } } /// Read a timestamp for measurements. diff --git a/libafl/src/bolts/staterestore.rs b/libafl/src/bolts/staterestore.rs index f874eb8464..39e2cec551 100644 --- a/libafl/src/bolts/staterestore.rs +++ b/libafl/src/bolts/staterestore.rs @@ -79,7 +79,7 @@ where let filename = format!("{:016x}.libafl_state", hasher.finish()); let tmpfile = temp_dir().join(&filename); - File::open(tmpfile)?.write_all(&serialized)?; + File::create(tmpfile)?.write_all(&serialized)?; // write the filename to shmem let filename_buf = postcard::to_allocvec(&filename)?; diff --git a/libafl_qemu/src/emu.rs b/libafl_qemu/src/emu.rs index a3697497f8..1e33e5c99b 100644 --- a/libafl_qemu/src/emu.rs +++ b/libafl_qemu/src/emu.rs @@ -11,7 +11,7 @@ use num::Num; use num_enum::{IntoPrimitive, TryFromPrimitive}; use std::{slice::from_raw_parts, str::from_utf8_unchecked}; -pub const SKIP_EXEC_HOOK: u32 = u32::MAX; +pub const SKIP_EXEC_HOOK: u64 = u64::MAX; #[derive(IntoPrimitive, TryFromPrimitive, Clone, Copy)] #[repr(i32)] @@ -109,16 +109,30 @@ extern "C" { static exec_path: *const u8; static guest_base: usize; - static mut libafl_exec_edge_hook: unsafe extern "C" fn(u32); - static mut libafl_gen_edge_hook: unsafe extern "C" fn(u64, u64) -> u32; + static mut libafl_exec_edge_hook: unsafe extern "C" fn(u64); + static mut libafl_gen_edge_hook: unsafe extern "C" fn(u64, u64) -> u64; static mut libafl_exec_block_hook: unsafe extern "C" fn(u64); - static mut libafl_gen_block_hook: unsafe extern "C" fn(u64) -> u32; + static mut libafl_gen_block_hook: unsafe extern "C" fn(u64) -> u64; - static mut libafl_exec_cmp_hook1: unsafe extern "C" fn(u32, u8, u8); - static mut libafl_exec_cmp_hook2: unsafe extern "C" fn(u32, u16, u16); - static mut libafl_exec_cmp_hook4: unsafe extern "C" fn(u32, u32, u32); - static mut libafl_exec_cmp_hook8: unsafe extern "C" fn(u32, u64, u64); - static mut libafl_gen_cmp_hook: unsafe extern "C" fn(u64, u32) -> u32; + static mut libafl_exec_read_hook1: unsafe extern "C" fn(u64, u64); + static mut libafl_exec_read_hook2: unsafe extern "C" fn(u64, u64); + static mut libafl_exec_read_hook4: unsafe extern "C" fn(u64, u64); + static mut libafl_exec_read_hook8: unsafe extern "C" fn(u64, u64); + static mut libafl_exec_read_hookN: unsafe extern "C" fn(u64, u64, u32); + static mut libafl_gen_read_hook: unsafe extern "C" fn(u32) -> u64; + + static mut libafl_exec_write_hook1: unsafe extern "C" fn(u64, u64); + static mut libafl_exec_write_hook2: unsafe extern "C" fn(u64, u64); + static mut libafl_exec_write_hook4: unsafe extern "C" fn(u64, u64); + static mut libafl_exec_write_hook8: unsafe extern "C" fn(u64, u64); + static mut libafl_exec_write_hookN: unsafe extern "C" fn(u64, u64, u32); + static mut libafl_gen_write_hook: unsafe extern "C" fn(u32) -> u64; + + static mut libafl_exec_cmp_hook1: unsafe extern "C" fn(u64, u8, u8); + static mut libafl_exec_cmp_hook2: unsafe extern "C" fn(u64, u16, u16); + static mut libafl_exec_cmp_hook4: unsafe extern "C" fn(u64, u32, u32); + static mut libafl_exec_cmp_hook8: unsafe extern "C" fn(u64, u64, u64); + static mut libafl_gen_cmp_hook: unsafe extern "C" fn(u64, u32) -> u64; static mut libafl_syscall_hook: unsafe extern "C" fn(i32, u64, u64, u64, u64, u64, u64, u64, u64) -> SyscallHookResult; @@ -283,39 +297,87 @@ pub fn unmap(addr: u64, size: usize) -> Result<(), String> { } } -pub fn set_exec_edge_hook(hook: extern "C" fn(id: u32)) { +pub fn set_exec_edge_hook(hook: extern "C" fn(id: u64)) { unsafe { libafl_exec_edge_hook = hook }; } -pub fn set_gen_edge_hook(hook: extern "C" fn(src: u64, dest: u64) -> u32) { +pub fn set_gen_edge_hook(hook: extern "C" fn(src: u64, dest: u64) -> u64) { unsafe { libafl_gen_edge_hook = hook }; } -pub fn set_exec_block_hook(hook: extern "C" fn(addr: u64)) { +pub fn set_exec_block_hook(hook: extern "C" fn(pc: u64)) { unsafe { libafl_exec_block_hook = hook }; } -pub fn set_gen_block_hook(hook: extern "C" fn(addr: u64) -> u32) { +pub fn set_gen_block_hook(hook: extern "C" fn(pc: u64) -> u64) { unsafe { libafl_gen_block_hook = hook }; } -pub fn set_exec_cmp1_hook(hook: extern "C" fn(id: u32, v0: u8, v1: u8)) { +pub fn set_exec_read1_hook(hook: extern "C" fn(id: u64, addr: u64)) { + unsafe { libafl_exec_read_hook1 = hook }; +} + +pub fn set_exec_read2_hook(hook: extern "C" fn(id: u64, addr: u64)) { + unsafe { libafl_exec_read_hook2 = hook }; +} + +pub fn set_exec_read4_hook(hook: extern "C" fn(id: u64, addr: u64)) { + unsafe { libafl_exec_read_hook4 = hook }; +} + +pub fn set_exec_read8_hook(hook: extern "C" fn(id: u64, addr: u64)) { + unsafe { libafl_exec_read_hook8 = hook }; +} + +pub fn set_exec_read_n_hook(hook: extern "C" fn(id: u64, addr: u64, size: u32)) { + unsafe { libafl_exec_read_hookN = hook }; +} + +pub fn set_gen_read_hook(hook: extern "C" fn(size: u32) -> u64) { + unsafe { libafl_gen_read_hook = hook }; +} + +pub fn set_exec_write1_hook(hook: extern "C" fn(id: u64, addr: u64)) { + unsafe { libafl_exec_write_hook1 = hook }; +} + +pub fn set_exec_write2_hook(hook: extern "C" fn(id: u64, addr: u64)) { + unsafe { libafl_exec_write_hook2 = hook }; +} + +pub fn set_exec_write4_hook(hook: extern "C" fn(id: u64, addr: u64)) { + unsafe { libafl_exec_write_hook4 = hook }; +} + +pub fn set_exec_write8_hook(hook: extern "C" fn(id: u64, addr: u64)) { + unsafe { libafl_exec_write_hook8 = hook }; +} + +pub fn set_exec_write_n_hook(hook: extern "C" fn(id: u64, addr: u64, size: u32)) { + unsafe { libafl_exec_write_hookN = hook }; +} + +pub fn set_gen_write_hook(hook: extern "C" fn(size: u32) -> u64) { + unsafe { libafl_gen_write_hook = hook }; +} + +pub fn set_exec_cmp1_hook(hook: extern "C" fn(id: u64, v0: u8, v1: u8)) { unsafe { libafl_exec_cmp_hook1 = hook }; } -pub fn set_exec_cmp2_hook(hook: extern "C" fn(id: u32, v0: u16, v1: u16)) { +pub fn set_exec_cmp2_hook(hook: extern "C" fn(id: u64, v0: u16, v1: u16)) { unsafe { libafl_exec_cmp_hook2 = hook }; } -pub fn set_exec_cmp4_hook(hook: extern "C" fn(id: u32, v0: u32, v1: u32)) { +pub fn set_exec_cmp4_hook(hook: extern "C" fn(id: u64, v0: u32, v1: u32)) { unsafe { libafl_exec_cmp_hook4 = hook }; } -pub fn set_exec_cmp8_hook(hook: extern "C" fn(id: u32, v0: u64, v1: u64)) { +pub fn set_exec_cmp8_hook(hook: extern "C" fn(id: u64, v0: u64, v1: u64)) { unsafe { libafl_exec_cmp_hook8 = hook }; } -pub fn set_gen_cmp_hook(hook: extern "C" fn(addr: u64, size: u32) -> u32) { +pub fn set_gen_cmp_hook(hook: extern "C" fn(pc: u64, size: u32) -> u64) { unsafe { libafl_gen_cmp_hook = hook }; } diff --git a/libafl_qemu/src/executor.rs b/libafl_qemu/src/executor.rs index e2660c3304..20e1b2cff4 100644 --- a/libafl_qemu/src/executor.rs +++ b/libafl_qemu/src/executor.rs @@ -17,29 +17,47 @@ use crate::{emu, emu::SKIP_EXEC_HOOK}; static mut GEN_EDGE_HOOK_PTR: *const c_void = ptr::null(); static mut GEN_BLOCK_HOOK_PTR: *const c_void = ptr::null(); +static mut GEN_READ_HOOK_PTR: *const c_void = ptr::null(); +static mut GEN_WRITE_HOOK_PTR: *const c_void = ptr::null(); static mut GEN_CMP_HOOK_PTR: *const c_void = ptr::null(); -extern "C" fn gen_edge_hook_wrapper(src: u64, dst: u64) -> u32 { +extern "C" fn gen_edge_hook_wrapper(src: u64, dst: u64) -> u64 { unsafe { let state = (GLOBAL_STATE.state_ptr as *mut S).as_mut().unwrap(); - let func: fn(&mut S, u64, u64) -> Option = transmute(GEN_EDGE_HOOK_PTR); + let func: fn(&mut S, u64, u64) -> Option = transmute(GEN_EDGE_HOOK_PTR); (func)(state, src, dst).map_or(SKIP_EXEC_HOOK, |id| id) } } -extern "C" fn gen_block_hook_wrapper(addr: u64) -> u32 { +extern "C" fn gen_block_hook_wrapper(pc: u64) -> u64 { unsafe { let state = (GLOBAL_STATE.state_ptr as *mut S).as_mut().unwrap(); - let func: fn(&mut S, u64) -> Option = transmute(GEN_BLOCK_HOOK_PTR); - (func)(state, addr).map_or(SKIP_EXEC_HOOK, |id| id) + let func: fn(&mut S, u64) -> Option = transmute(GEN_BLOCK_HOOK_PTR); + (func)(state, pc).map_or(SKIP_EXEC_HOOK, |id| id) } } -extern "C" fn gen_cmp_hook_wrapper(addr: u64, size: u32) -> u32 { +extern "C" fn gen_read_hook_wrapper(size: u32) -> u64 { unsafe { let state = (GLOBAL_STATE.state_ptr as *mut S).as_mut().unwrap(); - let func: fn(&mut S, u64, usize) -> Option = transmute(GEN_CMP_HOOK_PTR); - (func)(state, addr, size as usize).map_or(SKIP_EXEC_HOOK, |id| id) + let func: fn(&mut S, usize) -> Option = transmute(GEN_READ_HOOK_PTR); + (func)(state, size as usize).map_or(SKIP_EXEC_HOOK, |id| id) + } +} + +extern "C" fn gen_write_hook_wrapper(size: u32) -> u64 { + unsafe { + let state = (GLOBAL_STATE.state_ptr as *mut S).as_mut().unwrap(); + let func: fn(&mut S, usize) -> Option = transmute(GEN_WRITE_HOOK_PTR); + (func)(state, size as usize).map_or(SKIP_EXEC_HOOK, |id| id) + } +} + +extern "C" fn gen_cmp_hook_wrapper(pc: u64, size: u32) -> u64 { + unsafe { + let state = (GLOBAL_STATE.state_ptr as *mut S).as_mut().unwrap(); + let func: fn(&mut S, u64, usize) -> Option = transmute(GEN_CMP_HOOK_PTR); + (func)(state, pc, size as usize).map_or(SKIP_EXEC_HOOK, |id| id) } } @@ -86,57 +104,129 @@ where } #[allow(clippy::unused_self)] - pub fn hook_edge_generation(&self, hook: fn(&mut S, src: u64, dest: u64) -> Option) { + pub fn hook_edge_generation(&self, hook: fn(&mut S, src: u64, dest: u64) -> Option) { unsafe { GEN_EDGE_HOOK_PTR = hook as *const _ }; emu::set_gen_edge_hook(gen_edge_hook_wrapper::); } #[allow(clippy::unused_self)] - pub fn hook_edge_execution(&self, hook: extern "C" fn(id: u32)) { + pub fn hook_edge_execution(&self, hook: extern "C" fn(id: u64)) { emu::set_exec_edge_hook(hook); } #[allow(clippy::unused_self)] - pub fn hook_block_generation(&self, hook: fn(&mut S, addr: u64) -> Option) { + pub fn hook_block_generation(&self, hook: fn(&mut S, pc: u64) -> Option) { unsafe { GEN_BLOCK_HOOK_PTR = hook as *const _ }; emu::set_gen_block_hook(gen_block_hook_wrapper::); } #[allow(clippy::unused_self)] - pub fn hook_block_execution(&self, hook: extern "C" fn(addr: u64)) { + pub fn hook_block_execution(&self, hook: extern "C" fn(id: u64)) { emu::set_exec_block_hook(hook); } #[allow(clippy::unused_self)] - pub fn hook_cmp_generation(&self, hook: fn(&mut S, addr: u64, size: usize) -> Option) { + pub fn hook_read_generation(&self, hook: fn(&mut S, size: usize) -> Option) { + unsafe { GEN_READ_HOOK_PTR = hook as *const _ }; + emu::set_gen_read_hook(gen_read_hook_wrapper::); + } + + #[allow(clippy::unused_self)] + pub fn hook_read1_execution(&self, hook: extern "C" fn(id: u64, addr: u64)) { + emu::set_exec_read1_hook(hook); + } + + #[allow(clippy::unused_self)] + pub fn hook_read2_execution(&self, hook: extern "C" fn(id: u64, addr: u64)) { + emu::set_exec_read2_hook(hook); + } + + #[allow(clippy::unused_self)] + pub fn hook_read4_execution(&self, hook: extern "C" fn(id: u64, addr: u64)) { + emu::set_exec_read4_hook(hook); + } + + #[allow(clippy::unused_self)] + pub fn hook_read8_execution(&self, hook: extern "C" fn(id: u64, addr: u64)) { + emu::set_exec_read8_hook(hook); + } + + #[allow(clippy::unused_self)] + pub fn hook_read_n_execution(&self, hook: extern "C" fn(id: u64, addr: u64, size: u32)) { + emu::set_exec_read_n_hook(hook); + } + + #[allow(clippy::unused_self)] + pub fn hook_write_generation(&self, hook: fn(&mut S, size: usize) -> Option) { + unsafe { GEN_WRITE_HOOK_PTR = hook as *const _ }; + emu::set_gen_write_hook(gen_write_hook_wrapper::); + } + + #[allow(clippy::unused_self)] + pub fn hook_write1_execution(&self, hook: extern "C" fn(id: u64, addr: u64)) { + emu::set_exec_write1_hook(hook); + } + + #[allow(clippy::unused_self)] + pub fn hook_write2_execution(&self, hook: extern "C" fn(id: u64, addr: u64)) { + emu::set_exec_write2_hook(hook); + } + + #[allow(clippy::unused_self)] + pub fn hook_write4_execution(&self, hook: extern "C" fn(id: u64, addr: u64)) { + emu::set_exec_write4_hook(hook); + } + + #[allow(clippy::unused_self)] + pub fn hook_write8_execution(&self, hook: extern "C" fn(id: u64, addr: u64)) { + emu::set_exec_write8_hook(hook); + } + + #[allow(clippy::unused_self)] + pub fn hook_write_n_execution(&self, hook: extern "C" fn(id: u64, addr: u64, size: u32)) { + emu::set_exec_write_n_hook(hook); + } + + #[allow(clippy::unused_self)] + pub fn hook_cmp_generation(&self, hook: fn(&mut S, pc: u64, size: usize) -> Option) { unsafe { GEN_CMP_HOOK_PTR = hook as *const _ }; emu::set_gen_cmp_hook(gen_cmp_hook_wrapper::); } #[allow(clippy::unused_self)] - pub fn hook_cmp1_execution(&self, hook: extern "C" fn(id: u32, v0: u8, v1: u8)) { + pub fn hook_cmp1_execution(&self, hook: extern "C" fn(id: u64, v0: u8, v1: u8)) { emu::set_exec_cmp1_hook(hook); } #[allow(clippy::unused_self)] - pub fn hook_cmp2_execution(&self, hook: extern "C" fn(id: u32, v0: u16, v1: u16)) { + pub fn hook_cmp2_execution(&self, hook: extern "C" fn(id: u64, v0: u16, v1: u16)) { emu::set_exec_cmp2_hook(hook); } #[allow(clippy::unused_self)] - pub fn hook_cmp4_execution(&self, hook: extern "C" fn(id: u32, v0: u32, v1: u32)) { + pub fn hook_cmp4_execution(&self, hook: extern "C" fn(id: u64, v0: u32, v1: u32)) { emu::set_exec_cmp4_hook(hook); } #[allow(clippy::unused_self)] - pub fn hook_cmp8_execution(&self, hook: extern "C" fn(id: u32, v0: u64, v1: u64)) { + pub fn hook_cmp8_execution(&self, hook: extern "C" fn(id: u64, v0: u64, v1: u64)) { emu::set_exec_cmp8_hook(hook); } #[allow(clippy::unused_self)] pub fn hook_syscalls( &self, - hook: extern "C" fn(i32, u64, u64, u64, u64, u64, u64, u64, u64) -> SyscallHookResult, + hook: extern "C" fn( + sys_num: i32, + u64, + u64, + u64, + u64, + u64, + u64, + u64, + u64, + ) -> SyscallHookResult, ) { emu::set_syscall_hook(hook); } diff --git a/libafl_qemu/src/hooks.rs b/libafl_qemu/src/hooks.rs index f113c7ccd9..cd8f64fc77 100644 --- a/libafl_qemu/src/hooks.rs +++ b/libafl_qemu/src/hooks.rs @@ -10,8 +10,8 @@ pub use libafl_targets::{ #[derive(Default, Serialize, Deserialize)] pub struct QemuEdgesMapMetadata { - pub map: HashMap<(u64, u64), u32>, - pub current_id: u32, + pub map: HashMap<(u64, u64), u64>, + pub current_id: u64, } impl QemuEdgesMapMetadata { @@ -28,8 +28,8 @@ libafl::impl_serdeany!(QemuEdgesMapMetadata); #[derive(Default, Serialize, Deserialize)] pub struct QemuCmpsMapMetadata { - pub map: HashMap, - pub current_id: u32, + pub map: HashMap, + pub current_id: u64, } impl QemuCmpsMapMetadata { @@ -44,7 +44,7 @@ impl QemuCmpsMapMetadata { libafl::impl_serdeany!(QemuCmpsMapMetadata); -pub fn gen_unique_edge_ids(state: &mut S, src: u64, dest: u64) -> Option +pub fn gen_unique_edge_ids(state: &mut S, src: u64, dest: u64) -> Option where S: HasMetadata, { @@ -59,21 +59,21 @@ where if meta.map.contains_key(&(src, dest)) { Some(*meta.map.get(&(src, dest)).unwrap()) } else { - meta.current_id = ((id + 1) & (EDGES_MAP_SIZE - 1)) as u32; + meta.current_id = ((id + 1) & (EDGES_MAP_SIZE - 1)) as u64; unsafe { MAX_EDGES_NUM = meta.current_id as usize }; - Some(id as u32) + Some(id as u64) } } -pub extern "C" fn trace_edge_hitcount(id: u32) { +pub extern "C" fn trace_edge_hitcount(id: u64) { unsafe { EDGES_MAP[id as usize] += 1 }; } -pub extern "C" fn trace_edge_single(id: u32) { +pub extern "C" fn trace_edge_single(id: u64) { unsafe { EDGES_MAP[id as usize] = 1 }; } -pub fn gen_unique_cmp_ids(state: &mut S, addr: u64, _size: usize) -> Option +pub fn gen_unique_cmp_ids(state: &mut S, pc: u64, _size: usize) -> Option where S: HasMetadata, { @@ -85,26 +85,26 @@ where .get_mut::() .unwrap(); let id = meta.current_id as usize; - if meta.map.contains_key(&addr) { - Some(*meta.map.get(&addr).unwrap()) + if meta.map.contains_key(&pc) { + Some(*meta.map.get(&pc).unwrap()) } else { - meta.current_id = ((id + 1) & (CMPLOG_MAP_W - 1)) as u32; - Some(id as u32) + meta.current_id = ((id + 1) & (CMPLOG_MAP_W - 1)) as u64; + Some(id as u64) } } -pub extern "C" fn trace_cmp1_cmplog(id: u32, v0: u8, v1: u8) { +pub extern "C" fn trace_cmp1_cmplog(id: u64, v0: u8, v1: u8) { unsafe { __libafl_targets_cmplog_instructions(id as usize, 1, u64::from(v0), u64::from(v1)) } } -pub extern "C" fn trace_cmp2_cmplog(id: u32, v0: u16, v1: u16) { +pub extern "C" fn trace_cmp2_cmplog(id: u64, v0: u16, v1: u16) { unsafe { __libafl_targets_cmplog_instructions(id as usize, 2, u64::from(v0), u64::from(v1)) } } -pub extern "C" fn trace_cmp4_cmplog(id: u32, v0: u32, v1: u32) { +pub extern "C" fn trace_cmp4_cmplog(id: u64, v0: u32, v1: u32) { unsafe { __libafl_targets_cmplog_instructions(id as usize, 4, u64::from(v0), u64::from(v1)) } } -pub extern "C" fn trace_cmp8_cmplog(id: u32, v0: u64, v1: u64) { +pub extern "C" fn trace_cmp8_cmplog(id: u64, v0: u64, v1: u64) { unsafe { __libafl_targets_cmplog_instructions(id as usize, 8, v0, v1) } } diff --git a/libafl_qemu/src/weaks.c b/libafl_qemu/src/weaks.c index 0dfe19d91a..73cb4838ed 100644 --- a/libafl_qemu/src/weaks.c +++ b/libafl_qemu/src/weaks.c @@ -61,16 +61,30 @@ __attribute__((weak)) int target_munmap(abi_ulong start, abi_ulong len) { __attribute__((weak)) char* exec_path = NULL; __attribute__((weak)) size_t guest_base = 0; -__attribute__((weak)) void (*libafl_exec_edge_hook)(uint32_t); -__attribute__((weak)) uint32_t (*libafl_gen_edge_hook)(uint64_t, uint64_t); +__attribute__((weak)) void (*libafl_exec_edge_hook)(uint64_t); +__attribute__((weak)) uint64_t (*libafl_gen_edge_hook)(uint64_t, uint64_t); __attribute__((weak)) void (*libafl_exec_block_hook)(uint64_t); -__attribute__((weak)) uint32_t (*libafl_gen_block_hook)(uint64_t); +__attribute__((weak)) uint64_t (*libafl_gen_block_hook)(uint64_t); -__attribute__((weak)) void (*libafl_exec_cmp_hook1)(uint32_t, uint8_t, uint8_t); -__attribute__((weak)) void (*libafl_exec_cmp_hook2)(uint32_t, uint16_t, uint16_t); -__attribute__((weak)) void (*libafl_exec_cmp_hook4)(uint32_t, uint32_t, uint32_t); -__attribute__((weak)) void (*libafl_exec_cmp_hook8)(uint32_t, uint64_t, uint64_t); -__attribute__((weak)) uint32_t (*libafl_gen_cmp_hook)(uint64_t, uint32_t); +__attribute__((weak)) void (*libafl_exec_read_hook1)(uint64_t, uint64_t); +__attribute__((weak)) void (*libafl_exec_read_hook2)(uint64_t, uint64_t); +__attribute__((weak)) void (*libafl_exec_read_hook4)(uint64_t, uint64_t); +__attribute__((weak)) void (*libafl_exec_read_hook8)(uint64_t, uint64_t); +__attribute__((weak)) void (*libafl_exec_read_hookN)(uint64_t, uint64_t, uint32_t); +__attribute__((weak)) uint64_t (*libafl_gen_read_hook)(uint32_t); + +__attribute__((weak)) void (*libafl_exec_write_hook1)(uint64_t, uint64_t); +__attribute__((weak)) void (*libafl_exec_write_hook2)(uint64_t, uint64_t); +__attribute__((weak)) void (*libafl_exec_write_hook4)(uint64_t, uint64_t); +__attribute__((weak)) void (*libafl_exec_write_hook8)(uint64_t, uint64_t); +__attribute__((weak)) void (*libafl_exec_write_hookN)(uint64_t, uint64_t, uint32_t); +__attribute__((weak)) uint64_t (*libafl_gen_write_hook)(uint32_t); + +__attribute__((weak)) void (*libafl_exec_cmp_hook1)(uint64_t, uint8_t, uint8_t); +__attribute__((weak)) void (*libafl_exec_cmp_hook2)(uint64_t, uint16_t, uint16_t); +__attribute__((weak)) void (*libafl_exec_cmp_hook4)(uint64_t, uint32_t, uint32_t); +__attribute__((weak)) void (*libafl_exec_cmp_hook8)(uint64_t, uint64_t, uint64_t); +__attribute__((weak)) uint64_t (*libafl_gen_cmp_hook)(uint64_t, uint32_t); struct syshook_ret { uint64_t retval; diff --git a/libafl_sugar/src/qemu.rs b/libafl_sugar/src/qemu.rs index 6b69da4b6c..92028713c9 100644 --- a/libafl_sugar/src/qemu.rs +++ b/libafl_sugar/src/qemu.rs @@ -65,6 +65,21 @@ where /// Bytes harness #[builder(setter(strip_option))] harness: Option, + // Syscall hook + #[builder(default = None, setter(strip_option))] + syscall_hook: Option< + extern "C" fn( + sys_num: i32, + u64, + u64, + u64, + u64, + u64, + u64, + u64, + u64, + ) -> emu::SyscallHookResult, + >, } impl<'a, H> QemuBytesCoverageSugar<'a, H> @@ -171,6 +186,11 @@ where executor.hook_edge_generation(hooks::gen_unique_edge_ids); executor.hook_edge_execution(hooks::trace_edge_hitcount); + // Hook the syscalls + if let Some(hook) = self.syscall_hook { + executor.hook_syscalls(hook); + } + // Create the executor for an in-process function with one observer for edge coverage and one for the execution time let mut executor = TimeoutExecutor::new(executor, timeout);