
* Add ccache * Update codecov.yml * Add libnyx * Fix * Add nyx build script * Fix build.sh && init executor.rs * Fix commit * Fix code * initialize `exector.rs` * refine API in `nyx_bridge.rs` * initialze `run_target` * add `test_nyxhelper` * initize `test_executor` * remove `nyx_beidge.rs` * make `test_executor` compile * Improve test * refine code * update version * fix docker * fix docker * Fix clippy * Fix build * fix build && add `set_timeout` * Fix and refine CI * fix CI * Fix CI * Add platform restrict * cargo fmt * add parallel mode * add example `nyx_libxml2_parallel` * fix fuzzer example * fix CI * add README * fix CI * fix CI * fix CI * remove unwrap and NyxResult * code format fix * add libnyx's rev * fix format * change Duration format && Fix CI * caego fmt * fix CI * fix CI * Add doc * test CI * Update test_all_fuzzers.sh * Update test_all_fuzzers.sh * Update test_all_fuzzers.sh * add cache for apt and cargo-install * Update build_and_test.yml * Update build_and_test.yml * tmp test CI * fix CI * remove debug cmd * remove test * code refine * code refine * code refine * code refine * add Makefile * fix example doc for nyx * add `NyxHelper::new_with_initial_timeout` * fix `NyxHelper::new` * fix curl parameter * code refine * add check for setup script * use afl-clang-fast in nyx * fix logic * fix makefile * fix CI * Update build_and_test.yml * Update build_and_test.yml * remove debug cmd Co-authored-by: syheliel <syheliel@gmail.com> Co-authored-by: Dominik Maier <dmnk@google.com>
158 lines
5.2 KiB
Rust
158 lines
5.2 KiB
Rust
/// [`NyxHelper`] is used to wrap `NyxProcess`
|
|
use std::{
|
|
fmt::{self, Debug},
|
|
path::Path,
|
|
time::Duration,
|
|
};
|
|
|
|
use libafl::Error;
|
|
use libnyx::{NyxProcess, NyxReturnValue};
|
|
|
|
const INIT_TIMEOUT: Duration = Duration::new(2, 0);
|
|
pub struct NyxHelper {
|
|
pub nyx_process: NyxProcess,
|
|
/// real size of trace_bits
|
|
pub real_map_size: usize,
|
|
// real size of the trace_bits
|
|
pub map_size: usize,
|
|
/// shared memory with instruction bitmaps
|
|
pub trace_bits: *mut u8,
|
|
}
|
|
|
|
const MAX_FILE: u32 = 1024 * 1024;
|
|
#[derive(Clone, Copy, Debug)]
|
|
pub enum NyxProcessType {
|
|
/// stand alone mode
|
|
ALONE,
|
|
/// parallel mode's parent, used to create snapshot
|
|
PARENT,
|
|
/// parallel mode's child, consume snapshot and execute
|
|
CHILD,
|
|
}
|
|
impl NyxHelper {
|
|
/// create `NyxProcess` and do basic settings
|
|
/// It will convert instance to parent or child using `parent_cpu_id` when set`parallel_mode`
|
|
/// will fail if initial connection takes more than 2 seconds
|
|
pub fn new(
|
|
target_dir: &Path,
|
|
cpu_id: u32,
|
|
snap_mode: bool,
|
|
parallel_mode: bool,
|
|
parent_cpu_id: Option<u32>,
|
|
) -> Result<Self, Error> {
|
|
NyxHelper::new_with_initial_timeout(
|
|
target_dir,
|
|
cpu_id,
|
|
snap_mode,
|
|
parallel_mode,
|
|
parent_cpu_id,
|
|
INIT_TIMEOUT,
|
|
)
|
|
}
|
|
/// create `NyxProcess` and do basic settings
|
|
/// It will convert instance to parent or child using `parent_cpu_id` when set`parallel_mode`
|
|
/// will fail if initial connection takes more than `initial_timeout` seconds
|
|
pub fn new_with_initial_timeout(
|
|
target_dir: &Path,
|
|
cpu_id: u32,
|
|
snap_mode: bool,
|
|
parallel_mode: bool,
|
|
parent_cpu_id: Option<u32>,
|
|
initial_timeout: Duration,
|
|
) -> Result<Self, Error> {
|
|
let sharedir = match target_dir.to_str() {
|
|
Some(x) => x,
|
|
None => return Err(Error::illegal_argument("can't convert sharedir to str")),
|
|
};
|
|
let work_dir = target_dir.join("workdir");
|
|
let work_dir = work_dir.to_str().expect("unable to convert workdir to str");
|
|
let nyx_type = if parallel_mode {
|
|
let parent_cpu_id = match parent_cpu_id {
|
|
None => {
|
|
return Err(Error::illegal_argument(
|
|
"please set parent_cpu_id in nyx parallel mode",
|
|
))
|
|
}
|
|
Some(x) => x,
|
|
};
|
|
if cpu_id == parent_cpu_id {
|
|
NyxProcessType::PARENT
|
|
} else {
|
|
NyxProcessType::CHILD
|
|
}
|
|
} else {
|
|
NyxProcessType::ALONE
|
|
};
|
|
|
|
let nyx_process = match nyx_type {
|
|
NyxProcessType::ALONE => NyxProcess::new(sharedir, work_dir, cpu_id, MAX_FILE, true),
|
|
NyxProcessType::PARENT => {
|
|
NyxProcess::new_parent(sharedir, work_dir, cpu_id, MAX_FILE, true)
|
|
}
|
|
NyxProcessType::CHILD => NyxProcess::new_child(sharedir, work_dir, cpu_id, cpu_id),
|
|
};
|
|
|
|
let mut nyx_process =
|
|
nyx_process.map_err(|msg: String| -> Error { Error::illegal_argument(msg) })?;
|
|
|
|
let real_map_size = nyx_process.bitmap_buffer_size();
|
|
let map_size = ((real_map_size + 63) >> 6) << 6;
|
|
let trace_bits = nyx_process.bitmap_buffer_mut().as_mut_ptr();
|
|
nyx_process.option_set_reload_mode(snap_mode);
|
|
nyx_process.option_apply();
|
|
|
|
// default timeout for initial dry-run
|
|
let sec = initial_timeout
|
|
.as_secs()
|
|
.try_into()
|
|
.map_err(|_| -> Error { Error::illegal_argument("can't cast time's sec to u8") })?;
|
|
|
|
let micro_sec: u32 = initial_timeout.subsec_micros();
|
|
nyx_process.option_set_timeout(sec, micro_sec);
|
|
nyx_process.option_apply();
|
|
|
|
// dry run to check if qemu is spawned
|
|
nyx_process.set_input(b"INIT", 4);
|
|
match nyx_process.exec() {
|
|
NyxReturnValue::Error => {
|
|
nyx_process.shutdown();
|
|
let msg = "Error: Nyx runtime error has occured...";
|
|
return Err(Error::illegal_state(msg));
|
|
}
|
|
NyxReturnValue::IoError => {
|
|
let msg = "Error: QEMU-nyx died...";
|
|
return Err(Error::illegal_state(msg));
|
|
}
|
|
NyxReturnValue::Abort => {
|
|
nyx_process.shutdown();
|
|
let msg = "Error: Nyx abort occured...";
|
|
return Err(Error::illegal_state(msg));
|
|
}
|
|
_ => {}
|
|
}
|
|
Ok(Self {
|
|
nyx_process,
|
|
real_map_size,
|
|
map_size,
|
|
trace_bits,
|
|
})
|
|
}
|
|
|
|
/// set timeout
|
|
pub fn set_timeout(mut self, time: Duration) {
|
|
let sec: u8 = time
|
|
.as_secs()
|
|
.try_into()
|
|
.expect("can't cast time's sec to u8");
|
|
let micro_sec: u32 = time.subsec_micros();
|
|
self.nyx_process.option_set_timeout(sec, micro_sec);
|
|
self.nyx_process.option_apply();
|
|
}
|
|
}
|
|
|
|
impl Debug for NyxHelper {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
f.debug_struct("NyxInprocessHelper").finish()
|
|
}
|
|
}
|