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
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:
* arm

View File

@ -28,10 +28,8 @@ use libafl_bolts::{
AsSlice,
};
use libafl_qemu::{
elf::EasyElf,
modules::{drcov::DrCovModule, utils::filters::StdAddressFilter},
ArchExtras, CallingConvention, Emulator, GuestAddr, GuestReg, MmapPerms, QemuExecutor,
QemuExitReason, QemuRWError, QemuShutdownCause, Regs,
elf::EasyElf, modules::drcov::DrCovModule, ArchExtras, CallingConvention, Emulator, GuestAddr,
GuestReg, MmapPerms, Qemu, QemuExecutor, QemuExitReason, QemuRWError, QemuShutdownCause, Regs,
};
#[derive(Default)]
@ -127,9 +125,14 @@ pub fn fuzz() {
mut mgr: LlmpRestartingEventManager<_, _, _, _, _>,
client_description: ClientDescription| {
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()
.filter(StdAddressFilter::default())
.filename(cov_path.clone())
.full_trace(false)
.build());
@ -175,7 +178,7 @@ pub fn fuzz() {
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 {
let _ = qemu.write_mem(input_addr, buf);
qemu.write_reg(Regs::Pc, test_one_input_ptr)?;
@ -197,7 +200,9 @@ pub fn fuzz() {
};
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 mut buf = target.as_slice();
let mut len = buf.len();
@ -206,7 +211,13 @@ pub fn fuzz() {
len = MAX_INPUT_SIZE;
}
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
};
@ -215,6 +226,7 @@ pub fn fuzz() {
.cores
.position(core_id)
.expect("Failed to get core index");
let files = corpus_files
.iter()
.skip(files_per_core * core_idx)
@ -245,11 +257,6 @@ pub fn fuzz() {
let scheduler = QueueScheduler::new();
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(
emulator,
&mut harness,

View File

@ -207,7 +207,7 @@ where
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() {
state.add_metadata(QemuCmpsMapMetadata::new());
}

View File

@ -265,26 +265,27 @@ where
I: Unpin,
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
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(
Hook::Function(gen_unique_block_ids::<ET, F, I, S>),
Hook::Function(gen_block_lengths::<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() {
log::info!("Auto-filling module mapping for DrCov module from QEMU mapping.");
@ -392,7 +393,7 @@ where
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
.metadata_map_mut()
.get_mut::<DrCovMetadata>()

View File

@ -133,7 +133,7 @@ mod generators {
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);
match meta.map.entry((src, dest)) {