From 85ad4c43eba93fe44e6eeed34d0600bac3aa081e Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sat, 2 Jan 2021 00:20:14 +0100 Subject: [PATCH] added llmp restores --- afl/src/corpus/mod.rs | 49 ---------- afl/src/corpus/testcase.rs | 15 --- afl/src/events/llmp.rs | 182 ++++++++++++++++++++----------------- 3 files changed, 101 insertions(+), 145 deletions(-) diff --git a/afl/src/corpus/mod.rs b/afl/src/corpus/mod.rs index 92d047adf4..070fd496a7 100644 --- a/afl/src/corpus/mod.rs +++ b/afl/src/corpus/mod.rs @@ -380,55 +380,6 @@ where } } -/* TODO: Iterator corpus, like: - -enum MutationAction { - ReplaceInput(old_ref, new_val), - AppendNewInput(new_val), -} - -struct NewCorpus { - testcases: Vec, - offset: usize; -} - -impl NewCorpus { - - pub fn handle_mutation(&mut self, action: MutationAction) { - match action { - MutationAction::ReplaceInput() => {}, - MutationAction::AppendNewInput() => {}, - } - } -} - -impl Iterator for NewCorpus { - type Item = NewTestCase; - - fn next(&mut self) -> Option<&Self::Item> { - // FIXME: implement next here - self.offset = 3; - - // When no more stuff, return None - None - } -} - -And then: - - corpus.iter() - .mutate_foo() - .mutate_bar() - .set_observer(obs) - .execute_binary(|input| { - ... - }) - .map(|observers, input, mutators| match result { - /// do things depending on coverage, etc... - e.g. corpus.handle_mutation(MutationAction::AppendNewInput) - }) -*/ - #[cfg(test)] #[cfg(feature = "std")] mod tests { diff --git a/afl/src/corpus/testcase.rs b/afl/src/corpus/testcase.rs index c529ad78cd..2e9bd1d182 100644 --- a/afl/src/corpus/testcase.rs +++ b/afl/src/corpus/testcase.rs @@ -1,6 +1,4 @@ -use alloc::rc::Rc; use alloc::string::String; -use core::cell::RefCell; use core::convert::Into; use core::default::Default; use core::option::Option; @@ -10,10 +8,6 @@ use crate::inputs::Input; use crate::serde_anymap::{SerdeAny, SerdeAnyMap}; use crate::AflError; -// TODO PathBuf for no_std and change filename to PathBuf -//#[cfg(feature = "std")] -//use std::path::PathBuf; - /// An entry in the Testcase Corpus #[derive(Default, Serialize, Deserialize)] #[serde(bound = "I: serde::de::DeserializeOwned")] @@ -32,15 +26,6 @@ where metadatas: SerdeAnyMap, } -impl Into>> for Testcase -where - I: Input, -{ - fn into(self) -> Rc> { - Rc::new(RefCell::new(self)) - } -} - /// Impl of a testcase impl Testcase where diff --git a/afl/src/events/llmp.rs b/afl/src/events/llmp.rs index f52fbac479..54a01b9389 100644 --- a/afl/src/events/llmp.rs +++ b/afl/src/events/llmp.rs @@ -92,62 +92,6 @@ const LLMP_PAGE_HEADER_LEN: usize = size_of::(); /// TAGs used thorughout llmp pub type Tag = u32; -/// Sending end on a (unidirectional) sharedmap channel -#[derive(Clone, Debug)] -pub struct LlmpSender -where - SH: ShMem, -{ - /// ID of this sender. Only used in the broker. - pub id: u32, - /// Ref to the last message this sender sent on the last page. - /// If null, a new page (just) started. - pub last_msg_sent: *mut LlmpMsg, - /// A vec of page wrappers, each containing an intialized AfShmem - pub out_maps: Vec>, - /// If true, pages will never be pruned. - /// The broker uses this feature. - /// By keeping the message history around, - /// new clients may join at any time in the future. - pub keep_pages_forever: bool, -} - -/// Receiving end on a (unidirectional) sharedmap channel -#[derive(Clone, Debug)] -pub struct LlmpReceiver -where - SH: ShMem, -{ - pub id: u32, - /// Pointer to the last meg this received - pub last_msg_recvd: *mut LlmpMsg, - /// current page. After EOP, this gets replaced with the new one - pub current_recv_map: LlmpSharedMap, -} - -/// Client side of LLMP -#[derive(Clone, Debug)] -pub struct LlmpClient -where - SH: ShMem, -{ - /// Outgoing channel to the broker - pub llmp_out: LlmpSender, - /// Incoming (broker) broadcast map - pub llmp_in: LlmpReceiver, -} - -/// A page wrapper -#[derive(Clone, Debug)] -pub struct LlmpSharedMap -where - SH: ShMem, -{ - /// Shmem containg the actual (unsafe) page, - /// shared between one LlmpSender and one LlmpReceiver - shmem: SH, -} - /// Message sent over the "wire" #[derive(Copy, Clone, Debug)] #[repr(C, packed)] @@ -387,11 +331,53 @@ unsafe fn _llmp_next_msg_ptr(last_msg: *const LlmpMsg) -> *mut LlmpMsg { .offset((*last_msg).buf_len_padded as isize) as *mut LlmpMsg; } +/// Sending end on a (unidirectional) sharedmap channel +#[derive(Clone, Debug)] +pub struct LlmpSender +where + SH: ShMem, +{ + /// ID of this sender. Only used in the broker. + pub id: u32, + /// Ref to the last message this sender sent on the last page. + /// If null, a new page (just) started. + pub last_msg_sent: *mut LlmpMsg, + /// A vec of page wrappers, each containing an intialized AfShmem + pub out_maps: Vec>, + /// If true, pages will never be pruned. + /// The broker uses this feature. + /// By keeping the message history around, + /// new clients may join at any time in the future. + pub keep_pages_forever: bool, +} + /// An actor on the sendin part of the shared map impl LlmpSender where SH: ShMem, { + /// Reattach to a vacant out_map. + /// It is essential, that the receiver (or someone else) keeps a pointer to this map + /// else reattach will get a new, empty page, from the OS, or fail. + pub fn on_existing_map( + current_out_map: SH, + last_msg_sent_offset: Option, + ) -> Result { + let mut out_map = LlmpSharedMap::new(0, current_out_map); + let last_msg_sent = match last_msg_sent_offset { + Some(offset) => out_map.msg_from_offset(offset)?, + None => 0 as *mut LlmpMsg, + }; + + Ok(Self { + id: 0, + last_msg_sent, + out_maps: vec![out_map], + // drop pages to the broker if it already read them + keep_pages_forever: false, + }) + } + /// For non zero-copy, we want to get rid of old pages with duplicate messages in the client /// eventually. This function This funtion sees if we can unallocate older pages. /// The broker would have informed us by setting the save_to_unmap-flag. @@ -644,11 +630,44 @@ where } } +/// Receiving end on a (unidirectional) sharedmap channel +#[derive(Clone, Debug)] +pub struct LlmpReceiver +where + SH: ShMem, +{ + pub id: u32, + /// Pointer to the last meg this received + pub last_msg_recvd: *mut LlmpMsg, + /// current page. After EOP, this gets replaced with the new one + pub current_recv_map: LlmpSharedMap, +} + /// Receiving end of an llmp channel impl LlmpReceiver where SH: ShMem, { + /// Create a Receiver, reattaching to an existing sender map. + /// It is essential, that the sender (or someone else) keeps a pointer to the sender_map + /// else reattach will get a new, empty page, from the OS, or fail. + pub fn on_existing_map( + current_sender_map: SH, + last_msg_recvd_offset: Option, + ) -> Result { + let mut current_recv_map = LlmpSharedMap::new(0, current_sender_map); + let last_msg_recvd = match last_msg_recvd_offset { + Some(offset) => current_recv_map.msg_from_offset(offset)?, + None => 0 as *mut LlmpMsg, + }; + + Ok(Self { + id: 0, + current_recv_map, + last_msg_recvd, + }) + } + // Never inline, to not get some strange effects /// Read next message. #[inline(never)] @@ -784,6 +803,17 @@ where } } +/// A page wrapper +#[derive(Clone, Debug)] +pub struct LlmpSharedMap +where + SH: ShMem, +{ + /// Shmem containg the actual (unsafe) page, + /// shared between one LlmpSender and one LlmpReceiver + shmem: SH, +} + // TODO: May be obsolete /// The page struct, placed on a shared mem instance. /// A thin wrapper around a ShMem implementation, with special Llmp funcs @@ -1149,6 +1179,18 @@ where } } +/// Client side of LLMP +#[derive(Clone, Debug)] +pub struct LlmpClient +where + SH: ShMem, +{ + /// Outgoing channel to the broker + pub llmp_out: LlmpSender, + /// Incoming (broker) broadcast map + pub llmp_in: LlmpReceiver, +} + /// `n` clients connect to a broker. They share an outgoing map with the broker, /// and get incoming messages from the shared broker bus impl LlmpClient @@ -1157,38 +1199,16 @@ where { /// Reattach to a vacant client map. /// It is essential, that the broker (or someone else) kept a pointer to the out_map - /// else reattach will get a new, empty page, from the OS + /// else reattach will get a new, empty page, from the OS, or fail pub fn on_existing_map( current_out_map: SH, last_msg_sent_offset: Option, current_broker_map: SH, last_msg_recvd_offset: Option, ) -> Result { - let mut out_map = LlmpSharedMap::new(0, current_out_map); - let last_msg_sent = match last_msg_sent_offset { - Some(offset) => out_map.msg_from_offset(offset)?, - None => 0 as *mut LlmpMsg, - }; - - let mut current_recv_map = LlmpSharedMap::new(0, current_broker_map); - let last_msg_recvd = match last_msg_recvd_offset { - Some(offset) => current_recv_map.msg_from_offset(offset)?, - None => 0 as *mut LlmpMsg, - }; - Ok(Self { - llmp_out: LlmpSender { - id: 0, - last_msg_sent, - out_maps: vec![out_map], - // drop pages to the broker if it already read them - keep_pages_forever: false, - }, - llmp_in: LlmpReceiver { - id: 0, - current_recv_map, - last_msg_recvd, - }, + llmp_in: LlmpReceiver::on_existing_map(current_broker_map, last_msg_recvd_offset)?, + llmp_out: LlmpSender::on_existing_map(current_out_map, last_msg_sent_offset)?, }) }