Skip to content

Commit 9755d18

Browse files
WorksButNotTestedYour Name
andauthored
Write coverage for QEMU into separate files (#1571)
Co-authored-by: Your Name <[email protected]>
1 parent 78fd4e0 commit 9755d18

File tree

3 files changed

+31
-20
lines changed

3 files changed

+31
-20
lines changed

fuzzers/qemu_coverage/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,5 @@ clap = { version = "4.3.0", features = ["derive", "string"]}
2929
libafl = { path = "../../libafl/" }
3030
libafl_bolts = { path = "../../libafl_bolts/" }
3131
libafl_qemu = { path = "../../libafl_qemu/", features = ["usermode"] }
32+
log = {version = "0.4.20" }
3233
rangemap = { version = "1.3" }

fuzzers/qemu_coverage/Makefile.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ args = [
194194
dependencies = ["build"]
195195
script_runner="@shell"
196196
script='''
197+
rm -f ${TARGET_DIR}/${PROFILE_DIR}/qemu_coverage-${CARGO_MAKE_PROFILE}
197198
mv ${TARGET_DIR}/${PROFILE_DIR}/qemu_coverage ${TARGET_DIR}/${PROFILE_DIR}/qemu_coverage-${CARGO_MAKE_PROFILE}
198199
'''
199200

fuzzers/qemu_coverage/src/fuzzer.rs

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ pub struct FuzzerOptions {
8989
args: Vec<String>,
9090
}
9191

92+
pub const MAX_INPUT_SIZE: usize = 1048576; // 1MB
93+
9294
pub fn fuzz() {
9395
let mut options = FuzzerOptions::parse();
9496

@@ -105,10 +107,10 @@ pub fn fuzz() {
105107
let files_per_core = (num_files as f64 / num_cores as f64).ceil() as usize;
106108

107109
let program = env::args().next().unwrap();
108-
println!("Program: {program:}");
110+
log::debug!("Program: {program:}");
109111

110112
options.args.insert(0, program);
111-
println!("ARGS: {:#?}", options.args);
113+
log::debug!("ARGS: {:#?}", options.args);
112114

113115
env::remove_var("LD_LIBRARY_PATH");
114116
let env: Vec<(String, String)> = env::vars().collect();
@@ -120,13 +122,12 @@ pub fn fuzz() {
120122
let test_one_input_ptr = elf
121123
.resolve_symbol("LLVMFuzzerTestOneInput", emu.load_addr())
122124
.expect("Symbol LLVMFuzzerTestOneInput not found");
123-
println!("LLVMFuzzerTestOneInput @ {test_one_input_ptr:#x}");
125+
log::debug!("LLVMFuzzerTestOneInput @ {test_one_input_ptr:#x}");
124126

125-
emu.set_breakpoint(test_one_input_ptr);
126-
unsafe { emu.run() };
127+
emu.entry_break(test_one_input_ptr);
127128

128129
for m in emu.mappings() {
129-
println!(
130+
log::debug!(
130131
"Mapping: 0x{:016x}-0x{:016x}, {}",
131132
m.start(),
132133
m.end(),
@@ -135,16 +136,17 @@ pub fn fuzz() {
135136
}
136137

137138
let pc: GuestReg = emu.read_reg(Regs::Pc).unwrap();
138-
println!("Break at {pc:#x}");
139+
log::debug!("Break at {pc:#x}");
139140

140141
let ret_addr: GuestAddr = emu.read_return_address().unwrap();
141-
println!("Return address = {ret_addr:#x}");
142+
log::debug!("Return address = {ret_addr:#x}");
142143

143-
emu.remove_breakpoint(test_one_input_ptr);
144144
emu.set_breakpoint(ret_addr);
145145

146-
let input_addr = emu.map_private(0, 4096, MmapPerms::ReadWrite).unwrap();
147-
println!("Placing input at {input_addr:#x}");
146+
let input_addr = emu
147+
.map_private(0, MAX_INPUT_SIZE, MmapPerms::ReadWrite)
148+
.unwrap();
149+
log::debug!("Placing input at {input_addr:#x}");
148150

149151
let stack_ptr: GuestAddr = emu.read_reg(Regs::Sp).unwrap();
150152

@@ -163,12 +165,13 @@ pub fn fuzz() {
163165

164166
let mut harness = |input: &BytesInput| {
165167
let target = input.target_bytes();
166-
let buf = target
167-
.as_slice()
168-
.chunks(4096)
169-
.next()
170-
.expect("Failed to get chunk");
171-
let len = buf.len() as GuestReg;
168+
let mut buf = target.as_slice();
169+
let mut len = buf.len();
170+
if len > MAX_INPUT_SIZE {
171+
buf = &buf[0..MAX_INPUT_SIZE];
172+
len = MAX_INPUT_SIZE;
173+
}
174+
let len = len as GuestReg;
172175
reset(buf, len).unwrap();
173176
ExitKind::Ok
174177
};
@@ -226,12 +229,18 @@ pub fn fuzz() {
226229
},
227230
);
228231

232+
let mut coverage = PathBuf::from(&options.coverage);
233+
let coverage_name = coverage.file_stem().unwrap().to_str().unwrap();
234+
let coverage_extension = coverage.extension().unwrap_or_default().to_str().unwrap();
235+
let core = core_id.0;
236+
coverage.set_file_name(format!("{coverage_name}-{core:03}.{coverage_extension}"));
237+
229238
let mut hooks = QemuHooks::new(
230239
&emu,
231240
tuple_list!(QemuDrCovHelper::new(
232241
QemuInstrumentationFilter::None,
233242
rangemap,
234-
PathBuf::from(&options.coverage),
243+
PathBuf::from(coverage),
235244
false,
236245
)),
237246
);
@@ -255,10 +264,10 @@ pub fn fuzz() {
255264
println!("Failed to load initial corpus at {:?}", &corpus_dir);
256265
process::exit(0);
257266
});
258-
println!("We imported {} inputs from disk.", state.corpus().count());
267+
log::debug!("We imported {} inputs from disk.", state.corpus().count());
259268
}
260269

261-
println!("Processed {} inputs from disk.", files.len());
270+
log::debug!("Processed {} inputs from disk.", files.len());
262271

263272
mgr.send_exiting()?;
264273
Err(Error::ShuttingDown)?

0 commit comments

Comments
 (0)