-
-
Notifications
You must be signed in to change notification settings - Fork 383
Full libfuzzer shimming (for cargo-fuzz libfuzzer alternative and other use cases) #981
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
Changes from 85 commits
8568bb4
1caf157
8882d5e
e95ff89
2c5428a
8fd5474
3d2a4e9
016cadf
2157790
89ec678
89ac90c
629422b
5286103
f652f77
ce0be40
a1d059d
856e969
f87f2c4
9d976e5
9d32627
e51d3df
b750c3d
5711017
ce33aad
807b1be
25cc95b
538f9fa
ee12bd2
874b426
dc9cf00
f2778e1
580f8d0
03afd7d
9f07169
0e742c7
89735d1
5a8c7c5
6d8e4ea
4a06217
3af961a
64facff
9d2589d
f8a6142
86f29a9
a45e04d
3aad5e9
5f6f8c9
d3c32ce
84a9d3a
d4b0140
81f2020
067d7e4
7ed73a2
bec635b
51824bd
14287d0
80ba77a
e363c40
a41cab1
7c77e55
6b1c16c
381c834
537bd1a
29fa6de
e23c81b
74f3c02
89143dd
11165cf
37a2175
fd3bc07
aaff794
368815c
d49d8fc
476200d
6f0c7be
d05916c
69ace6c
3e0118f
dbea434
ae4686c
d5b39e8
cf0e1ef
ebe961d
0122a03
f6d225c
d5d654e
b7e2752
9020704
ff23e2b
672137c
49718c8
aefcb82
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -114,6 +114,7 @@ jobs: | |
with: | ||
profile: minimal | ||
toolchain: stable | ||
components: llvm-tools | ||
- name: Install and cache deps | ||
uses: awalsh128/[email protected] | ||
with: | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,6 +33,8 @@ perf.data.old | |
.vscode | ||
test.dict | ||
|
||
.idea/ | ||
|
||
# Ignore all built fuzzers | ||
fuzzer_* | ||
AFLplusplus | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -50,6 +50,8 @@ where | |
inner: InMemoryCorpus<I>, | ||
dir_path: PathBuf, | ||
meta_format: Option<OnDiskMetadataFormat>, | ||
prefix: Option<String>, | ||
locking: bool, | ||
} | ||
|
||
impl<I> UsesInput for InMemoryOnDiskCorpus<I> | ||
|
@@ -209,20 +211,41 @@ where | |
where | ||
P: AsRef<Path>, | ||
{ | ||
Self::_new(dir_path.as_ref(), Some(OnDiskMetadataFormat::JsonPretty)) | ||
Self::_new( | ||
dir_path.as_ref(), | ||
Some(OnDiskMetadataFormat::JsonPretty), | ||
None, | ||
true, | ||
) | ||
} | ||
|
||
/// Creates the [`InMemoryOnDiskCorpus`] specifying the format in which `Metadata` will be saved to disk. | ||
/// | ||
/// Will error, if [`std::fs::create_dir_all()`] failed for `dir_path`. | ||
pub fn with_meta_format<P>( | ||
dir_path: P, | ||
meta_format: OnDiskMetadataFormat, | ||
meta_format: Option<OnDiskMetadataFormat>, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think having an There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it is... 😔 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now or later? :D |
||
) -> Result<Self, Error> | ||
where | ||
P: AsRef<Path>, | ||
{ | ||
Self::_new(dir_path.as_ref(), Some(meta_format)) | ||
Self::_new(dir_path.as_ref(), meta_format, None, true) | ||
} | ||
|
||
/// Creates the [`InMemoryOnDiskCorpus`] specifying the format in which `Metadata` will be saved to disk | ||
/// and the prefix for the filenames. | ||
/// | ||
/// Will error, if [`std::fs::create_dir_all()`] failed for `dir_path`. | ||
pub fn with_meta_format_and_prefix<P>( | ||
dir_path: P, | ||
meta_format: Option<OnDiskMetadataFormat>, | ||
prefix: Option<String>, | ||
locking: bool, | ||
) -> Result<Self, Error> | ||
where | ||
P: AsRef<Path>, | ||
{ | ||
Self::_new(dir_path.as_ref(), meta_format, prefix, locking) | ||
} | ||
|
||
/// Creates an [`InMemoryOnDiskCorpus`] that will not store .metadata files | ||
|
@@ -232,16 +255,27 @@ where | |
where | ||
P: AsRef<Path>, | ||
{ | ||
Self::_new(dir_path.as_ref(), None) | ||
Self::_new(dir_path.as_ref(), None, None, true) | ||
} | ||
|
||
/// Private fn to crate a new corpus at the given (non-generic) path with the given optional `meta_format` | ||
fn _new(dir_path: &Path, meta_format: Option<OnDiskMetadataFormat>) -> Result<Self, Error> { | ||
fs::create_dir_all(dir_path)?; | ||
fn _new( | ||
dir_path: &Path, | ||
meta_format: Option<OnDiskMetadataFormat>, | ||
prefix: Option<String>, | ||
locking: bool, | ||
) -> Result<Self, Error> { | ||
match fs::create_dir_all(dir_path) { | ||
Ok(()) => {} | ||
Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists => {} | ||
Err(e) => return Err(e.into()), | ||
} | ||
Ok(InMemoryOnDiskCorpus { | ||
inner: InMemoryCorpus::new(), | ||
dir_path: dir_path.into(), | ||
meta_format, | ||
prefix, | ||
locking, | ||
}) | ||
} | ||
|
||
|
@@ -265,19 +299,21 @@ where | |
return Ok(()); | ||
} | ||
|
||
let new_lock_filename = format!(".{new_filename}.lafl_lock"); | ||
if self.locking { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why would you not be locking? Are you using one folder per node? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you aren't forking, you probably don't want to lock. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fork as in multicore? Then I agree. Although you can also restart, you wouldn't have to fork :P There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does libafl_libfuzzer support a non-forking multiprocess mode btw? Might be relevant for some targets There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
How do you mean? With e.g. threads instead of forks? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. LibAFL launcher can start new processes instead of fork, yes There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So, it should just use whatever's appropriate for the system. I don't specify fork/process explicitly. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You need to specifically not use fork for some targets like browsers - they don't cope well with forking since all vital threads die in the forked process. |
||
let new_lock_filename = format!(".{new_filename}.lafl_lock"); | ||
|
||
// Try to create lock file for new testcases | ||
if OpenOptions::new() | ||
.create(true) | ||
.write(true) | ||
.open(self.dir_path.join(new_lock_filename)) | ||
.is_err() | ||
{ | ||
*testcase.filename_mut() = Some(old_filename); | ||
return Err(Error::illegal_state( | ||
"unable to create lock file for new testcase", | ||
)); | ||
// Try to create lock file for new testcases | ||
if OpenOptions::new() | ||
.create(true) | ||
.write(true) | ||
.open(self.dir_path.join(new_lock_filename)) | ||
.is_err() | ||
{ | ||
*testcase.filename_mut() = Some(old_filename); | ||
return Err(Error::illegal_state( | ||
"unable to create lock file for new testcase", | ||
)); | ||
} | ||
} | ||
|
||
let new_file_path = self.dir_path.join(&new_filename); | ||
|
@@ -311,18 +347,15 @@ where | |
fn save_testcase(&self, testcase: &mut Testcase<I>, idx: CorpusId) -> Result<(), Error> { | ||
let file_name_orig = testcase.filename_mut().take().unwrap_or_else(|| { | ||
// TODO walk entry metadata to ask for pieces of filename (e.g. :havoc in AFL) | ||
|
||
testcase.input().as_ref().unwrap().generate_name(idx.0) | ||
}); | ||
if testcase.file_path().is_some() { | ||
// We already have a valid path, no need to do calculate anything | ||
*testcase.filename_mut() = Some(file_name_orig); | ||
} else { | ||
// New testcase, we need to save it. | ||
let mut file_name = file_name_orig.clone(); | ||
|
||
let mut ctr = 2; | ||
let file_name = loop { | ||
// New testcase, we need to save it. | ||
let mut file_name = file_name_orig.clone(); | ||
|
||
let mut ctr = 2; | ||
let file_name = if self.locking { | ||
loop { | ||
let lockfile_name = format!(".{file_name}.lafl_lock"); | ||
let lockfile_path = self.dir_path.join(lockfile_name); | ||
|
||
|
@@ -337,11 +370,19 @@ where | |
|
||
file_name = format!("{file_name_orig}-{ctr}"); | ||
ctr += 1; | ||
}; | ||
} | ||
} else { | ||
file_name | ||
}; | ||
|
||
if testcase | ||
.file_path() | ||
.as_ref() | ||
.map_or(true, |path| !path.starts_with(&self.dir_path)) | ||
{ | ||
*testcase.file_path_mut() = Some(self.dir_path.join(&file_name)); | ||
*testcase.filename_mut() = Some(file_name); | ||
} | ||
*testcase.filename_mut() = Some(file_name); | ||
|
||
if self.meta_format.is_some() { | ||
let metafile_name = format!(".{}.metadata", testcase.filename().as_ref().unwrap()); | ||
|
@@ -389,6 +430,12 @@ where | |
} | ||
Ok(()) | ||
} | ||
|
||
/// Path to the corpus directory associated with this corpus | ||
#[must_use] | ||
pub fn dir_path(&self) -> &PathBuf { | ||
&self.dir_path | ||
} | ||
} | ||
|
||
#[cfg(feature = "python")] | ||
|
Uh oh!
There was an error while loading. Please reload this page.