Fix qemu cov (#2875)

* fix drcov module hooks setup
This commit is contained in:
Romain Malmain 2025-01-22 14:05:25 +01:00 committed by GitHub
parent 2842f95e2a
commit d9e8b59cb6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 36 additions and 28 deletions

View File

@ -2,7 +2,7 @@
This folder contains an example fuzzer which runs each entry in the input corpus and collects This folder contains an example fuzzer which runs each entry in the input corpus and collects
the cumuative coverage data in drcov format. This fuzzer also distributes the test cases in the cumuative coverage data in drcov format. This fuzzer also distributes the test cases in
the input corupus evenly across the selected cores. the input corpus evenly across the selected cores.
The following architectures are supported: The following architectures are supported:
* arm * arm

View File

@ -28,10 +28,8 @@ use libafl_bolts::{
AsSlice, AsSlice,
}; };
use libafl_qemu::{ use libafl_qemu::{
elf::EasyElf, elf::EasyElf, modules::drcov::DrCovModule, ArchExtras, CallingConvention, Emulator, GuestAddr,
modules::{drcov::DrCovModule, utils::filters::StdAddressFilter}, GuestReg, MmapPerms, Qemu, QemuExecutor, QemuExitReason, QemuRWError, QemuShutdownCause, Regs,
ArchExtras, CallingConvention, Emulator, GuestAddr, GuestReg, MmapPerms, QemuExecutor,
QemuExitReason, QemuRWError, QemuShutdownCause, Regs,
}; };
#[derive(Default)] #[derive(Default)]
@ -127,9 +125,14 @@ pub fn fuzz() {
mut mgr: LlmpRestartingEventManager<_, _, _, _, _>, mut mgr: LlmpRestartingEventManager<_, _, _, _, _>,
client_description: ClientDescription| { client_description: ClientDescription| {
let mut cov_path = options.coverage_path.clone(); let mut cov_path = options.coverage_path.clone();
let core_id = client_description.core_id();
let coverage_name = cov_path.file_stem().unwrap().to_str().unwrap();
let coverage_extension = cov_path.extension().unwrap_or_default().to_str().unwrap();
let core = core_id.0;
cov_path.set_file_name(format!("{coverage_name}-{core:03}.{coverage_extension}"));
let emulator_modules = tuple_list!(DrCovModule::builder() let emulator_modules = tuple_list!(DrCovModule::builder()
.filter(StdAddressFilter::default())
.filename(cov_path.clone()) .filename(cov_path.clone())
.full_trace(false) .full_trace(false)
.build()); .build());
@ -175,7 +178,7 @@ pub fn fuzz() {
let stack_ptr: GuestAddr = qemu.read_reg(Regs::Sp).unwrap(); let stack_ptr: GuestAddr = qemu.read_reg(Regs::Sp).unwrap();
let reset = |buf: &[u8], len: GuestReg| -> Result<(), QemuRWError> { let reset = |qemu: Qemu, buf: &[u8], len: GuestReg| -> Result<(), QemuRWError> {
unsafe { unsafe {
let _ = qemu.write_mem(input_addr, buf); let _ = qemu.write_mem(input_addr, buf);
qemu.write_reg(Regs::Pc, test_one_input_ptr)?; qemu.write_reg(Regs::Pc, test_one_input_ptr)?;
@ -197,7 +200,9 @@ pub fn fuzz() {
}; };
let mut harness = let mut harness =
|_emulator: &mut Emulator<_, _, _, _, _, _, _>, _state: &mut _, input: &BytesInput| { |emulator: &mut Emulator<_, _, _, _, _, _, _>, state: &mut _, input: &BytesInput| {
let qemu = emulator.qemu();
let target = input.target_bytes(); let target = input.target_bytes();
let mut buf = target.as_slice(); let mut buf = target.as_slice();
let mut len = buf.len(); let mut len = buf.len();
@ -206,7 +211,13 @@ pub fn fuzz() {
len = MAX_INPUT_SIZE; len = MAX_INPUT_SIZE;
} }
let len = len as GuestReg; let len = len as GuestReg;
reset(buf, len).unwrap(); reset(qemu, buf, len).unwrap();
unsafe {
let ret = emulator.run(state, input);
log::warn!("ret = {ret:?}");
}
ExitKind::Ok ExitKind::Ok
}; };
@ -215,6 +226,7 @@ pub fn fuzz() {
.cores .cores
.position(core_id) .position(core_id)
.expect("Failed to get core index"); .expect("Failed to get core index");
let files = corpus_files let files = corpus_files
.iter() .iter()
.skip(files_per_core * core_idx) .skip(files_per_core * core_idx)
@ -245,11 +257,6 @@ pub fn fuzz() {
let scheduler = QueueScheduler::new(); let scheduler = QueueScheduler::new();
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);
let coverage_name = cov_path.file_stem().unwrap().to_str().unwrap();
let coverage_extension = cov_path.extension().unwrap_or_default().to_str().unwrap();
let core = core_id.0;
cov_path.set_file_name(format!("{coverage_name}-{core:03}.{coverage_extension}"));
let mut executor = QemuExecutor::new( let mut executor = QemuExecutor::new(
emulator, emulator,
&mut harness, &mut harness,

View File

@ -207,7 +207,7 @@ where
return None; return None;
} }
} }
let state = state.expect("The gen_unique_cmp_ids hook works only for in-process fuzzing"); let state = state.expect("The gen_unique_cmp_ids hook works only for in-process fuzzing. Is the Executor initialized?");
if state.metadata_map().get::<QemuCmpsMapMetadata>().is_none() { if state.metadata_map().get::<QemuCmpsMapMetadata>().is_none() {
state.add_metadata(QemuCmpsMapMetadata::new()); state.add_metadata(QemuCmpsMapMetadata::new());
} }

View File

@ -265,26 +265,27 @@ where
I: Unpin, I: Unpin,
S: Unpin + HasMetadata, S: Unpin + HasMetadata,
{ {
fn post_qemu_init<ET>(&mut self, _qemu: Qemu, emulator_modules: &mut EmulatorModules<ET, I, S>) fn post_qemu_init<ET>(&mut self, _qemu: Qemu, _emulator_modules: &mut EmulatorModules<ET, I, S>)
where where
ET: EmulatorModuleTuple<I, S>, ET: EmulatorModuleTuple<I, S>,
{
}
#[cfg(feature = "usermode")]
fn first_exec<ET>(
&mut self,
qemu: Qemu,
emulator_modules: &mut EmulatorModules<ET, I, S>,
_state: &mut S,
) where
ET: EmulatorModuleTuple<I, S>,
{ {
emulator_modules.blocks( emulator_modules.blocks(
Hook::Function(gen_unique_block_ids::<ET, F, I, S>), Hook::Function(gen_unique_block_ids::<ET, F, I, S>),
Hook::Function(gen_block_lengths::<ET, F, I, S>), Hook::Function(gen_block_lengths::<ET, F, I, S>),
Hook::Function(exec_trace_block::<ET, F, I, S>), Hook::Function(exec_trace_block::<ET, F, I, S>),
); );
}
#[cfg(feature = "usermode")]
fn first_exec<ET>(
&mut self,
qemu: Qemu,
_emulator_modules: &mut EmulatorModules<ET, I, S>,
_state: &mut S,
) where
ET: EmulatorModuleTuple<I, S>,
{
if self.module_mapping.is_none() { if self.module_mapping.is_none() {
log::info!("Auto-filling module mapping for DrCov module from QEMU mapping."); log::info!("Auto-filling module mapping for DrCov module from QEMU mapping.");
@ -392,7 +393,7 @@ where
return None; return None;
} }
let state = state.expect("The gen_unique_block_ids hook works only for in-process fuzzing"); let state = state.expect("The gen_unique_block_ids hook works only for in-process fuzzing. Is the Executor initialized?");
if state if state
.metadata_map_mut() .metadata_map_mut()
.get_mut::<DrCovMetadata>() .get_mut::<DrCovMetadata>()

View File

@ -133,7 +133,7 @@ mod generators {
let mask: usize = get_mask::<IS_CONST_MAP, MAP_SIZE>(); let mask: usize = get_mask::<IS_CONST_MAP, MAP_SIZE>();
let state = state.expect("The gen_unique_edge_ids hook works only for in-process fuzzing"); let state = state.expect("The gen_unique_edge_ids hook works only for in-process fuzzing. Is the Executor initialized?");
let meta = state.metadata_or_insert_with(QemuEdgesMapMetadata::new); let meta = state.metadata_or_insert_with(QemuEdgesMapMetadata::new);
match meta.map.entry((src, dest)) { match meta.map.entry((src, dest)) {