diff --git a/afl/src/events/llmp_translated.rs b/afl/src/events/llmp_translated.rs index cddcbe5267..91269d6f6e 100644 --- a/afl/src/events/llmp_translated.rs +++ b/afl/src/events/llmp_translated.rs @@ -59,30 +59,28 @@ use crate::AflError; use super::shmem_translated::AflShmem; -/// The header length of a llmp page in a shared map (until messages start) -const LLMP_PAGE_HEADER_LEN: usize = size_of::(); - /// We'll start off with 256 megabyte maps per fuzzer -const LLMP_INITIAL_MAP_SIZE: usize = 1 << 28; - -/// A msg fresh from the press: No tag got sent by the user yet -const LLMP_TAG_UNSET: u32 = 0xdeadaf; -/// This message should not exist yet. Some bug in unsafe code! -const LLMP_TAG_UNINITIALIZED: u32 = 0xa143af11; -/// The end of page mesasge -/// When receiving this, a new sharedmap needs to be allocated. -const LLMP_TAG_END_OF_PAGE: u32 = 0xaf1e0f1; -/// A new client for this broekr got added. -const LLMP_TAG_NEW_SHM_CLIENT: u32 = 0xc11e471; - +const LLMP_PREF_INITIAL_MAP_SIZE: usize = 1 << 28; /// 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_ALIGNNMENT: usize = 64; +const LLMP_PREF_ALIGNNMENT: usize = 64; + +/// A msg fresh from the press: No tag got sent by the user yet +const LLMP_TAG_UNSET: u32 = 0xDEADAF; +/// This message should not exist yet. Some bug in unsafe code! +const LLMP_TAG_UNINITIALIZED: u32 = 0xA143AF11; +/// The end of page mesasge +/// When receiving this, a new sharedmap needs to be allocated. +const LLMP_TAG_END_OF_PAGE: u32 = 0xAF1E0F1; +/// A new client for this broekr got added. +const LLMP_TAG_NEW_SHM_CLIENT: u32 = 0xC11E471; /// Size of a new page message, header, payload, and alignment const EOP_MSG_SIZE: usize = llmp_align(size_of::() + size_of::()); +/// The header length of a llmp page in a shared map (until messages start) +const LLMP_PAGE_HEADER_LEN: usize = size_of::(); -/// Message Hook +/// Message hook type pub type LlmpMsgHookFn = unsafe fn(client_id: u32, msg: *mut LlmpMsg) -> LlmpMsgHookResult; /// Sending end on a (unidirectional) sharedmap channel @@ -115,7 +113,9 @@ pub struct LlmpReceiver { /// Client side of LLMP #[derive(Clone)] pub struct LlmpClient { + /// Outgoing channel to the broker pub llmp_out: LlmpSender, + /// Incoming (broker) broadcast map pub llmp_in: LlmpReceiver, } @@ -144,19 +144,6 @@ pub struct LlmpMsg { pub buf: [u8; 0], } -/// The broker (node 0) -#[derive(Clone)] -#[repr(C)] -pub struct LlmpBroker { - /// Broadcast map from broker to all clients - pub llmp_out: LlmpSender, - /// Users of Llmp can add message handlers in the broker. - /// This allows us to intercept messages right in the broker - /// This keeps the out map clean. - pub msg_hooks: Vec, - pub llmp_clients: Vec, -} - /// Contents of the share mem pages, used by llmp internally #[derive(Copy, Clone)] #[repr(C, packed)] @@ -171,6 +158,19 @@ pub struct LlmpPage { pub messages: [LlmpMsg; 0], } +/// The broker (node 0) +#[derive(Clone)] +#[repr(C)] +pub struct LlmpBroker { + /// Broadcast map from broker to all clients + pub llmp_out: LlmpSender, + /// Users of Llmp can add message handlers in the broker. + /// This allows us to intercept messages right in the broker + /// This keeps the out map clean. + pub msg_hooks: Vec, + pub llmp_clients: Vec, +} + /// Result of an LLMP Mesasge hook pub enum LlmpMsgHookResult { /// This has been handled in the broker. No need to forward. @@ -202,19 +202,19 @@ unsafe fn llmp_msg_in_page(page: *mut LlmpPage, msg: *mut LlmpMsg) -> bool { && (page as *mut u8).offset((*page).size_total as isize) > msg as *mut u8; } -/// allign to LLMP_ALIGNNMENT=64 bytes +/// allign to LLMP_PREF_ALIGNNMENT=64 bytes #[inline] const fn llmp_align(to_align: usize) -> usize { // check if we need to align first - if LLMP_ALIGNNMENT == 0 { + if LLMP_PREF_ALIGNNMENT == 0 { return to_align; } // Then do the alignment - let modulo = to_align % LLMP_ALIGNNMENT; + let modulo = to_align % LLMP_PREF_ALIGNNMENT; if modulo == 0 { to_align } else { - to_align + LLMP_ALIGNNMENT - modulo + to_align + LLMP_PREF_ALIGNNMENT - modulo } } @@ -225,7 +225,7 @@ const fn llmp_align(to_align: usize) -> usize { fn new_map_size(max_alloc: usize) -> usize { next_pow2(max( max_alloc * 2 + EOP_MSG_SIZE + LLMP_PAGE_HEADER_LEN, - LLMP_INITIAL_MAP_SIZE, + LLMP_PREF_INITIAL_MAP_SIZE, ) as u64) as usize } @@ -566,24 +566,26 @@ impl LlmpReceiver { /// The page struct, placed on a shared mem instance. impl LlmpSharedMap { - /// Creates a new page with minimum prev_max_alloc_size or LLMP_INITIAL_MAP_SIZE + /// Creates a new page with minimum prev_max_alloc_size or LLMP_PREF_INITIAL_MAP_SIZE /// returning the initialized shared mem struct - pub unsafe fn new(sender: u32, min_size: usize) -> Result { + pub fn new(sender: u32, min_size: usize) -> Result { // Create a new shard page. let mut shmem = AflShmem::new(new_map_size(min_size))?; - _llmp_page_init(&mut shmem, sender); + unsafe { + _llmp_page_init(&mut shmem, sender); + } Ok(Self { shmem }) } /// Initialize from a 0-terminated sharedmap id string and its size - pub unsafe fn from_str(shm_str: &CStr, map_size: usize) -> Result { + pub fn from_str(shm_str: &CStr, map_size: usize) -> Result { let shmem = AflShmem::from_str(shm_str, map_size)?; // Not initializing the page here - the other side should have done it already! Ok(Self { shmem }) } /// Initialize from a shm_str with fixed len of 20 - pub unsafe fn from_name_slice(shm_str: &[u8; 20], map_size: usize) -> Result { + pub fn from_name_slice(shm_str: &[u8; 20], map_size: usize) -> Result { let shmem = AflShmem::from_name_slice(shm_str, map_size)?; // Not initializing the page here - the other side should have done it already! Ok(Self { shmem }) @@ -744,12 +746,12 @@ impl LlmpBroker { /// and get incoming messages from the shared broker bus impl LlmpClient { /// Creates a new LlmpClient - pub unsafe fn new(initial_broker_map: LlmpSharedMap) -> Result { + pub fn new(initial_broker_map: LlmpSharedMap) -> Result { Ok(Self { llmp_out: LlmpSender { id: 0, last_msg_sent: 0 as *mut LlmpMsg, - out_maps: vec![LlmpSharedMap::new(0, LLMP_INITIAL_MAP_SIZE)?], + out_maps: vec![LlmpSharedMap::new(0, LLMP_PREF_INITIAL_MAP_SIZE)?], // drop pages to the broker if it already read them keep_pages_forever: false, }, @@ -766,6 +768,28 @@ impl LlmpClient { self.llmp_out.send(msg) } + /// Allocates a message of the given size, tags it, and sends it off. + pub fn send_buf(&mut self, tag: u32, buf: &[u8]) -> Result<(), AflError> { + // Make sure we don't reuse already allocated tags + if tag == LLMP_TAG_NEW_SHM_CLIENT + || tag == LLMP_TAG_END_OF_PAGE + || tag == LLMP_TAG_UNINITIALIZED + || tag == LLMP_TAG_UNSET + { + return Err(AflError::Unknown(format!( + "Reserved tag supplied to send_buf ({:#X})", + tag + ))); + } + unsafe { + let msg = self.alloc_next(buf.len())?; + (*msg).tag = tag; + buf.as_ptr() + .copy_to_nonoverlapping((*msg).buf.as_mut_ptr(), buf.len()); + self.send(msg) + } + } + /// A client receives a broadcast message. /// Returns null if no message is availiable pub unsafe fn recv(&mut self) -> Result, AflError> { diff --git a/afl/src/events/shmem_translated.rs b/afl/src/events/shmem_translated.rs index 0f1b901ef1..e11c000cd3 100644 --- a/afl/src/events/shmem_translated.rs +++ b/afl/src/events/shmem_translated.rs @@ -101,9 +101,11 @@ impl AflShmem { } /// Generate a shared map with a fixed byte array of 20 - pub unsafe fn from_name_slice(shm_str: &[u8; 20], map_size: usize) -> Result { - let str_bytes = shm_str as *const [u8; 20] as *const libc::c_char; - Self::from_str(CStr::from_ptr(str_bytes), map_size) + pub fn from_name_slice(shm_str: &[u8; 20], map_size: usize) -> Result { + unsafe { + let str_bytes = shm_str as *const [u8; 20] as *const libc::c_char; + Self::from_str(CStr::from_ptr(str_bytes), map_size) + } } pub fn new(map_size: usize) -> Result {