diff --git a/config/src/config.rs b/config/src/config.rs index e2d1767..d4dc4df 100644 --- a/config/src/config.rs +++ b/config/src/config.rs @@ -7,6 +7,8 @@ use crate::loader::*; use libc::fcntl; +const DEFAULT_AUX_BUFFER_SIZE: usize = 4096; + fn into_absolute_path(path_to_sharedir: &str, path_to_file: String) -> String { let path_to_default_config = Path::new(&path_to_file); @@ -214,6 +216,9 @@ pub struct RuntimeConfig { /* worker_id of the current QEMU Nyx instance */ worker_id: usize, + + /* aux_buffer size */ + aux_buffer_size: usize, } impl RuntimeConfig{ @@ -224,6 +229,7 @@ impl RuntimeConfig{ reuse_snapshot_path: None, debug_mode: false, worker_id: 0, + aux_buffer_size: DEFAULT_AUX_BUFFER_SIZE, } } @@ -273,6 +279,20 @@ impl RuntimeConfig{ pub fn set_worker_id(&mut self, thread_id: usize){ self.worker_id = thread_id; } + + pub fn set_aux_buffer_size(&mut self, aux_buffer_size: usize) -> bool{ + + if aux_buffer_size < DEFAULT_AUX_BUFFER_SIZE || (aux_buffer_size & 0xfff) != 0 { + return false; + } + + self.aux_buffer_size = aux_buffer_size; + return true + } + + pub fn aux_buffer_size(&self) -> usize { + self.aux_buffer_size + } } diff --git a/fuzz_runner/src/nyx/aux_buffer.rs b/fuzz_runner/src/nyx/aux_buffer.rs index fc6207f..2fe8444 100644 --- a/fuzz_runner/src/nyx/aux_buffer.rs +++ b/fuzz_runner/src/nyx/aux_buffer.rs @@ -46,11 +46,12 @@ pub struct AuxBuffer { pub config: &'static mut auxilary_buffer_config_s, pub result: &'static mut auxilary_buffer_result_s, pub misc: &'static mut auxilary_buffer_misc_s, + size: usize, /* total size of the aux buffer */ } impl AuxBuffer { - pub fn new_readonly(file: File, read_only: bool) -> Self { + pub fn new_readonly(file: File, read_only: bool, size: usize) -> Self { let mut prot = ProtFlags::PROT_READ; if !read_only{ @@ -59,9 +60,9 @@ impl AuxBuffer { let flags = MapFlags::MAP_SHARED; let null_addr = std::num::NonZeroUsize::new(0); - let size = std::num::NonZeroUsize::new(AUX_BUFFER_SIZE).unwrap(); + let aux_buffer_alloc_size = std::num::NonZeroUsize::new(size).unwrap(); unsafe { - let ptr = mmap(null_addr, size, prot, flags, file.into_raw_fd(), 0).unwrap(); + let ptr = mmap(null_addr, aux_buffer_alloc_size, prot, flags, file.into_raw_fd(), 0).unwrap(); let header = (ptr.add(HEADER_OFFSET) as *mut auxilary_buffer_header_s) .as_mut() .unwrap(); @@ -83,12 +84,27 @@ impl AuxBuffer { config, result, misc, + size, }; } } - pub fn new(file: File) -> Self { - return AuxBuffer::new_readonly(file, false); + pub fn new(file: File, size: usize) -> Self { + return AuxBuffer::new_readonly(file, false, size); + } + + pub fn size(&self) -> usize { + return self.size; + } + + /* This is a somewhat hacky way of returning a slice of the total misc area */ + pub fn misc_slice(&self) -> &[u8] { + return unsafe { std::slice::from_raw_parts(self.misc as *const auxilary_buffer_misc_s as *const u8, self.size - MISC_OFFSET) }; + } + + /* same... */ + pub fn misc_data_slice(&self) -> &[u8] { + return unsafe { std::slice::from_raw_parts((self.misc as *const auxilary_buffer_misc_s as *const u8).offset(std::mem::size_of::() as isize), self.size - MISC_OFFSET - std::mem::size_of::()) }; } pub fn validate_header(&self) -> Result<(), String> { @@ -199,6 +215,7 @@ fn inspect_bytes(bs: &[u8]) -> String { } visible } + impl auxilary_buffer_misc_s{ pub fn as_slice(&self) -> &[u8]{ assert!(self.len as usize <= self.data.len()); @@ -209,6 +226,7 @@ impl auxilary_buffer_misc_s{ } } +/* FIXME: will fail if the aux_buffer is > 4KB in size */ impl fmt::Debug for auxilary_buffer_misc_s { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("auxilary_buffer_misc_s") diff --git a/fuzz_runner/src/nyx/params.rs b/fuzz_runner/src/nyx/params.rs index b3eab6a..9c3b18e 100644 --- a/fuzz_runner/src/nyx/params.rs +++ b/fuzz_runner/src/nyx/params.rs @@ -14,6 +14,7 @@ pub struct QemuParams { pub cow_primary_size: Option, pub hprintf_fd: Option, + pub aux_buffer_size: usize, } impl QemuParams { @@ -96,6 +97,7 @@ impl QemuParams { nyx_ops += &format!(",worker_id={}", qemu_id); nyx_ops += &format!(",workdir={}", workdir); nyx_ops += &format!(",sharedir={}", sharedir); + nyx_ops += &format!(",aux_buffer_size={}", fuzzer_config.runtime.aux_buffer_size()); let mut i = 0; for filter in fuzzer_config.fuzz.ipt_filters{ @@ -185,6 +187,7 @@ impl QemuParams { write_protected_input_buffer: fuzzer_config.fuzz.write_protected_input_buffer, cow_primary_size: fuzzer_config.fuzz.cow_primary_size, hprintf_fd: fuzzer_config.runtime.hprintf_fd(), + aux_buffer_size: fuzzer_config.runtime.aux_buffer_size(), } } diff --git a/fuzz_runner/src/nyx/qemu_process.rs b/fuzz_runner/src/nyx/qemu_process.rs index 5dcb2e0..921c9f1 100644 --- a/fuzz_runner/src/nyx/qemu_process.rs +++ b/fuzz_runner/src/nyx/qemu_process.rs @@ -212,7 +212,7 @@ impl QemuProcess { .open(¶ms.qemu_aux_buffer_filename) .expect("couldn't open aux buffer file"); - AuxBuffer::new(aux_shm_f) + AuxBuffer::new(aux_shm_f, params.aux_buffer_size) }; match aux_buffer.validate_header(){ @@ -373,16 +373,15 @@ impl QemuProcess { } } - match self.aux.result.exec_result_code { NYX_HPRINTF => { let len = self.aux.misc.len; - QemuProcess::output_hprintf(&mut self.hprintf_file, &String::from_utf8_lossy(&self.aux.misc.data[0..len as usize]).yellow()); + QemuProcess::output_hprintf(&mut self.hprintf_file, &String::from_utf8_lossy(&self.aux.misc_data_slice()[0..len as usize]).yellow()); continue; }, NYX_ABORT => { let len = self.aux.misc.len; - println!("[!] libnyx: agent abort() -> \"{}\"", String::from_utf8_lossy(&self.aux.misc.data[0..len as usize]).red()); + println!("[!] libnyx: agent abort() -> \"{}\"", String::from_utf8_lossy(&self.aux.misc_data_slice()[0..len as usize]).red()); break; }, NYX_SUCCESS | NYX_CRASH | NYX_INPUT_WRITE | NYX_TIMEOUT => { diff --git a/libnyx/src/ffi.rs b/libnyx/src/ffi.rs index 61ffa9f..eb2f020 100644 --- a/libnyx/src/ffi.rs +++ b/libnyx/src/ffi.rs @@ -141,6 +141,17 @@ pub extern "C" fn nyx_config_set_reuse_snapshot_path(config: * mut c_void, reuse } } +/* FFI function to set the aux_buffer size */ +#[no_mangle] +pub extern "C" fn nyx_config_set_aux_buffer_size(config: * mut c_void, aux_buffer_size: u32) -> bool { + let cfg = __nyx_config_check_ptr(config); + + assert_eq!(aux_buffer_size > 0, true); + unsafe{ + return NyxConfig::set_aux_buffer_size(&mut *cfg, aux_buffer_size as usize); + } +} + #[no_mangle] pub extern "C" fn nyx_new(config: * mut c_void, worker_id: u32) -> * mut NyxProcess { diff --git a/libnyx/src/lib.rs b/libnyx/src/lib.rs index 68a6949..967433f 100644 --- a/libnyx/src/lib.rs +++ b/libnyx/src/lib.rs @@ -228,6 +228,11 @@ impl NyxConfig { self.config.runtime.set_worker_id(worker_id); } + /* Sets the QEMU-Nyx aux buffer size (must be a multiple of 4KB; default value is 4KB). */ + pub fn set_aux_buffer_size(&mut self, size: usize) -> bool{ + return self.config.runtime.set_aux_buffer_size(size); + } + pub fn dict(&self) -> Vec> { self.config.fuzz.dict.clone() } @@ -258,6 +263,10 @@ impl NyxProcess { pub fn aux_buffer_as_mut_ptr(&self) -> *mut u8 { std::ptr::addr_of!(self.process.aux_buffer().header.magic) as *mut u8 } + + pub fn aux_buffer_size(&self) -> usize { + self.process.aux_buffer().size() + } pub fn input_buffer(&self) -> &[u8] { self.process.payload @@ -317,7 +326,11 @@ impl NyxProcess { } pub fn aux_misc(&self) -> Vec{ - self.process.aux_buffer().misc.as_slice().to_vec() + self.process.aux_buffer().misc_slice().to_vec() + } + + pub fn aux_data_misc(&self) -> Vec{ + self.process.aux_buffer().misc_data_slice().to_vec() } pub fn aux_tmp_snapshot_created(&self) -> bool { @@ -326,7 +339,7 @@ impl NyxProcess { pub fn aux_string(&self) -> String { let len = self.process.aux_buffer().misc.len; - String::from_utf8_lossy(&self.process.aux_buffer().misc.data[0..len as usize]).to_string() + String::from_utf8_lossy(&self.process.aux_buffer().misc_data_slice()[0..len as usize]).to_string() } pub fn exec(&mut self) -> NyxReturnValue {