Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor of Qemu configuration #2707

Merged
merged 36 commits into from
Jan 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
af20343
qemu config refactoring
rmalmain Nov 19, 2024
5fa831a
Merge branch 'main' into qemu_builder_update
rmalmain Nov 22, 2024
28655d8
* QEMU error refactoring*
rmalmain Nov 25, 2024
b85ab06
update test
rmalmain Nov 25, 2024
47d2741
Light refactor of EmulatorModules
rmalmain Nov 26, 2024
0d37b78
Merge branch 'main' into qemu_builder_update
rmalmain Nov 26, 2024
1c61b38
fmt
rmalmain Nov 26, 2024
525fd11
* asan fixed size accesses working with generics
rmalmain Nov 26, 2024
5346f83
fmt
rmalmain Nov 26, 2024
17059d7
fix fuzzers
rmalmain Nov 27, 2024
c50ba05
* refactor asan and asanguest modules to avoid custom init of QEMU an…
rmalmain Nov 27, 2024
8d8631e
fmt
rmalmain Nov 27, 2024
f2491c1
clippy
rmalmain Nov 27, 2024
a12dc91
Merge branch 'main' into qemu_builder_update
rmalmain Nov 27, 2024
76480c1
fix qemu_coverage
rmalmain Nov 27, 2024
46f0da7
fmt
rmalmain Nov 27, 2024
3464e44
forgot qemu args in launcher
rmalmain Nov 28, 2024
005475b
use correct args
rmalmain Nov 28, 2024
ea840cf
adapt api
rmalmain Nov 28, 2024
2998445
testing stuff
rmalmain Nov 28, 2024
c5b3e19
Merge branch 'main' into qemu_builder_update
rmalmain Dec 5, 2024
0fe2977
new builder?
rmalmain Dec 5, 2024
b7f5240
use closure for qemu config from emulator builder.
rmalmain Dec 5, 2024
413767f
better format
rmalmain Dec 5, 2024
8b04e3f
clippy + fmt
rmalmain Dec 5, 2024
a9aac40
Merge branch 'main' into qemu_builder_update
rmalmain Jan 6, 2025
3703ed3
allow -> expect
rmalmain Jan 6, 2025
749aea9
fix bloom
rmalmain Jan 6, 2025
7366985
revert configuration through closure, doesn't seem more natural than …
rmalmain Jan 6, 2025
085eca2
remove dynamic builder
rmalmain Jan 6, 2025
4b0510f
remove derive_builder
rmalmain Jan 6, 2025
cb65e6c
start writing emulator doc.
rmalmain Jan 6, 2025
71921c6
AsRawFd import
rmalmain Jan 6, 2025
a06bd6f
fmt
rmalmain Jan 6, 2025
74be6bf
allow and not expect
rmalmain Jan 6, 2025
a36e501
fix builder call
rmalmain Jan 6, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion fuzzers/binary_only/fuzzbench_fork_qemu/src/fuzzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ fn fuzz(
);

let emulator = Emulator::empty()
.qemu_cli(args)
.qemu_parameters(args)
.modules(emulator_modules)
.build()?;

Expand Down
52 changes: 27 additions & 25 deletions fuzzers/binary_only/fuzzbench_qemu/src/fuzzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ use libafl_qemu::{
GuestReg,
//snapshot::QemuSnapshotHelper,
MmapPerms,
Qemu,
QemuExecutor,
QemuExitError,
QemuExitReason,
Expand Down Expand Up @@ -175,8 +174,33 @@ fn fuzz(
env::remove_var("LD_LIBRARY_PATH");

let args: Vec<String> = env::args().collect();
let qemu = Qemu::init(&args).expect("QEMU init failed");
// let (emu, asan) = init_with_asan(&mut args, &mut env).unwrap();

// Create an observation channel using the coverage map
let mut edges_observer = unsafe {
HitcountsMapObserver::new(VariableMapObserver::from_mut_slice(
"edges",
OwnedMutSlice::from_raw_parts_mut(edges_map_mut_ptr(), EDGES_MAP_ALLOCATED_SIZE),
&raw mut MAX_EDGES_FOUND,
))
.track_indices()
};

let modules = tuple_list!(
StdEdgeCoverageModule::builder()
.map_observer(edges_observer.as_mut())
.build()
.unwrap(),
CmpLogModule::default(),
// QemuAsanHelper::default(asan),
//QemuSnapshotHelper::new()
);

let emulator = Emulator::empty()
.qemu_parameters(args)
.modules(modules)
.build()?;

let qemu = emulator.qemu();

let mut elf_buffer = Vec::new();
let elf = EasyElf::from_file(qemu.binary_path(), &mut elf_buffer)?;
Expand Down Expand Up @@ -255,16 +279,6 @@ fn fuzz(
},
};

// Create an observation channel using the coverage map
let mut edges_observer = unsafe {
HitcountsMapObserver::new(VariableMapObserver::from_mut_slice(
"edges",
OwnedMutSlice::from_raw_parts_mut(edges_map_mut_ptr(), EDGES_MAP_ALLOCATED_SIZE),
&raw mut MAX_EDGES_FOUND,
))
.track_indices()
};

// Create an observation channel to keep track of the execution time
let time_observer = TimeObserver::new("time");

Expand Down Expand Up @@ -364,18 +378,6 @@ fn fuzz(
ExitKind::Ok
};

let modules = tuple_list!(
StdEdgeCoverageModule::builder()
.map_observer(edges_observer.as_mut())
.build()
.unwrap(),
CmpLogModule::default(),
// QemuAsanHelper::default(asan),
//QemuSnapshotHelper::new()
);

let emulator = Emulator::empty().qemu(qemu).modules(modules).build()?;

// Create the executor for an in-process function with one observer for edge coverage and one for the execution time
let executor = QemuExecutor::new(
emulator,
Expand Down
51 changes: 27 additions & 24 deletions fuzzers/binary_only/qemu_cmin/src/fuzzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ use libafl_bolts::{
};
use libafl_qemu::{
elf::EasyElf, modules::edges::StdEdgeCoverageChildModule, ArchExtras, CallingConvention,
Emulator, GuestAddr, GuestReg, MmapPerms, Qemu, QemuExitError, QemuExitReason,
QemuForkExecutor, QemuShutdownCause, Regs,
Emulator, GuestAddr, GuestReg, MmapPerms, QemuExitError, QemuExitReason, QemuForkExecutor,
QemuShutdownCause, Regs,
};
use libafl_targets::{EDGES_MAP_DEFAULT_SIZE, EDGES_MAP_PTR};

Expand Down Expand Up @@ -113,7 +113,31 @@ pub fn fuzz() -> Result<(), Error> {
log::debug!("ARGS: {:#?}", options.args);

env::remove_var("LD_LIBRARY_PATH");
let qemu = Qemu::init(&options.args).unwrap();

let mut shmem_provider = StdShMemProvider::new().expect("Failed to init shared memory");

let mut edges_shmem = shmem_provider.new_shmem(EDGES_MAP_DEFAULT_SIZE).unwrap();
let edges = edges_shmem.as_slice_mut();
unsafe { EDGES_MAP_PTR = edges.as_mut_ptr() };

let mut edges_observer = unsafe {
HitcountsMapObserver::new(ConstMapObserver::from_mut_ptr(
"edges",
NonNull::new(edges.as_mut_ptr())
.expect("The edge map pointer is null.")
.cast::<[u8; EDGES_MAP_DEFAULT_SIZE]>(),
))
};

let modules = tuple_list!(StdEdgeCoverageChildModule::builder()
.const_map_observer(edges_observer.as_mut())
.build()?);

let emulator = Emulator::empty()
.qemu_parameters(options.args)
.modules(modules)
.build()?;
let qemu = emulator.qemu();

let mut elf_buffer = Vec::new();
let elf = EasyElf::from_file(qemu.binary_path(), &mut elf_buffer).unwrap();
Expand All @@ -139,8 +163,6 @@ pub fn fuzz() -> Result<(), Error> {

let stack_ptr: GuestAddr = qemu.read_reg(Regs::Sp).unwrap();

let mut shmem_provider = StdShMemProvider::new().expect("Failed to init shared memory");

let monitor = SimpleMonitor::with_user_monitor(|s| {
println!("{s}");
});
Expand All @@ -157,19 +179,6 @@ pub fn fuzz() -> Result<(), Error> {
},
};

let mut edges_shmem = shmem_provider.new_shmem(EDGES_MAP_DEFAULT_SIZE).unwrap();
let edges = edges_shmem.as_slice_mut();
unsafe { EDGES_MAP_PTR = edges.as_mut_ptr() };

let mut edges_observer = unsafe {
HitcountsMapObserver::new(ConstMapObserver::from_mut_ptr(
"edges",
NonNull::new(edges.as_mut_ptr())
.expect("The edge map pointer is null.")
.cast::<[u8; EDGES_MAP_DEFAULT_SIZE]>(),
))
};

let mut feedback = MaxMapFeedback::new(&edges_observer);

let mut objective = ();
Expand Down Expand Up @@ -222,12 +231,6 @@ pub fn fuzz() -> Result<(), Error> {
ExitKind::Ok
};

let modules = tuple_list!(StdEdgeCoverageChildModule::builder()
.const_map_observer(edges_observer.as_mut())
.build()?);

let emulator = Emulator::empty().qemu(qemu).modules(modules).build()?;

let mut executor = QemuForkExecutor::new(
emulator,
&mut harness,
Expand Down
147 changes: 74 additions & 73 deletions fuzzers/binary_only/qemu_coverage/src/fuzzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use libafl_bolts::{
use libafl_qemu::{
elf::EasyElf,
modules::{drcov::DrCovModule, StdAddressFilter},
ArchExtras, CallingConvention, Emulator, GuestAddr, GuestReg, MmapPerms, Qemu, QemuExecutor,
ArchExtras, CallingConvention, Emulator, GuestAddr, GuestReg, MmapPerms, QemuExecutor,
QemuExitReason, QemuRWError, QemuShutdownCause, Regs,
};

Expand Down Expand Up @@ -123,80 +123,93 @@ pub fn fuzz() {

env::remove_var("LD_LIBRARY_PATH");

let qemu = Qemu::init(&options.args).unwrap();

let mut elf_buffer = Vec::new();
let elf = EasyElf::from_file(qemu.binary_path(), &mut elf_buffer).unwrap();

let test_one_input_ptr = elf
.resolve_symbol("LLVMFuzzerTestOneInput", qemu.load_addr())
.expect("Symbol LLVMFuzzerTestOneInput not found");
log::debug!("LLVMFuzzerTestOneInput @ {test_one_input_ptr:#x}");
let mut run_client = |state: Option<_>,
mut mgr: LlmpRestartingEventManager<_, _, _>,
client_description: ClientDescription| {
let mut cov_path = options.coverage_path.clone();

qemu.entry_break(test_one_input_ptr);
let emulator_modules = tuple_list!(DrCovModule::builder()
.filter(StdAddressFilter::default())
.filename(cov_path.clone())
.full_trace(false)
.build());

for m in qemu.mappings() {
log::debug!(
"Mapping: 0x{:016x}-0x{:016x}, {}",
m.start(),
m.end(),
m.path().unwrap_or(&"<EMPTY>".to_string())
);
}
let emulator = Emulator::empty()
.qemu_parameters(options.args.clone())
.modules(emulator_modules)
.build()
.expect("QEMU initialization failed");
let qemu = emulator.qemu();

let mut elf_buffer = Vec::new();
let elf = EasyElf::from_file(qemu.binary_path(), &mut elf_buffer).unwrap();

let test_one_input_ptr = elf
.resolve_symbol("LLVMFuzzerTestOneInput", qemu.load_addr())
.expect("Symbol LLVMFuzzerTestOneInput not found");
log::debug!("LLVMFuzzerTestOneInput @ {test_one_input_ptr:#x}");

qemu.entry_break(test_one_input_ptr);

for m in qemu.mappings() {
log::debug!(
"Mapping: 0x{:016x}-0x{:016x}, {}",
m.start(),
m.end(),
m.path().unwrap_or(&"<EMPTY>".to_string())
);
}

let pc: GuestReg = qemu.read_reg(Regs::Pc).unwrap();
log::debug!("Break at {pc:#x}");
let pc: GuestReg = qemu.read_reg(Regs::Pc).unwrap();
log::debug!("Break at {pc:#x}");

let ret_addr: GuestAddr = qemu.read_return_address().unwrap();
log::debug!("Return address = {ret_addr:#x}");
let ret_addr: GuestAddr = qemu.read_return_address().unwrap();
log::debug!("Return address = {ret_addr:#x}");

qemu.set_breakpoint(ret_addr);
qemu.set_breakpoint(ret_addr);

let input_addr = qemu
.map_private(0, MAX_INPUT_SIZE, MmapPerms::ReadWrite)
.unwrap();
log::debug!("Placing input at {input_addr:#x}");
let input_addr = qemu
.map_private(0, MAX_INPUT_SIZE, MmapPerms::ReadWrite)
.unwrap();
log::debug!("Placing input at {input_addr:#x}");

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> {
unsafe {
let _ = qemu.write_mem(input_addr, buf);
qemu.write_reg(Regs::Pc, test_one_input_ptr)?;
qemu.write_reg(Regs::Sp, stack_ptr)?;
qemu.write_return_address(ret_addr)?;
qemu.write_function_argument(CallingConvention::Cdecl, 0, input_addr)?;
qemu.write_function_argument(CallingConvention::Cdecl, 1, len)?;
let reset = |buf: &[u8], len: GuestReg| -> Result<(), QemuRWError> {
unsafe {
let _ = qemu.write_mem(input_addr, buf);
qemu.write_reg(Regs::Pc, test_one_input_ptr)?;
qemu.write_reg(Regs::Sp, stack_ptr)?;
qemu.write_return_address(ret_addr)?;
qemu.write_function_argument(CallingConvention::Cdecl, 0, input_addr)?;
qemu.write_function_argument(CallingConvention::Cdecl, 1, len)?;

match qemu.run() {
Ok(QemuExitReason::Breakpoint(_)) => {}
Ok(QemuExitReason::End(QemuShutdownCause::HostSignal(Signal::SigInterrupt))) => {
process::exit(0)
match qemu.run() {
Ok(QemuExitReason::Breakpoint(_)) => {}
Ok(QemuExitReason::End(QemuShutdownCause::HostSignal(
Signal::SigInterrupt,
))) => process::exit(0),
_ => panic!("Unexpected QEMU exit."),
}
_ => panic!("Unexpected QEMU exit."),
}

Ok(())
}
};

let mut harness =
|_emulator: &mut Emulator<_, _, _, _, _>, _state: &mut _, input: &BytesInput| {
let target = input.target_bytes();
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;
Ok(())
}
let len = len as GuestReg;
reset(buf, len).unwrap();
ExitKind::Ok
};

let mut run_client = |state: Option<_>,
mut mgr: LlmpRestartingEventManager<_, _, _>,
client_description: ClientDescription| {
let mut harness =
|_emulator: &mut Emulator<_, _, _, _, _>, _state: &mut _, input: &BytesInput| {
let target = input.target_bytes();
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
};

let core_id = client_description.core_id();
let core_idx = options
.cores
Expand Down Expand Up @@ -232,23 +245,11 @@ pub fn fuzz() {
let scheduler = QueueScheduler::new();
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);

let mut cov_path = options.coverage_path.clone();
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)
.full_trace(false)
.build());

let emulator = Emulator::empty()
.qemu(qemu)
.modules(emulator_modules)
.build()?;

let mut executor = QemuExecutor::new(
emulator,
&mut harness,
Expand Down
Loading
Loading