Skip to content

Commit 3094664

Browse files
WorksButNotTestedYour Name
and
Your Name
authored
Add filter to ASAN module in qemu_launcher (#3089)
also add filters to rasan runner. Co-authored-by: Your Name <[email protected]>
1 parent 1b85a92 commit 3094664

File tree

4 files changed

+98
-24
lines changed

4 files changed

+98
-24
lines changed

fuzzers/binary_only/qemu_launcher/src/client.rs

+46-16
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ use libafl::{
1010
};
1111
use libafl_bolts::{rands::StdRand, tuples::tuple_list};
1212
use libafl_qemu::modules::{
13-
asan::AsanModule, asan_guest::AsanGuestModule, cmplog::CmpLogModule, DrCovModule,
14-
InjectionModule,
13+
asan::AsanModule, asan_guest::AsanGuestModule, cmplog::CmpLogModule,
14+
utils::filters::StdAddressFilter, DrCovModule, InjectionModule,
1515
};
1616

1717
use crate::{
@@ -111,6 +111,17 @@ impl Client<'_> {
111111
.client_description(client_description)
112112
.extra_tokens(extra_tokens);
113113

114+
let asan_filter = if let Some(include_asan) = &self.options.include_asan {
115+
log::info!("ASAN includes: {include_asan:#x?}");
116+
StdAddressFilter::allow_list(include_asan.to_vec())
117+
} else if let Some(exclude_asan) = &self.options.exclude_asan {
118+
log::info!("ASAN excludes: {exclude_asan:#x?}");
119+
StdAddressFilter::deny_list(exclude_asan.to_vec())
120+
} else {
121+
log::info!("ASAN no additional filter");
122+
StdAddressFilter::default()
123+
};
124+
114125
if self.options.rerun_input.is_some() {
115126
if is_drcov {
116127
// Special code path for re-running inputs with DrCov and Asan.
@@ -123,7 +134,13 @@ impl Client<'_> {
123134
.filename(drcov.clone())
124135
.full_trace(true)
125136
.build(),
126-
unsafe { AsanModule::builder().env(&env).asan_report().build() }
137+
unsafe {
138+
AsanModule::builder()
139+
.env(&env)
140+
.filter(asan_filter)
141+
.asan_report()
142+
.build()
143+
}
127144
);
128145

129146
instance_builder.build().run(args, modules, state)
@@ -133,7 +150,7 @@ impl Client<'_> {
133150
.filename(drcov.clone())
134151
.full_trace(true)
135152
.build(),
136-
AsanGuestModule::default(&env),
153+
AsanGuestModule::new(&env, asan_filter),
137154
);
138155

139156
instance_builder.build().run(args, modules, state)
@@ -146,12 +163,17 @@ impl Client<'_> {
146163
instance_builder.build().run(args, modules, state)
147164
}
148165
} else if is_asan {
149-
let modules =
150-
tuple_list!(unsafe { AsanModule::builder().env(&env).asan_report().build() });
166+
let modules = tuple_list!(unsafe {
167+
AsanModule::builder()
168+
.env(&env)
169+
.filter(asan_filter)
170+
.asan_report()
171+
.build()
172+
});
151173

152174
instance_builder.build().run(args, modules, state)
153175
} else if is_asan_guest {
154-
let modules = tuple_list!(AsanGuestModule::default(&env));
176+
let modules = tuple_list!(AsanGuestModule::new(&env, asan_filter));
155177

156178
instance_builder.build().run(args, modules, state)
157179
} else {
@@ -165,7 +187,7 @@ impl Client<'_> {
165187
args,
166188
tuple_list!(
167189
CmpLogModule::default(),
168-
AsanModule::builder().env(&env).build(),
190+
AsanModule::builder().env(&env).filter(asan_filter).build(),
169191
injection_module,
170192
),
171193
state,
@@ -175,7 +197,7 @@ impl Client<'_> {
175197
args,
176198
tuple_list!(
177199
CmpLogModule::default(),
178-
AsanModule::builder().env(&env).build()
200+
AsanModule::builder().env(&env).filter(asan_filter).build()
179201
),
180202
state,
181203
)
@@ -186,36 +208,44 @@ impl Client<'_> {
186208
args,
187209
tuple_list!(
188210
CmpLogModule::default(),
189-
AsanGuestModule::default(&env),
211+
AsanGuestModule::new(&env, asan_filter),
190212
injection_module
191213
),
192214
state,
193215
)
194216
} else {
195217
instance_builder.build().run(
196218
args,
197-
tuple_list!(CmpLogModule::default(), AsanGuestModule::default(&env),),
219+
tuple_list!(
220+
CmpLogModule::default(),
221+
AsanGuestModule::new(&env, asan_filter),
222+
),
198223
state,
199224
)
200225
}
201226
} else if is_asan {
202227
if let Some(injection_module) = injection_module {
203228
instance_builder.build().run(
204229
args,
205-
tuple_list!(AsanModule::builder().env(&env).build(), injection_module),
230+
tuple_list!(
231+
AsanModule::builder().env(&env).filter(asan_filter).build(),
232+
injection_module
233+
),
206234
state,
207235
)
208236
} else {
209237
instance_builder.build().run(
210238
args,
211-
tuple_list!(AsanModule::builder().env(&env).build()),
239+
tuple_list!(AsanModule::builder().env(&env).filter(asan_filter).build()),
212240
state,
213241
)
214242
}
215243
} else if is_asan_guest {
216-
instance_builder
217-
.build()
218-
.run(args, tuple_list!(AsanGuestModule::default(&env)), state)
244+
instance_builder.build().run(
245+
args,
246+
tuple_list!(AsanGuestModule::new(&env, asan_filter)),
247+
state,
248+
)
219249
} else if is_cmplog {
220250
if let Some(injection_module) = injection_module {
221251
instance_builder.build().run(

fuzzers/binary_only/qemu_launcher/src/options.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,18 @@ pub struct FuzzerOptions {
6868
#[arg(long = "iterations", help = "Maximum number of iterations")]
6969
pub iterations: Option<u64>,
7070

71-
#[arg(long = "include", help="Include address ranges", value_parser = FuzzerOptions::parse_ranges)]
71+
#[arg(long = "include", help="Include coverage address ranges", value_parser = FuzzerOptions::parse_ranges)]
7272
pub include: Option<Vec<Range<GuestAddr>>>,
7373

74-
#[arg(long = "exclude", help="Exclude address ranges", value_parser = FuzzerOptions::parse_ranges, conflicts_with="include")]
74+
#[arg(long = "exclude", help="Exclude coverage address ranges", value_parser = FuzzerOptions::parse_ranges, conflicts_with="include")]
7575
pub exclude: Option<Vec<Range<GuestAddr>>>,
7676

77+
#[arg(long = "include-asan", help="Include asan address ranges", value_parser = FuzzerOptions::parse_ranges)]
78+
pub include_asan: Option<Vec<Range<GuestAddr>>>,
79+
80+
#[arg(long = "exclude-asan", help="Exclude asan address ranges", value_parser = FuzzerOptions::parse_ranges, conflicts_with="include_asan")]
81+
pub exclude_asan: Option<Vec<Range<GuestAddr>>>,
82+
7783
#[arg(
7884
short = 'd',
7985
help = "Write a DrCov Trace for the current input. Requires -r."

libafl_qemu/librasan/Justfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ test: test_asan
1414

1515
pretty_rust:
1616
#!/bin/sh
17-
MAIN_LLVM_VERSION=$LLVM_VERSION cargo run --manifest-path ../../utils/libafl_fmt/Cargo.toml --release -- -v
17+
MAIN_LLVM_VERSION=$LLVM_VERSION cargo run --manifest-path ../../utils/libafl_repo_tools/Cargo.toml --release -- -v
1818

1919
pretty_toml:
2020
#!/bin/sh

libafl_qemu/librasan/runner/src/fuzz.rs

+43-5
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
use std::{env, fmt::Write};
1+
use std::{env, fmt::Write, ops::Range};
22

33
use clap::{Parser, builder::Str};
44
use libafl_bolts::{Error, tuples::tuple_list};
55
use libafl_qemu::{
6-
Emulator, NopEmulatorDriver, NopSnapshotManager, QemuExitError, QemuInitError,
6+
Emulator, GuestAddr, NopEmulatorDriver, NopSnapshotManager, QemuExitError, QemuInitError,
77
command::NopCommandManager,
88
elf::EasyElf,
9-
modules::{AsanGuestModule, AsanModule, EmulatorModuleTuple},
9+
modules::{AsanGuestModule, AsanModule, EmulatorModuleTuple, utils::filters::StdAddressFilter},
1010
};
1111
use log::{error, info};
1212
use thiserror::Error;
@@ -60,10 +60,37 @@ pub struct FuzzerOptions {
6060
#[clap(short, long, help = "Enable output from the fuzzer clients")]
6161
pub verbose: bool,
6262

63+
#[arg(long = "include-asan", help="Include asan address ranges", value_parser = FuzzerOptions::parse_ranges)]
64+
pub include_asan: Option<Vec<Range<GuestAddr>>>,
65+
66+
#[arg(long = "exclude-asan", help="Exclude asan address ranges", value_parser = FuzzerOptions::parse_ranges, conflicts_with="include_asan")]
67+
pub exclude_asan: Option<Vec<Range<GuestAddr>>>,
68+
6369
#[arg(last = true, help = "Arguments passed to the target")]
6470
pub args: Vec<String>,
6571
}
6672

73+
impl FuzzerOptions {
74+
fn parse_ranges(src: &str) -> Result<Range<GuestAddr>, Error> {
75+
let parts = src.split('-').collect::<Vec<&str>>();
76+
if parts.len() == 2 {
77+
let start =
78+
GuestAddr::from_str_radix(parts[0].trim_start_matches("0x"), 16).map_err(|e| {
79+
Error::illegal_argument(format!("Invalid start address: {} ({e:})", parts[0]))
80+
})?;
81+
let end =
82+
GuestAddr::from_str_radix(parts[1].trim_start_matches("0x"), 16).map_err(|e| {
83+
Error::illegal_argument(format!("Invalid end address: {} ({e:})", parts[1]))
84+
})?;
85+
Ok(Range { start, end })
86+
} else {
87+
Err(Error::illegal_argument(format!(
88+
"Invalid range provided: {src:}"
89+
)))
90+
}
91+
}
92+
}
93+
6794
pub fn fuzz() {
6895
env_logger::init();
6996
let mut options = FuzzerOptions::parse();
@@ -78,14 +105,25 @@ pub fn fuzz() {
78105
.filter(|(k, _v)| k != "LD_LIBRARY_PATH")
79106
.collect::<Vec<(String, String)>>();
80107

108+
let asan_filter = if let Some(include_asan) = &options.include_asan {
109+
info!("ASAN includes: {include_asan:#x?}");
110+
StdAddressFilter::allow_list(include_asan.to_vec())
111+
} else if let Some(exclude_asan) = &options.exclude_asan {
112+
info!("ASAN excludes: {exclude_asan:#x?}");
113+
StdAddressFilter::deny_list(exclude_asan.to_vec())
114+
} else {
115+
info!("ASAN no additional filter");
116+
StdAddressFilter::default()
117+
};
118+
81119
let ret = if options.asan {
82120
info!("Enabling ASAN");
83-
let modules = tuple_list!(AsanModule::builder().env(&env).build());
121+
let modules = tuple_list!(AsanModule::builder().env(&env).filter(asan_filter).build());
84122
info!("Modules: {:#?}", modules);
85123
run(options, modules)
86124
} else if options.gasan {
87125
info!("Enabling Guest ASAN");
88-
let modules = tuple_list!(AsanGuestModule::default(&env));
126+
let modules = tuple_list!(AsanGuestModule::new(&env, asan_filter));
89127
info!("Modules: {:#?}", modules);
90128
run(options, modules)
91129
} else {

0 commit comments

Comments
 (0)