From b33cb5d721f440febd70d73abd05c7e4d442bef9 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sun, 14 Mar 2021 19:58:04 +0100 Subject: [PATCH] debugging llmp --- libafl/Cargo.toml | 1 + libafl/examples/llmp_test/main.rs | 30 +++++++++++++-- libafl/src/bolts/llmp.rs | 57 ++++++++++++++++------------- libafl/src/bolts/os/unix_signals.rs | 2 +- 4 files changed, 60 insertions(+), 30 deletions(-) diff --git a/libafl/Cargo.toml b/libafl/Cargo.toml index 01a78fc319..29b65a59cd 100644 --- a/libafl/Cargo.toml +++ b/libafl/Cargo.toml @@ -35,6 +35,7 @@ std = [] # print, sharedmap, ... support runtime = [] # a runtime for clang inmem-executor anymapdbg = ["serde_json"] # uses serde_json to Debug the anymap trait. Disable for smaller footprint. derive = ["libafl_derive"] # provide derive(SerdeAny) macro. +llmp_small_maps = [] # reduces initial map size for llmp [[example]] name = "llmp_test" diff --git a/libafl/examples/llmp_test/main.rs b/libafl/examples/llmp_test/main.rs index 4dadc2ebf4..fcb03d3872 100644 --- a/libafl/examples/llmp_test/main.rs +++ b/libafl/examples/llmp_test/main.rs @@ -8,14 +8,16 @@ use core::{convert::TryInto, time::Duration}; #[cfg(all(unix, feature = "std"))] use std::{thread, time}; +use libafl::bolts::llmp::Tag; #[cfg(all(unix, feature = "std"))] use libafl::{ bolts::{llmp, shmem::UnixShMem}, Error, }; -const _TAG_SIMPLE_U32_V1: u32 = 0x51300321; -const _TAG_MATH_RESULT_V1: u32 = 0x77474331; +const _TAG_SIMPLE_U32_V1: Tag = 0x51300321; +const _TAG_MATH_RESULT_V1: Tag = 0x77474331; +const _TAG_1MEG_V1: Tag = 0xB1111161; #[cfg(all(unix, feature = "std"))] fn adder_loop(port: u16) -> ! { @@ -35,7 +37,11 @@ fn adder_loop(port: u16) -> ! { current_result = current_result.wrapping_add(u32::from_le_bytes(buf.try_into().unwrap())); } - _ => println!("Adder Client ignored unknown message {}", tag), + _ => println!( + "Adder Client ignored unknown message {} with {} bytes", + tag, + buf.len() + ), }; } @@ -55,6 +61,19 @@ fn adder_loop(port: u16) -> ! { } } +#[cfg(all(unix, feature = "std"))] +fn large_msg_loop(port: u16) -> ! { + let mut client = llmp::LlmpClient::::create_attach_to_tcp(port).unwrap(); + + let meg_buf = [1u8; 1 << 20]; + + loop { + client.send_buf(_TAG_1MEG_V1, &meg_buf).unwrap(); + println!("Sending the next megabyte"); + thread::sleep(time::Duration::from_millis(100)) + } +} + #[cfg(all(unix, feature = "std"))] fn broker_message_hook( client_id: u32, @@ -95,7 +114,7 @@ fn main() { let mode = std::env::args() .nth(1) - .expect("no mode specified, chose 'broker', 'ctr', or 'adder'"); + .expect("no mode specified, chose 'broker', 'ctr', 'adder', or 'large'"); let port: u16 = std::env::args() .nth(2) .unwrap_or("1337".into()) @@ -128,6 +147,9 @@ fn main() { "adder" => { adder_loop(port); } + "large" => { + large_msg_loop(port); + } _ => { println!("No valid mode supplied"); } diff --git a/libafl/src/bolts/llmp.rs b/libafl/src/bolts/llmp.rs index 8e4076af86..36e1f16a7a 100644 --- a/libafl/src/bolts/llmp.rs +++ b/libafl/src/bolts/llmp.rs @@ -102,10 +102,14 @@ use crate::{ use super::shmem::HasFd; /// We'll start off with 256 megabyte maps per fuzzer client -const LLMP_PREF_INITIAL_MAP_SIZE: usize = 1 << 28; +#[cfg(not(feature = "llmp_small_maps"))] +const LLMP_CFG_INITIAL_MAP_SIZE: usize = 1 << 28; +/// If llmp_small_maps is set, we start off with 1 meg. +#[cfg(feature = "llmp_small_maps")] +const LLMP_CFG_INITIAL_MAP_SIZE: usize = 1 << 20; /// What byte count to align messages to /// LlmpMsg sizes (including header) will always be rounded up to be a multiple of this value -const LLMP_PREF_ALIGNNMENT: usize = 64; +const LLMP_CFG_ALIGNNMENT: usize = 64; /// A msg fresh from the press: No tag got sent by the user yet const LLMP_TAG_UNSET: Tag = 0xDEADAF; @@ -199,19 +203,19 @@ unsafe fn llmp_msg_in_page(page: *const LlmpPage, msg: *const LlmpMsg) -> bool { && (page as *const u8).add((*page).size_total) > msg as *const u8 } -/// allign to LLMP_PREF_ALIGNNMENT=64 bytes +/// allign to LLMP_CFG_ALIGNNMENT=64 bytes #[inline] const fn llmp_align(to_align: usize) -> usize { // check if we need to align first - if LLMP_PREF_ALIGNNMENT == 0 { + if LLMP_CFG_ALIGNNMENT == 0 { return to_align; } // Then do the alignment - let modulo = to_align % LLMP_PREF_ALIGNNMENT; + let modulo = to_align % LLMP_CFG_ALIGNNMENT; if modulo == 0 { to_align } else { - to_align + LLMP_PREF_ALIGNNMENT - modulo + to_align + LLMP_CFG_ALIGNNMENT - modulo } } @@ -235,7 +239,7 @@ fn msg_offset_from_env(env_name: &str) -> Result, Error> { fn new_map_size(max_alloc: usize) -> usize { max( max_alloc * 2 + EOP_MSG_SIZE + LLMP_PAGE_HEADER_LEN, - LLMP_PREF_INITIAL_MAP_SIZE, + LLMP_CFG_INITIAL_MAP_SIZE, ) .next_power_of_two() } @@ -543,7 +547,7 @@ where last_msg_sent: ptr::null_mut(), out_maps: vec![LlmpSharedMap::new( 0, - SH::new_map(new_map_size(LLMP_PREF_INITIAL_MAP_SIZE))?, + SH::new_map(new_map_size(LLMP_CFG_INITIAL_MAP_SIZE))?, )], // drop pages to the broker if it already read them keep_pages_forever, @@ -573,7 +577,7 @@ where pub fn to_env(&self, env_name: &str) -> Result<(), Error> { let current_out_map = self.out_maps.last().unwrap(); current_out_map.shmem.write_to_env(env_name)?; - current_out_map.msg_to_env(self.last_msg_sent, env_name) + unsafe { current_out_map.msg_to_env(self.last_msg_sent, env_name) } } /// Waits for this sender to be save to unmap. @@ -930,7 +934,7 @@ where pub fn to_env(&self, env_name: &str) -> Result<(), Error> { let current_out_map = &self.current_recv_map; current_out_map.shmem.write_to_env(env_name)?; - current_out_map.msg_to_env(self.last_msg_recvd, env_name) + unsafe { current_out_map.msg_to_env(self.last_msg_recvd, env_name) } } /// Create a Receiver, reattaching to an existing sender map. @@ -1203,14 +1207,16 @@ where /// Store this msg offset to env_name + _OFFSET env variable. /// It can be restored using msg_from_env with the same env_name later. + /// # Safety + /// This function will dereference the msg ptr, make sure it's valid. #[cfg(feature = "std")] - pub fn msg_to_env(&self, msg: *const LlmpMsg, map_env_name: &str) -> Result<(), Error> { + pub unsafe fn msg_to_env(&self, msg: *const LlmpMsg, map_env_name: &str) -> Result<(), Error> { if msg.is_null() { env::set_var(&format!("{}_OFFSET", map_env_name), _NULL_ENV_STR) } else { env::set_var( &format!("{}_OFFSET", map_env_name), - format!("{}", unsafe { self.msg_to_offset(msg) }?), + format!("{}", self.msg_to_offset(msg)?), ) }; Ok(()) @@ -1327,9 +1333,8 @@ where msg.copy_to_nonoverlapping(out, size_of::() + (*msg).buf_len_padded as usize); (*out).buf_len_padded = actual_size; /* We need to replace the message ID with our own */ - match self.llmp_out.send(out) { - Err(e) => panic!("Error sending msg: {:?}", e), - _ => (), + if let Err(e) = self.llmp_out.send(out) { + panic!("Error sending msg: {:?}", e) }; self.llmp_out.last_msg_sent = out; Ok(()) @@ -1433,7 +1438,7 @@ where // Tcp out map sends messages from background thread tcp server to foreground client let tcp_out_map = LlmpSharedMap::new( llmp_tcp_id, - SH::new_map(new_map_size(LLMP_PREF_INITIAL_MAP_SIZE))?, + SH::new_map(new_map_size(LLMP_CFG_INITIAL_MAP_SIZE))?, ); let tcp_out_map_str = tcp_out_map.shmem.shm_str(); let tcp_out_map_size = tcp_out_map.shmem.map().len(); @@ -1476,7 +1481,7 @@ where (*msg).tag = LLMP_TAG_NEW_SHM_CLIENT; let pageinfo = (*msg).buf.as_mut_ptr() as *mut LlmpPayloadSharedMapInfo; (*pageinfo).shm_str = new_client_map_str; - (*pageinfo).map_size = LLMP_PREF_INITIAL_MAP_SIZE; + (*pageinfo).map_size = LLMP_CFG_INITIAL_MAP_SIZE; match new_client_sender.send(msg) { Ok(()) => (), Err(e) => println!("Error forwarding client on map: {:?}", e), @@ -1492,10 +1497,12 @@ where .to_string_lossy() .into_owned() .parse() - .expect(&format!( - "ShmId is not a valid int file descriptor: {:?}", - broadcast_str_initial - )); + .unwrap_or_else(|_| { + panic!( + "ShmId is not a valid int file descriptor: {:?}", + broadcast_str_initial + ) + }); match sendmsg( stream.as_raw_fd(), @@ -1539,7 +1546,7 @@ where let pageinfo = (*msg).buf.as_mut_ptr() as *mut LlmpPayloadSharedMapInfo; (*pageinfo).shm_str = fdstr; - (*pageinfo).map_size = LLMP_PREF_INITIAL_MAP_SIZE; + (*pageinfo).map_size = LLMP_CFG_INITIAL_MAP_SIZE; match new_client_sender.send(msg) { Ok(()) => (), Err(e) => { @@ -1750,7 +1757,7 @@ where last_msg_sent: ptr::null_mut(), out_maps: vec![LlmpSharedMap::new( 0, - SH::new_map(new_map_size(LLMP_PREF_INITIAL_MAP_SIZE))?, + SH::new_map(new_map_size(LLMP_CFG_INITIAL_MAP_SIZE))?, )], // drop pages to the broker if it already read them keep_pages_forever: false, @@ -1851,7 +1858,7 @@ where let ret = Self::new(LlmpSharedMap::existing(SH::existing_from_shm_slice( &new_broker_map_str, - LLMP_PREF_INITIAL_MAP_SIZE, + LLMP_CFG_INITIAL_MAP_SIZE, )?))?; stream.write_all(ret.sender.out_maps.first().unwrap().shmem.shm_slice())?; @@ -1895,7 +1902,7 @@ where let ret = Self::new(LlmpSharedMap::existing(SH::existing_from_shm_slice( &fdstr, - LLMP_PREF_INITIAL_MAP_SIZE, + LLMP_CFG_INITIAL_MAP_SIZE, )?))?; match sendmsg( diff --git a/libafl/src/bolts/os/unix_signals.rs b/libafl/src/bolts/os/unix_signals.rs index 737cf533fa..8248306a45 100644 --- a/libafl/src/bolts/os/unix_signals.rs +++ b/libafl/src/bolts/os/unix_signals.rs @@ -22,7 +22,7 @@ use crate::Error; pub use libc::{c_void, siginfo_t}; -#[derive(IntoPrimitive, TryFromPrimitive, Hash, Clone, Copy)] +#[derive(IntoPrimitive, TryFromPrimitive, Clone, Copy)] #[repr(i32)] pub enum Signal { SigAbort = SIGABRT,