Write coverage for QEMU into separate files (#1571)
Co-authored-by: Your Name <you@example.com>
This commit is contained in:
parent
78fd4e0d39
commit
9755d189dd
@ -29,4 +29,5 @@ clap = { version = "4.3.0", features = ["derive", "string"]}
|
|||||||
libafl = { path = "../../libafl/" }
|
libafl = { path = "../../libafl/" }
|
||||||
libafl_bolts = { path = "../../libafl_bolts/" }
|
libafl_bolts = { path = "../../libafl_bolts/" }
|
||||||
libafl_qemu = { path = "../../libafl_qemu/", features = ["usermode"] }
|
libafl_qemu = { path = "../../libafl_qemu/", features = ["usermode"] }
|
||||||
|
log = {version = "0.4.20" }
|
||||||
rangemap = { version = "1.3" }
|
rangemap = { version = "1.3" }
|
||||||
|
@ -194,6 +194,7 @@ args = [
|
|||||||
dependencies = ["build"]
|
dependencies = ["build"]
|
||||||
script_runner="@shell"
|
script_runner="@shell"
|
||||||
script='''
|
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}
|
mv ${TARGET_DIR}/${PROFILE_DIR}/qemu_coverage ${TARGET_DIR}/${PROFILE_DIR}/qemu_coverage-${CARGO_MAKE_PROFILE}
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
@ -89,6 +89,8 @@ pub struct FuzzerOptions {
|
|||||||
args: Vec<String>,
|
args: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const MAX_INPUT_SIZE: usize = 1048576; // 1MB
|
||||||
|
|
||||||
pub fn fuzz() {
|
pub fn fuzz() {
|
||||||
let mut options = FuzzerOptions::parse();
|
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 files_per_core = (num_files as f64 / num_cores as f64).ceil() as usize;
|
||||||
|
|
||||||
let program = env::args().next().unwrap();
|
let program = env::args().next().unwrap();
|
||||||
println!("Program: {program:}");
|
log::debug!("Program: {program:}");
|
||||||
|
|
||||||
options.args.insert(0, program);
|
options.args.insert(0, program);
|
||||||
println!("ARGS: {:#?}", options.args);
|
log::debug!("ARGS: {:#?}", options.args);
|
||||||
|
|
||||||
env::remove_var("LD_LIBRARY_PATH");
|
env::remove_var("LD_LIBRARY_PATH");
|
||||||
let env: Vec<(String, String)> = env::vars().collect();
|
let env: Vec<(String, String)> = env::vars().collect();
|
||||||
@ -120,13 +122,12 @@ pub fn fuzz() {
|
|||||||
let test_one_input_ptr = elf
|
let test_one_input_ptr = elf
|
||||||
.resolve_symbol("LLVMFuzzerTestOneInput", emu.load_addr())
|
.resolve_symbol("LLVMFuzzerTestOneInput", emu.load_addr())
|
||||||
.expect("Symbol LLVMFuzzerTestOneInput not found");
|
.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);
|
emu.entry_break(test_one_input_ptr);
|
||||||
unsafe { emu.run() };
|
|
||||||
|
|
||||||
for m in emu.mappings() {
|
for m in emu.mappings() {
|
||||||
println!(
|
log::debug!(
|
||||||
"Mapping: 0x{:016x}-0x{:016x}, {}",
|
"Mapping: 0x{:016x}-0x{:016x}, {}",
|
||||||
m.start(),
|
m.start(),
|
||||||
m.end(),
|
m.end(),
|
||||||
@ -135,16 +136,17 @@ pub fn fuzz() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let pc: GuestReg = emu.read_reg(Regs::Pc).unwrap();
|
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();
|
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);
|
emu.set_breakpoint(ret_addr);
|
||||||
|
|
||||||
let input_addr = emu.map_private(0, 4096, MmapPerms::ReadWrite).unwrap();
|
let input_addr = emu
|
||||||
println!("Placing input at {input_addr:#x}");
|
.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();
|
let stack_ptr: GuestAddr = emu.read_reg(Regs::Sp).unwrap();
|
||||||
|
|
||||||
@ -163,12 +165,13 @@ pub fn fuzz() {
|
|||||||
|
|
||||||
let mut harness = |input: &BytesInput| {
|
let mut harness = |input: &BytesInput| {
|
||||||
let target = input.target_bytes();
|
let target = input.target_bytes();
|
||||||
let buf = target
|
let mut buf = target.as_slice();
|
||||||
.as_slice()
|
let mut len = buf.len();
|
||||||
.chunks(4096)
|
if len > MAX_INPUT_SIZE {
|
||||||
.next()
|
buf = &buf[0..MAX_INPUT_SIZE];
|
||||||
.expect("Failed to get chunk");
|
len = MAX_INPUT_SIZE;
|
||||||
let len = buf.len() as GuestReg;
|
}
|
||||||
|
let len = len as GuestReg;
|
||||||
reset(buf, len).unwrap();
|
reset(buf, len).unwrap();
|
||||||
ExitKind::Ok
|
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(
|
let mut hooks = QemuHooks::new(
|
||||||
&emu,
|
&emu,
|
||||||
tuple_list!(QemuDrCovHelper::new(
|
tuple_list!(QemuDrCovHelper::new(
|
||||||
QemuInstrumentationFilter::None,
|
QemuInstrumentationFilter::None,
|
||||||
rangemap,
|
rangemap,
|
||||||
PathBuf::from(&options.coverage),
|
PathBuf::from(coverage),
|
||||||
false,
|
false,
|
||||||
)),
|
)),
|
||||||
);
|
);
|
||||||
@ -255,10 +264,10 @@ pub fn fuzz() {
|
|||||||
println!("Failed to load initial corpus at {:?}", &corpus_dir);
|
println!("Failed to load initial corpus at {:?}", &corpus_dir);
|
||||||
process::exit(0);
|
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()?;
|
mgr.send_exiting()?;
|
||||||
Err(Error::ShuttingDown)?
|
Err(Error::ShuttingDown)?
|
||||||
|
Loading…
x
Reference in New Issue
Block a user