diff --git a/fuzzers/qemu_coverage/Cargo.toml b/fuzzers/qemu_coverage/Cargo.toml index d9424a374c..fe2c6f1ecb 100644 --- a/fuzzers/qemu_coverage/Cargo.toml +++ b/fuzzers/qemu_coverage/Cargo.toml @@ -29,4 +29,5 @@ clap = { version = "4.3.0", features = ["derive", "string"]} libafl = { path = "../../libafl/" } libafl_bolts = { path = "../../libafl_bolts/" } libafl_qemu = { path = "../../libafl_qemu/", features = ["usermode"] } +log = {version = "0.4.20" } rangemap = { version = "1.3" } diff --git a/fuzzers/qemu_coverage/Makefile.toml b/fuzzers/qemu_coverage/Makefile.toml index 6f3e0ae01b..0fbf461de8 100644 --- a/fuzzers/qemu_coverage/Makefile.toml +++ b/fuzzers/qemu_coverage/Makefile.toml @@ -194,6 +194,7 @@ args = [ dependencies = ["build"] script_runner="@shell" script=''' +rm -f ${TARGET_DIR}/${PROFILE_DIR}/qemu_coverage-${CARGO_MAKE_PROFILE} mv ${TARGET_DIR}/${PROFILE_DIR}/qemu_coverage ${TARGET_DIR}/${PROFILE_DIR}/qemu_coverage-${CARGO_MAKE_PROFILE} ''' diff --git a/fuzzers/qemu_coverage/src/fuzzer.rs b/fuzzers/qemu_coverage/src/fuzzer.rs index 2742575c99..d6df3637d8 100644 --- a/fuzzers/qemu_coverage/src/fuzzer.rs +++ b/fuzzers/qemu_coverage/src/fuzzer.rs @@ -89,6 +89,8 @@ pub struct FuzzerOptions { args: Vec, } +pub const MAX_INPUT_SIZE: usize = 1048576; // 1MB + pub fn fuzz() { let mut options = FuzzerOptions::parse(); @@ -105,10 +107,10 @@ pub fn fuzz() { let files_per_core = (num_files as f64 / num_cores as f64).ceil() as usize; let program = env::args().next().unwrap(); - println!("Program: {program:}"); + log::debug!("Program: {program:}"); options.args.insert(0, program); - println!("ARGS: {:#?}", options.args); + log::debug!("ARGS: {:#?}", options.args); env::remove_var("LD_LIBRARY_PATH"); let env: Vec<(String, String)> = env::vars().collect(); @@ -120,13 +122,12 @@ pub fn fuzz() { let test_one_input_ptr = elf .resolve_symbol("LLVMFuzzerTestOneInput", emu.load_addr()) .expect("Symbol LLVMFuzzerTestOneInput not found"); - println!("LLVMFuzzerTestOneInput @ {test_one_input_ptr:#x}"); + log::debug!("LLVMFuzzerTestOneInput @ {test_one_input_ptr:#x}"); - emu.set_breakpoint(test_one_input_ptr); - unsafe { emu.run() }; + emu.entry_break(test_one_input_ptr); for m in emu.mappings() { - println!( + log::debug!( "Mapping: 0x{:016x}-0x{:016x}, {}", m.start(), m.end(), @@ -135,16 +136,17 @@ pub fn fuzz() { } let pc: GuestReg = emu.read_reg(Regs::Pc).unwrap(); - println!("Break at {pc:#x}"); + log::debug!("Break at {pc:#x}"); let ret_addr: GuestAddr = emu.read_return_address().unwrap(); - println!("Return address = {ret_addr:#x}"); + log::debug!("Return address = {ret_addr:#x}"); - emu.remove_breakpoint(test_one_input_ptr); emu.set_breakpoint(ret_addr); - let input_addr = emu.map_private(0, 4096, MmapPerms::ReadWrite).unwrap(); - println!("Placing input at {input_addr:#x}"); + let input_addr = emu + .map_private(0, MAX_INPUT_SIZE, MmapPerms::ReadWrite) + .unwrap(); + log::debug!("Placing input at {input_addr:#x}"); let stack_ptr: GuestAddr = emu.read_reg(Regs::Sp).unwrap(); @@ -163,12 +165,13 @@ pub fn fuzz() { let mut harness = |input: &BytesInput| { let target = input.target_bytes(); - let buf = target - .as_slice() - .chunks(4096) - .next() - .expect("Failed to get chunk"); - let len = buf.len() as GuestReg; + let mut buf = target.as_slice(); + let mut len = buf.len(); + if len > MAX_INPUT_SIZE { + buf = &buf[0..MAX_INPUT_SIZE]; + len = MAX_INPUT_SIZE; + } + let len = len as GuestReg; reset(buf, len).unwrap(); ExitKind::Ok }; @@ -226,12 +229,18 @@ pub fn fuzz() { }, ); + let mut coverage = PathBuf::from(&options.coverage); + let coverage_name = coverage.file_stem().unwrap().to_str().unwrap(); + let coverage_extension = coverage.extension().unwrap_or_default().to_str().unwrap(); + let core = core_id.0; + coverage.set_file_name(format!("{coverage_name}-{core:03}.{coverage_extension}")); + let mut hooks = QemuHooks::new( &emu, tuple_list!(QemuDrCovHelper::new( QemuInstrumentationFilter::None, rangemap, - PathBuf::from(&options.coverage), + PathBuf::from(coverage), false, )), ); @@ -255,10 +264,10 @@ pub fn fuzz() { println!("Failed to load initial corpus at {:?}", &corpus_dir); process::exit(0); }); - println!("We imported {} inputs from disk.", state.corpus().count()); + log::debug!("We imported {} inputs from disk.", state.corpus().count()); } - println!("Processed {} inputs from disk.", files.len()); + log::debug!("Processed {} inputs from disk.", files.len()); mgr.send_exiting()?; Err(Error::ShuttingDown)?