Remove ShMemProvider bound from struct definitions (#2861)
* No more ShMemProvider bound constraint in struct definition whenever possible * Introduce StdShMem * Update CONTRIBUTING.md
This commit is contained in:
parent
348bfdc7d7
commit
8089b18d34
@ -75,7 +75,7 @@ pub trait X
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- __Ideally__ the types used in the the arguments of methods in traits should have the same as the types defined on the traits.
|
- __Ideally__ the types used in the arguments of methods in traits should have the same as the types defined on the traits.
|
||||||
```rust
|
```rust
|
||||||
pub trait X<A, B, C> // <- this trait have 3 generics, A, B, and C
|
pub trait X<A, B, C> // <- this trait have 3 generics, A, B, and C
|
||||||
{
|
{
|
||||||
@ -84,6 +84,22 @@ pub trait X<A, B, C> // <- this trait have 3 generics, A, B, and C
|
|||||||
fn do_other_stuff(&self, a: A, b: B); // <- this is not ideal because it does not have C.
|
fn do_other_stuff(&self, a: A, b: B); // <- this is not ideal because it does not have C.
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
- Generic naming should be consistent. Do NOT use multiple name for the same generic, it just makes things more confusing. Do:
|
||||||
|
```rust
|
||||||
|
pub struct X<A> {
|
||||||
|
phantom: PhanomData<A>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<A> X<A> {}
|
||||||
|
```
|
||||||
|
But not:
|
||||||
|
```rust
|
||||||
|
pub struct X<A> {
|
||||||
|
phantom: PhanomData<A>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B> X<B> {} // <- Do NOT do that, use A instead of B
|
||||||
|
```
|
||||||
- Always alphabetically order the type generics. Therefore,
|
- Always alphabetically order the type generics. Therefore,
|
||||||
```rust
|
```rust
|
||||||
pub struct X<E, EM, OT, S, Z> {}; // <- Generics are alphabetically ordered
|
pub struct X<E, EM, OT, S, Z> {}; // <- Generics are alphabetically ordered
|
||||||
@ -91,4 +107,31 @@ pub struct X<E, EM, OT, S, Z> {}; // <- Generics are alphabetically ordered
|
|||||||
But not,
|
But not,
|
||||||
```rust
|
```rust
|
||||||
pub struct X<S, OT, Z, EM, E> {}; // <- Generics are not ordered
|
pub struct X<S, OT, Z, EM, E> {}; // <- Generics are not ordered
|
||||||
```
|
```
|
||||||
|
- Similarly, generic bounds in `where` clauses should be alphabetically sorted. Prefer:
|
||||||
|
```rust
|
||||||
|
pub trait FooA {}
|
||||||
|
pub trait FooB {}
|
||||||
|
|
||||||
|
pub struct X<A, B>;
|
||||||
|
|
||||||
|
impl<A, B> X<A, B>
|
||||||
|
where
|
||||||
|
A: FooA,
|
||||||
|
B: FooB,
|
||||||
|
{}
|
||||||
|
```
|
||||||
|
Over:
|
||||||
|
```rust
|
||||||
|
pub trait FooA {}
|
||||||
|
pub trait FooB {}
|
||||||
|
|
||||||
|
pub struct X<A, B>;
|
||||||
|
|
||||||
|
impl<A, B> X<A, B>
|
||||||
|
where
|
||||||
|
B: FooB, // <-|
|
||||||
|
// | Generic bounds are not alphabetically ordered.
|
||||||
|
A: FooA, // <-|
|
||||||
|
{}
|
||||||
|
```
|
||||||
|
@ -96,7 +96,7 @@ unsafe fn fuzz(
|
|||||||
let shmem_provider = StdShMemProvider::new()?;
|
let shmem_provider = StdShMemProvider::new()?;
|
||||||
|
|
||||||
let mut run_client = |state: Option<_>,
|
let mut run_client = |state: Option<_>,
|
||||||
mgr: LlmpRestartingEventManager<_, _, _, _>,
|
mgr: LlmpRestartingEventManager<_, _, _, _, _>,
|
||||||
client_description: ClientDescription| {
|
client_description: ClientDescription| {
|
||||||
// The restarting state will spawn the same process again as child, then restarted it each time it crashes.
|
// The restarting state will spawn the same process again as child, then restarted it each time it crashes.
|
||||||
|
|
||||||
@ -104,7 +104,7 @@ unsafe fn fuzz(
|
|||||||
|
|
||||||
if options.asan && options.asan_cores.contains(client_description.core_id()) {
|
if options.asan && options.asan_cores.contains(client_description.core_id()) {
|
||||||
(|state: Option<_>,
|
(|state: Option<_>,
|
||||||
mut mgr: LlmpRestartingEventManager<_, _, _, _>,
|
mut mgr: LlmpRestartingEventManager<_, _, _, _, _>,
|
||||||
_client_description| {
|
_client_description| {
|
||||||
let gum = Gum::obtain();
|
let gum = Gum::obtain();
|
||||||
|
|
||||||
@ -231,7 +231,7 @@ unsafe fn fuzz(
|
|||||||
})(state, mgr, client_description)
|
})(state, mgr, client_description)
|
||||||
} else if options.cmplog && options.cmplog_cores.contains(client_description.core_id()) {
|
} else if options.cmplog && options.cmplog_cores.contains(client_description.core_id()) {
|
||||||
(|state: Option<_>,
|
(|state: Option<_>,
|
||||||
mut mgr: LlmpRestartingEventManager<_, _, _, _>,
|
mut mgr: LlmpRestartingEventManager<_, _, _, _, _>,
|
||||||
_client_description| {
|
_client_description| {
|
||||||
let gum = Gum::obtain();
|
let gum = Gum::obtain();
|
||||||
|
|
||||||
@ -367,7 +367,7 @@ unsafe fn fuzz(
|
|||||||
})(state, mgr, client_description)
|
})(state, mgr, client_description)
|
||||||
} else {
|
} else {
|
||||||
(|state: Option<_>,
|
(|state: Option<_>,
|
||||||
mut mgr: LlmpRestartingEventManager<_, _, _, _>,
|
mut mgr: LlmpRestartingEventManager<_, _, _, _, _>,
|
||||||
_client_description| {
|
_client_description| {
|
||||||
let gum = Gum::obtain();
|
let gum = Gum::obtain();
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut run_client = |state: Option<_>,
|
let mut run_client = |state: Option<_>,
|
||||||
mgr: LlmpRestartingEventManager<_, _, _, _>,
|
mgr: LlmpRestartingEventManager<_, _, _, _, _>,
|
||||||
client_description: ClientDescription| {
|
client_description: ClientDescription| {
|
||||||
// The restarting state will spawn the same process again as child, then restarted it each time it crashes.
|
// The restarting state will spawn the same process again as child, then restarted it each time it crashes.
|
||||||
|
|
||||||
@ -101,7 +101,7 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> {
|
|||||||
|
|
||||||
// if options.asan && options.asan_cores.contains(client_description.core_id()) {
|
// if options.asan && options.asan_cores.contains(client_description.core_id()) {
|
||||||
(|state: Option<_>,
|
(|state: Option<_>,
|
||||||
mut mgr: LlmpRestartingEventManager<_, _, _, _>,
|
mut mgr: LlmpRestartingEventManager<_, _, _, _, _>,
|
||||||
_client_description| {
|
_client_description| {
|
||||||
let gum = Gum::obtain();
|
let gum = Gum::obtain();
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> {
|
|||||||
let shmem_provider = StdShMemProvider::new()?;
|
let shmem_provider = StdShMemProvider::new()?;
|
||||||
|
|
||||||
let mut run_client = |state: Option<_>,
|
let mut run_client = |state: Option<_>,
|
||||||
mgr: LlmpRestartingEventManager<_, _, _, _>,
|
mgr: LlmpRestartingEventManager<_, _, _, _, _>,
|
||||||
client_description: ClientDescription| {
|
client_description: ClientDescription| {
|
||||||
// The restarting state will spawn the same process again as child, then restarted it each time it crashes.
|
// The restarting state will spawn the same process again as child, then restarted it each time it crashes.
|
||||||
|
|
||||||
@ -98,7 +98,7 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> {
|
|||||||
|
|
||||||
if options.asan && options.asan_cores.contains(client_description.core_id()) {
|
if options.asan && options.asan_cores.contains(client_description.core_id()) {
|
||||||
(|state: Option<_>,
|
(|state: Option<_>,
|
||||||
mut mgr: LlmpRestartingEventManager<_, _, _, _>,
|
mut mgr: LlmpRestartingEventManager<_, _, _, _, _>,
|
||||||
_client_description| {
|
_client_description| {
|
||||||
let gum = Gum::obtain();
|
let gum = Gum::obtain();
|
||||||
|
|
||||||
@ -214,7 +214,7 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> {
|
|||||||
})(state, mgr, client_description)
|
})(state, mgr, client_description)
|
||||||
} else if options.cmplog && options.cmplog_cores.contains(client_description.core_id()) {
|
} else if options.cmplog && options.cmplog_cores.contains(client_description.core_id()) {
|
||||||
(|state: Option<_>,
|
(|state: Option<_>,
|
||||||
mut mgr: LlmpRestartingEventManager<_, _, _, _>,
|
mut mgr: LlmpRestartingEventManager<_, _, _, _, _>,
|
||||||
_client_description| {
|
_client_description| {
|
||||||
let gum = Gum::obtain();
|
let gum = Gum::obtain();
|
||||||
|
|
||||||
@ -344,7 +344,7 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> {
|
|||||||
})(state, mgr, client_description)
|
})(state, mgr, client_description)
|
||||||
} else {
|
} else {
|
||||||
(|state: Option<_>,
|
(|state: Option<_>,
|
||||||
mut mgr: LlmpRestartingEventManager<_, _, _, _>,
|
mut mgr: LlmpRestartingEventManager<_, _, _, _, _>,
|
||||||
_client_description| {
|
_client_description| {
|
||||||
let gum = Gum::obtain();
|
let gum = Gum::obtain();
|
||||||
|
|
||||||
|
@ -124,7 +124,7 @@ pub fn fuzz() {
|
|||||||
env::remove_var("LD_LIBRARY_PATH");
|
env::remove_var("LD_LIBRARY_PATH");
|
||||||
|
|
||||||
let mut run_client = |state: Option<_>,
|
let mut run_client = |state: Option<_>,
|
||||||
mut mgr: LlmpRestartingEventManager<_, _, _, _>,
|
mut mgr: LlmpRestartingEventManager<_, _, _, _, _>,
|
||||||
client_description: ClientDescription| {
|
client_description: ClientDescription| {
|
||||||
let mut cov_path = options.coverage_path.clone();
|
let mut cov_path = options.coverage_path.clone();
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ use libafl::events::SimpleEventManager;
|
|||||||
use libafl::events::{LlmpRestartingEventManager, MonitorTypedEventManager};
|
use libafl::events::{LlmpRestartingEventManager, MonitorTypedEventManager};
|
||||||
use libafl::{
|
use libafl::{
|
||||||
corpus::{Corpus, InMemoryOnDiskCorpus, OnDiskCorpus},
|
corpus::{Corpus, InMemoryOnDiskCorpus, OnDiskCorpus},
|
||||||
events::{ClientDescription, EventRestarter, NopEventManager},
|
events::{ClientDescription, EventRestarter},
|
||||||
executors::{Executor, ShadowExecutor},
|
executors::{Executor, ShadowExecutor},
|
||||||
feedback_or, feedback_or_fast,
|
feedback_or, feedback_or_fast,
|
||||||
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
||||||
@ -30,7 +30,7 @@ use libafl::{
|
|||||||
Error, HasMetadata, NopFuzzer,
|
Error, HasMetadata, NopFuzzer,
|
||||||
};
|
};
|
||||||
#[cfg(not(feature = "simplemgr"))]
|
#[cfg(not(feature = "simplemgr"))]
|
||||||
use libafl_bolts::shmem::StdShMemProvider;
|
use libafl_bolts::shmem::{StdShMem, StdShMemProvider};
|
||||||
use libafl_bolts::{
|
use libafl_bolts::{
|
||||||
ownedref::OwnedMutSlice,
|
ownedref::OwnedMutSlice,
|
||||||
rands::StdRand,
|
rands::StdRand,
|
||||||
@ -58,7 +58,7 @@ pub type ClientState =
|
|||||||
pub type ClientMgr<M> = SimpleEventManager<BytesInput, M, ClientState>;
|
pub type ClientMgr<M> = SimpleEventManager<BytesInput, M, ClientState>;
|
||||||
#[cfg(not(feature = "simplemgr"))]
|
#[cfg(not(feature = "simplemgr"))]
|
||||||
pub type ClientMgr<M> = MonitorTypedEventManager<
|
pub type ClientMgr<M> = MonitorTypedEventManager<
|
||||||
LlmpRestartingEventManager<(), BytesInput, ClientState, StdShMemProvider>,
|
LlmpRestartingEventManager<(), BytesInput, ClientState, StdShMem, StdShMemProvider>,
|
||||||
M,
|
M,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
@ -68,6 +68,12 @@ where
|
|||||||
Ok(false)
|
Ok(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "track_hit_feedbacks")]
|
||||||
|
#[inline]
|
||||||
|
fn last_result(&self) -> Result<bool, Error> {
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
|
||||||
fn append_metadata(
|
fn append_metadata(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
@ -78,10 +84,4 @@ where
|
|||||||
(self.func)(state, testcase, &self.out_dir)?;
|
(self.func)(state, testcase, &self.out_dir)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "track_hit_feedbacks")]
|
|
||||||
#[inline]
|
|
||||||
fn last_result(&self) -> Result<bool, Error> {
|
|
||||||
Ok(false)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ use libafl::{
|
|||||||
Error, Fuzzer, HasFeedback, HasMetadata, SerdeAny,
|
Error, Fuzzer, HasFeedback, HasMetadata, SerdeAny,
|
||||||
};
|
};
|
||||||
#[cfg(not(feature = "fuzzbench"))]
|
#[cfg(not(feature = "fuzzbench"))]
|
||||||
use libafl_bolts::shmem::StdShMemProvider;
|
use libafl_bolts::shmem::{StdShMem, StdShMemProvider};
|
||||||
use libafl_bolts::{
|
use libafl_bolts::{
|
||||||
core_affinity::CoreId,
|
core_affinity::CoreId,
|
||||||
current_nanos, current_time,
|
current_nanos, current_time,
|
||||||
@ -77,10 +77,11 @@ pub type LibaflFuzzState =
|
|||||||
|
|
||||||
#[cfg(not(feature = "fuzzbench"))]
|
#[cfg(not(feature = "fuzzbench"))]
|
||||||
type LibaflFuzzManager = CentralizedEventManager<
|
type LibaflFuzzManager = CentralizedEventManager<
|
||||||
LlmpRestartingEventManager<(), BytesInput, LibaflFuzzState, StdShMemProvider>,
|
LlmpRestartingEventManager<(), BytesInput, LibaflFuzzState, StdShMem, StdShMemProvider>,
|
||||||
(),
|
(),
|
||||||
BytesInput,
|
BytesInput,
|
||||||
LibaflFuzzState,
|
LibaflFuzzState,
|
||||||
|
StdShMem,
|
||||||
StdShMemProvider,
|
StdShMemProvider,
|
||||||
>;
|
>;
|
||||||
#[cfg(feature = "fuzzbench")]
|
#[cfg(feature = "fuzzbench")]
|
||||||
|
@ -30,7 +30,7 @@ use libafl::{
|
|||||||
use libafl_bolts::{
|
use libafl_bolts::{
|
||||||
current_nanos,
|
current_nanos,
|
||||||
rands::StdRand,
|
rands::StdRand,
|
||||||
shmem::StdShMemProvider,
|
shmem::{StdShMem, StdShMemProvider},
|
||||||
tuples::{tuple_list, Merge},
|
tuples::{tuple_list, Merge},
|
||||||
};
|
};
|
||||||
use libafl_nyx::{
|
use libafl_nyx::{
|
||||||
@ -44,7 +44,7 @@ pub type ClientState =
|
|||||||
StdState<InMemoryOnDiskCorpus<BytesInput>, BytesInput, StdRand, OnDiskCorpus<BytesInput>>;
|
StdState<InMemoryOnDiskCorpus<BytesInput>, BytesInput, StdRand, OnDiskCorpus<BytesInput>>;
|
||||||
|
|
||||||
pub type ClientMgr<M> = MonitorTypedEventManager<
|
pub type ClientMgr<M> = MonitorTypedEventManager<
|
||||||
LlmpRestartingEventManager<(), BytesInput, ClientState, StdShMemProvider>,
|
LlmpRestartingEventManager<(), BytesInput, ClientState, StdShMem, StdShMemProvider>,
|
||||||
M,
|
M,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ pub extern "C" fn libafl_main() {
|
|||||||
|
|
||||||
let mut secondary_run_client =
|
let mut secondary_run_client =
|
||||||
|state: Option<_>,
|
|state: Option<_>,
|
||||||
mut mgr: CentralizedEventManager<_, _, _, _, _>,
|
mut mgr: CentralizedEventManager<_, _, _, _, _, _>,
|
||||||
_client_description: ClientDescription| {
|
_client_description: ClientDescription| {
|
||||||
// Create an observation channel using the coverage map
|
// Create an observation channel using the coverage map
|
||||||
let edges_observer =
|
let edges_observer =
|
||||||
|
@ -219,7 +219,7 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
|||||||
|
|
||||||
let orig_size = state.corpus().count();
|
let orig_size = state.corpus().count();
|
||||||
let msg = "Started distillation...".to_string();
|
let msg = "Started distillation...".to_string();
|
||||||
<LlmpRestartingEventManager<_, _, _, _> as EventFirer<BytesInput, _>>::log(
|
<LlmpRestartingEventManager<_, _, _, _, _> as EventFirer<BytesInput, _>>::log(
|
||||||
&mut restarting_mgr,
|
&mut restarting_mgr,
|
||||||
&mut state,
|
&mut state,
|
||||||
LogSeverity::Info,
|
LogSeverity::Info,
|
||||||
@ -227,7 +227,7 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
|||||||
)?;
|
)?;
|
||||||
minimizer.minimize(&mut fuzzer, &mut executor, &mut restarting_mgr, &mut state)?;
|
minimizer.minimize(&mut fuzzer, &mut executor, &mut restarting_mgr, &mut state)?;
|
||||||
let msg = format!("Distilled out {} cases", orig_size - state.corpus().count());
|
let msg = format!("Distilled out {} cases", orig_size - state.corpus().count());
|
||||||
<LlmpRestartingEventManager<_, _, _, _> as EventFirer<BytesInput, _>>::log(
|
<LlmpRestartingEventManager<_, _, _, _, _> as EventFirer<BytesInput, _>>::log(
|
||||||
&mut restarting_mgr,
|
&mut restarting_mgr,
|
||||||
&mut state,
|
&mut state,
|
||||||
LogSeverity::Info,
|
LogSeverity::Info,
|
||||||
|
@ -162,7 +162,7 @@ pub extern "C" fn libafl_main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let mut run_client = |state: Option<_>,
|
let mut run_client = |state: Option<_>,
|
||||||
mut restarting_mgr: LlmpRestartingEventManager<_, _, _, _>,
|
mut restarting_mgr: LlmpRestartingEventManager<_, _, _, _, _>,
|
||||||
client_description: ClientDescription| {
|
client_description: ClientDescription| {
|
||||||
// Create an observation channel using the coverage map
|
// Create an observation channel using the coverage map
|
||||||
let edges_observer =
|
let edges_observer =
|
||||||
|
@ -157,7 +157,7 @@ pub extern "C" fn libafl_main() {
|
|||||||
|
|
||||||
let mut secondary_run_client =
|
let mut secondary_run_client =
|
||||||
|state: Option<_>,
|
|state: Option<_>,
|
||||||
mut mgr: CentralizedEventManager<_, _, _, _>,
|
mut mgr: CentralizedEventManager<_, _, _, _, _, _>,
|
||||||
_client_description: ClientDescription| {
|
_client_description: ClientDescription| {
|
||||||
// Create an observation channel using the coverage map
|
// Create an observation channel using the coverage map
|
||||||
let edges_observer =
|
let edges_observer =
|
||||||
|
@ -5,7 +5,6 @@ use core::{fmt::Debug, marker::PhantomData};
|
|||||||
use libafl_bolts::{compress::GzipCompressor, llmp::LLMP_FLAG_COMPRESSED};
|
use libafl_bolts::{compress::GzipCompressor, llmp::LLMP_FLAG_COMPRESSED};
|
||||||
use libafl_bolts::{
|
use libafl_bolts::{
|
||||||
llmp::{Flags, LlmpBrokerInner, LlmpHook, LlmpMsgHookResult, Tag},
|
llmp::{Flags, LlmpBrokerInner, LlmpHook, LlmpMsgHookResult, Tag},
|
||||||
shmem::ShMemProvider,
|
|
||||||
ClientId, Error,
|
ClientId, Error,
|
||||||
};
|
};
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
@ -21,14 +20,13 @@ pub struct CentralizedLlmpHook<I> {
|
|||||||
phantom: PhantomData<I>,
|
phantom: PhantomData<I>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I, SP> LlmpHook<SP> for CentralizedLlmpHook<I>
|
impl<I, SHM, SP> LlmpHook<SHM, SP> for CentralizedLlmpHook<I>
|
||||||
where
|
where
|
||||||
I: DeserializeOwned,
|
I: DeserializeOwned,
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
{
|
||||||
fn on_new_message(
|
fn on_new_message(
|
||||||
&mut self,
|
&mut self,
|
||||||
_broker_inner: &mut LlmpBrokerInner<SP>,
|
_broker_inner: &mut LlmpBrokerInner<SHM, SP>,
|
||||||
client_id: ClientId,
|
client_id: ClientId,
|
||||||
msg_tag: &mut Tag,
|
msg_tag: &mut Tag,
|
||||||
_msg_flags: &mut Flags,
|
_msg_flags: &mut Flags,
|
||||||
|
@ -11,7 +11,6 @@ use libafl_bolts::llmp::LLMP_FLAG_COMPRESSED;
|
|||||||
use libafl_bolts::{
|
use libafl_bolts::{
|
||||||
llmp::{Flags, LlmpBrokerInner, LlmpHook, LlmpMsgHookResult, Tag, LLMP_FLAG_FROM_MM},
|
llmp::{Flags, LlmpBrokerInner, LlmpHook, LlmpMsgHookResult, Tag, LLMP_FLAG_FROM_MM},
|
||||||
ownedref::OwnedRef,
|
ownedref::OwnedRef,
|
||||||
shmem::ShMemProvider,
|
|
||||||
ClientId, Error,
|
ClientId, Error,
|
||||||
};
|
};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
@ -149,16 +148,15 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A, I, SP> LlmpHook<SP> for TcpMultiMachineLlmpSenderHook<A, I>
|
impl<A, I, SHM, SP> LlmpHook<SHM, SP> for TcpMultiMachineLlmpSenderHook<A, I>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
A: Clone + Display + ToSocketAddrs + Send + Sync + 'static,
|
A: Clone + Display + ToSocketAddrs + Send + Sync + 'static,
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
{
|
||||||
/// check for received messages, and forward them alongside the incoming message to inner.
|
/// check for received messages, and forward them alongside the incoming message to inner.
|
||||||
fn on_new_message(
|
fn on_new_message(
|
||||||
&mut self,
|
&mut self,
|
||||||
_broker_inner: &mut LlmpBrokerInner<SP>,
|
_broker_inner: &mut LlmpBrokerInner<SHM, SP>,
|
||||||
_client_id: ClientId,
|
_client_id: ClientId,
|
||||||
_msg_tag: &mut Tag,
|
_msg_tag: &mut Tag,
|
||||||
_msg_flags: &mut Flags,
|
_msg_flags: &mut Flags,
|
||||||
@ -211,16 +209,15 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A, I, SP> LlmpHook<SP> for TcpMultiMachineLlmpReceiverHook<A, I>
|
impl<A, I, SHM, SP> LlmpHook<SHM, SP> for TcpMultiMachineLlmpReceiverHook<A, I>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
A: Clone + Display + ToSocketAddrs + Send + Sync + 'static,
|
A: Clone + Display + ToSocketAddrs + Send + Sync + 'static,
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
{
|
||||||
/// check for received messages, and forward them alongside the incoming message to inner.
|
/// check for received messages, and forward them alongside the incoming message to inner.
|
||||||
fn on_new_message(
|
fn on_new_message(
|
||||||
&mut self,
|
&mut self,
|
||||||
_broker_inner: &mut LlmpBrokerInner<SP>,
|
_broker_inner: &mut LlmpBrokerInner<SHM, SP>,
|
||||||
_client_id: ClientId,
|
_client_id: ClientId,
|
||||||
_msg_tag: &mut Tag,
|
_msg_tag: &mut Tag,
|
||||||
_msg_flags: &mut Flags,
|
_msg_flags: &mut Flags,
|
||||||
|
@ -6,7 +6,6 @@ use core::marker::PhantomData;
|
|||||||
use libafl_bolts::{compress::GzipCompressor, llmp::LLMP_FLAG_COMPRESSED};
|
use libafl_bolts::{compress::GzipCompressor, llmp::LLMP_FLAG_COMPRESSED};
|
||||||
use libafl_bolts::{
|
use libafl_bolts::{
|
||||||
llmp::{Flags, LlmpBrokerInner, LlmpHook, LlmpMsgHookResult, Tag},
|
llmp::{Flags, LlmpBrokerInner, LlmpHook, LlmpMsgHookResult, Tag},
|
||||||
shmem::ShMemProvider,
|
|
||||||
ClientId,
|
ClientId,
|
||||||
};
|
};
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
@ -40,15 +39,14 @@ pub struct StdLlmpEventHook<I, MT> {
|
|||||||
phantom: PhantomData<I>,
|
phantom: PhantomData<I>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I, MT, SP> LlmpHook<SP> for StdLlmpEventHook<I, MT>
|
impl<I, MT, SHM, SP> LlmpHook<SHM, SP> for StdLlmpEventHook<I, MT>
|
||||||
where
|
where
|
||||||
I: DeserializeOwned,
|
I: DeserializeOwned,
|
||||||
SP: ShMemProvider,
|
|
||||||
MT: Monitor,
|
MT: Monitor,
|
||||||
{
|
{
|
||||||
fn on_new_message(
|
fn on_new_message(
|
||||||
&mut self,
|
&mut self,
|
||||||
_broker_inner: &mut LlmpBrokerInner<SP>,
|
_broker_inner: &mut LlmpBrokerInner<SHM, SP>,
|
||||||
client_id: ClientId,
|
client_id: ClientId,
|
||||||
msg_tag: &mut Tag,
|
msg_tag: &mut Tag,
|
||||||
#[cfg(feature = "llmp_compression")] msg_flags: &mut Flags,
|
#[cfg(feature = "llmp_compression")] msg_flags: &mut Flags,
|
||||||
|
@ -18,7 +18,7 @@ use libafl_bolts::{
|
|||||||
};
|
};
|
||||||
use libafl_bolts::{
|
use libafl_bolts::{
|
||||||
llmp::{LlmpClient, LlmpClientDescription, Tag},
|
llmp::{LlmpClient, LlmpClientDescription, Tag},
|
||||||
shmem::{NopShMemProvider, ShMemProvider},
|
shmem::{NopShMem, NopShMemProvider, ShMem, ShMemProvider},
|
||||||
tuples::{Handle, MatchNameRef},
|
tuples::{Handle, MatchNameRef},
|
||||||
ClientId,
|
ClientId,
|
||||||
};
|
};
|
||||||
@ -46,13 +46,10 @@ pub(crate) const _LLMP_TAG_TO_MAIN: Tag = Tag(0x3453453);
|
|||||||
|
|
||||||
/// A wrapper manager to implement a main-secondary architecture with another broker
|
/// A wrapper manager to implement a main-secondary architecture with another broker
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct CentralizedEventManager<EM, EMH, I, S, SP>
|
pub struct CentralizedEventManager<EM, EMH, I, S, SHM, SP> {
|
||||||
where
|
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
|
||||||
inner: EM,
|
inner: EM,
|
||||||
/// The centralized LLMP client for inter process communication
|
/// The centralized LLMP client for inter process communication
|
||||||
client: LlmpClient<SP>,
|
client: LlmpClient<SHM, SP>,
|
||||||
#[cfg(feature = "llmp_compression")]
|
#[cfg(feature = "llmp_compression")]
|
||||||
compressor: GzipCompressor,
|
compressor: GzipCompressor,
|
||||||
time_ref: Option<Handle<TimeObserver>>,
|
time_ref: Option<Handle<TimeObserver>>,
|
||||||
@ -61,7 +58,16 @@ where
|
|||||||
phantom: PhantomData<(I, S)>,
|
phantom: PhantomData<(I, S)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CentralizedEventManager<NopEventManager, (), NopInput, NopState<NopInput>, NopShMemProvider> {
|
impl
|
||||||
|
CentralizedEventManager<
|
||||||
|
NopEventManager,
|
||||||
|
(),
|
||||||
|
NopInput,
|
||||||
|
NopState<NopInput>,
|
||||||
|
NopShMem,
|
||||||
|
NopShMemProvider,
|
||||||
|
>
|
||||||
|
{
|
||||||
/// Creates a builder for [`CentralizedEventManager`]
|
/// Creates a builder for [`CentralizedEventManager`]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn builder() -> CentralizedEventManagerBuilder {
|
pub fn builder() -> CentralizedEventManagerBuilder {
|
||||||
@ -95,13 +101,14 @@ impl CentralizedEventManagerBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new [`CentralizedEventManager`].
|
/// Creates a new [`CentralizedEventManager`].
|
||||||
|
#[expect(clippy::type_complexity)]
|
||||||
pub fn build_from_client<EM, EMH, I, S, SP>(
|
pub fn build_from_client<EM, EMH, I, S, SP>(
|
||||||
self,
|
self,
|
||||||
inner: EM,
|
inner: EM,
|
||||||
hooks: EMH,
|
hooks: EMH,
|
||||||
client: LlmpClient<SP>,
|
client: LlmpClient<SP::ShMem, SP>,
|
||||||
time_obs: Option<Handle<TimeObserver>>,
|
time_obs: Option<Handle<TimeObserver>>,
|
||||||
) -> Result<CentralizedEventManager<EM, EMH, I, S, SP>, Error>
|
) -> Result<CentralizedEventManager<EM, EMH, I, S, SP::ShMem, SP>, Error>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
SP: ShMemProvider,
|
||||||
{
|
{
|
||||||
@ -121,16 +128,17 @@ impl CentralizedEventManagerBuilder {
|
|||||||
///
|
///
|
||||||
/// If the port is not yet bound, it will act as a broker; otherwise, it
|
/// If the port is not yet bound, it will act as a broker; otherwise, it
|
||||||
/// will act as a client.
|
/// will act as a client.
|
||||||
pub fn build_on_port<EM, EMH, I, S, SP>(
|
pub fn build_on_port<EM, EMH, I, S, SHM, SP>(
|
||||||
self,
|
self,
|
||||||
inner: EM,
|
inner: EM,
|
||||||
hooks: EMH,
|
hooks: EMH,
|
||||||
shmem_provider: SP,
|
shmem_provider: SP,
|
||||||
port: u16,
|
port: u16,
|
||||||
time_obs: Option<Handle<TimeObserver>>,
|
time_obs: Option<Handle<TimeObserver>>,
|
||||||
) -> Result<CentralizedEventManager<EM, EMH, I, S, SP>, Error>
|
) -> Result<CentralizedEventManager<EM, EMH, I, S, SHM, SP>, Error>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
let client = LlmpClient::create_attach_to_tcp(shmem_provider, port)?;
|
let client = LlmpClient::create_attach_to_tcp(shmem_provider, port)?;
|
||||||
Self::build_from_client(self, inner, hooks, client, time_obs)
|
Self::build_from_client(self, inner, hooks, client, time_obs)
|
||||||
@ -138,42 +146,43 @@ impl CentralizedEventManagerBuilder {
|
|||||||
|
|
||||||
/// If a client respawns, it may reuse the existing connection, previously
|
/// If a client respawns, it may reuse the existing connection, previously
|
||||||
/// stored by [`LlmpClient::to_env()`].
|
/// stored by [`LlmpClient::to_env()`].
|
||||||
pub fn build_existing_client_from_env<EM, EMH, I, S, SP>(
|
pub fn build_existing_client_from_env<EM, EMH, I, S, SHM, SP>(
|
||||||
self,
|
self,
|
||||||
inner: EM,
|
inner: EM,
|
||||||
hooks: EMH,
|
hooks: EMH,
|
||||||
shmem_provider: SP,
|
shmem_provider: SP,
|
||||||
env_name: &str,
|
env_name: &str,
|
||||||
time_obs: Option<Handle<TimeObserver>>,
|
time_obs: Option<Handle<TimeObserver>>,
|
||||||
) -> Result<CentralizedEventManager<EM, EMH, I, S, SP>, Error>
|
) -> Result<CentralizedEventManager<EM, EMH, I, S, SHM, SP>, Error>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
let client = LlmpClient::on_existing_from_env(shmem_provider, env_name)?;
|
let client = LlmpClient::on_existing_from_env(shmem_provider, env_name)?;
|
||||||
Self::build_from_client(self, inner, hooks, client, time_obs)
|
Self::build_from_client(self, inner, hooks, client, time_obs)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create an existing client from description
|
/// Create an existing client from description
|
||||||
pub fn existing_client_from_description<EM, EMH, I, S, SP>(
|
pub fn existing_client_from_description<EM, EMH, I, S, SHM, SP>(
|
||||||
self,
|
self,
|
||||||
inner: EM,
|
inner: EM,
|
||||||
hooks: EMH,
|
hooks: EMH,
|
||||||
shmem_provider: SP,
|
shmem_provider: SP,
|
||||||
description: &LlmpClientDescription,
|
description: &LlmpClientDescription,
|
||||||
time_obs: Option<Handle<TimeObserver>>,
|
time_obs: Option<Handle<TimeObserver>>,
|
||||||
) -> Result<CentralizedEventManager<EM, EMH, I, S, SP>, Error>
|
) -> Result<CentralizedEventManager<EM, EMH, I, S, SHM, SP>, Error>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
let client = LlmpClient::existing_client_from_description(shmem_provider, description)?;
|
let client = LlmpClient::existing_client_from_description(shmem_provider, description)?;
|
||||||
Self::build_from_client(self, inner, hooks, client, time_obs)
|
Self::build_from_client(self, inner, hooks, client, time_obs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EM, EMH, I, S, SP> AdaptiveSerializer for CentralizedEventManager<EM, EMH, I, S, SP>
|
impl<EM, EMH, I, S, SHM, SP> AdaptiveSerializer for CentralizedEventManager<EM, EMH, I, S, SHM, SP>
|
||||||
where
|
where
|
||||||
EM: AdaptiveSerializer,
|
EM: AdaptiveSerializer,
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
{
|
||||||
fn serialization_time(&self) -> Duration {
|
fn serialization_time(&self) -> Duration {
|
||||||
self.inner.serialization_time()
|
self.inner.serialization_time()
|
||||||
@ -206,13 +215,14 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EM, EMH, I, S, SP> EventFirer<I, S> for CentralizedEventManager<EM, EMH, I, S, SP>
|
impl<EM, EMH, I, S, SHM, SP> EventFirer<I, S> for CentralizedEventManager<EM, EMH, I, S, SHM, SP>
|
||||||
where
|
where
|
||||||
EM: HasEventManagerId + EventFirer<I, S>,
|
EM: HasEventManagerId + EventFirer<I, S>,
|
||||||
EMH: EventManagerHooksTuple<I, S>,
|
EMH: EventManagerHooksTuple<I, S>,
|
||||||
SP: ShMemProvider,
|
|
||||||
S: Stoppable,
|
S: Stoppable,
|
||||||
I: Input,
|
I: Input,
|
||||||
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
fn should_send(&self) -> bool {
|
fn should_send(&self) -> bool {
|
||||||
self.inner.should_send()
|
self.inner.should_send()
|
||||||
@ -263,10 +273,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EM, EMH, I, S, SP> EventRestarter<S> for CentralizedEventManager<EM, EMH, I, S, SP>
|
impl<EM, EMH, I, S, SHM, SP> EventRestarter<S> for CentralizedEventManager<EM, EMH, I, S, SHM, SP>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
|
||||||
EM: EventRestarter<S>,
|
EM: EventRestarter<S>,
|
||||||
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn on_restart(&mut self, state: &mut S) -> Result<(), Error> {
|
fn on_restart(&mut self, state: &mut S) -> Result<(), Error> {
|
||||||
@ -276,10 +287,10 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EM, EMH, I, OT, S, SP> CanSerializeObserver<OT> for CentralizedEventManager<EM, EMH, I, S, SP>
|
impl<EM, EMH, I, OT, S, SHM, SP> CanSerializeObserver<OT>
|
||||||
|
for CentralizedEventManager<EM, EMH, I, S, SHM, SP>
|
||||||
where
|
where
|
||||||
EM: AdaptiveSerializer,
|
EM: AdaptiveSerializer,
|
||||||
SP: ShMemProvider,
|
|
||||||
OT: Serialize + MatchNameRef,
|
OT: Serialize + MatchNameRef,
|
||||||
{
|
{
|
||||||
fn serialize_observers(&mut self, observers: &OT) -> Result<Option<Vec<u8>>, Error> {
|
fn serialize_observers(&mut self, observers: &OT) -> Result<Option<Vec<u8>>, Error> {
|
||||||
@ -292,10 +303,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EM, EMH, I, S, SP> ManagerExit for CentralizedEventManager<EM, EMH, I, S, SP>
|
impl<EM, EMH, I, S, SHM, SP> ManagerExit for CentralizedEventManager<EM, EMH, I, S, SHM, SP>
|
||||||
where
|
where
|
||||||
EM: ManagerExit,
|
EM: ManagerExit,
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
fn send_exiting(&mut self) -> Result<(), Error> {
|
fn send_exiting(&mut self) -> Result<(), Error> {
|
||||||
self.client.sender_mut().send_exiting()?;
|
self.client.sender_mut().send_exiting()?;
|
||||||
@ -309,15 +321,17 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E, EM, EMH, I, S, SP, Z> EventProcessor<E, S, Z> for CentralizedEventManager<EM, EMH, I, S, SP>
|
impl<E, EM, EMH, I, S, SHM, SP, Z> EventProcessor<E, S, Z>
|
||||||
|
for CentralizedEventManager<EM, EMH, I, S, SHM, SP>
|
||||||
where
|
where
|
||||||
E: HasObservers,
|
E: HasObservers,
|
||||||
E::Observers: DeserializeOwned,
|
E::Observers: DeserializeOwned,
|
||||||
EM: EventProcessor<E, S, Z> + HasEventManagerId + EventFirer<I, S>,
|
EM: EventProcessor<E, S, Z> + HasEventManagerId + EventFirer<I, S>,
|
||||||
EMH: EventManagerHooksTuple<I, S>,
|
EMH: EventManagerHooksTuple<I, S>,
|
||||||
S: Stoppable,
|
|
||||||
I: Input,
|
I: Input,
|
||||||
SP: ShMemProvider,
|
S: Stoppable,
|
||||||
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
Z: ExecutionProcessor<Self, I, E::Observers, S> + EvaluatorObservers<E, Self, I, S>,
|
Z: ExecutionProcessor<Self, I, E::Observers, S> + EvaluatorObservers<E, Self, I, S>,
|
||||||
{
|
{
|
||||||
fn process(&mut self, fuzzer: &mut Z, state: &mut S, executor: &mut E) -> Result<usize, Error> {
|
fn process(&mut self, fuzzer: &mut Z, state: &mut S, executor: &mut E) -> Result<usize, Error> {
|
||||||
@ -337,13 +351,14 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EM, EMH, I, S, SP> ProgressReporter<S> for CentralizedEventManager<EM, EMH, I, S, SP>
|
impl<EM, EMH, I, S, SHM, SP> ProgressReporter<S> for CentralizedEventManager<EM, EMH, I, S, SHM, SP>
|
||||||
where
|
where
|
||||||
EM: EventFirer<I, S> + HasEventManagerId,
|
EM: EventFirer<I, S> + HasEventManagerId,
|
||||||
EMH: EventManagerHooksTuple<I, S>,
|
EMH: EventManagerHooksTuple<I, S>,
|
||||||
S: HasExecutions + HasMetadata + HasLastReportTime + Stoppable + MaybeHasClientPerfMonitor,
|
|
||||||
I: Input,
|
I: Input,
|
||||||
SP: ShMemProvider,
|
S: HasExecutions + HasMetadata + HasLastReportTime + Stoppable + MaybeHasClientPerfMonitor,
|
||||||
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
fn maybe_report_progress(
|
fn maybe_report_progress(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -358,19 +373,19 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EM, EMH, I, S, SP> HasEventManagerId for CentralizedEventManager<EM, EMH, I, S, SP>
|
impl<EM, EMH, I, S, SHM, SP> HasEventManagerId for CentralizedEventManager<EM, EMH, I, S, SHM, SP>
|
||||||
where
|
where
|
||||||
EM: HasEventManagerId,
|
EM: HasEventManagerId,
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
{
|
||||||
fn mgr_id(&self) -> EventManagerId {
|
fn mgr_id(&self) -> EventManagerId {
|
||||||
self.inner.mgr_id()
|
self.inner.mgr_id()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EM, EMH, I, S, SP> CentralizedEventManager<EM, EMH, I, S, SP>
|
impl<EM, EMH, I, S, SHM, SP> CentralizedEventManager<EM, EMH, I, S, SHM, SP>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
/// Describe the client event manager's LLMP parts in a restorable fashion
|
/// Describe the client event manager's LLMP parts in a restorable fashion
|
||||||
pub fn describe(&self) -> Result<LlmpClientDescription, Error> {
|
pub fn describe(&self) -> Result<LlmpClientDescription, Error> {
|
||||||
@ -389,13 +404,14 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EM, EMH, I, S, SP> CentralizedEventManager<EM, EMH, I, S, SP>
|
impl<EM, EMH, I, S, SHM, SP> CentralizedEventManager<EM, EMH, I, S, SHM, SP>
|
||||||
where
|
where
|
||||||
EM: HasEventManagerId + EventFirer<I, S>,
|
EM: HasEventManagerId + EventFirer<I, S>,
|
||||||
EMH: EventManagerHooksTuple<I, S>,
|
EMH: EventManagerHooksTuple<I, S>,
|
||||||
S: Stoppable,
|
|
||||||
I: Input,
|
I: Input,
|
||||||
SP: ShMemProvider,
|
S: Stoppable,
|
||||||
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
#[cfg(feature = "llmp_compression")]
|
#[cfg(feature = "llmp_compression")]
|
||||||
fn forward_to_main(&mut self, event: &Event<I>) -> Result<(), Error> {
|
fn forward_to_main(&mut self, event: &Event<I>) -> Result<(), Error> {
|
||||||
|
@ -208,7 +208,6 @@ impl<CF, MT, SP> Debug for Launcher<'_, CF, MT, SP> {
|
|||||||
impl<CF, MT, SP> Launcher<'_, CF, MT, SP>
|
impl<CF, MT, SP> Launcher<'_, CF, MT, SP>
|
||||||
where
|
where
|
||||||
MT: Monitor + Clone,
|
MT: Monitor + Clone,
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
{
|
||||||
/// Launch the broker and the clients and fuzz
|
/// Launch the broker and the clients and fuzz
|
||||||
#[cfg(any(windows, not(feature = "fork"), all(unix, feature = "fork")))]
|
#[cfg(any(windows, not(feature = "fork"), all(unix, feature = "fork")))]
|
||||||
@ -216,11 +215,12 @@ where
|
|||||||
where
|
where
|
||||||
CF: FnOnce(
|
CF: FnOnce(
|
||||||
Option<S>,
|
Option<S>,
|
||||||
LlmpRestartingEventManager<(), I, S, SP>,
|
LlmpRestartingEventManager<(), I, S, SP::ShMem, SP>,
|
||||||
ClientDescription,
|
ClientDescription,
|
||||||
) -> Result<(), Error>,
|
) -> Result<(), Error>,
|
||||||
I: DeserializeOwned,
|
I: DeserializeOwned,
|
||||||
S: DeserializeOwned + Serialize,
|
S: DeserializeOwned + Serialize,
|
||||||
|
SP: ShMemProvider,
|
||||||
{
|
{
|
||||||
Self::launch_with_hooks(self, tuple_list!())
|
Self::launch_with_hooks(self, tuple_list!())
|
||||||
}
|
}
|
||||||
@ -240,7 +240,7 @@ where
|
|||||||
EMH: EventManagerHooksTuple<I, S> + Clone + Copy,
|
EMH: EventManagerHooksTuple<I, S> + Clone + Copy,
|
||||||
CF: FnOnce(
|
CF: FnOnce(
|
||||||
Option<S>,
|
Option<S>,
|
||||||
LlmpRestartingEventManager<EMH, I, S, SP>,
|
LlmpRestartingEventManager<EMH, I, S, SP::ShMem, SP>,
|
||||||
ClientDescription,
|
ClientDescription,
|
||||||
) -> Result<(), Error>,
|
) -> Result<(), Error>,
|
||||||
{
|
{
|
||||||
@ -385,7 +385,7 @@ where
|
|||||||
where
|
where
|
||||||
CF: FnOnce(
|
CF: FnOnce(
|
||||||
Option<S>,
|
Option<S>,
|
||||||
LlmpRestartingEventManager<EMH, I, S, SP>,
|
LlmpRestartingEventManager<EMH, I, S, SP::ShMem, SP>,
|
||||||
ClientDescription,
|
ClientDescription,
|
||||||
) -> Result<(), Error>,
|
) -> Result<(), Error>,
|
||||||
EMH: EventManagerHooksTuple<I, S> + Clone + Copy,
|
EMH: EventManagerHooksTuple<I, S> + Clone + Copy,
|
||||||
@ -620,7 +620,7 @@ impl<CF, MF, MT, SP> Debug for CentralizedLauncher<'_, CF, MF, MT, SP> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The standard inner manager of centralized
|
/// The standard inner manager of centralized
|
||||||
pub type StdCentralizedInnerMgr<I, S, SP> = LlmpRestartingEventManager<(), I, S, SP>;
|
pub type StdCentralizedInnerMgr<I, S, SHM, SP> = LlmpRestartingEventManager<(), I, S, SHM, SP>;
|
||||||
|
|
||||||
#[cfg(all(unix, feature = "fork"))]
|
#[cfg(all(unix, feature = "fork"))]
|
||||||
impl<CF, MF, MT, SP> CentralizedLauncher<'_, CF, MF, MT, SP>
|
impl<CF, MF, MT, SP> CentralizedLauncher<'_, CF, MF, MT, SP>
|
||||||
@ -635,12 +635,26 @@ where
|
|||||||
I: DeserializeOwned + Input + Send + Sync + 'static,
|
I: DeserializeOwned + Input + Send + Sync + 'static,
|
||||||
CF: FnOnce(
|
CF: FnOnce(
|
||||||
Option<S>,
|
Option<S>,
|
||||||
CentralizedEventManager<StdCentralizedInnerMgr<I, S, SP>, (), I, S, SP>,
|
CentralizedEventManager<
|
||||||
|
StdCentralizedInnerMgr<I, S, SP::ShMem, SP>,
|
||||||
|
(),
|
||||||
|
I,
|
||||||
|
S,
|
||||||
|
SP::ShMem,
|
||||||
|
SP,
|
||||||
|
>,
|
||||||
ClientDescription,
|
ClientDescription,
|
||||||
) -> Result<(), Error>,
|
) -> Result<(), Error>,
|
||||||
MF: FnOnce(
|
MF: FnOnce(
|
||||||
Option<S>,
|
Option<S>,
|
||||||
CentralizedEventManager<StdCentralizedInnerMgr<I, S, SP>, (), I, S, SP>,
|
CentralizedEventManager<
|
||||||
|
StdCentralizedInnerMgr<I, S, SP::ShMem, SP>,
|
||||||
|
(),
|
||||||
|
I,
|
||||||
|
S,
|
||||||
|
SP::ShMem,
|
||||||
|
SP,
|
||||||
|
>,
|
||||||
ClientDescription,
|
ClientDescription,
|
||||||
) -> Result<(), Error>,
|
) -> Result<(), Error>,
|
||||||
{
|
{
|
||||||
@ -682,13 +696,13 @@ where
|
|||||||
I: Input + Send + Sync + 'static,
|
I: Input + Send + Sync + 'static,
|
||||||
CF: FnOnce(
|
CF: FnOnce(
|
||||||
Option<S>,
|
Option<S>,
|
||||||
CentralizedEventManager<EM, (), I, S, SP>,
|
CentralizedEventManager<EM, (), I, S, SP::ShMem, SP>,
|
||||||
ClientDescription,
|
ClientDescription,
|
||||||
) -> Result<(), Error>,
|
) -> Result<(), Error>,
|
||||||
EMB: FnOnce(&Self, ClientDescription) -> Result<(Option<S>, EM), Error>,
|
EMB: FnOnce(&Self, ClientDescription) -> Result<(Option<S>, EM), Error>,
|
||||||
MF: FnOnce(
|
MF: FnOnce(
|
||||||
Option<S>,
|
Option<S>,
|
||||||
CentralizedEventManager<EM, (), I, S, SP>, // No broker_hooks for centralized EM
|
CentralizedEventManager<EM, (), I, S, SP::ShMem, SP>, // No broker_hooks for centralized EM
|
||||||
ClientDescription,
|
ClientDescription,
|
||||||
) -> Result<(), Error>,
|
) -> Result<(), Error>,
|
||||||
{
|
{
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use alloc::string::ToString;
|
use alloc::string::ToString;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use core::{marker::PhantomData, time::Duration};
|
use core::{fmt::Debug, marker::PhantomData, time::Duration};
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use std::net::TcpStream;
|
use std::net::TcpStream;
|
||||||
|
|
||||||
@ -18,7 +18,7 @@ use libafl_bolts::{
|
|||||||
use libafl_bolts::{
|
use libafl_bolts::{
|
||||||
current_time,
|
current_time,
|
||||||
llmp::{LlmpClient, LlmpClientDescription, LLMP_FLAG_FROM_MM},
|
llmp::{LlmpClient, LlmpClientDescription, LLMP_FLAG_FROM_MM},
|
||||||
shmem::{NopShMemProvider, ShMemProvider},
|
shmem::{NopShMem, NopShMemProvider, ShMem, ShMemProvider},
|
||||||
tuples::Handle,
|
tuples::Handle,
|
||||||
ClientId,
|
ClientId,
|
||||||
};
|
};
|
||||||
@ -59,9 +59,10 @@ const INITIAL_EVENT_BUFFER_SIZE: usize = 1024 * 4;
|
|||||||
|
|
||||||
/// An `EventManager` that forwards all events to other attached fuzzers on shared maps or via tcp,
|
/// An `EventManager` that forwards all events to other attached fuzzers on shared maps or via tcp,
|
||||||
/// using low-level message passing, `llmp`.
|
/// using low-level message passing, `llmp`.
|
||||||
pub struct LlmpEventManager<EMH, I, S, SP>
|
pub struct LlmpEventManager<EMH, I, S, SHM, SP>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
/// We only send 1 testcase for every `throttle` second
|
/// We only send 1 testcase for every `throttle` second
|
||||||
pub(crate) throttle: Option<Duration>,
|
pub(crate) throttle: Option<Duration>,
|
||||||
@ -69,7 +70,7 @@ where
|
|||||||
last_sent: Duration,
|
last_sent: Duration,
|
||||||
hooks: EMH,
|
hooks: EMH,
|
||||||
/// The LLMP client for inter process communication
|
/// The LLMP client for inter process communication
|
||||||
llmp: LlmpClient<SP>,
|
llmp: LlmpClient<SHM, SP>,
|
||||||
#[cfg(feature = "llmp_compression")]
|
#[cfg(feature = "llmp_compression")]
|
||||||
compressor: GzipCompressor,
|
compressor: GzipCompressor,
|
||||||
/// The configuration defines this specific fuzzer.
|
/// The configuration defines this specific fuzzer.
|
||||||
@ -85,7 +86,7 @@ where
|
|||||||
event_buffer: Vec<u8>,
|
event_buffer: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LlmpEventManager<(), NopState<NopInput>, NopInput, NopShMemProvider> {
|
impl LlmpEventManager<(), NopState<NopInput>, NopInput, NopShMem, NopShMemProvider> {
|
||||||
/// Creates a builder for [`LlmpEventManager`]
|
/// Creates a builder for [`LlmpEventManager`]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn builder() -> LlmpEventManagerBuilder<()> {
|
pub fn builder() -> LlmpEventManagerBuilder<()> {
|
||||||
@ -134,14 +135,15 @@ impl<EMH> LlmpEventManagerBuilder<EMH> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create a manager from a raw LLMP client
|
/// Create a manager from a raw LLMP client
|
||||||
pub fn build_from_client<I, S, SP>(
|
pub fn build_from_client<I, S, SHM, SP>(
|
||||||
self,
|
self,
|
||||||
llmp: LlmpClient<SP>,
|
llmp: LlmpClient<SHM, SP>,
|
||||||
configuration: EventConfig,
|
configuration: EventConfig,
|
||||||
time_ref: Option<Handle<TimeObserver>>,
|
time_ref: Option<Handle<TimeObserver>>,
|
||||||
) -> Result<LlmpEventManager<EMH, I, S, SP>, Error>
|
) -> Result<LlmpEventManager<EMH, I, S, SHM, SP>, Error>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
Ok(LlmpEventManager {
|
Ok(LlmpEventManager {
|
||||||
throttle: self.throttle,
|
throttle: self.throttle,
|
||||||
@ -164,15 +166,16 @@ impl<EMH> LlmpEventManagerBuilder<EMH> {
|
|||||||
/// Create an LLMP event manager on a port.
|
/// Create an LLMP event manager on a port.
|
||||||
/// It expects a broker to exist on this port.
|
/// It expects a broker to exist on this port.
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub fn build_on_port<I, S, SP>(
|
pub fn build_on_port<I, S, SHM, SP>(
|
||||||
self,
|
self,
|
||||||
shmem_provider: SP,
|
shmem_provider: SP,
|
||||||
port: u16,
|
port: u16,
|
||||||
configuration: EventConfig,
|
configuration: EventConfig,
|
||||||
time_ref: Option<Handle<TimeObserver>>,
|
time_ref: Option<Handle<TimeObserver>>,
|
||||||
) -> Result<LlmpEventManager<EMH, I, S, SP>, Error>
|
) -> Result<LlmpEventManager<EMH, I, S, SHM, SP>, Error>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
let llmp = LlmpClient::create_attach_to_tcp(shmem_provider, port)?;
|
let llmp = LlmpClient::create_attach_to_tcp(shmem_provider, port)?;
|
||||||
Self::build_from_client(self, llmp, configuration, time_ref)
|
Self::build_from_client(self, llmp, configuration, time_ref)
|
||||||
@ -181,30 +184,32 @@ impl<EMH> LlmpEventManagerBuilder<EMH> {
|
|||||||
/// If a client respawns, it may reuse the existing connection, previously
|
/// If a client respawns, it may reuse the existing connection, previously
|
||||||
/// stored by [`LlmpClient::to_env()`].
|
/// stored by [`LlmpClient::to_env()`].
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub fn build_existing_client_from_env<I, S, SP>(
|
pub fn build_existing_client_from_env<I, S, SHM, SP>(
|
||||||
self,
|
self,
|
||||||
shmem_provider: SP,
|
shmem_provider: SP,
|
||||||
env_name: &str,
|
env_name: &str,
|
||||||
configuration: EventConfig,
|
configuration: EventConfig,
|
||||||
time_ref: Option<Handle<TimeObserver>>,
|
time_ref: Option<Handle<TimeObserver>>,
|
||||||
) -> Result<LlmpEventManager<EMH, I, S, SP>, Error>
|
) -> Result<LlmpEventManager<EMH, I, S, SHM, SP>, Error>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
let llmp = LlmpClient::on_existing_from_env(shmem_provider, env_name)?;
|
let llmp = LlmpClient::on_existing_from_env(shmem_provider, env_name)?;
|
||||||
Self::build_from_client(self, llmp, configuration, time_ref)
|
Self::build_from_client(self, llmp, configuration, time_ref)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create an existing client from description
|
/// Create an existing client from description
|
||||||
pub fn build_existing_client_from_description<I, S, SP>(
|
pub fn build_existing_client_from_description<I, S, SHM, SP>(
|
||||||
self,
|
self,
|
||||||
shmem_provider: SP,
|
shmem_provider: SP,
|
||||||
description: &LlmpClientDescription,
|
description: &LlmpClientDescription,
|
||||||
configuration: EventConfig,
|
configuration: EventConfig,
|
||||||
time_ref: Option<Handle<TimeObserver>>,
|
time_ref: Option<Handle<TimeObserver>>,
|
||||||
) -> Result<LlmpEventManager<EMH, I, S, SP>, Error>
|
) -> Result<LlmpEventManager<EMH, I, S, SHM, SP>, Error>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
let llmp = LlmpClient::existing_client_from_description(shmem_provider, description)?;
|
let llmp = LlmpClient::existing_client_from_description(shmem_provider, description)?;
|
||||||
Self::build_from_client(self, llmp, configuration, time_ref)
|
Self::build_from_client(self, llmp, configuration, time_ref)
|
||||||
@ -212,19 +217,21 @@ impl<EMH> LlmpEventManagerBuilder<EMH> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
impl<EMH, I, OT, S, SP> CanSerializeObserver<OT> for LlmpEventManager<EMH, I, S, SP>
|
impl<EMH, I, OT, S, SHM, SP> CanSerializeObserver<OT> for LlmpEventManager<EMH, I, S, SHM, SP>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
|
||||||
OT: Serialize + MatchNameRef,
|
OT: Serialize + MatchNameRef,
|
||||||
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
fn serialize_observers(&mut self, observers: &OT) -> Result<Option<Vec<u8>>, Error> {
|
fn serialize_observers(&mut self, observers: &OT) -> Result<Option<Vec<u8>>, Error> {
|
||||||
serialize_observers_adaptive::<Self, OT>(self, observers, 2, 80)
|
serialize_observers_adaptive::<Self, OT>(self, observers, 2, 80)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EMH, I, S, SP> AdaptiveSerializer for LlmpEventManager<EMH, I, S, SP>
|
impl<EMH, I, S, SHM, SP> AdaptiveSerializer for LlmpEventManager<EMH, I, S, SHM, SP>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
fn serialization_time(&self) -> Duration {
|
fn serialization_time(&self) -> Duration {
|
||||||
self.serialization_time
|
self.serialization_time
|
||||||
@ -257,9 +264,10 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EMH, I, S, SP> core::fmt::Debug for LlmpEventManager<EMH, I, S, SP>
|
impl<EMH, I, S, SHM, SP> Debug for LlmpEventManager<EMH, I, S, SHM, SP>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
let mut debug_struct = f.debug_struct("LlmpEventManager");
|
let mut debug_struct = f.debug_struct("LlmpEventManager");
|
||||||
@ -274,9 +282,10 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EMH, I, S, SP> Drop for LlmpEventManager<EMH, I, S, SP>
|
impl<EMH, I, S, SHM, SP> Drop for LlmpEventManager<EMH, I, S, SHM, SP>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
/// LLMP clients will have to wait until their pages are mapped by somebody.
|
/// LLMP clients will have to wait until their pages are mapped by somebody.
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
@ -284,9 +293,10 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EMH, I, S, SP> LlmpEventManager<EMH, I, S, SP>
|
impl<EMH, I, S, SHM, SP> LlmpEventManager<EMH, I, S, SHM, SP>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
/// Calling this function will tell the llmp broker that this client is exiting
|
/// Calling this function will tell the llmp broker that this client is exiting
|
||||||
/// This should be called from the restarter not from the actual fuzzer client
|
/// This should be called from the restarter not from the actual fuzzer client
|
||||||
@ -334,9 +344,10 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EMH, I, S, SP> LlmpEventManager<EMH, I, S, SP>
|
impl<EMH, I, S, SHM, SP> LlmpEventManager<EMH, I, S, SHM, SP>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
// Handle arriving events in the client
|
// Handle arriving events in the client
|
||||||
fn handle_in_client<E, Z>(
|
fn handle_in_client<E, Z>(
|
||||||
@ -423,7 +434,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EMH, I, S, SP: ShMemProvider> LlmpEventManager<EMH, I, S, SP> {
|
impl<EMH, I, S, SHM, SP> LlmpEventManager<EMH, I, S, SHM, SP>
|
||||||
|
where
|
||||||
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
|
{
|
||||||
/// Send information that this client is exiting.
|
/// Send information that this client is exiting.
|
||||||
/// The other side may free up all allocated memory.
|
/// The other side may free up all allocated memory.
|
||||||
/// We are no longer allowed to send anything afterwards.
|
/// We are no longer allowed to send anything afterwards.
|
||||||
@ -432,18 +447,12 @@ impl<EMH, I, S, SP: ShMemProvider> LlmpEventManager<EMH, I, S, SP> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EMH, I, S, SP> EventFirer<I, S> for LlmpEventManager<EMH, I, S, SP>
|
impl<EMH, I, S, SHM, SP> EventFirer<I, S> for LlmpEventManager<EMH, I, S, SHM, SP>
|
||||||
where
|
where
|
||||||
I: Serialize,
|
I: Serialize,
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
fn should_send(&self) -> bool {
|
|
||||||
if let Some(throttle) = self.throttle {
|
|
||||||
current_time() - self.last_sent > throttle
|
|
||||||
} else {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn fire(&mut self, _state: &mut S, event: Event<I>) -> Result<(), Error> {
|
fn fire(&mut self, _state: &mut S, event: Event<I>) -> Result<(), Error> {
|
||||||
#[cfg(feature = "llmp_compression")]
|
#[cfg(feature = "llmp_compression")]
|
||||||
let flags = LLMP_FLAG_INITIALIZED;
|
let flags = LLMP_FLAG_INITIALIZED;
|
||||||
@ -490,46 +499,57 @@ where
|
|||||||
self.last_sent = current_time();
|
self.last_sent = current_time();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn configuration(&self) -> EventConfig {
|
fn configuration(&self) -> EventConfig {
|
||||||
self.configuration
|
self.configuration
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn should_send(&self) -> bool {
|
||||||
|
if let Some(throttle) = self.throttle {
|
||||||
|
current_time() - self.last_sent > throttle
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EMH, I, S, SP> EventRestarter<S> for LlmpEventManager<EMH, I, S, SP>
|
impl<EMH, I, S, SHM, SP> EventRestarter<S> for LlmpEventManager<EMH, I, S, SHM, SP>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
|
||||||
S: HasCurrentStageId,
|
S: HasCurrentStageId,
|
||||||
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
fn on_restart(&mut self, state: &mut S) -> Result<(), Error> {
|
fn on_restart(&mut self, state: &mut S) -> Result<(), Error> {
|
||||||
std_on_restart(self, state)
|
std_on_restart(self, state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EMH, I, S, SP> ManagerExit for LlmpEventManager<EMH, I, S, SP>
|
impl<EMH, I, S, SHM, SP> ManagerExit for LlmpEventManager<EMH, I, S, SHM, SP>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
|
fn send_exiting(&mut self) -> Result<(), Error> {
|
||||||
|
self.llmp.sender_mut().send_exiting()
|
||||||
|
}
|
||||||
|
|
||||||
/// The LLMP client needs to wait until a broker has mapped all pages before shutting down.
|
/// The LLMP client needs to wait until a broker has mapped all pages before shutting down.
|
||||||
/// Otherwise, the OS may already have removed the shared maps.
|
/// Otherwise, the OS may already have removed the shared maps.
|
||||||
fn await_restart_safe(&mut self) {
|
fn await_restart_safe(&mut self) {
|
||||||
// wait until we can drop the message safely.
|
// wait until we can drop the message safely.
|
||||||
self.llmp.await_safe_to_unmap_blocking();
|
self.llmp.await_safe_to_unmap_blocking();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send_exiting(&mut self) -> Result<(), Error> {
|
|
||||||
self.llmp.sender_mut().send_exiting()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E, EMH, I, S, SP, Z> EventProcessor<E, S, Z> for LlmpEventManager<EMH, I, S, SP>
|
impl<E, EMH, I, S, SHM, SP, Z> EventProcessor<E, S, Z> for LlmpEventManager<EMH, I, S, SHM, SP>
|
||||||
where
|
where
|
||||||
E: HasObservers,
|
E: HasObservers,
|
||||||
E::Observers: DeserializeOwned,
|
E::Observers: DeserializeOwned,
|
||||||
S: HasImported + HasSolutions<I> + HasCurrentTestcase<I> + Stoppable,
|
|
||||||
EMH: EventManagerHooksTuple<I, S>,
|
EMH: EventManagerHooksTuple<I, S>,
|
||||||
I: DeserializeOwned + Input,
|
I: DeserializeOwned + Input,
|
||||||
SP: ShMemProvider,
|
S: HasImported + HasSolutions<I> + HasCurrentTestcase<I> + Stoppable,
|
||||||
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
Z: ExecutionProcessor<Self, I, E::Observers, S> + EvaluatorObservers<E, Self, I, S>,
|
Z: ExecutionProcessor<Self, I, E::Observers, S> + EvaluatorObservers<E, Self, I, S>,
|
||||||
{
|
{
|
||||||
fn process(&mut self, fuzzer: &mut Z, state: &mut S, executor: &mut E) -> Result<usize, Error> {
|
fn process(&mut self, fuzzer: &mut Z, state: &mut S, executor: &mut E) -> Result<usize, Error> {
|
||||||
@ -537,14 +557,15 @@ where
|
|||||||
let self_id = self.llmp.sender().id();
|
let self_id = self.llmp.sender().id();
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
while let Some((client_id, tag, flags, msg)) = self.llmp.recv_buf_with_flags()? {
|
while let Some((client_id, tag, flags, msg)) = self.llmp.recv_buf_with_flags()? {
|
||||||
assert!(
|
assert_ne!(
|
||||||
tag != _LLMP_TAG_EVENT_TO_BROKER,
|
tag, _LLMP_TAG_EVENT_TO_BROKER,
|
||||||
"EVENT_TO_BROKER parcel should not have arrived in the client!"
|
"EVENT_TO_BROKER parcel should not have arrived in the client!"
|
||||||
);
|
);
|
||||||
|
|
||||||
if client_id == self_id {
|
if client_id == self_id {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "llmp_compression"))]
|
#[cfg(not(feature = "llmp_compression"))]
|
||||||
let event_bytes = msg;
|
let event_bytes = msg;
|
||||||
#[cfg(feature = "llmp_compression")]
|
#[cfg(feature = "llmp_compression")]
|
||||||
@ -556,6 +577,7 @@ where
|
|||||||
} else {
|
} else {
|
||||||
msg
|
msg
|
||||||
};
|
};
|
||||||
|
|
||||||
let event: Event<I> = postcard::from_bytes(event_bytes)?;
|
let event: Event<I> = postcard::from_bytes(event_bytes)?;
|
||||||
log::debug!("Received event in normal llmp {}", event.name_detailed());
|
log::debug!("Received event in normal llmp {}", event.name_detailed());
|
||||||
|
|
||||||
@ -576,11 +598,12 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EMH, I, S, SP> ProgressReporter<S> for LlmpEventManager<EMH, I, S, SP>
|
impl<EMH, I, S, SHM, SP> ProgressReporter<S> for LlmpEventManager<EMH, I, S, SHM, SP>
|
||||||
where
|
where
|
||||||
S: HasExecutions + HasLastReportTime + HasMetadata + MaybeHasClientPerfMonitor,
|
|
||||||
SP: ShMemProvider,
|
|
||||||
I: Serialize,
|
I: Serialize,
|
||||||
|
S: HasExecutions + HasLastReportTime + HasMetadata + MaybeHasClientPerfMonitor,
|
||||||
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
fn maybe_report_progress(
|
fn maybe_report_progress(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -595,9 +618,10 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EMH, I, S, SP> HasEventManagerId for LlmpEventManager<EMH, I, S, SP>
|
impl<EMH, I, S, SHM, SP> HasEventManagerId for LlmpEventManager<EMH, I, S, SHM, SP>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
/// Gets the id assigned to this staterestorer.
|
/// Gets the id assigned to this staterestorer.
|
||||||
fn mgr_id(&self) -> EventManagerId {
|
fn mgr_id(&self) -> EventManagerId {
|
||||||
|
@ -9,7 +9,7 @@ use libafl_bolts::{
|
|||||||
};
|
};
|
||||||
use libafl_bolts::{
|
use libafl_bolts::{
|
||||||
llmp::{LlmpClient, LlmpClientDescription, Tag},
|
llmp::{LlmpClient, LlmpClientDescription, Tag},
|
||||||
shmem::{NopShMemProvider, ShMemProvider},
|
shmem::{NopShMem, NopShMemProvider, ShMem, ShMemProvider},
|
||||||
ClientId,
|
ClientId,
|
||||||
};
|
};
|
||||||
use serde::{de::DeserializeOwned, Serialize};
|
use serde::{de::DeserializeOwned, Serialize};
|
||||||
@ -84,12 +84,9 @@ impl LlmpShouldSaveState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A manager-like llmp client that converts between input types
|
/// A manager-like llmp client that converts between input types
|
||||||
pub struct LlmpEventConverter<I, IC, ICB, S, SP>
|
pub struct LlmpEventConverter<I, IC, ICB, S, SHM, SP> {
|
||||||
where
|
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
|
||||||
throttle: Option<Duration>,
|
throttle: Option<Duration>,
|
||||||
llmp: LlmpClient<SP>,
|
llmp: LlmpClient<SHM, SP>,
|
||||||
last_sent: Duration,
|
last_sent: Duration,
|
||||||
#[cfg(feature = "llmp_compression")]
|
#[cfg(feature = "llmp_compression")]
|
||||||
compressor: GzipCompressor,
|
compressor: GzipCompressor,
|
||||||
@ -104,6 +101,7 @@ impl
|
|||||||
NopInputConverter<NopInput>,
|
NopInputConverter<NopInput>,
|
||||||
NopInputConverter<NopInput>,
|
NopInputConverter<NopInput>,
|
||||||
NopState<NopInput>,
|
NopState<NopInput>,
|
||||||
|
NopShMem,
|
||||||
NopShMemProvider,
|
NopShMemProvider,
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
@ -136,15 +134,12 @@ impl LlmpEventConverterBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create a event converter from a raw llmp client
|
/// Create a event converter from a raw llmp client
|
||||||
pub fn build_from_client<I, IC, ICB, S, SP>(
|
pub fn build_from_client<I, IC, ICB, S, SHM, SP>(
|
||||||
self,
|
self,
|
||||||
llmp: LlmpClient<SP>,
|
llmp: LlmpClient<SHM, SP>,
|
||||||
converter: Option<IC>,
|
converter: Option<IC>,
|
||||||
converter_back: Option<ICB>,
|
converter_back: Option<ICB>,
|
||||||
) -> Result<LlmpEventConverter<I, IC, ICB, S, SP>, Error>
|
) -> Result<LlmpEventConverter<I, IC, ICB, S, SHM, SP>, Error> {
|
||||||
where
|
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
|
||||||
Ok(LlmpEventConverter {
|
Ok(LlmpEventConverter {
|
||||||
throttle: self.throttle,
|
throttle: self.throttle,
|
||||||
last_sent: Duration::from_secs(0),
|
last_sent: Duration::from_secs(0),
|
||||||
@ -159,15 +154,16 @@ impl LlmpEventConverterBuilder {
|
|||||||
|
|
||||||
/// Create a client from port and the input converters
|
/// Create a client from port and the input converters
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub fn build_on_port<I, IC, ICB, S, SP>(
|
pub fn build_on_port<I, IC, ICB, S, SHM, SP>(
|
||||||
self,
|
self,
|
||||||
shmem_provider: SP,
|
shmem_provider: SP,
|
||||||
port: u16,
|
port: u16,
|
||||||
converter: Option<IC>,
|
converter: Option<IC>,
|
||||||
converter_back: Option<ICB>,
|
converter_back: Option<ICB>,
|
||||||
) -> Result<LlmpEventConverter<I, IC, ICB, S, SP>, Error>
|
) -> Result<LlmpEventConverter<I, IC, ICB, S, SHM, SP>, Error>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
let llmp = LlmpClient::create_attach_to_tcp(shmem_provider, port)?;
|
let llmp = LlmpClient::create_attach_to_tcp(shmem_provider, port)?;
|
||||||
Ok(LlmpEventConverter {
|
Ok(LlmpEventConverter {
|
||||||
@ -184,15 +180,16 @@ impl LlmpEventConverterBuilder {
|
|||||||
|
|
||||||
/// If a client respawns, it may reuse the existing connection, previously stored by [`LlmpClient::to_env()`].
|
/// If a client respawns, it may reuse the existing connection, previously stored by [`LlmpClient::to_env()`].
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub fn build_existing_client_from_env<I, IC, ICB, S, SP>(
|
pub fn build_existing_client_from_env<I, IC, ICB, S, SHM, SP>(
|
||||||
self,
|
self,
|
||||||
shmem_provider: SP,
|
shmem_provider: SP,
|
||||||
env_name: &str,
|
env_name: &str,
|
||||||
converter: Option<IC>,
|
converter: Option<IC>,
|
||||||
converter_back: Option<ICB>,
|
converter_back: Option<ICB>,
|
||||||
) -> Result<LlmpEventConverter<I, IC, ICB, S, SP>, Error>
|
) -> Result<LlmpEventConverter<I, IC, ICB, S, SHM, SP>, Error>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
let llmp = LlmpClient::on_existing_from_env(shmem_provider, env_name)?;
|
let llmp = LlmpClient::on_existing_from_env(shmem_provider, env_name)?;
|
||||||
Ok(LlmpEventConverter {
|
Ok(LlmpEventConverter {
|
||||||
@ -208,11 +205,12 @@ impl LlmpEventConverterBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I, IC, ICB, S, SP> Debug for LlmpEventConverter<I, IC, ICB, S, SP>
|
impl<I, IC, ICB, S, SHM, SP> Debug for LlmpEventConverter<I, IC, ICB, S, SHM, SP>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
|
||||||
IC: Debug,
|
IC: Debug,
|
||||||
ICB: Debug,
|
ICB: Debug,
|
||||||
|
SHM: Debug,
|
||||||
|
SP: Debug,
|
||||||
{
|
{
|
||||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
let mut debug_struct = f.debug_struct("LlmpEventConverter");
|
let mut debug_struct = f.debug_struct("LlmpEventConverter");
|
||||||
@ -228,9 +226,10 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I, IC, ICB, S, SP> LlmpEventConverter<I, IC, ICB, S, SP>
|
impl<I, IC, ICB, S, SHM, SP> LlmpEventConverter<I, IC, ICB, S, SHM, SP>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
// TODO other new_* routines
|
// TODO other new_* routines
|
||||||
|
|
||||||
@ -341,8 +340,8 @@ where
|
|||||||
let self_id = self.llmp.sender().id();
|
let self_id = self.llmp.sender().id();
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
while let Some((client_id, tag, _flags, msg)) = self.llmp.recv_buf_with_flags()? {
|
while let Some((client_id, tag, _flags, msg)) = self.llmp.recv_buf_with_flags()? {
|
||||||
assert!(
|
assert_ne!(
|
||||||
tag != _LLMP_TAG_EVENT_TO_BROKER,
|
tag, _LLMP_TAG_EVENT_TO_BROKER,
|
||||||
"EVENT_TO_BROKER parcel should not have arrived in the client!"
|
"EVENT_TO_BROKER parcel should not have arrived in the client!"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -370,11 +369,12 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I, IC, ICB, S, SP> EventFirer<I, S> for LlmpEventConverter<I, IC, ICB, S, SP>
|
impl<I, IC, ICB, S, SHM, SP> EventFirer<I, S> for LlmpEventConverter<I, IC, ICB, S, SHM, SP>
|
||||||
where
|
where
|
||||||
IC: InputConverter<From = I>,
|
IC: InputConverter<From = I>,
|
||||||
SP: ShMemProvider,
|
|
||||||
IC::To: Serialize,
|
IC::To: Serialize,
|
||||||
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
fn should_send(&self) -> bool {
|
fn should_send(&self) -> bool {
|
||||||
if let Some(throttle) = self.throttle {
|
if let Some(throttle) = self.throttle {
|
||||||
|
@ -22,7 +22,7 @@ use libafl_bolts::{
|
|||||||
core_affinity::CoreId,
|
core_affinity::CoreId,
|
||||||
llmp::{Broker, LlmpBroker, LlmpConnection},
|
llmp::{Broker, LlmpBroker, LlmpConnection},
|
||||||
os::CTRL_C_EXIT,
|
os::CTRL_C_EXIT,
|
||||||
shmem::{ShMemProvider, StdShMemProvider},
|
shmem::{ShMem, ShMemProvider, StdShMem, StdShMemProvider},
|
||||||
staterestore::StateRestorer,
|
staterestore::StateRestorer,
|
||||||
tuples::{tuple_list, Handle, MatchNameRef},
|
tuples::{tuple_list, Handle, MatchNameRef},
|
||||||
};
|
};
|
||||||
@ -55,21 +55,23 @@ use crate::{
|
|||||||
|
|
||||||
/// A manager that can restart on the fly, storing states in-between (in `on_restart`)
|
/// A manager that can restart on the fly, storing states in-between (in `on_restart`)
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct LlmpRestartingEventManager<EMH, I, S, SP>
|
pub struct LlmpRestartingEventManager<EMH, I, S, SHM, SP>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
/// The embedded LLMP event manager
|
/// The embedded LLMP event manager
|
||||||
llmp_mgr: LlmpEventManager<EMH, I, S, SP>,
|
llmp_mgr: LlmpEventManager<EMH, I, S, SHM, SP>,
|
||||||
/// The staterestorer to serialize the state for the next runner
|
/// The staterestorer to serialize the state for the next runner
|
||||||
staterestorer: StateRestorer<SP>,
|
staterestorer: StateRestorer<SHM, SP>,
|
||||||
/// Decide if the state restorer must save the serialized state
|
/// Decide if the state restorer must save the serialized state
|
||||||
save_state: LlmpShouldSaveState,
|
save_state: LlmpShouldSaveState,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EMH, I, S, SP> AdaptiveSerializer for LlmpRestartingEventManager<EMH, I, S, SP>
|
impl<EMH, I, S, SHM, SP> AdaptiveSerializer for LlmpRestartingEventManager<EMH, I, S, SHM, SP>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
fn serialization_time(&self) -> Duration {
|
fn serialization_time(&self) -> Duration {
|
||||||
self.llmp_mgr.serialization_time()
|
self.llmp_mgr.serialization_time()
|
||||||
@ -102,11 +104,12 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EMH, I, S, SP> ProgressReporter<S> for LlmpRestartingEventManager<EMH, I, S, SP>
|
impl<EMH, I, S, SHM, SP> ProgressReporter<S> for LlmpRestartingEventManager<EMH, I, S, SHM, SP>
|
||||||
where
|
where
|
||||||
S: HasExecutions + HasLastReportTime + HasMetadata + Serialize + MaybeHasClientPerfMonitor,
|
|
||||||
SP: ShMemProvider,
|
|
||||||
I: Serialize,
|
I: Serialize,
|
||||||
|
S: HasExecutions + HasLastReportTime + HasMetadata + Serialize + MaybeHasClientPerfMonitor,
|
||||||
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
fn maybe_report_progress(
|
fn maybe_report_progress(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -121,16 +124,13 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EMH, I, S, SP> EventFirer<I, S> for LlmpRestartingEventManager<EMH, I, S, SP>
|
impl<EMH, I, S, SHM, SP> EventFirer<I, S> for LlmpRestartingEventManager<EMH, I, S, SHM, SP>
|
||||||
where
|
where
|
||||||
I: Serialize,
|
I: Serialize,
|
||||||
S: Serialize,
|
S: Serialize,
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
fn should_send(&self) -> bool {
|
|
||||||
<LlmpEventManager<EMH, I, S, SP> as EventFirer<I, S>>::should_send(&self.llmp_mgr)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fire(&mut self, state: &mut S, event: Event<I>) -> Result<(), Error> {
|
fn fire(&mut self, state: &mut S, event: Event<I>) -> Result<(), Error> {
|
||||||
// Check if we are going to crash in the event, in which case we store our current state for the next runner
|
// Check if we are going to crash in the event, in which case we store our current state for the next runner
|
||||||
self.llmp_mgr.fire(state, event)?;
|
self.llmp_mgr.fire(state, event)?;
|
||||||
@ -139,25 +139,32 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn configuration(&self) -> EventConfig {
|
fn configuration(&self) -> EventConfig {
|
||||||
<LlmpEventManager<EMH, I, S, SP> as EventFirer<I, S>>::configuration(&self.llmp_mgr)
|
<LlmpEventManager<EMH, I, S, SHM, SP> as EventFirer<I, S>>::configuration(&self.llmp_mgr)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn should_send(&self) -> bool {
|
||||||
|
<LlmpEventManager<EMH, I, S, SHM, SP> as EventFirer<I, S>>::should_send(&self.llmp_mgr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
impl<EMH, I, OT, S, SP> CanSerializeObserver<OT> for LlmpRestartingEventManager<EMH, I, S, SP>
|
impl<EMH, I, OT, S, SHM, SP> CanSerializeObserver<OT>
|
||||||
|
for LlmpRestartingEventManager<EMH, I, S, SHM, SP>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
|
||||||
OT: Serialize + MatchNameRef,
|
OT: Serialize + MatchNameRef,
|
||||||
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
fn serialize_observers(&mut self, observers: &OT) -> Result<Option<Vec<u8>>, Error> {
|
fn serialize_observers(&mut self, observers: &OT) -> Result<Option<Vec<u8>>, Error> {
|
||||||
serialize_observers_adaptive::<Self, OT>(self, observers, 2, 80)
|
serialize_observers_adaptive::<Self, OT>(self, observers, 2, 80)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EMH, I, S, SP> EventRestarter<S> for LlmpRestartingEventManager<EMH, I, S, SP>
|
impl<EMH, I, S, SHM, SP> EventRestarter<S> for LlmpRestartingEventManager<EMH, I, S, SHM, SP>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
|
||||||
S: Serialize + HasCurrentStageId,
|
S: Serialize + HasCurrentStageId,
|
||||||
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
/// Reset the single page (we reuse it over and over from pos 0), then send the current state to the next runner.
|
/// Reset the single page (we reuse it over and over from pos 0), then send the current state to the next runner.
|
||||||
fn on_restart(&mut self, state: &mut S) -> Result<(), Error> {
|
fn on_restart(&mut self, state: &mut S) -> Result<(), Error> {
|
||||||
@ -180,9 +187,10 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EMH, I, S, SP> ManagerExit for LlmpRestartingEventManager<EMH, I, S, SP>
|
impl<EMH, I, S, SHM, SP> ManagerExit for LlmpRestartingEventManager<EMH, I, S, SHM, SP>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
fn send_exiting(&mut self) -> Result<(), Error> {
|
fn send_exiting(&mut self) -> Result<(), Error> {
|
||||||
self.staterestorer.send_exiting();
|
self.staterestorer.send_exiting();
|
||||||
@ -199,16 +207,18 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E, EMH, I, S, SP, Z> EventProcessor<E, S, Z> for LlmpRestartingEventManager<EMH, I, S, SP>
|
impl<E, EMH, I, S, SHM, SP, Z> EventProcessor<E, S, Z>
|
||||||
|
for LlmpRestartingEventManager<EMH, I, S, SHM, SP>
|
||||||
where
|
where
|
||||||
EMH: EventManagerHooksTuple<I, S>,
|
|
||||||
E: HasObservers,
|
E: HasObservers,
|
||||||
E::Observers: DeserializeOwned,
|
E::Observers: DeserializeOwned,
|
||||||
S: HasImported + HasCurrentTestcase<I> + HasSolutions<I> + Stoppable + Serialize,
|
EMH: EventManagerHooksTuple<I, S>,
|
||||||
I: DeserializeOwned + Input,
|
I: DeserializeOwned + Input,
|
||||||
SP: ShMemProvider,
|
S: HasImported + HasCurrentTestcase<I> + HasSolutions<I> + Stoppable + Serialize,
|
||||||
Z: ExecutionProcessor<LlmpEventManager<EMH, I, S, SP>, I, E::Observers, S>
|
SHM: ShMem,
|
||||||
+ EvaluatorObservers<E, LlmpEventManager<EMH, I, S, SP>, I, S>,
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
|
Z: ExecutionProcessor<LlmpEventManager<EMH, I, S, SHM, SP>, I, E::Observers, S>
|
||||||
|
+ EvaluatorObservers<E, LlmpEventManager<EMH, I, S, SHM, SP>, I, S>,
|
||||||
{
|
{
|
||||||
fn process(&mut self, fuzzer: &mut Z, state: &mut S, executor: &mut E) -> Result<usize, Error> {
|
fn process(&mut self, fuzzer: &mut Z, state: &mut S, executor: &mut E) -> Result<usize, Error> {
|
||||||
let res = self.llmp_mgr.process(fuzzer, state, executor)?;
|
let res = self.llmp_mgr.process(fuzzer, state, executor)?;
|
||||||
@ -221,9 +231,10 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EMH, I, S, SP> HasEventManagerId for LlmpRestartingEventManager<EMH, I, S, SP>
|
impl<EMH, I, S, SHM, SP> HasEventManagerId for LlmpRestartingEventManager<EMH, I, S, SHM, SP>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
fn mgr_id(&self) -> EventManagerId {
|
fn mgr_id(&self) -> EventManagerId {
|
||||||
self.llmp_mgr.mgr_id()
|
self.llmp_mgr.mgr_id()
|
||||||
@ -236,15 +247,16 @@ const _ENV_FUZZER_RECEIVER: &str = "_AFL_ENV_FUZZER_RECEIVER";
|
|||||||
/// The llmp (2 way) connection from a fuzzer to the broker (broadcasting all other fuzzer messages)
|
/// The llmp (2 way) connection from a fuzzer to the broker (broadcasting all other fuzzer messages)
|
||||||
const _ENV_FUZZER_BROKER_CLIENT_INITIAL: &str = "_AFL_ENV_FUZZER_BROKER_CLIENT";
|
const _ENV_FUZZER_BROKER_CLIENT_INITIAL: &str = "_AFL_ENV_FUZZER_BROKER_CLIENT";
|
||||||
|
|
||||||
impl<EMH, I, S, SP> LlmpRestartingEventManager<EMH, I, S, SP>
|
impl<EMH, I, S, SHM, SP> LlmpRestartingEventManager<EMH, I, S, SHM, SP>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
|
||||||
S: Serialize,
|
S: Serialize,
|
||||||
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
/// Create a new runner, the executed child doing the actual fuzzing.
|
/// Create a new runner, the executed child doing the actual fuzzing.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
llmp_mgr: LlmpEventManager<EMH, I, S, SP>,
|
llmp_mgr: LlmpEventManager<EMH, I, S, SHM, SP>,
|
||||||
staterestorer: StateRestorer<SP>,
|
staterestorer: StateRestorer<SHM, SP>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
llmp_mgr,
|
llmp_mgr,
|
||||||
@ -255,8 +267,8 @@ where
|
|||||||
|
|
||||||
/// Create a new runner specifying if it must save the serialized state on restart.
|
/// Create a new runner specifying if it must save the serialized state on restart.
|
||||||
pub fn with_save_state(
|
pub fn with_save_state(
|
||||||
llmp_mgr: LlmpEventManager<EMH, I, S, SP>,
|
llmp_mgr: LlmpEventManager<EMH, I, S, SHM, SP>,
|
||||||
staterestorer: StateRestorer<SP>,
|
staterestorer: StateRestorer<SHM, SP>,
|
||||||
save_state: LlmpShouldSaveState,
|
save_state: LlmpShouldSaveState,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -267,12 +279,12 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the staterestorer
|
/// Get the staterestorer
|
||||||
pub fn staterestorer(&self) -> &StateRestorer<SP> {
|
pub fn staterestorer(&self) -> &StateRestorer<SHM, SP> {
|
||||||
&self.staterestorer
|
&self.staterestorer
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the staterestorer (mutable)
|
/// Get the staterestorer (mutable)
|
||||||
pub fn staterestorer_mut(&mut self) -> &mut StateRestorer<SP> {
|
pub fn staterestorer_mut(&mut self) -> &mut StateRestorer<SHM, SP> {
|
||||||
&mut self.staterestorer
|
&mut self.staterestorer
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -314,7 +326,7 @@ pub fn setup_restarting_mgr_std<I, MT, S>(
|
|||||||
) -> Result<
|
) -> Result<
|
||||||
(
|
(
|
||||||
Option<S>,
|
Option<S>,
|
||||||
LlmpRestartingEventManager<(), I, S, StdShMemProvider>,
|
LlmpRestartingEventManager<(), I, S, StdShMem, StdShMemProvider>,
|
||||||
),
|
),
|
||||||
Error,
|
Error,
|
||||||
>
|
>
|
||||||
@ -347,7 +359,7 @@ pub fn setup_restarting_mgr_std_adaptive<I, MT, S>(
|
|||||||
) -> Result<
|
) -> Result<
|
||||||
(
|
(
|
||||||
Option<S>,
|
Option<S>,
|
||||||
LlmpRestartingEventManager<(), I, S, StdShMemProvider>,
|
LlmpRestartingEventManager<(), I, S, StdShMem, StdShMemProvider>,
|
||||||
),
|
),
|
||||||
Error,
|
Error,
|
||||||
>
|
>
|
||||||
@ -414,20 +426,26 @@ pub struct RestartingMgr<EMH, I, MT, S, SP> {
|
|||||||
impl<EMH, I, MT, S, SP> RestartingMgr<EMH, I, MT, S, SP>
|
impl<EMH, I, MT, S, SP> RestartingMgr<EMH, I, MT, S, SP>
|
||||||
where
|
where
|
||||||
EMH: EventManagerHooksTuple<I, S> + Copy + Clone,
|
EMH: EventManagerHooksTuple<I, S> + Copy + Clone,
|
||||||
SP: ShMemProvider,
|
|
||||||
S: Serialize + DeserializeOwned,
|
|
||||||
I: DeserializeOwned,
|
I: DeserializeOwned,
|
||||||
MT: Monitor + Clone,
|
MT: Monitor + Clone,
|
||||||
|
S: Serialize + DeserializeOwned,
|
||||||
|
SP: ShMemProvider,
|
||||||
{
|
{
|
||||||
/// Launch the broker and the clients and fuzz
|
/// Launch the broker and the clients and fuzz
|
||||||
pub fn launch(
|
pub fn launch(
|
||||||
&mut self,
|
&mut self,
|
||||||
) -> Result<(Option<S>, LlmpRestartingEventManager<EMH, I, S, SP>), Error> {
|
) -> Result<
|
||||||
|
(
|
||||||
|
Option<S>,
|
||||||
|
LlmpRestartingEventManager<EMH, I, S, SP::ShMem, SP>,
|
||||||
|
),
|
||||||
|
Error,
|
||||||
|
> {
|
||||||
// We start ourselves as child process to actually fuzz
|
// We start ourselves as child process to actually fuzz
|
||||||
let (staterestorer, new_shmem_provider, core_id) = if std::env::var(_ENV_FUZZER_SENDER)
|
let (staterestorer, new_shmem_provider, core_id) = if std::env::var(_ENV_FUZZER_SENDER)
|
||||||
.is_err()
|
.is_err()
|
||||||
{
|
{
|
||||||
let broker_things = |mut broker: LlmpBroker<_, SP>, remote_broker_addr| {
|
let broker_things = |mut broker: LlmpBroker<_, SP::ShMem, SP>, remote_broker_addr| {
|
||||||
if let Some(remote_broker_addr) = remote_broker_addr {
|
if let Some(remote_broker_addr) = remote_broker_addr {
|
||||||
log::info!("B2b: Connecting to {:?}", &remote_broker_addr);
|
log::info!("B2b: Connecting to {:?}", &remote_broker_addr);
|
||||||
broker.inner_mut().connect_b2b(remote_broker_addr)?;
|
broker.inner_mut().connect_b2b(remote_broker_addr)?;
|
||||||
@ -467,13 +485,14 @@ where
|
|||||||
return Err(Error::shutting_down());
|
return Err(Error::shutting_down());
|
||||||
}
|
}
|
||||||
LlmpConnection::IsClient { client } => {
|
LlmpConnection::IsClient { client } => {
|
||||||
let mgr: LlmpEventManager<EMH, I, S, SP> = LlmpEventManager::builder()
|
let mgr: LlmpEventManager<EMH, I, S, SP::ShMem, SP> =
|
||||||
.hooks(self.hooks)
|
LlmpEventManager::builder()
|
||||||
.build_from_client(
|
.hooks(self.hooks)
|
||||||
client,
|
.build_from_client(
|
||||||
self.configuration,
|
client,
|
||||||
self.time_ref.clone(),
|
self.configuration,
|
||||||
)?;
|
self.time_ref.clone(),
|
||||||
|
)?;
|
||||||
(mgr, None)
|
(mgr, None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -516,11 +535,11 @@ where
|
|||||||
|
|
||||||
// First, create a channel from the current fuzzer to the next to store state between restarts.
|
// First, create a channel from the current fuzzer to the next to store state between restarts.
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
let staterestorer: StateRestorer<SP> =
|
let staterestorer: StateRestorer<SP::ShMem, SP> =
|
||||||
StateRestorer::new(self.shmem_provider.new_shmem(256 * 1024 * 1024)?);
|
StateRestorer::new(self.shmem_provider.new_shmem(256 * 1024 * 1024)?);
|
||||||
|
|
||||||
#[cfg(not(unix))]
|
#[cfg(not(unix))]
|
||||||
let staterestorer: StateRestorer<SP> =
|
let staterestorer: StateRestorer<SP::ShMem, SP> =
|
||||||
StateRestorer::new(self.shmem_provider.new_shmem(256 * 1024 * 1024)?);
|
StateRestorer::new(self.shmem_provider.new_shmem(256 * 1024 * 1024)?);
|
||||||
// Store the information to a map.
|
// Store the information to a map.
|
||||||
staterestorer.write_to_env(_ENV_FUZZER_SENDER)?;
|
staterestorer.write_to_env(_ENV_FUZZER_SENDER)?;
|
||||||
@ -683,7 +702,7 @@ mod tests {
|
|||||||
use libafl_bolts::{
|
use libafl_bolts::{
|
||||||
llmp::{LlmpClient, LlmpSharedMap},
|
llmp::{LlmpClient, LlmpSharedMap},
|
||||||
rands::StdRand,
|
rands::StdRand,
|
||||||
shmem::{ShMemProvider, StdShMemProvider},
|
shmem::{ShMemProvider, StdShMem, StdShMemProvider},
|
||||||
staterestore::StateRestorer,
|
staterestore::StateRestorer,
|
||||||
tuples::{tuple_list, Handled},
|
tuples::{tuple_list, Handled},
|
||||||
ClientId,
|
ClientId,
|
||||||
@ -772,7 +791,7 @@ mod tests {
|
|||||||
let mut stages = tuple_list!(StdMutationalStage::new(mutator));
|
let mut stages = tuple_list!(StdMutationalStage::new(mutator));
|
||||||
|
|
||||||
// First, create a channel from the current fuzzer to the next to store state between restarts.
|
// First, create a channel from the current fuzzer to the next to store state between restarts.
|
||||||
let mut staterestorer = StateRestorer::<StdShMemProvider>::new(
|
let mut staterestorer = StateRestorer::<StdShMem, StdShMemProvider>::new(
|
||||||
shmem_provider.new_shmem(256 * 1024 * 1024).unwrap(),
|
shmem_provider.new_shmem(256 * 1024 * 1024).unwrap(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -13,7 +13,11 @@ use libafl_bolts::os::unix_signals::setup_signal_handler;
|
|||||||
use libafl_bolts::os::{fork, ForkResult};
|
use libafl_bolts::os::{fork, ForkResult};
|
||||||
use libafl_bolts::ClientId;
|
use libafl_bolts::ClientId;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use libafl_bolts::{os::CTRL_C_EXIT, shmem::ShMemProvider, staterestore::StateRestorer};
|
use libafl_bolts::{
|
||||||
|
os::CTRL_C_EXIT,
|
||||||
|
shmem::{ShMem, ShMemProvider},
|
||||||
|
staterestore::StateRestorer,
|
||||||
|
};
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
@ -280,23 +284,19 @@ where
|
|||||||
/// `restarter` will start a new process each time the child crashes or times out.
|
/// `restarter` will start a new process each time the child crashes or times out.
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SimpleRestartingEventManager<I, MT, S, SP>
|
pub struct SimpleRestartingEventManager<I, MT, S, SHM, SP> {
|
||||||
where
|
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
|
||||||
/// The actual simple event mgr
|
/// The actual simple event mgr
|
||||||
inner: SimpleEventManager<I, MT, S>,
|
inner: SimpleEventManager<I, MT, S>,
|
||||||
/// [`StateRestorer`] for restarts
|
/// [`StateRestorer`] for restarts
|
||||||
staterestorer: StateRestorer<SP>,
|
staterestorer: StateRestorer<SHM, SP>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
impl<I, MT, S, SP> EventFirer<I, S> for SimpleRestartingEventManager<I, MT, S, SP>
|
impl<I, MT, S, SHM, SP> EventFirer<I, S> for SimpleRestartingEventManager<I, MT, S, SHM, SP>
|
||||||
where
|
where
|
||||||
I: Debug,
|
I: Debug,
|
||||||
MT: Monitor,
|
MT: Monitor,
|
||||||
S: Stoppable,
|
S: Stoppable,
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
{
|
||||||
fn should_send(&self) -> bool {
|
fn should_send(&self) -> bool {
|
||||||
true
|
true
|
||||||
@ -308,9 +308,10 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
impl<I, MT, S, SP> EventRestarter<S> for SimpleRestartingEventManager<I, MT, S, SP>
|
impl<I, MT, S, SHM, SP> EventRestarter<S> for SimpleRestartingEventManager<I, MT, S, SHM, SP>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
S: HasCurrentStageId + Serialize,
|
S: HasCurrentStageId + Serialize,
|
||||||
MT: Monitor,
|
MT: Monitor,
|
||||||
{
|
{
|
||||||
@ -329,9 +330,9 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
impl<I, MT, OT, S, SP> CanSerializeObserver<OT> for SimpleRestartingEventManager<I, MT, S, SP>
|
impl<I, MT, OT, S, SHM, SP> CanSerializeObserver<OT>
|
||||||
|
for SimpleRestartingEventManager<I, MT, S, SHM, SP>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
|
||||||
OT: Serialize,
|
OT: Serialize,
|
||||||
{
|
{
|
||||||
fn serialize_observers(&mut self, observers: &OT) -> Result<Option<Vec<u8>>, Error> {
|
fn serialize_observers(&mut self, observers: &OT) -> Result<Option<Vec<u8>>, Error> {
|
||||||
@ -340,9 +341,10 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
impl<I, MT, S, SP> ManagerExit for SimpleRestartingEventManager<I, MT, S, SP>
|
impl<I, MT, S, SHM, SP> ManagerExit for SimpleRestartingEventManager<I, MT, S, SHM, SP>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
fn send_exiting(&mut self) -> Result<(), Error> {
|
fn send_exiting(&mut self) -> Result<(), Error> {
|
||||||
self.staterestorer.send_exiting();
|
self.staterestorer.send_exiting();
|
||||||
@ -354,12 +356,14 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
impl<E, I, MT, S, SP, Z> EventProcessor<E, S, Z> for SimpleRestartingEventManager<I, MT, S, SP>
|
impl<E, I, MT, S, SHM, SP, Z> EventProcessor<E, S, Z>
|
||||||
|
for SimpleRestartingEventManager<I, MT, S, SHM, SP>
|
||||||
where
|
where
|
||||||
I: Debug,
|
I: Debug,
|
||||||
MT: Monitor,
|
MT: Monitor,
|
||||||
SP: ShMemProvider,
|
|
||||||
S: Stoppable,
|
S: Stoppable,
|
||||||
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
fn process(&mut self, fuzzer: &mut Z, state: &mut S, executor: &mut E) -> Result<usize, Error> {
|
fn process(&mut self, fuzzer: &mut Z, state: &mut S, executor: &mut E) -> Result<usize, Error> {
|
||||||
self.inner.process(fuzzer, state, executor)
|
self.inner.process(fuzzer, state, executor)
|
||||||
@ -371,11 +375,10 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
impl<I, MT, S, SP> ProgressReporter<S> for SimpleRestartingEventManager<I, MT, S, SP>
|
impl<I, MT, S, SHM, SP> ProgressReporter<S> for SimpleRestartingEventManager<I, MT, S, SHM, SP>
|
||||||
where
|
where
|
||||||
I: Debug,
|
I: Debug,
|
||||||
MT: Monitor,
|
MT: Monitor,
|
||||||
SP: ShMemProvider,
|
|
||||||
S: HasExecutions + HasMetadata + HasLastReportTime + Stoppable + MaybeHasClientPerfMonitor,
|
S: HasExecutions + HasMetadata + HasLastReportTime + Stoppable + MaybeHasClientPerfMonitor,
|
||||||
{
|
{
|
||||||
fn maybe_report_progress(
|
fn maybe_report_progress(
|
||||||
@ -392,25 +395,23 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
impl<I, MT, S, SP> HasEventManagerId for SimpleRestartingEventManager<I, MT, S, SP>
|
impl<I, MT, S, SHM, SP> HasEventManagerId for SimpleRestartingEventManager<I, MT, S, SHM, SP> {
|
||||||
where
|
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
|
||||||
fn mgr_id(&self) -> EventManagerId {
|
fn mgr_id(&self) -> EventManagerId {
|
||||||
self.inner.mgr_id()
|
self.inner.mgr_id()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
impl<I, MT, S, SP> SimpleRestartingEventManager<I, MT, S, SP>
|
impl<I, MT, S, SHM, SP> SimpleRestartingEventManager<I, MT, S, SHM, SP>
|
||||||
where
|
where
|
||||||
I: Debug,
|
I: Debug,
|
||||||
MT: Monitor,
|
MT: Monitor,
|
||||||
S: Stoppable,
|
S: Stoppable,
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
/// Creates a new [`SimpleEventManager`].
|
/// Creates a new [`SimpleEventManager`].
|
||||||
fn launched(monitor: MT, staterestorer: StateRestorer<SP>) -> Self {
|
fn launched(monitor: MT, staterestorer: StateRestorer<SHM, SP>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
staterestorer,
|
staterestorer,
|
||||||
inner: SimpleEventManager::new(monitor),
|
inner: SimpleEventManager::new(monitor),
|
||||||
@ -429,10 +430,10 @@ where
|
|||||||
let mut staterestorer = if std::env::var(_ENV_FUZZER_SENDER).is_err() {
|
let mut staterestorer = if std::env::var(_ENV_FUZZER_SENDER).is_err() {
|
||||||
// First, create a place to store state in, for restarts.
|
// First, create a place to store state in, for restarts.
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
let staterestorer: StateRestorer<SP> =
|
let staterestorer: StateRestorer<SHM, SP> =
|
||||||
StateRestorer::new(shmem_provider.new_shmem(256 * 1024 * 1024)?);
|
StateRestorer::new(shmem_provider.new_shmem(256 * 1024 * 1024)?);
|
||||||
#[cfg(not(unix))]
|
#[cfg(not(unix))]
|
||||||
let staterestorer: StateRestorer<SP> =
|
let staterestorer: StateRestorer<SHM, SP> =
|
||||||
StateRestorer::new(shmem_provider.new_shmem(256 * 1024 * 1024)?);
|
StateRestorer::new(shmem_provider.new_shmem(256 * 1024 * 1024)?);
|
||||||
|
|
||||||
//let staterestorer = { LlmpSender::new(shmem_provider.clone(), 0, false)? };
|
//let staterestorer = { LlmpSender::new(shmem_provider.clone(), 0, false)? };
|
||||||
|
@ -25,7 +25,7 @@ use libafl_bolts::os::{fork, ForkResult};
|
|||||||
use libafl_bolts::{
|
use libafl_bolts::{
|
||||||
core_affinity::CoreId,
|
core_affinity::CoreId,
|
||||||
os::CTRL_C_EXIT,
|
os::CTRL_C_EXIT,
|
||||||
shmem::{ShMemProvider, StdShMemProvider},
|
shmem::{ShMem, ShMemProvider, StdShMem, StdShMemProvider},
|
||||||
staterestore::StateRestorer,
|
staterestore::StateRestorer,
|
||||||
tuples::tuple_list,
|
tuples::tuple_list,
|
||||||
ClientId,
|
ClientId,
|
||||||
@ -819,24 +819,20 @@ impl<EMH, I, S> HasEventManagerId for TcpEventManager<EMH, I, S> {
|
|||||||
|
|
||||||
/// A manager that can restart on the fly, storing states in-between (in `on_restart`)
|
/// A manager that can restart on the fly, storing states in-between (in `on_restart`)
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct TcpRestartingEventManager<EMH, I, S, SP>
|
pub struct TcpRestartingEventManager<EMH, I, S, SHM, SP> {
|
||||||
where
|
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
|
||||||
/// The embedded TCP event manager
|
/// The embedded TCP event manager
|
||||||
tcp_mgr: TcpEventManager<EMH, I, S>,
|
tcp_mgr: TcpEventManager<EMH, I, S>,
|
||||||
/// The staterestorer to serialize the state for the next runner
|
/// The staterestorer to serialize the state for the next runner
|
||||||
staterestorer: StateRestorer<SP>,
|
staterestorer: StateRestorer<SHM, SP>,
|
||||||
/// Decide if the state restorer must save the serialized state
|
/// Decide if the state restorer must save the serialized state
|
||||||
save_state: bool,
|
save_state: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EMH, I, S, SP> ProgressReporter<S> for TcpRestartingEventManager<EMH, I, S, SP>
|
impl<EMH, I, S, SHM, SP> ProgressReporter<S> for TcpRestartingEventManager<EMH, I, S, SHM, SP>
|
||||||
where
|
where
|
||||||
EMH: EventManagerHooksTuple<I, S>,
|
EMH: EventManagerHooksTuple<I, S>,
|
||||||
S: HasMetadata + HasExecutions + HasLastReportTime + MaybeHasClientPerfMonitor,
|
S: HasMetadata + HasExecutions + HasLastReportTime + MaybeHasClientPerfMonitor,
|
||||||
I: Serialize,
|
I: Serialize,
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
{
|
||||||
fn maybe_report_progress(
|
fn maybe_report_progress(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -851,11 +847,10 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EMH, I, S, SP> EventFirer<I, S> for TcpRestartingEventManager<EMH, I, S, SP>
|
impl<EMH, I, S, SHM, SP> EventFirer<I, S> for TcpRestartingEventManager<EMH, I, S, SHM, SP>
|
||||||
where
|
where
|
||||||
EMH: EventManagerHooksTuple<I, S>,
|
EMH: EventManagerHooksTuple<I, S>,
|
||||||
I: Serialize,
|
I: Serialize,
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
{
|
||||||
fn should_send(&self) -> bool {
|
fn should_send(&self) -> bool {
|
||||||
self.tcp_mgr.should_send()
|
self.tcp_mgr.should_send()
|
||||||
@ -871,30 +866,32 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EMH, I, S, SP> ManagerExit for TcpRestartingEventManager<EMH, I, S, SP>
|
impl<EMH, I, S, SHM, SP> ManagerExit for TcpRestartingEventManager<EMH, I, S, SHM, SP>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
/// The tcp client needs to wait until a broker mapped all pages, before shutting down.
|
|
||||||
/// Otherwise, the OS may already have removed the shared maps,
|
|
||||||
#[inline]
|
|
||||||
fn await_restart_safe(&mut self) {
|
|
||||||
self.tcp_mgr.await_restart_safe();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn send_exiting(&mut self) -> Result<(), Error> {
|
fn send_exiting(&mut self) -> Result<(), Error> {
|
||||||
self.staterestorer.send_exiting();
|
self.staterestorer.send_exiting();
|
||||||
// Also inform the broker that we are about to exit.
|
// Also inform the broker that we are about to exit.
|
||||||
// This way, the broker can clean up the pages, and eventually exit.
|
// This way, the broker can clean up the pages, and eventually exit.
|
||||||
self.tcp_mgr.send_exiting()
|
self.tcp_mgr.send_exiting()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The tcp client needs to wait until a broker mapped all pages, before shutting down.
|
||||||
|
/// Otherwise, the OS may already have removed the shared maps,
|
||||||
|
#[inline]
|
||||||
|
fn await_restart_safe(&mut self) {
|
||||||
|
self.tcp_mgr.await_restart_safe();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EMH, I, S, SP> EventRestarter<S> for TcpRestartingEventManager<EMH, I, S, SP>
|
impl<EMH, I, S, SHM, SP> EventRestarter<S> for TcpRestartingEventManager<EMH, I, S, SHM, SP>
|
||||||
where
|
where
|
||||||
EMH: EventManagerHooksTuple<I, S>,
|
EMH: EventManagerHooksTuple<I, S>,
|
||||||
S: HasExecutions + HasCurrentStageId + Serialize,
|
S: HasExecutions + HasCurrentStageId + Serialize,
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
/// Reset the single page (we reuse it over and over from pos 0), then send the current state to the next runner.
|
/// Reset the single page (we reuse it over and over from pos 0), then send the current state to the next runner.
|
||||||
fn on_restart(&mut self, state: &mut S) -> Result<(), Error> {
|
fn on_restart(&mut self, state: &mut S) -> Result<(), Error> {
|
||||||
@ -913,7 +910,8 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E, EMH, I, S, SP, Z> EventProcessor<E, S, Z> for TcpRestartingEventManager<EMH, I, S, SP>
|
impl<E, EMH, I, S, SHM, SP, Z> EventProcessor<E, S, Z>
|
||||||
|
for TcpRestartingEventManager<EMH, I, S, SHM, SP>
|
||||||
where
|
where
|
||||||
E: HasObservers + Executor<TcpEventManager<EMH, I, S>, I, S, Z>,
|
E: HasObservers + Executor<TcpEventManager<EMH, I, S>, I, S, Z>,
|
||||||
for<'a> E::Observers: Deserialize<'a>,
|
for<'a> E::Observers: Deserialize<'a>,
|
||||||
@ -926,7 +924,8 @@ where
|
|||||||
+ HasSolutions<I>
|
+ HasSolutions<I>
|
||||||
+ HasCurrentTestcase<I>
|
+ HasCurrentTestcase<I>
|
||||||
+ Stoppable,
|
+ Stoppable,
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
Z: ExecutionProcessor<TcpEventManager<EMH, I, S>, I, E::Observers, S>
|
Z: ExecutionProcessor<TcpEventManager<EMH, I, S>, I, E::Observers, S>
|
||||||
+ EvaluatorObservers<E, TcpEventManager<EMH, I, S>, I, S>,
|
+ EvaluatorObservers<E, TcpEventManager<EMH, I, S>, I, S>,
|
||||||
{
|
{
|
||||||
@ -939,10 +938,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EMH, I, S, SP> HasEventManagerId for TcpRestartingEventManager<EMH, I, S, SP>
|
impl<EMH, I, S, SHM, SP> HasEventManagerId for TcpRestartingEventManager<EMH, I, S, SHM, SP> {
|
||||||
where
|
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
|
||||||
fn mgr_id(&self) -> EventManagerId {
|
fn mgr_id(&self) -> EventManagerId {
|
||||||
self.tcp_mgr.mgr_id()
|
self.tcp_mgr.mgr_id()
|
||||||
}
|
}
|
||||||
@ -954,13 +950,12 @@ const _ENV_FUZZER_RECEIVER: &str = "_AFL_ENV_FUZZER_RECEIVER";
|
|||||||
/// The tcp (2 way) connection from a fuzzer to the broker (broadcasting all other fuzzer messages)
|
/// The tcp (2 way) connection from a fuzzer to the broker (broadcasting all other fuzzer messages)
|
||||||
const _ENV_FUZZER_BROKER_CLIENT_INITIAL: &str = "_AFL_ENV_FUZZER_BROKER_CLIENT";
|
const _ENV_FUZZER_BROKER_CLIENT_INITIAL: &str = "_AFL_ENV_FUZZER_BROKER_CLIENT";
|
||||||
|
|
||||||
impl<EMH, I, S, SP> TcpRestartingEventManager<EMH, I, S, SP>
|
impl<EMH, I, S, SHM, SP> TcpRestartingEventManager<EMH, I, S, SHM, SP>
|
||||||
where
|
where
|
||||||
EMH: EventManagerHooksTuple<I, S>,
|
EMH: EventManagerHooksTuple<I, S>,
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
{
|
||||||
/// Create a new runner, the executed child doing the actual fuzzing.
|
/// Create a new runner, the executed child doing the actual fuzzing.
|
||||||
pub fn new(tcp_mgr: TcpEventManager<EMH, I, S>, staterestorer: StateRestorer<SP>) -> Self {
|
pub fn new(tcp_mgr: TcpEventManager<EMH, I, S>, staterestorer: StateRestorer<SHM, SP>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
tcp_mgr,
|
tcp_mgr,
|
||||||
staterestorer,
|
staterestorer,
|
||||||
@ -971,7 +966,7 @@ where
|
|||||||
/// Create a new runner specifying if it must save the serialized state on restart.
|
/// Create a new runner specifying if it must save the serialized state on restart.
|
||||||
pub fn with_save_state(
|
pub fn with_save_state(
|
||||||
tcp_mgr: TcpEventManager<EMH, I, S>,
|
tcp_mgr: TcpEventManager<EMH, I, S>,
|
||||||
staterestorer: StateRestorer<SP>,
|
staterestorer: StateRestorer<SHM, SP>,
|
||||||
save_state: bool,
|
save_state: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -982,12 +977,12 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the staterestorer
|
/// Get the staterestorer
|
||||||
pub fn staterestorer(&self) -> &StateRestorer<SP> {
|
pub fn staterestorer(&self) -> &StateRestorer<SHM, SP> {
|
||||||
&self.staterestorer
|
&self.staterestorer
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the staterestorer (mutable)
|
/// Get the staterestorer (mutable)
|
||||||
pub fn staterestorer_mut(&mut self) -> &mut StateRestorer<SP> {
|
pub fn staterestorer_mut(&mut self) -> &mut StateRestorer<SHM, SP> {
|
||||||
&mut self.staterestorer
|
&mut self.staterestorer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1018,7 +1013,7 @@ pub fn setup_restarting_mgr_tcp<I, MT, S>(
|
|||||||
) -> Result<
|
) -> Result<
|
||||||
(
|
(
|
||||||
Option<S>,
|
Option<S>,
|
||||||
TcpRestartingEventManager<(), I, S, StdShMemProvider>,
|
TcpRestartingEventManager<(), I, S, StdShMem, StdShMemProvider>,
|
||||||
),
|
),
|
||||||
Error,
|
Error,
|
||||||
>
|
>
|
||||||
@ -1049,12 +1044,7 @@ where
|
|||||||
/// `restarter` and `runner`, that can be used on systems both with and without `fork` support. The
|
/// `restarter` and `runner`, that can be used on systems both with and without `fork` support. The
|
||||||
/// `restarter` will start a new process each time the child crashes or times out.
|
/// `restarter` will start a new process each time the child crashes or times out.
|
||||||
#[derive(TypedBuilder, Debug)]
|
#[derive(TypedBuilder, Debug)]
|
||||||
pub struct TcpRestartingMgr<EMH, I, MT, S, SP>
|
pub struct TcpRestartingMgr<EMH, I, MT, S, SP> {
|
||||||
where
|
|
||||||
MT: Monitor,
|
|
||||||
S: DeserializeOwned,
|
|
||||||
SP: ShMemProvider + 'static,
|
|
||||||
{
|
|
||||||
/// The shared memory provider to use for the broker or client spawned by the restarting
|
/// The shared memory provider to use for the broker or client spawned by the restarting
|
||||||
/// manager.
|
/// manager.
|
||||||
shmem_provider: SP,
|
shmem_provider: SP,
|
||||||
@ -1095,7 +1085,6 @@ where
|
|||||||
EMH: EventManagerHooksTuple<I, S> + Copy + Clone,
|
EMH: EventManagerHooksTuple<I, S> + Copy + Clone,
|
||||||
I: Input,
|
I: Input,
|
||||||
MT: Monitor + Clone,
|
MT: Monitor + Clone,
|
||||||
SP: ShMemProvider,
|
|
||||||
S: HasExecutions
|
S: HasExecutions
|
||||||
+ HasMetadata
|
+ HasMetadata
|
||||||
+ HasImported
|
+ HasImported
|
||||||
@ -1103,11 +1092,18 @@ where
|
|||||||
+ HasCurrentTestcase<I>
|
+ HasCurrentTestcase<I>
|
||||||
+ DeserializeOwned
|
+ DeserializeOwned
|
||||||
+ Stoppable,
|
+ Stoppable,
|
||||||
|
SP: ShMemProvider,
|
||||||
{
|
{
|
||||||
/// Launch the restarting manager
|
/// Launch the restarting manager
|
||||||
pub fn launch(
|
pub fn launch(
|
||||||
&mut self,
|
&mut self,
|
||||||
) -> Result<(Option<S>, TcpRestartingEventManager<EMH, I, S, SP>), Error> {
|
) -> Result<
|
||||||
|
(
|
||||||
|
Option<S>,
|
||||||
|
TcpRestartingEventManager<EMH, I, S, SP::ShMem, SP>,
|
||||||
|
),
|
||||||
|
Error,
|
||||||
|
> {
|
||||||
// We start ourself as child process to actually fuzz
|
// We start ourself as child process to actually fuzz
|
||||||
let (staterestorer, _new_shmem_provider, core_id) = if env::var(_ENV_FUZZER_SENDER).is_err()
|
let (staterestorer, _new_shmem_provider, core_id) = if env::var(_ENV_FUZZER_SENDER).is_err()
|
||||||
{
|
{
|
||||||
@ -1185,11 +1181,11 @@ where
|
|||||||
|
|
||||||
// First, create a channel from the current fuzzer to the next to store state between restarts.
|
// First, create a channel from the current fuzzer to the next to store state between restarts.
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
let staterestorer: StateRestorer<SP> =
|
let staterestorer: StateRestorer<SP::ShMem, SP> =
|
||||||
StateRestorer::new(self.shmem_provider.new_shmem(256 * 1024 * 1024)?);
|
StateRestorer::new(self.shmem_provider.new_shmem(256 * 1024 * 1024)?);
|
||||||
|
|
||||||
#[cfg(not(unix))]
|
#[cfg(not(unix))]
|
||||||
let staterestorer: StateRestorer<SP> =
|
let staterestorer: StateRestorer<SP::ShMem, SP> =
|
||||||
StateRestorer::new(self.shmem_provider.new_shmem(256 * 1024 * 1024)?);
|
StateRestorer::new(self.shmem_provider.new_shmem(256 * 1024 * 1024)?);
|
||||||
// Store the information to a map.
|
// Store the information to a map.
|
||||||
staterestorer.write_to_env(_ENV_FUZZER_SENDER)?;
|
staterestorer.write_to_env(_ENV_FUZZER_SENDER)?;
|
||||||
|
@ -22,7 +22,7 @@ use libafl_bolts::{
|
|||||||
fs::{get_unique_std_input_file, InputFile},
|
fs::{get_unique_std_input_file, InputFile},
|
||||||
os::{dup2, pipes::Pipe},
|
os::{dup2, pipes::Pipe},
|
||||||
ownedref::OwnedSlice,
|
ownedref::OwnedSlice,
|
||||||
shmem::{ShMem, ShMemProvider, UnixShMemProvider},
|
shmem::{ShMem, ShMemProvider, UnixShMem, UnixShMemProvider},
|
||||||
tuples::{Handle, Handled, MatchNameRef, Prepend, RefIndexable},
|
tuples::{Handle, Handled, MatchNameRef, Prepend, RefIndexable},
|
||||||
AsSlice, AsSliceMut, Truncate,
|
AsSlice, AsSliceMut, Truncate,
|
||||||
};
|
};
|
||||||
@ -606,10 +606,7 @@ impl Forkserver {
|
|||||||
///
|
///
|
||||||
/// Shared memory feature is also available, but you have to set things up in your code.
|
/// Shared memory feature is also available, but you have to set things up in your code.
|
||||||
/// Please refer to AFL++'s docs. <https://github.com/AFLplusplus/AFLplusplus/blob/stable/instrumentation/README.persistent_mode.md>
|
/// Please refer to AFL++'s docs. <https://github.com/AFLplusplus/AFLplusplus/blob/stable/instrumentation/README.persistent_mode.md>
|
||||||
pub struct ForkserverExecutor<I, OT, S, SP, TC>
|
pub struct ForkserverExecutor<I, OT, S, SHM, TC> {
|
||||||
where
|
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
|
||||||
target: OsString,
|
target: OsString,
|
||||||
args: Vec<OsString>,
|
args: Vec<OsString>,
|
||||||
input_file: InputFile,
|
input_file: InputFile,
|
||||||
@ -617,7 +614,7 @@ where
|
|||||||
uses_shmem_testcase: bool,
|
uses_shmem_testcase: bool,
|
||||||
forkserver: Forkserver,
|
forkserver: Forkserver,
|
||||||
observers: OT,
|
observers: OT,
|
||||||
map: Option<SP::ShMem>,
|
map: Option<SHM>,
|
||||||
phantom: PhantomData<(I, S)>,
|
phantom: PhantomData<(I, S)>,
|
||||||
map_size: Option<usize>,
|
map_size: Option<usize>,
|
||||||
min_input_size: usize,
|
min_input_size: usize,
|
||||||
@ -628,11 +625,11 @@ where
|
|||||||
crash_exitcode: Option<i8>,
|
crash_exitcode: Option<i8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I, OT, S, SP, TC> Debug for ForkserverExecutor<I, OT, S, SP, TC>
|
impl<I, OT, S, SHM, TC> Debug for ForkserverExecutor<I, OT, S, SHM, TC>
|
||||||
where
|
where
|
||||||
TC: Debug,
|
TC: Debug,
|
||||||
OT: Debug,
|
OT: Debug,
|
||||||
SP: ShMemProvider,
|
SHM: Debug,
|
||||||
{
|
{
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
f.debug_struct("ForkserverExecutor")
|
f.debug_struct("ForkserverExecutor")
|
||||||
@ -648,7 +645,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ForkserverExecutor<(), (), (), UnixShMemProvider, ()> {
|
impl ForkserverExecutor<(), (), (), UnixShMem, ()> {
|
||||||
/// Builder for `ForkserverExecutor`
|
/// Builder for `ForkserverExecutor`
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn builder(
|
pub fn builder(
|
||||||
@ -658,11 +655,11 @@ impl ForkserverExecutor<(), (), (), UnixShMemProvider, ()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I, OT, S, SP, TC> ForkserverExecutor<I, OT, S, SP, TC>
|
impl<I, OT, S, SHM, TC> ForkserverExecutor<I, OT, S, SHM, TC>
|
||||||
where
|
where
|
||||||
OT: ObserversTuple<I, S>,
|
OT: ObserversTuple<I, S>,
|
||||||
SP: ShMemProvider,
|
|
||||||
TC: TargetBytesConverter<I>,
|
TC: TargetBytesConverter<I>,
|
||||||
|
SHM: ShMem,
|
||||||
{
|
{
|
||||||
/// The `target` binary that's going to run.
|
/// The `target` binary that's going to run.
|
||||||
pub fn target(&self) -> &OsString {
|
pub fn target(&self) -> &OsString {
|
||||||
@ -827,9 +824,10 @@ pub struct ForkserverExecutorBuilder<'a, TC, SP> {
|
|||||||
target_bytes_converter: TC,
|
target_bytes_converter: TC,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, TC, SP> ForkserverExecutorBuilder<'a, TC, SP>
|
impl<'a, TC, SHM, SP> ForkserverExecutorBuilder<'a, TC, SP>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
/// Builds `ForkserverExecutor`.
|
/// Builds `ForkserverExecutor`.
|
||||||
/// This Forkserver will attempt to provide inputs over shared mem when `shmem_provider` is given.
|
/// This Forkserver will attempt to provide inputs over shared mem when `shmem_provider` is given.
|
||||||
@ -840,10 +838,9 @@ where
|
|||||||
pub fn build<I, OT, S>(
|
pub fn build<I, OT, S>(
|
||||||
mut self,
|
mut self,
|
||||||
observers: OT,
|
observers: OT,
|
||||||
) -> Result<ForkserverExecutor<I, OT, S, SP, TC>, Error>
|
) -> Result<ForkserverExecutor<I, OT, S, SHM, TC>, Error>
|
||||||
where
|
where
|
||||||
OT: ObserversTuple<I, S>,
|
OT: ObserversTuple<I, S>,
|
||||||
SP: ShMemProvider,
|
|
||||||
TC: TargetBytesConverter<I>,
|
TC: TargetBytesConverter<I>,
|
||||||
{
|
{
|
||||||
let (forkserver, input_file, map) = self.build_helper()?;
|
let (forkserver, input_file, map) = self.build_helper()?;
|
||||||
@ -905,13 +902,12 @@ where
|
|||||||
mut self,
|
mut self,
|
||||||
mut map_observer: A,
|
mut map_observer: A,
|
||||||
other_observers: OT,
|
other_observers: OT,
|
||||||
) -> Result<ForkserverExecutor<I, (A, OT), S, SP, TC>, Error>
|
) -> Result<ForkserverExecutor<I, (A, OT), S, SHM, TC>, Error>
|
||||||
where
|
where
|
||||||
A: Observer<I, S> + AsMut<MO>,
|
A: Observer<I, S> + AsMut<MO>,
|
||||||
I: Input + HasTargetBytes,
|
I: Input + HasTargetBytes,
|
||||||
MO: MapObserver + Truncate, // TODO maybe enforce Entry = u8 for the cov map
|
MO: MapObserver + Truncate, // TODO maybe enforce Entry = u8 for the cov map
|
||||||
OT: ObserversTuple<I, S> + Prepend<MO>,
|
OT: ObserversTuple<I, S> + Prepend<MO>,
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
{
|
||||||
let (forkserver, input_file, map) = self.build_helper()?;
|
let (forkserver, input_file, map) = self.build_helper()?;
|
||||||
|
|
||||||
@ -965,10 +961,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[expect(clippy::pedantic)]
|
#[expect(clippy::pedantic)]
|
||||||
fn build_helper(&mut self) -> Result<(Forkserver, InputFile, Option<SP::ShMem>), Error>
|
fn build_helper(&mut self) -> Result<(Forkserver, InputFile, Option<SHM>), Error> {
|
||||||
where
|
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
|
||||||
let input_filename = match &self.input_filename {
|
let input_filename = match &self.input_filename {
|
||||||
Some(name) => name.clone(),
|
Some(name) => name.clone(),
|
||||||
None => {
|
None => {
|
||||||
@ -1042,7 +1035,7 @@ where
|
|||||||
fn initialize_forkserver(
|
fn initialize_forkserver(
|
||||||
&mut self,
|
&mut self,
|
||||||
status: i32,
|
status: i32,
|
||||||
map: Option<&SP::ShMem>,
|
map: Option<&SHM>,
|
||||||
forkserver: &mut Forkserver,
|
forkserver: &mut Forkserver,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let keep = status;
|
let keep = status;
|
||||||
@ -1140,7 +1133,7 @@ where
|
|||||||
fn initialize_old_forkserver(
|
fn initialize_old_forkserver(
|
||||||
&mut self,
|
&mut self,
|
||||||
status: i32,
|
status: i32,
|
||||||
map: Option<&SP::ShMem>,
|
map: Option<&SHM>,
|
||||||
forkserver: &mut Forkserver,
|
forkserver: &mut Forkserver,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
if status & FS_OPT_ENABLED == FS_OPT_ENABLED && status & FS_OPT_MAPSIZE == FS_OPT_MAPSIZE {
|
if status & FS_OPT_ENABLED == FS_OPT_ENABLED && status & FS_OPT_MAPSIZE == FS_OPT_MAPSIZE {
|
||||||
@ -1505,7 +1498,7 @@ impl<'a> ForkserverExecutorBuilder<'a, NopTargetBytesConverter<BytesInput>, Unix
|
|||||||
|
|
||||||
impl<'a, TC> ForkserverExecutorBuilder<'a, TC, UnixShMemProvider> {
|
impl<'a, TC> ForkserverExecutorBuilder<'a, TC, UnixShMemProvider> {
|
||||||
/// Shmem provider for forkserver's shared memory testcase feature.
|
/// Shmem provider for forkserver's shared memory testcase feature.
|
||||||
pub fn shmem_provider<SP: ShMemProvider>(
|
pub fn shmem_provider<SP>(
|
||||||
self,
|
self,
|
||||||
shmem_provider: &'a mut SP,
|
shmem_provider: &'a mut SP,
|
||||||
) -> ForkserverExecutorBuilder<'a, TC, SP> {
|
) -> ForkserverExecutorBuilder<'a, TC, SP> {
|
||||||
@ -1577,12 +1570,12 @@ impl Default
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EM, I, OT, S, SP, TC, Z> Executor<EM, I, S, Z> for ForkserverExecutor<I, OT, S, SP, TC>
|
impl<EM, I, OT, S, SHM, TC, Z> Executor<EM, I, S, Z> for ForkserverExecutor<I, OT, S, SHM, TC>
|
||||||
where
|
where
|
||||||
OT: ObserversTuple<I, S>,
|
OT: ObserversTuple<I, S>,
|
||||||
SP: ShMemProvider,
|
|
||||||
S: HasExecutions,
|
S: HasExecutions,
|
||||||
TC: TargetBytesConverter<I>,
|
TC: TargetBytesConverter<I>,
|
||||||
|
SHM: ShMem,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn run_target(
|
fn run_target(
|
||||||
@ -1596,25 +1589,21 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I, OT, S, SP, TC> HasTimeout for ForkserverExecutor<I, OT, S, SP, TC>
|
impl<I, OT, S, SHM, TC> HasTimeout for ForkserverExecutor<I, OT, S, SHM, TC> {
|
||||||
where
|
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn set_timeout(&mut self, timeout: Duration) {
|
|
||||||
self.timeout = TimeSpec::from_duration(timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn timeout(&self) -> Duration {
|
fn timeout(&self) -> Duration {
|
||||||
self.timeout.into()
|
self.timeout.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn set_timeout(&mut self, timeout: Duration) {
|
||||||
|
self.timeout = TimeSpec::from_duration(timeout);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I, OT, S, SP, TC> HasObservers for ForkserverExecutor<I, OT, S, SP, TC>
|
impl<I, OT, S, SHM, TC> HasObservers for ForkserverExecutor<I, OT, S, SHM, TC>
|
||||||
where
|
where
|
||||||
OT: ObserversTuple<I, S>,
|
OT: ObserversTuple<I, S>,
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
{
|
||||||
type Observers = OT;
|
type Observers = OT;
|
||||||
|
|
||||||
|
@ -74,6 +74,7 @@ where
|
|||||||
/// # Safety
|
/// # Safety
|
||||||
/// This function sets a bunch of raw pointers in global variables, reused in other parts of
|
/// This function sets a bunch of raw pointers in global variables, reused in other parts of
|
||||||
/// the code.
|
/// the code.
|
||||||
|
// TODO: Remove EM and Z from function bound and add it to struct instead to avoid possible type confusion
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn enter_target<EM, Z>(
|
pub unsafe fn enter_target<EM, Z>(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -27,8 +27,8 @@ use crate::{
|
|||||||
|
|
||||||
/// The process executor simply calls a target function, as mutable reference to a closure
|
/// The process executor simply calls a target function, as mutable reference to a closure
|
||||||
/// The internal state of the executor is made available to the harness.
|
/// The internal state of the executor is made available to the harness.
|
||||||
pub type StatefulInProcessExecutor<'a, H, I, OT, S, ES> =
|
pub type StatefulInProcessExecutor<'a, ES, H, I, OT, S> =
|
||||||
StatefulGenericInProcessExecutor<H, &'a mut H, (), I, OT, S, ES>;
|
StatefulGenericInProcessExecutor<ES, H, &'a mut H, (), I, OT, S>;
|
||||||
|
|
||||||
/// The process executor simply calls a target function, as boxed `FnMut` trait object
|
/// The process executor simply calls a target function, as boxed `FnMut` trait object
|
||||||
/// The internal state of the executor is made available to the harness.
|
/// The internal state of the executor is made available to the harness.
|
||||||
@ -44,7 +44,7 @@ pub type OwnedInProcessExecutor<I, OT, S, ES> = StatefulGenericInProcessExecutor
|
|||||||
|
|
||||||
/// The inmem executor simply calls a target function, then returns afterwards.
|
/// The inmem executor simply calls a target function, then returns afterwards.
|
||||||
/// The harness can access the internal state of the executor.
|
/// The harness can access the internal state of the executor.
|
||||||
pub struct StatefulGenericInProcessExecutor<H, HB, HT, I, OT, S, ES> {
|
pub struct StatefulGenericInProcessExecutor<ES, H, HB, HT, I, OT, S> {
|
||||||
/// The harness function, being executed for each fuzzing loop execution
|
/// The harness function, being executed for each fuzzing loop execution
|
||||||
harness_fn: HB,
|
harness_fn: HB,
|
||||||
/// The state used as argument of the harness
|
/// The state used as argument of the harness
|
||||||
@ -54,7 +54,7 @@ pub struct StatefulGenericInProcessExecutor<H, HB, HT, I, OT, S, ES> {
|
|||||||
phantom: PhantomData<(ES, *const H)>,
|
phantom: PhantomData<(ES, *const H)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<H, HB, HT, I, OT, S, ES> Debug for StatefulGenericInProcessExecutor<H, HB, HT, I, OT, S, ES>
|
impl<H, HB, HT, I, OT, S, ES> Debug for StatefulGenericInProcessExecutor<ES, H, HB, HT, I, OT, S>
|
||||||
where
|
where
|
||||||
OT: Debug,
|
OT: Debug,
|
||||||
{
|
{
|
||||||
@ -67,7 +67,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<EM, H, HB, HT, I, OT, S, Z, ES> Executor<EM, I, S, Z>
|
impl<EM, H, HB, HT, I, OT, S, Z, ES> Executor<EM, I, S, Z>
|
||||||
for StatefulGenericInProcessExecutor<H, HB, HT, I, OT, S, ES>
|
for StatefulGenericInProcessExecutor<ES, H, HB, HT, I, OT, S>
|
||||||
where
|
where
|
||||||
H: FnMut(&mut ES, &mut S, &I) -> ExitKind + Sized,
|
H: FnMut(&mut ES, &mut S, &I) -> ExitKind + Sized,
|
||||||
HB: BorrowMut<H>,
|
HB: BorrowMut<H>,
|
||||||
@ -99,7 +99,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<H, HB, HT, I, OT, S, ES> HasObservers
|
impl<H, HB, HT, I, OT, S, ES> HasObservers
|
||||||
for StatefulGenericInProcessExecutor<H, HB, HT, I, OT, S, ES>
|
for StatefulGenericInProcessExecutor<ES, H, HB, HT, I, OT, S>
|
||||||
where
|
where
|
||||||
H: FnMut(&mut ES, &mut S, &I) -> ExitKind + Sized,
|
H: FnMut(&mut ES, &mut S, &I) -> ExitKind + Sized,
|
||||||
HB: BorrowMut<H>,
|
HB: BorrowMut<H>,
|
||||||
@ -118,7 +118,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, H, I, OT, S, ES> StatefulInProcessExecutor<'a, H, I, OT, S, ES>
|
impl<'a, H, I, OT, S, ES> StatefulInProcessExecutor<'a, ES, H, I, OT, S>
|
||||||
where
|
where
|
||||||
H: FnMut(&mut ES, &mut S, &I) -> ExitKind + Sized,
|
H: FnMut(&mut ES, &mut S, &I) -> ExitKind + Sized,
|
||||||
OT: ObserversTuple<I, S>,
|
OT: ObserversTuple<I, S>,
|
||||||
@ -224,7 +224,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<H, HB, HT, I, OT, S, ES> StatefulGenericInProcessExecutor<H, HB, HT, I, OT, S, ES> {
|
impl<H, HB, HT, I, OT, S, ES> StatefulGenericInProcessExecutor<ES, H, HB, HT, I, OT, S> {
|
||||||
/// The executor state given to the harness
|
/// The executor state given to the harness
|
||||||
pub fn exposed_executor_state(&self) -> &ES {
|
pub fn exposed_executor_state(&self) -> &ES {
|
||||||
&self.exposed_executor_state
|
&self.exposed_executor_state
|
||||||
@ -236,7 +236,7 @@ impl<H, HB, HT, I, OT, S, ES> StatefulGenericInProcessExecutor<H, HB, HT, I, OT,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<H, HB, HT, I, OT, S, ES> StatefulGenericInProcessExecutor<H, HB, HT, I, OT, S, ES>
|
impl<H, HB, HT, I, OT, S, ES> StatefulGenericInProcessExecutor<ES, H, HB, HT, I, OT, S>
|
||||||
where
|
where
|
||||||
H: FnMut(&mut ES, &mut S, &I) -> ExitKind + Sized,
|
H: FnMut(&mut ES, &mut S, &I) -> ExitKind + Sized,
|
||||||
HB: BorrowMut<H>,
|
HB: BorrowMut<H>,
|
||||||
@ -364,7 +364,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<H, HB, HT, I, OT, S, ES> HasInProcessHooks<I, S>
|
impl<H, HB, HT, I, OT, S, ES> HasInProcessHooks<I, S>
|
||||||
for StatefulGenericInProcessExecutor<H, HB, HT, I, OT, S, ES>
|
for StatefulGenericInProcessExecutor<ES, H, HB, HT, I, OT, S>
|
||||||
{
|
{
|
||||||
/// the timeout handler
|
/// the timeout handler
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -32,7 +32,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Inner state of GenericInProcessExecutor-like structures.
|
/// Inner state of GenericInProcessExecutor-like structures.
|
||||||
pub struct GenericInProcessForkExecutorInner<HT, I, OT, S, SP, EM, Z> {
|
pub struct GenericInProcessForkExecutorInner<EM, HT, I, OT, S, SP, Z> {
|
||||||
pub(super) hooks: (InChildProcessHooks<I, S>, HT),
|
pub(super) hooks: (InChildProcessHooks<I, S>, HT),
|
||||||
pub(super) shmem_provider: SP,
|
pub(super) shmem_provider: SP,
|
||||||
pub(super) observers: OT,
|
pub(super) observers: OT,
|
||||||
@ -40,10 +40,10 @@ pub struct GenericInProcessForkExecutorInner<HT, I, OT, S, SP, EM, Z> {
|
|||||||
pub(super) itimerspec: libc::itimerspec,
|
pub(super) itimerspec: libc::itimerspec,
|
||||||
#[cfg(all(unix, not(target_os = "linux")))]
|
#[cfg(all(unix, not(target_os = "linux")))]
|
||||||
pub(super) itimerval: Itimerval,
|
pub(super) itimerval: Itimerval,
|
||||||
pub(super) phantom: PhantomData<(I, S, EM, Z)>,
|
pub(super) phantom: PhantomData<(EM, I, S, Z)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<HT, I, OT, S, SP, EM, Z> Debug for GenericInProcessForkExecutorInner<HT, I, OT, S, SP, EM, Z>
|
impl<EM, HT, I, OT, S, SP, Z> Debug for GenericInProcessForkExecutorInner<EM, HT, I, OT, S, SP, Z>
|
||||||
where
|
where
|
||||||
HT: Debug,
|
HT: Debug,
|
||||||
OT: Debug,
|
OT: Debug,
|
||||||
@ -104,11 +104,11 @@ fn parse_itimerval(timeout: Duration) -> Itimerval {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EM, HT, I, OT, S, SP, Z> GenericInProcessForkExecutorInner<HT, I, OT, S, SP, EM, Z>
|
impl<EM, HT, I, OT, S, SP, Z> GenericInProcessForkExecutorInner<EM, HT, I, OT, S, SP, Z>
|
||||||
where
|
where
|
||||||
HT: ExecutorHooksTuple<I, S>,
|
HT: ExecutorHooksTuple<I, S>,
|
||||||
SP: ShMemProvider,
|
|
||||||
OT: ObserversTuple<I, S>,
|
OT: ObserversTuple<I, S>,
|
||||||
|
SP: ShMemProvider,
|
||||||
{
|
{
|
||||||
pub(super) unsafe fn pre_run_target_child(
|
pub(super) unsafe fn pre_run_target_child(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -195,7 +195,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<HT, I, OT, S, SP, EM, Z> GenericInProcessForkExecutorInner<HT, I, OT, S, SP, EM, Z>
|
impl<EM, HT, I, OT, S, SP, Z> GenericInProcessForkExecutorInner<EM, HT, I, OT, S, SP, Z>
|
||||||
where
|
where
|
||||||
HT: ExecutorHooksTuple<I, S>,
|
HT: ExecutorHooksTuple<I, S>,
|
||||||
OT: ObserversTuple<I, S>,
|
OT: ObserversTuple<I, S>,
|
||||||
@ -284,8 +284,8 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<HT, I, OT, S, SP, EM, Z> HasObservers
|
impl<EM, HT, I, OT, S, SP, Z> HasObservers
|
||||||
for GenericInProcessForkExecutorInner<HT, I, OT, S, SP, EM, Z>
|
for GenericInProcessForkExecutorInner<EM, HT, I, OT, S, SP, Z>
|
||||||
{
|
{
|
||||||
type Observers = OT;
|
type Observers = OT;
|
||||||
|
|
||||||
|
@ -39,10 +39,10 @@ pub mod stateful;
|
|||||||
///
|
///
|
||||||
/// On Linux, when fuzzing a Rust target, set `panic = "abort"` in your `Cargo.toml` (see [Cargo documentation](https://doc.rust-lang.org/cargo/reference/profiles.html#panic)).
|
/// On Linux, when fuzzing a Rust target, set `panic = "abort"` in your `Cargo.toml` (see [Cargo documentation](https://doc.rust-lang.org/cargo/reference/profiles.html#panic)).
|
||||||
/// Else panics can not be caught by `LibAFL`.
|
/// Else panics can not be caught by `LibAFL`.
|
||||||
pub type InProcessForkExecutor<'a, H, I, OT, S, SP, EM, Z> =
|
pub type InProcessForkExecutor<'a, EM, H, I, OT, S, SP, Z> =
|
||||||
GenericInProcessForkExecutor<'a, H, (), I, OT, S, SP, EM, Z>;
|
GenericInProcessForkExecutor<'a, EM, H, (), I, OT, S, SP, Z>;
|
||||||
|
|
||||||
impl<'a, H, I, OT, S, SP, EM, Z> InProcessForkExecutor<'a, H, I, OT, S, SP, EM, Z>
|
impl<'a, H, I, OT, S, SP, EM, Z> InProcessForkExecutor<'a, EM, H, I, OT, S, SP, Z>
|
||||||
where
|
where
|
||||||
OT: ObserversTuple<I, S>,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
@ -73,13 +73,13 @@ where
|
|||||||
///
|
///
|
||||||
/// On Linux, when fuzzing a Rust target, set `panic = "abort"` in your `Cargo.toml` (see [Cargo documentation](https://doc.rust-lang.org/cargo/reference/profiles.html#panic)).
|
/// On Linux, when fuzzing a Rust target, set `panic = "abort"` in your `Cargo.toml` (see [Cargo documentation](https://doc.rust-lang.org/cargo/reference/profiles.html#panic)).
|
||||||
/// Else panics can not be caught by `LibAFL`.
|
/// Else panics can not be caught by `LibAFL`.
|
||||||
pub struct GenericInProcessForkExecutor<'a, H, HT, I, OT, S, SP, EM, Z> {
|
pub struct GenericInProcessForkExecutor<'a, EM, H, HT, I, OT, S, SP, Z> {
|
||||||
harness_fn: &'a mut H,
|
harness_fn: &'a mut H,
|
||||||
inner: GenericInProcessForkExecutorInner<HT, I, OT, S, SP, EM, Z>,
|
inner: GenericInProcessForkExecutorInner<EM, HT, I, OT, S, SP, Z>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<H, HT, I, OT, S, SP, EM, Z> Debug
|
impl<H, HT, I, OT, S, SP, EM, Z> Debug
|
||||||
for GenericInProcessForkExecutor<'_, H, HT, I, OT, S, SP, EM, Z>
|
for GenericInProcessForkExecutor<'_, EM, H, HT, I, OT, S, SP, Z>
|
||||||
where
|
where
|
||||||
HT: Debug,
|
HT: Debug,
|
||||||
OT: Debug,
|
OT: Debug,
|
||||||
@ -103,13 +103,13 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<EM, H, HT, I, OT, S, SP, Z> Executor<EM, I, S, Z>
|
impl<EM, H, HT, I, OT, S, SP, Z> Executor<EM, I, S, Z>
|
||||||
for GenericInProcessForkExecutor<'_, H, HT, I, OT, S, SP, EM, Z>
|
for GenericInProcessForkExecutor<'_, EM, H, HT, I, OT, S, SP, Z>
|
||||||
where
|
where
|
||||||
H: FnMut(&I) -> ExitKind + Sized,
|
H: FnMut(&I) -> ExitKind + Sized,
|
||||||
S: HasExecutions,
|
|
||||||
SP: ShMemProvider,
|
|
||||||
HT: ExecutorHooksTuple<I, S>,
|
HT: ExecutorHooksTuple<I, S>,
|
||||||
OT: ObserversTuple<I, S>,
|
OT: ObserversTuple<I, S>,
|
||||||
|
S: HasExecutions,
|
||||||
|
SP: ShMemProvider,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn run_target(
|
fn run_target(
|
||||||
@ -141,7 +141,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, H, HT, I, OT, S, SP, EM, Z> GenericInProcessForkExecutor<'a, H, HT, I, OT, S, SP, EM, Z>
|
impl<'a, H, HT, I, OT, S, SP, EM, Z> GenericInProcessForkExecutor<'a, EM, H, HT, I, OT, S, SP, Z>
|
||||||
where
|
where
|
||||||
HT: ExecutorHooksTuple<I, S>,
|
HT: ExecutorHooksTuple<I, S>,
|
||||||
OT: ObserversTuple<I, S>,
|
OT: ObserversTuple<I, S>,
|
||||||
@ -187,7 +187,7 @@ where {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<H, HT, I, OT, S, SP, EM, Z> HasObservers
|
impl<H, HT, I, OT, S, SP, EM, Z> HasObservers
|
||||||
for GenericInProcessForkExecutor<'_, H, HT, I, OT, S, SP, EM, Z>
|
for GenericInProcessForkExecutor<'_, EM, H, HT, I, OT, S, SP, Z>
|
||||||
{
|
{
|
||||||
type Observers = OT;
|
type Observers = OT;
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
//! The harness can access internal state.
|
//! The harness can access internal state.
|
||||||
use core::{
|
use core::{
|
||||||
fmt::{self, Debug, Formatter},
|
fmt::{self, Debug, Formatter},
|
||||||
marker::PhantomData,
|
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -25,12 +24,13 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// The `StatefulInProcessForkExecutor` with no user hooks
|
/// The `StatefulInProcessForkExecutor` with no user hooks
|
||||||
pub type StatefulInProcessForkExecutor<'a, H, I, OT, S, SP, ES, EM, Z> =
|
pub type StatefulInProcessForkExecutor<'a, EM, ES, H, I, OT, S, SP, Z> =
|
||||||
StatefulGenericInProcessForkExecutor<'a, H, (), I, OT, S, SP, ES, EM, Z>;
|
StatefulGenericInProcessForkExecutor<'a, EM, ES, H, (), I, OT, S, SP, Z>;
|
||||||
|
|
||||||
impl<'a, H, I, OT, S, SP, ES, EM, Z> StatefulInProcessForkExecutor<'a, H, I, OT, S, SP, ES, EM, Z>
|
impl<'a, H, I, OT, S, SP, ES, EM, Z> StatefulInProcessForkExecutor<'a, EM, ES, H, I, OT, S, SP, Z>
|
||||||
where
|
where
|
||||||
OT: ObserversTuple<I, S>,
|
OT: ObserversTuple<I, S>,
|
||||||
|
SP: ShMemProvider,
|
||||||
{
|
{
|
||||||
#[expect(clippy::too_many_arguments)]
|
#[expect(clippy::too_many_arguments)]
|
||||||
/// The constructor for `InProcessForkExecutor`
|
/// The constructor for `InProcessForkExecutor`
|
||||||
@ -59,18 +59,17 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// [`StatefulGenericInProcessForkExecutor`] is an executor that forks the current process before each execution. Harness can access some internal state.
|
/// [`StatefulGenericInProcessForkExecutor`] is an executor that forks the current process before each execution. Harness can access some internal state.
|
||||||
pub struct StatefulGenericInProcessForkExecutor<'a, H, HT, I, OT, S, SP, ES, EM, Z> {
|
pub struct StatefulGenericInProcessForkExecutor<'a, EM, ES, H, HT, I, OT, S, SP, Z> {
|
||||||
/// The harness function, being executed for each fuzzing loop execution
|
/// The harness function, being executed for each fuzzing loop execution
|
||||||
harness_fn: &'a mut H,
|
harness_fn: &'a mut H,
|
||||||
/// The state used as argument of the harness
|
/// The state used as argument of the harness
|
||||||
pub exposed_executor_state: ES,
|
pub exposed_executor_state: ES,
|
||||||
/// Inner state of the executor
|
/// Inner state of the executor
|
||||||
pub inner: GenericInProcessForkExecutorInner<HT, I, OT, S, SP, EM, Z>,
|
pub inner: GenericInProcessForkExecutorInner<EM, HT, I, OT, S, SP, Z>,
|
||||||
phantom: PhantomData<ES>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<H, HT, I, OT, S, SP, ES, EM, Z> Debug
|
impl<H, HT, I, OT, S, SP, ES, EM, Z> Debug
|
||||||
for StatefulGenericInProcessForkExecutor<'_, H, HT, I, OT, S, SP, ES, EM, Z>
|
for StatefulGenericInProcessForkExecutor<'_, EM, ES, H, HT, I, OT, S, SP, Z>
|
||||||
where
|
where
|
||||||
HT: Debug,
|
HT: Debug,
|
||||||
OT: Debug,
|
OT: Debug,
|
||||||
@ -94,7 +93,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<EM, H, HT, I, OT, S, SP, Z, ES> Executor<EM, I, S, Z>
|
impl<EM, H, HT, I, OT, S, SP, Z, ES> Executor<EM, I, S, Z>
|
||||||
for StatefulGenericInProcessForkExecutor<'_, H, HT, I, OT, S, SP, ES, EM, Z>
|
for StatefulGenericInProcessForkExecutor<'_, EM, ES, H, HT, I, OT, S, SP, Z>
|
||||||
where
|
where
|
||||||
H: FnMut(&mut ES, &I) -> ExitKind + Sized,
|
H: FnMut(&mut ES, &I) -> ExitKind + Sized,
|
||||||
HT: ExecutorHooksTuple<I, S>,
|
HT: ExecutorHooksTuple<I, S>,
|
||||||
@ -133,7 +132,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, H, HT, I, OT, S, SP, ES, EM, Z>
|
impl<'a, H, HT, I, OT, S, SP, ES, EM, Z>
|
||||||
StatefulGenericInProcessForkExecutor<'a, H, HT, I, OT, S, SP, ES, EM, Z>
|
StatefulGenericInProcessForkExecutor<'a, EM, ES, H, HT, I, OT, S, SP, Z>
|
||||||
where
|
where
|
||||||
HT: ExecutorHooksTuple<I, S>,
|
HT: ExecutorHooksTuple<I, S>,
|
||||||
OT: ObserversTuple<I, S>,
|
OT: ObserversTuple<I, S>,
|
||||||
@ -163,7 +162,6 @@ where
|
|||||||
timeout,
|
timeout,
|
||||||
shmem_provider,
|
shmem_provider,
|
||||||
)?,
|
)?,
|
||||||
phantom: PhantomData,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,7 +179,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<H, HT, I, OT, S, SP, ES, EM, Z> HasObservers
|
impl<H, HT, I, OT, S, SP, ES, EM, Z> HasObservers
|
||||||
for StatefulGenericInProcessForkExecutor<'_, H, HT, I, OT, S, SP, ES, EM, Z>
|
for StatefulGenericInProcessForkExecutor<'_, EM, ES, H, HT, I, OT, S, SP, Z>
|
||||||
{
|
{
|
||||||
type Observers = OT;
|
type Observers = OT;
|
||||||
|
|
||||||
|
@ -219,7 +219,7 @@ impl<R: Read> MessageFileReader<R> {
|
|||||||
|
|
||||||
/// A `MessageFileWriter` writes a stream of [`SymExpr`] to any [`Write`]. For each written expression, it returns
|
/// A `MessageFileWriter` writes a stream of [`SymExpr`] to any [`Write`]. For each written expression, it returns
|
||||||
/// a [`SymExprRef`] which should be used to refer back to it.
|
/// a [`SymExprRef`] which should be used to refer back to it.
|
||||||
pub struct MessageFileWriter<W: Write> {
|
pub struct MessageFileWriter<W> {
|
||||||
id_counter: usize,
|
id_counter: usize,
|
||||||
writer: W,
|
writer: W,
|
||||||
writer_start_position: u64,
|
writer_start_position: u64,
|
||||||
@ -396,7 +396,7 @@ impl<W: Write + Seek> MessageFileWriter<W> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
use libafl_bolts::shmem::{ShMem, ShMemCursor, ShMemProvider, StdShMemProvider};
|
use libafl_bolts::shmem::{ShMem, ShMemCursor, ShMemProvider, StdShMem, StdShMemProvider};
|
||||||
|
|
||||||
/// The default environment variable name to use for the shared memory used by the concolic tracing
|
/// The default environment variable name to use for the shared memory used by the concolic tracing
|
||||||
pub const DEFAULT_ENV_NAME: &str = "SHARED_MEMORY_MESSAGES";
|
pub const DEFAULT_ENV_NAME: &str = "SHARED_MEMORY_MESSAGES";
|
||||||
@ -439,14 +439,17 @@ impl<'buffer> MessageFileReader<Cursor<&'buffer [u8]>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: ShMem> MessageFileWriter<ShMemCursor<T>> {
|
impl<SHM> MessageFileWriter<ShMemCursor<SHM>>
|
||||||
|
where
|
||||||
|
SHM: ShMem,
|
||||||
|
{
|
||||||
/// Creates a new `MessageFileWriter` from the given [`ShMemCursor`].
|
/// Creates a new `MessageFileWriter` from the given [`ShMemCursor`].
|
||||||
pub fn from_shmem(shmem: T) -> io::Result<Self> {
|
pub fn from_shmem(shmem: SHM) -> io::Result<Self> {
|
||||||
Self::from_writer(ShMemCursor::new(shmem))
|
Self::from_writer(ShMemCursor::new(shmem))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MessageFileWriter<ShMemCursor<<StdShMemProvider as ShMemProvider>::ShMem>> {
|
impl MessageFileWriter<ShMemCursor<StdShMem>> {
|
||||||
/// Creates a new `MessageFileWriter` by reading a [`ShMem`] from the given environment variable.
|
/// Creates a new `MessageFileWriter` by reading a [`ShMem`] from the given environment variable.
|
||||||
pub fn from_stdshmem_env_with_name(env_name: impl AsRef<str>) -> io::Result<Self> {
|
pub fn from_stdshmem_env_with_name(env_name: impl AsRef<str>) -> io::Result<Self> {
|
||||||
Self::from_shmem(
|
Self::from_shmem(
|
||||||
@ -464,8 +467,7 @@ impl MessageFileWriter<ShMemCursor<<StdShMemProvider as ShMemProvider>::ShMem>>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A writer that will write messages to a shared memory buffer.
|
/// A writer that will write messages to a shared memory buffer.
|
||||||
pub type StdShMemMessageFileWriter =
|
pub type StdShMemMessageFileWriter<SHM> = MessageFileWriter<ShMemCursor<SHM>>;
|
||||||
MessageFileWriter<ShMemCursor<<StdShMemProvider as ShMemProvider>::ShMem>>;
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod serialization_tests {
|
mod serialization_tests {
|
||||||
|
@ -7,7 +7,12 @@ use alloc::{
|
|||||||
use core::{marker::PhantomData, time::Duration};
|
use core::{marker::PhantomData, time::Duration};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use libafl_bolts::{current_time, fs::find_new_files_rec, shmem::ShMemProvider, Named};
|
use libafl_bolts::{
|
||||||
|
current_time,
|
||||||
|
fs::find_new_files_rec,
|
||||||
|
shmem::{ShMem, ShMemProvider},
|
||||||
|
Named,
|
||||||
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -219,14 +224,12 @@ impl SyncFromBrokerMetadata {
|
|||||||
|
|
||||||
/// A stage that loads testcases from disk to sync with other fuzzers such as AFL++
|
/// A stage that loads testcases from disk to sync with other fuzzers such as AFL++
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SyncFromBrokerStage<I, IC, ICB, S, SP>
|
pub struct SyncFromBrokerStage<I, IC, ICB, S, SHM, SP> {
|
||||||
where
|
client: LlmpEventConverter<I, IC, ICB, S, SHM, SP>,
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
|
||||||
client: LlmpEventConverter<I, IC, ICB, S, SP>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E, EM, I, IC, ICB, DI, S, SP, Z> Stage<E, EM, S, Z> for SyncFromBrokerStage<I, IC, ICB, S, SP>
|
impl<E, EM, I, IC, ICB, DI, S, SHM, SP, Z> Stage<E, EM, S, Z>
|
||||||
|
for SyncFromBrokerStage<I, IC, ICB, S, SHM, SP>
|
||||||
where
|
where
|
||||||
DI: Input,
|
DI: Input,
|
||||||
EM: EventFirer<I, S>,
|
EM: EventFirer<I, S>,
|
||||||
@ -242,7 +245,8 @@ where
|
|||||||
+ HasCurrentTestcase<I>
|
+ HasCurrentTestcase<I>
|
||||||
+ Stoppable
|
+ Stoppable
|
||||||
+ MaybeHasClientPerfMonitor,
|
+ MaybeHasClientPerfMonitor,
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
Z: EvaluatorObservers<E, EM, I, S> + ExecutionProcessor<EM, I, E::Observers, S>,
|
Z: EvaluatorObservers<E, EM, I, S> + ExecutionProcessor<EM, I, E::Observers, S>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -316,13 +320,10 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I, IC, ICB, S, SP> SyncFromBrokerStage<I, IC, ICB, S, SP>
|
impl<I, IC, ICB, S, SHM, SP> SyncFromBrokerStage<I, IC, ICB, S, SHM, SP> {
|
||||||
where
|
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
|
||||||
/// Creates a new [`SyncFromBrokerStage`]
|
/// Creates a new [`SyncFromBrokerStage`]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new(client: LlmpEventConverter<I, IC, ICB, S, SP>) -> Self {
|
pub fn new(client: LlmpEventConverter<I, IC, ICB, S, SHM, SP>) -> Self {
|
||||||
Self { client }
|
Self { client }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -113,13 +113,13 @@ impl<SP> Default for LlmpExampleHook<SP> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "std", not(target_os = "haiku")))]
|
#[cfg(all(feature = "std", not(target_os = "haiku")))]
|
||||||
impl<SP> LlmpHook<SP> for LlmpExampleHook<SP>
|
impl<SHM, SP> LlmpHook<SHM, SP> for LlmpExampleHook<SP>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider + 'static,
|
SP: ShMemProvider<ShMem = SHM> + 'static,
|
||||||
{
|
{
|
||||||
fn on_new_message(
|
fn on_new_message(
|
||||||
&mut self,
|
&mut self,
|
||||||
_broker_inner: &mut LlmpBrokerInner<SP>,
|
_broker_inner: &mut LlmpBrokerInner<SHM, SP>,
|
||||||
client_id: ClientId,
|
client_id: ClientId,
|
||||||
msg_tag: &mut Tag,
|
msg_tag: &mut Tag,
|
||||||
_msg_flags: &mut Flags,
|
_msg_flags: &mut Flags,
|
||||||
|
@ -251,6 +251,7 @@ mod linux {
|
|||||||
use super::CoreId;
|
use super::CoreId;
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
|
#[allow(trivial_numeric_casts)]
|
||||||
pub fn get_core_ids() -> Result<Vec<CoreId>, Error> {
|
pub fn get_core_ids() -> Result<Vec<CoreId>, Error> {
|
||||||
let full_set = get_affinity_mask()?;
|
let full_set = get_affinity_mask()?;
|
||||||
let mut core_ids: Vec<CoreId> = Vec::new();
|
let mut core_ids: Vec<CoreId> = Vec::new();
|
||||||
|
@ -707,25 +707,23 @@ impl LlmpMsg {
|
|||||||
|
|
||||||
/// An Llmp instance
|
/// An Llmp instance
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum LlmpConnection<HT, SP>
|
pub enum LlmpConnection<HT, SHM, SP> {
|
||||||
where
|
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
|
||||||
/// A broker and a thread using this tcp background thread
|
/// A broker and a thread using this tcp background thread
|
||||||
IsBroker {
|
IsBroker {
|
||||||
/// The [`LlmpBroker`] of this [`LlmpConnection`].
|
/// The [`LlmpBroker`] of this [`LlmpConnection`].
|
||||||
broker: LlmpBroker<HT, SP>,
|
broker: LlmpBroker<HT, SHM, SP>,
|
||||||
},
|
},
|
||||||
/// A client, connected to the port
|
/// A client, connected to the port
|
||||||
IsClient {
|
IsClient {
|
||||||
/// The [`LlmpClient`] of this [`LlmpConnection`].
|
/// The [`LlmpClient`] of this [`LlmpConnection`].
|
||||||
client: LlmpClient<SP>,
|
client: LlmpClient<SHM, SP>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<SP> LlmpConnection<(), SP>
|
impl<SHM, SP> LlmpConnection<(), SHM, SP>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
/// Creates either a broker, if the tcp port is not bound, or a client, connected to this port.
|
/// Creates either a broker, if the tcp port is not bound, or a client, connected to this port.
|
||||||
@ -776,10 +774,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<MT, SP> LlmpConnection<MT, SP>
|
impl<MT, SHM, SP> LlmpConnection<MT, SHM, SP>
|
||||||
where
|
where
|
||||||
MT: LlmpHookTuple<SP>,
|
MT: LlmpHookTuple<SHM, SP>,
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
/// Describe this in a reproducible fashion, if it's a client
|
/// Describe this in a reproducible fashion, if it's a client
|
||||||
pub fn describe(&self) -> Result<LlmpClientDescription, Error> {
|
pub fn describe(&self) -> Result<LlmpClientDescription, Error> {
|
||||||
@ -793,7 +792,7 @@ where
|
|||||||
pub fn existing_client_from_description(
|
pub fn existing_client_from_description(
|
||||||
shmem_provider: SP,
|
shmem_provider: SP,
|
||||||
description: &LlmpClientDescription,
|
description: &LlmpClientDescription,
|
||||||
) -> Result<LlmpConnection<MT, SP>, Error> {
|
) -> Result<LlmpConnection<MT, SHM, SP>, Error> {
|
||||||
Ok(LlmpConnection::IsClient {
|
Ok(LlmpConnection::IsClient {
|
||||||
client: LlmpClient::existing_client_from_description(shmem_provider, description)?,
|
client: LlmpClient::existing_client_from_description(shmem_provider, description)?,
|
||||||
})
|
})
|
||||||
@ -891,23 +890,20 @@ struct LlmpClientExitInfo {
|
|||||||
|
|
||||||
/// Sending end on a (unidirectional) sharedmap channel
|
/// Sending end on a (unidirectional) sharedmap channel
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct LlmpSender<SP>
|
pub struct LlmpSender<SHM, SP> {
|
||||||
where
|
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
|
||||||
/// ID of this sender.
|
/// ID of this sender.
|
||||||
id: ClientId,
|
id: ClientId,
|
||||||
/// Ref to the last message this sender sent on the last page.
|
/// Ref to the last message this sender sent on the last page.
|
||||||
/// If null, a new page (just) started.
|
/// If null, a new page (just) started.
|
||||||
last_msg_sent: *const LlmpMsg,
|
last_msg_sent: *const LlmpMsg,
|
||||||
/// A vec of page wrappers, each containing an initialized [`ShMem`]
|
/// A vec of page wrappers, each containing an initialized [`ShMem`]
|
||||||
out_shmems: Vec<LlmpSharedMap<SP::ShMem>>,
|
out_shmems: Vec<LlmpSharedMap<SHM>>,
|
||||||
/// A vec of pages that we previously used, but that have served its purpose
|
/// A vec of pages that we previously used, but that have served its purpose
|
||||||
/// (no potential receivers are left).
|
/// (no potential receivers are left).
|
||||||
/// Instead of freeing them, we keep them around to potentially reuse them later,
|
/// Instead of freeing them, we keep them around to potentially reuse them later,
|
||||||
/// if they are still large enough.
|
/// if they are still large enough.
|
||||||
/// This way, the OS doesn't have to spend time zeroing pages, and getting rid of our old pages
|
/// This way, the OS doesn't have to spend time zeroing pages, and getting rid of our old pages
|
||||||
unused_shmem_cache: Vec<LlmpSharedMap<SP::ShMem>>,
|
unused_shmem_cache: Vec<LlmpSharedMap<SHM>>,
|
||||||
/// If true, pages will never be pruned.
|
/// If true, pages will never be pruned.
|
||||||
/// The broker uses this feature.
|
/// The broker uses this feature.
|
||||||
/// By keeping the message history around,
|
/// By keeping the message history around,
|
||||||
@ -920,9 +916,10 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// An actor on the sending part of the shared map
|
/// An actor on the sending part of the shared map
|
||||||
impl<SP> LlmpSender<SP>
|
impl<SHM, SP> LlmpSender<SHM, SP>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
/// Create a new [`LlmpSender`] using a given [`ShMemProvider`], and `id`.
|
/// Create a new [`LlmpSender`] using a given [`ShMemProvider`], and `id`.
|
||||||
/// If `keep_pages_forever` is `true`, `ShMem` will never be freed.
|
/// If `keep_pages_forever` is `true`, `ShMem` will never be freed.
|
||||||
@ -1068,7 +1065,7 @@ where
|
|||||||
/// else reattach will get a new, empty page, from the OS, or fail.
|
/// else reattach will get a new, empty page, from the OS, or fail.
|
||||||
pub fn on_existing_shmem(
|
pub fn on_existing_shmem(
|
||||||
shmem_provider: SP,
|
shmem_provider: SP,
|
||||||
current_out_shmem: SP::ShMem,
|
current_out_shmem: SHM,
|
||||||
last_msg_sent_offset: Option<u64>,
|
last_msg_sent_offset: Option<u64>,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
let mut out_shmem = LlmpSharedMap::existing(current_out_shmem);
|
let mut out_shmem = LlmpSharedMap::existing(current_out_shmem);
|
||||||
@ -1307,7 +1304,7 @@ where
|
|||||||
&mut self,
|
&mut self,
|
||||||
sender_id: ClientId,
|
sender_id: ClientId,
|
||||||
next_min_shmem_size: usize,
|
next_min_shmem_size: usize,
|
||||||
) -> Result<LlmpSharedMap<<SP>::ShMem>, Error> {
|
) -> Result<LlmpSharedMap<SHM>, Error> {
|
||||||
// Find a shared map that has been released to reuse, from which all receivers left / finished reading.
|
// Find a shared map that has been released to reuse, from which all receivers left / finished reading.
|
||||||
let cached_shmem = self
|
let cached_shmem = self
|
||||||
.unused_shmem_cache
|
.unused_shmem_cache
|
||||||
@ -1586,10 +1583,7 @@ where
|
|||||||
|
|
||||||
/// Receiving end on a (unidirectional) sharedmap channel
|
/// Receiving end on a (unidirectional) sharedmap channel
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct LlmpReceiver<SP>
|
pub struct LlmpReceiver<SHM, SP> {
|
||||||
where
|
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
|
||||||
/// Client Id of this receiver
|
/// Client Id of this receiver
|
||||||
id: ClientId,
|
id: ClientId,
|
||||||
/// Pointer to the last message received
|
/// Pointer to the last message received
|
||||||
@ -1600,15 +1594,16 @@ where
|
|||||||
/// The shmem provider
|
/// The shmem provider
|
||||||
shmem_provider: SP,
|
shmem_provider: SP,
|
||||||
/// current page. After EOP, this gets replaced with the new one
|
/// current page. After EOP, this gets replaced with the new one
|
||||||
current_recv_shmem: LlmpSharedMap<SP::ShMem>,
|
current_recv_shmem: LlmpSharedMap<SHM>,
|
||||||
/// Caches the highest msg id we've seen so far
|
/// Caches the highest msg id we've seen so far
|
||||||
highest_msg_id: MessageId,
|
highest_msg_id: MessageId,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Receiving end of an llmp channel
|
/// Receiving end of an llmp channel
|
||||||
impl<SP> LlmpReceiver<SP>
|
impl<SHM, SP> LlmpReceiver<SHM, SP>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
/// Reattach to a vacant `recv_shmem`, to with a previous sender stored the information in an env before.
|
/// Reattach to a vacant `recv_shmem`, to with a previous sender stored the information in an env before.
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
@ -1634,7 +1629,7 @@ where
|
|||||||
/// else reattach will get a new, empty page, from the OS, or fail.
|
/// else reattach will get a new, empty page, from the OS, or fail.
|
||||||
pub fn on_existing_shmem(
|
pub fn on_existing_shmem(
|
||||||
shmem_provider: SP,
|
shmem_provider: SP,
|
||||||
current_sender_shmem: SP::ShMem,
|
current_sender_shmem: SHM,
|
||||||
last_msg_recvd_offset: Option<u64>,
|
last_msg_recvd_offset: Option<u64>,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
let mut current_recv_shmem = LlmpSharedMap::existing(current_sender_shmem);
|
let mut current_recv_shmem = LlmpSharedMap::existing(current_sender_shmem);
|
||||||
@ -1897,10 +1892,7 @@ where
|
|||||||
|
|
||||||
/// A page wrapper
|
/// A page wrapper
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct LlmpSharedMap<SHM>
|
pub struct LlmpSharedMap<SHM> {
|
||||||
where
|
|
||||||
SHM: ShMem,
|
|
||||||
{
|
|
||||||
/// Shmem containg the actual (unsafe) page,
|
/// Shmem containg the actual (unsafe) page,
|
||||||
/// shared between one `LlmpSender` and one `LlmpReceiver`
|
/// shared between one `LlmpSender` and one `LlmpReceiver`
|
||||||
shmem: SHM,
|
shmem: SHM,
|
||||||
@ -2050,18 +2042,15 @@ where
|
|||||||
|
|
||||||
/// The inner state of [`LlmpBroker`]
|
/// The inner state of [`LlmpBroker`]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct LlmpBrokerInner<SP>
|
pub struct LlmpBrokerInner<SHM, SP> {
|
||||||
where
|
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
|
||||||
/// Broadcast map from broker to all clients
|
/// Broadcast map from broker to all clients
|
||||||
llmp_out: LlmpSender<SP>,
|
llmp_out: LlmpSender<SHM, SP>,
|
||||||
/// Users of Llmp can add message handlers in the broker.
|
/// Users of Llmp can add message handlers in the broker.
|
||||||
/// This allows us to intercept messages right in the broker.
|
/// This allows us to intercept messages right in the broker.
|
||||||
/// This keeps the out map clean.
|
/// This keeps the out map clean.
|
||||||
/// The backing values of `llmp_clients` [`ClientId`]s will always be sorted (but not gapless)
|
/// The backing values of `llmp_clients` [`ClientId`]s will always be sorted (but not gapless)
|
||||||
/// Make sure to always increase `num_clients_seen` when pushing a new [`LlmpReceiver`] to `llmp_clients`!
|
/// Make sure to always increase `num_clients_seen` when pushing a new [`LlmpReceiver`] to `llmp_clients`!
|
||||||
llmp_clients: Vec<LlmpReceiver<SP>>,
|
llmp_clients: Vec<LlmpReceiver<SHM, SP>>,
|
||||||
/// The own listeners we spawned via `launch_listener` or `crate_attach_to_tcp`.
|
/// The own listeners we spawned via `launch_listener` or `crate_attach_to_tcp`.
|
||||||
/// Listeners will be ignored for `exit_cleanly_after` and they are never considered to have timed out.
|
/// Listeners will be ignored for `exit_cleanly_after` and they are never considered to have timed out.
|
||||||
listeners: Vec<ClientId>,
|
listeners: Vec<ClientId>,
|
||||||
@ -2078,12 +2067,9 @@ where
|
|||||||
|
|
||||||
/// The broker (node 0)
|
/// The broker (node 0)
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct LlmpBroker<HT, SP>
|
pub struct LlmpBroker<HT, SHM, SP> {
|
||||||
where
|
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
|
||||||
/// The broker
|
/// The broker
|
||||||
inner: LlmpBrokerInner<SP>,
|
inner: LlmpBrokerInner<SHM, SP>,
|
||||||
/// Llmp hooks
|
/// Llmp hooks
|
||||||
hooks: HT,
|
hooks: HT,
|
||||||
}
|
}
|
||||||
@ -2118,10 +2104,11 @@ pub trait Broker {
|
|||||||
fn nb_listeners(&self) -> usize;
|
fn nb_listeners(&self) -> usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<HT, SP> Broker for LlmpBroker<HT, SP>
|
impl<HT, SHM, SP> Broker for LlmpBroker<HT, SHM, SP>
|
||||||
where
|
where
|
||||||
HT: LlmpHookTuple<SP>,
|
HT: LlmpHookTuple<SHM, SP>,
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
fn is_shutting_down(&self) -> bool {
|
fn is_shutting_down(&self) -> bool {
|
||||||
self.inner.is_shutting_down()
|
self.inner.is_shutting_down()
|
||||||
@ -2215,15 +2202,12 @@ impl CtrlHandler for LlmpShutdownSignalHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Llmp hooks
|
/// Llmp hooks
|
||||||
pub trait LlmpHook<SP>
|
pub trait LlmpHook<SHM, SP> {
|
||||||
where
|
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
|
||||||
/// Hook called whenever a new message is received. It receives an llmp message as input, does
|
/// Hook called whenever a new message is received. It receives an llmp message as input, does
|
||||||
/// something with it (read, transform, forward, etc...) and decides to discard it or not.
|
/// something with it (read, transform, forward, etc...) and decides to discard it or not.
|
||||||
fn on_new_message(
|
fn on_new_message(
|
||||||
&mut self,
|
&mut self,
|
||||||
broker_inner: &mut LlmpBrokerInner<SP>,
|
broker_inner: &mut LlmpBrokerInner<SHM, SP>,
|
||||||
client_id: ClientId,
|
client_id: ClientId,
|
||||||
msg_tag: &mut Tag,
|
msg_tag: &mut Tag,
|
||||||
msg_flags: &mut Flags,
|
msg_flags: &mut Flags,
|
||||||
@ -2238,14 +2222,11 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A tuple of Llmp hooks. They are evaluated sequentially, and returns if one decides to filter out the evaluated message.
|
/// A tuple of Llmp hooks. They are evaluated sequentially, and returns if one decides to filter out the evaluated message.
|
||||||
pub trait LlmpHookTuple<SP>
|
pub trait LlmpHookTuple<SHM, SP> {
|
||||||
where
|
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
|
||||||
/// Call all hook callbacks on new message.
|
/// Call all hook callbacks on new message.
|
||||||
fn on_new_message_all(
|
fn on_new_message_all(
|
||||||
&mut self,
|
&mut self,
|
||||||
inner: &mut LlmpBrokerInner<SP>,
|
inner: &mut LlmpBrokerInner<SHM, SP>,
|
||||||
client_id: ClientId,
|
client_id: ClientId,
|
||||||
msg_tag: &mut Tag,
|
msg_tag: &mut Tag,
|
||||||
msg_flags: &mut Flags,
|
msg_flags: &mut Flags,
|
||||||
@ -2257,13 +2238,10 @@ where
|
|||||||
fn on_timeout_all(&mut self) -> Result<(), Error>;
|
fn on_timeout_all(&mut self) -> Result<(), Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<SP> LlmpHookTuple<SP> for ()
|
impl<SHM, SP> LlmpHookTuple<SHM, SP> for () {
|
||||||
where
|
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
|
||||||
fn on_new_message_all(
|
fn on_new_message_all(
|
||||||
&mut self,
|
&mut self,
|
||||||
_inner: &mut LlmpBrokerInner<SP>,
|
_inner: &mut LlmpBrokerInner<SHM, SP>,
|
||||||
_client_id: ClientId,
|
_client_id: ClientId,
|
||||||
_msg_tag: &mut Tag,
|
_msg_tag: &mut Tag,
|
||||||
_msg_flags: &mut Flags,
|
_msg_flags: &mut Flags,
|
||||||
@ -2278,15 +2256,14 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Head, Tail, SP> LlmpHookTuple<SP> for (Head, Tail)
|
impl<Head, Tail, SHM, SP> LlmpHookTuple<SHM, SP> for (Head, Tail)
|
||||||
where
|
where
|
||||||
Head: LlmpHook<SP>,
|
Head: LlmpHook<SHM, SP>,
|
||||||
Tail: LlmpHookTuple<SP>,
|
Tail: LlmpHookTuple<SHM, SP>,
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
{
|
||||||
fn on_new_message_all(
|
fn on_new_message_all(
|
||||||
&mut self,
|
&mut self,
|
||||||
inner: &mut LlmpBrokerInner<SP>,
|
inner: &mut LlmpBrokerInner<SHM, SP>,
|
||||||
client_id: ClientId,
|
client_id: ClientId,
|
||||||
msg_tag: &mut Tag,
|
msg_tag: &mut Tag,
|
||||||
msg_flags: &mut Flags,
|
msg_flags: &mut Flags,
|
||||||
@ -2315,15 +2292,12 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<SP> LlmpBroker<(), SP>
|
impl<SHM, SP> LlmpBroker<(), SHM, SP> {
|
||||||
where
|
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
|
||||||
/// Add hooks to a hookless [`LlmpBroker`].
|
/// Add hooks to a hookless [`LlmpBroker`].
|
||||||
/// We do not support replacing hooks for now.
|
/// We do not support replacing hooks for now.
|
||||||
pub fn add_hooks<HT>(self, hooks: HT) -> LlmpBroker<HT, SP>
|
pub fn add_hooks<HT>(self, hooks: HT) -> LlmpBroker<HT, SHM, SP>
|
||||||
where
|
where
|
||||||
HT: LlmpHookTuple<SP>,
|
HT: LlmpHookTuple<SHM, SP>,
|
||||||
{
|
{
|
||||||
LlmpBroker {
|
LlmpBroker {
|
||||||
inner: self.inner,
|
inner: self.inner,
|
||||||
@ -2446,10 +2420,11 @@ impl Brokers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<HT, SP> LlmpBroker<HT, SP>
|
impl<HT, SHM, SP> LlmpBroker<HT, SHM, SP>
|
||||||
where
|
where
|
||||||
HT: LlmpHookTuple<SP>,
|
HT: LlmpHookTuple<SHM, SP>,
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
/// Create and initialize a new [`LlmpBroker`], associated with some hooks.
|
/// Create and initialize a new [`LlmpBroker`], associated with some hooks.
|
||||||
pub fn new(shmem_provider: SP, hooks: HT) -> Result<Self, Error> {
|
pub fn new(shmem_provider: SP, hooks: HT) -> Result<Self, Error> {
|
||||||
@ -2496,12 +2471,12 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the inner state of the broker
|
/// Get the inner state of the broker
|
||||||
pub fn inner(&self) -> &LlmpBrokerInner<SP> {
|
pub fn inner(&self) -> &LlmpBrokerInner<SHM, SP> {
|
||||||
&self.inner
|
&self.inner
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the inner mutable state of the broker
|
/// Get the inner mutable state of the broker
|
||||||
pub fn inner_mut(&mut self) -> &mut LlmpBrokerInner<SP> {
|
pub fn inner_mut(&mut self) -> &mut LlmpBrokerInner<SHM, SP> {
|
||||||
&mut self.inner
|
&mut self.inner
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2829,9 +2804,10 @@ where
|
|||||||
|
|
||||||
/// The broker forwards all messages to its own bus-like broadcast map.
|
/// The broker forwards all messages to its own bus-like broadcast map.
|
||||||
/// It may intercept messages passing through.
|
/// It may intercept messages passing through.
|
||||||
impl<SP> LlmpBrokerInner<SP>
|
impl<SHM, SP> LlmpBrokerInner<SHM, SP>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
/// Create and initialize a new [`LlmpBrokerInner`], associated with some hooks.
|
/// Create and initialize a new [`LlmpBrokerInner`], associated with some hooks.
|
||||||
pub fn new(shmem_provider: SP) -> Result<Self, Error> {
|
pub fn new(shmem_provider: SP) -> Result<Self, Error> {
|
||||||
@ -2917,7 +2893,7 @@ where
|
|||||||
/// Will increase `num_clients_seen`.
|
/// Will increase `num_clients_seen`.
|
||||||
/// The backing values of `llmp_clients` [`ClientId`]s will always be sorted (but not gapless)
|
/// The backing values of `llmp_clients` [`ClientId`]s will always be sorted (but not gapless)
|
||||||
/// returns the [`ClientId`] of the new client.
|
/// returns the [`ClientId`] of the new client.
|
||||||
pub fn add_client(&mut self, mut client_receiver: LlmpReceiver<SP>) -> ClientId {
|
pub fn add_client(&mut self, mut client_receiver: LlmpReceiver<SHM, SP>) -> ClientId {
|
||||||
let id = self.peek_next_client_id();
|
let id = self.peek_next_client_id();
|
||||||
client_receiver.id = id;
|
client_receiver.id = id;
|
||||||
self.llmp_clients.push(client_receiver);
|
self.llmp_clients.push(client_receiver);
|
||||||
@ -2932,7 +2908,7 @@ where
|
|||||||
|
|
||||||
/// Registers a new client for the given sharedmap str and size.
|
/// Registers a new client for the given sharedmap str and size.
|
||||||
/// Returns the id of the new client in [`broker.client_shmem`]
|
/// Returns the id of the new client in [`broker.client_shmem`]
|
||||||
pub fn register_client(&mut self, mut client_page: LlmpSharedMap<SP::ShMem>) -> ClientId {
|
pub fn register_client(&mut self, mut client_page: LlmpSharedMap<SHM>) -> ClientId {
|
||||||
// Tell the client it may unmap its initial allocated shmem page now.
|
// Tell the client it may unmap its initial allocated shmem page now.
|
||||||
// Since we now have a handle to it, it won't be umapped too early (only after we also unmap it)
|
// Since we now have a handle to it, it won't be umapped too early (only after we also unmap it)
|
||||||
client_page.mark_safe_to_unmap();
|
client_page.mark_safe_to_unmap();
|
||||||
@ -3090,7 +3066,7 @@ where
|
|||||||
/// Upon receiving this message, the broker should map the announced page and start tracking it for new messages.
|
/// Upon receiving this message, the broker should map the announced page and start tracking it for new messages.
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
fn announce_new_client(
|
fn announce_new_client(
|
||||||
sender: &mut LlmpSender<SP>,
|
sender: &mut LlmpSender<SHM, SP>,
|
||||||
shmem_description: &ShMemDescription,
|
shmem_description: &ShMemDescription,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -3108,7 +3084,7 @@ where
|
|||||||
|
|
||||||
/// Tell the broker to disconnect this client from it.
|
/// Tell the broker to disconnect this client from it.
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
fn announce_client_exit(sender: &mut LlmpSender<SP>, client_id: u32) -> Result<(), Error> {
|
fn announce_client_exit(sender: &mut LlmpSender<SHM, SP>, client_id: u32) -> Result<(), Error> {
|
||||||
// # Safety
|
// # Safety
|
||||||
// No user-provided potentially unsafe parameters.
|
// No user-provided potentially unsafe parameters.
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -3280,7 +3256,7 @@ where
|
|||||||
mut stream: TcpStream,
|
mut stream: TcpStream,
|
||||||
request: &TcpRequest,
|
request: &TcpRequest,
|
||||||
current_client_id: &mut ClientId,
|
current_client_id: &mut ClientId,
|
||||||
sender: &mut LlmpSender<SP>,
|
sender: &mut LlmpSender<SHM, SP>,
|
||||||
broker_shmem_description: &ShMemDescription,
|
broker_shmem_description: &ShMemDescription,
|
||||||
) {
|
) {
|
||||||
match request {
|
match request {
|
||||||
@ -3451,21 +3427,19 @@ pub struct LlmpClientDescription {
|
|||||||
|
|
||||||
/// Client side of LLMP
|
/// Client side of LLMP
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct LlmpClient<SP>
|
pub struct LlmpClient<SHM, SP> {
|
||||||
where
|
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
|
||||||
/// Outgoing channel to the broker
|
/// Outgoing channel to the broker
|
||||||
sender: LlmpSender<SP>,
|
sender: LlmpSender<SHM, SP>,
|
||||||
/// Incoming (broker) broadcast map
|
/// Incoming (broker) broadcast map
|
||||||
receiver: LlmpReceiver<SP>,
|
receiver: LlmpReceiver<SHM, SP>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `n` clients connect to a broker. They share an outgoing map with the broker,
|
/// `n` clients connect to a broker. They share an outgoing map with the broker,
|
||||||
/// and get incoming messages from the shared broker bus
|
/// and get incoming messages from the shared broker bus
|
||||||
impl<SP> LlmpClient<SP>
|
impl<SHM, SP> LlmpClient<SHM, SP>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
/// Reattach to a vacant client map.
|
/// Reattach to a vacant client map.
|
||||||
/// It is essential, that the broker (or someone else) kept a pointer to the `out_shmem`
|
/// It is essential, that the broker (or someone else) kept a pointer to the `out_shmem`
|
||||||
@ -3473,9 +3447,9 @@ where
|
|||||||
#[allow(clippy::needless_pass_by_value)] // no longer necessary on nightly
|
#[allow(clippy::needless_pass_by_value)] // no longer necessary on nightly
|
||||||
pub fn on_existing_shmem(
|
pub fn on_existing_shmem(
|
||||||
shmem_provider: SP,
|
shmem_provider: SP,
|
||||||
_current_out_shmem: SP::ShMem,
|
_current_out_shmem: SHM,
|
||||||
_last_msg_sent_offset: Option<u64>,
|
_last_msg_sent_offset: Option<u64>,
|
||||||
current_broker_shmem: SP::ShMem,
|
current_broker_shmem: SHM,
|
||||||
last_msg_recvd_offset: Option<u64>,
|
last_msg_recvd_offset: Option<u64>,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
@ -3542,25 +3516,25 @@ where
|
|||||||
|
|
||||||
/// Outgoing channel to the broker
|
/// Outgoing channel to the broker
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn sender(&self) -> &LlmpSender<SP> {
|
pub fn sender(&self) -> &LlmpSender<SHM, SP> {
|
||||||
&self.sender
|
&self.sender
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Outgoing channel to the broker (mut)
|
/// Outgoing channel to the broker (mut)
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn sender_mut(&mut self) -> &mut LlmpSender<SP> {
|
pub fn sender_mut(&mut self) -> &mut LlmpSender<SHM, SP> {
|
||||||
&mut self.sender
|
&mut self.sender
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Incoming (broker) broadcast map
|
/// Incoming (broker) broadcast map
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn receiver(&self) -> &LlmpReceiver<SP> {
|
pub fn receiver(&self) -> &LlmpReceiver<SHM, SP> {
|
||||||
&self.receiver
|
&self.receiver
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Incoming (broker) broadcast map (mut)
|
/// Incoming (broker) broadcast map (mut)
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn receiver_mut(&mut self) -> &mut LlmpReceiver<SP> {
|
pub fn receiver_mut(&mut self) -> &mut LlmpReceiver<SHM, SP> {
|
||||||
&mut self.receiver
|
&mut self.receiver
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3588,7 +3562,7 @@ where
|
|||||||
/// Creates a new [`LlmpClient`]
|
/// Creates a new [`LlmpClient`]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
mut shmem_provider: SP,
|
mut shmem_provider: SP,
|
||||||
initial_broker_shmem: LlmpSharedMap<SP::ShMem>,
|
initial_broker_shmem: LlmpSharedMap<SHM>,
|
||||||
sender_id: ClientId,
|
sender_id: ClientId,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
@ -11,6 +11,7 @@ use alloc::{
|
|||||||
vec::Vec,
|
vec::Vec,
|
||||||
};
|
};
|
||||||
use core::{
|
use core::{
|
||||||
|
fmt::Debug,
|
||||||
mem::ManuallyDrop,
|
mem::ManuallyDrop,
|
||||||
ops::{Deref, DerefMut},
|
ops::{Deref, DerefMut},
|
||||||
};
|
};
|
||||||
@ -60,10 +61,7 @@ const AFL_SHMEM_SERVICE_STARTED: &str = "AFL_SHMEM_SERVICE_STARTED";
|
|||||||
|
|
||||||
/// s out served shared maps, as used on Android.
|
/// s out served shared maps, as used on Android.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ServedShMemProvider<SP>
|
pub struct ServedShMemProvider<SP> {
|
||||||
where
|
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
|
||||||
stream: UnixStream,
|
stream: UnixStream,
|
||||||
inner: SP,
|
inner: SP,
|
||||||
id: i32,
|
id: i32,
|
||||||
@ -76,17 +74,14 @@ where
|
|||||||
/// [`ShMem`] that got served from a [`ShMemService`] via domain sockets and can now be used in this program.
|
/// [`ShMem`] that got served from a [`ShMemService`] via domain sockets and can now be used in this program.
|
||||||
/// It works around Android's lack of "proper" shared maps.
|
/// It works around Android's lack of "proper" shared maps.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct ServedShMem<SH>
|
pub struct ServedShMem<SHM> {
|
||||||
where
|
inner: ManuallyDrop<SHM>,
|
||||||
SH: ShMem,
|
|
||||||
{
|
|
||||||
inner: ManuallyDrop<SH>,
|
|
||||||
server_fd: i32,
|
server_fd: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<SH> Deref for ServedShMem<SH>
|
impl<SHM> Deref for ServedShMem<SHM>
|
||||||
where
|
where
|
||||||
SH: ShMem,
|
SHM: Deref<Target = [u8]>,
|
||||||
{
|
{
|
||||||
type Target = [u8];
|
type Target = [u8];
|
||||||
|
|
||||||
@ -95,18 +90,18 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<SH> DerefMut for ServedShMem<SH>
|
impl<SHM> DerefMut for ServedShMem<SHM>
|
||||||
where
|
where
|
||||||
SH: ShMem,
|
SHM: DerefMut<Target = [u8]>,
|
||||||
{
|
{
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
&mut self.inner
|
&mut self.inner
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<SH> ShMem for ServedShMem<SH>
|
impl<SHM> ShMem for ServedShMem<SHM>
|
||||||
where
|
where
|
||||||
SH: ShMem,
|
SHM: ShMem,
|
||||||
{
|
{
|
||||||
fn id(&self) -> ShMemId {
|
fn id(&self) -> ShMemId {
|
||||||
let client_id = self.inner.id();
|
let client_id = self.inner.id();
|
||||||
@ -114,10 +109,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<SP> ServedShMemProvider<SP>
|
impl<SP> ServedShMemProvider<SP> {
|
||||||
where
|
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
|
||||||
/// Send a request to the server, and wait for a response
|
/// Send a request to the server, and wait for a response
|
||||||
#[expect(clippy::similar_names)] // id and fd
|
#[expect(clippy::similar_names)] // id and fd
|
||||||
fn send_receive(&mut self, request: ServedShMemRequest) -> Result<(i32, i32), Error> {
|
fn send_receive(&mut self, request: ServedShMemRequest) -> Result<(i32, i32), Error> {
|
||||||
@ -290,18 +282,12 @@ pub enum ServedShMemRequest {
|
|||||||
|
|
||||||
/// Client side communicating with the [`ShMemServer`]
|
/// Client side communicating with the [`ShMemServer`]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct SharedShMemClient<SH>
|
struct SharedShMemClient<SHM> {
|
||||||
where
|
|
||||||
SH: ShMem,
|
|
||||||
{
|
|
||||||
stream: UnixStream,
|
stream: UnixStream,
|
||||||
maps: HashMap<i32, Vec<Rc<RefCell<SH>>>>,
|
maps: HashMap<i32, Vec<Rc<RefCell<SHM>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<SH> SharedShMemClient<SH>
|
impl<SHM> SharedShMemClient<SHM> {
|
||||||
where
|
|
||||||
SH: ShMem,
|
|
||||||
{
|
|
||||||
fn new(stream: UnixStream) -> Self {
|
fn new(stream: UnixStream) -> Self {
|
||||||
Self {
|
Self {
|
||||||
stream,
|
stream,
|
||||||
@ -312,11 +298,8 @@ where
|
|||||||
|
|
||||||
/// Response from Server to Client
|
/// Response from Server to Client
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum ServedShMemResponse<SP>
|
enum ServedShMemResponse<SHM> {
|
||||||
where
|
Mapping(Rc<RefCell<SHM>>),
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
|
||||||
Mapping(Rc<RefCell<SP::ShMem>>),
|
|
||||||
Id(i32),
|
Id(i32),
|
||||||
RefCount(u32),
|
RefCount(u32),
|
||||||
}
|
}
|
||||||
@ -332,22 +315,19 @@ enum ShMemServiceStatus {
|
|||||||
/// The [`ShMemService`] is a service handing out [`ShMem`] pages via unix domain sockets.
|
/// The [`ShMemService`] is a service handing out [`ShMem`] pages via unix domain sockets.
|
||||||
/// It is mainly used and needed on Android.
|
/// It is mainly used and needed on Android.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum ShMemService<SP>
|
pub enum ShMemService<SP> {
|
||||||
where
|
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
|
||||||
/// A started service
|
/// A started service
|
||||||
Started {
|
Started {
|
||||||
/// The background thread
|
/// The background thread
|
||||||
bg_thread: Arc<Mutex<ShMemServiceThread>>,
|
bg_thread: Arc<Mutex<ShMemServiceThread>>,
|
||||||
/// The pantom data
|
/// The phantom data
|
||||||
phantom: PhantomData<SP>,
|
phantom: PhantomData<SP>,
|
||||||
},
|
},
|
||||||
/// A failed service
|
/// A failed service
|
||||||
Failed {
|
Failed {
|
||||||
/// The error message
|
/// The error message
|
||||||
err_msg: String,
|
err_msg: String,
|
||||||
/// The pantom data
|
/// The phantom data
|
||||||
phantom: PhantomData<SP>,
|
phantom: PhantomData<SP>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -412,7 +392,7 @@ where
|
|||||||
let syncpair = Arc::new((Mutex::new(ShMemServiceStatus::Starting), Condvar::new()));
|
let syncpair = Arc::new((Mutex::new(ShMemServiceStatus::Starting), Condvar::new()));
|
||||||
let childsyncpair = Arc::clone(&syncpair);
|
let childsyncpair = Arc::clone(&syncpair);
|
||||||
let join_handle = thread::spawn(move || {
|
let join_handle = thread::spawn(move || {
|
||||||
let mut worker = match ServedShMemServiceWorker::<SP>::new() {
|
let mut worker = match ServedShMemServiceWorker::<SP::ShMem, SP>::new() {
|
||||||
Ok(worker) => worker,
|
Ok(worker) => worker,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
// Make sure the parent processes can continue
|
// Make sure the parent processes can continue
|
||||||
@ -472,20 +452,18 @@ where
|
|||||||
|
|
||||||
/// The struct for the worker, handling incoming requests for [`ShMem`].
|
/// The struct for the worker, handling incoming requests for [`ShMem`].
|
||||||
#[expect(clippy::type_complexity)]
|
#[expect(clippy::type_complexity)]
|
||||||
struct ServedShMemServiceWorker<SP>
|
struct ServedShMemServiceWorker<SHM, SP> {
|
||||||
where
|
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
|
||||||
provider: SP,
|
provider: SP,
|
||||||
clients: HashMap<RawFd, SharedShMemClient<SP::ShMem>>,
|
clients: HashMap<RawFd, SharedShMemClient<SHM>>,
|
||||||
/// Maps from a pre-fork (parent) client id to its cloned maps.
|
/// Maps from a pre-fork (parent) client id to its cloned maps.
|
||||||
forking_clients: HashMap<RawFd, HashMap<i32, Vec<Rc<RefCell<SP::ShMem>>>>>,
|
forking_clients: HashMap<RawFd, HashMap<i32, Vec<Rc<RefCell<SHM>>>>>,
|
||||||
all_shmems: HashMap<i32, Weak<RefCell<SP::ShMem>>>,
|
all_shmems: HashMap<i32, Weak<RefCell<SHM>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<SP> ServedShMemServiceWorker<SP>
|
impl<SHM, SP> ServedShMemServiceWorker<SHM, SP>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
/// Create a new [`ShMemService`]
|
/// Create a new [`ShMemService`]
|
||||||
fn new() -> Result<Self, Error> {
|
fn new() -> Result<Self, Error> {
|
||||||
@ -497,7 +475,7 @@ where
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn upgrade_shmem_with_id(&mut self, description_id: i32) -> Rc<RefCell<SP::ShMem>> {
|
fn upgrade_shmem_with_id(&mut self, description_id: i32) -> Rc<RefCell<SHM>> {
|
||||||
self.all_shmems
|
self.all_shmems
|
||||||
.get_mut(&description_id)
|
.get_mut(&description_id)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@ -507,7 +485,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Read and handle the client request, send the answer over unix fd.
|
/// Read and handle the client request, send the answer over unix fd.
|
||||||
fn handle_request(&mut self, client_id: RawFd) -> Result<ServedShMemResponse<SP>, Error> {
|
fn handle_request(&mut self, client_id: RawFd) -> Result<ServedShMemResponse<SHM>, Error> {
|
||||||
let request = self.read_request(client_id)?;
|
let request = self.read_request(client_id)?;
|
||||||
|
|
||||||
// log::trace!("got ashmem client: {}, request:{:?}", client_id, request);
|
// log::trace!("got ashmem client: {}, request:{:?}", client_id, request);
|
||||||
|
@ -190,7 +190,7 @@ where
|
|||||||
/// # Safety
|
/// # Safety
|
||||||
/// The shared memory needs to start with a valid object of type `T`.
|
/// The shared memory needs to start with a valid object of type `T`.
|
||||||
/// Any use of this [`OwnedRef`] will dereference a pointer to the shared memory accordingly.
|
/// Any use of this [`OwnedRef`] will dereference a pointer to the shared memory accordingly.
|
||||||
pub unsafe fn from_shmem<S: ShMem>(shmem: &mut S) -> Self {
|
pub unsafe fn from_shmem<SHM: ShMem>(shmem: &mut SHM) -> Self {
|
||||||
Self::from_ptr(shmem.as_mut_ptr_of().unwrap())
|
Self::from_ptr(shmem.as_mut_ptr_of().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -325,7 +325,7 @@ where
|
|||||||
/// # Safety
|
/// # Safety
|
||||||
/// The shared memory needs to start with a valid object of type `T`.
|
/// The shared memory needs to start with a valid object of type `T`.
|
||||||
/// Any use of this [`OwnedRefMut`] will dereference a pointer to the shared memory accordingly.
|
/// Any use of this [`OwnedRefMut`] will dereference a pointer to the shared memory accordingly.
|
||||||
pub unsafe fn from_shmem<S: ShMem>(shmem: &mut S) -> Self {
|
pub unsafe fn from_shmem<SHM: ShMem>(shmem: &mut SHM) -> Self {
|
||||||
Self::from_mut_ptr(shmem.as_mut_ptr_of().unwrap())
|
Self::from_mut_ptr(shmem.as_mut_ptr_of().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,25 +32,50 @@ pub use win32_shmem::{Win32ShMem, Win32ShMemProvider};
|
|||||||
#[cfg(all(unix, feature = "std", not(target_os = "haiku")))]
|
#[cfg(all(unix, feature = "std", not(target_os = "haiku")))]
|
||||||
use crate::os::pipes::Pipe;
|
use crate::os::pipes::Pipe;
|
||||||
#[cfg(all(feature = "std", unix, not(target_os = "haiku")))]
|
#[cfg(all(feature = "std", unix, not(target_os = "haiku")))]
|
||||||
pub use crate::os::unix_shmem_server::{ServedShMemProvider, ShMemService};
|
pub use crate::os::unix_shmem_server::{ServedShMem, ServedShMemProvider, ShMemService};
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
/// The standard sharedmem provider
|
/// The standard sharedmem provider
|
||||||
#[cfg(all(windows, feature = "std"))]
|
#[cfg(all(windows, feature = "std"))]
|
||||||
pub type StdShMemProvider = Win32ShMemProvider;
|
pub type StdShMemProvider = Win32ShMemProvider;
|
||||||
|
/// The standard sharedmem
|
||||||
|
#[cfg(all(windows, feature = "std"))]
|
||||||
|
pub type StdShMem = Win32ShMem;
|
||||||
|
|
||||||
|
/// The standard sharedmem
|
||||||
|
#[cfg(all(target_os = "android", feature = "std"))]
|
||||||
|
pub type StdShMem = RcShMem<
|
||||||
|
ServedShMem<unix_shmem::ashmem::AshmemShMem>,
|
||||||
|
ServedShMemProvider<unix_shmem::ashmem::AshmemShMemProvider>,
|
||||||
|
>;
|
||||||
|
|
||||||
/// The standard sharedmem provider
|
/// The standard sharedmem provider
|
||||||
#[cfg(all(target_os = "android", feature = "std"))]
|
#[cfg(all(target_os = "android", feature = "std"))]
|
||||||
pub type StdShMemProvider =
|
pub type StdShMemProvider =
|
||||||
RcShMemProvider<ServedShMemProvider<unix_shmem::ashmem::AshmemShMemProvider>>;
|
RcShMemProvider<ServedShMemProvider<unix_shmem::ashmem::AshmemShMemProvider>>;
|
||||||
|
|
||||||
/// The standard sharedmem service
|
/// The standard sharedmem service
|
||||||
#[cfg(all(target_os = "android", feature = "std"))]
|
#[cfg(all(target_os = "android", feature = "std"))]
|
||||||
pub type StdShMemService = ShMemService<unix_shmem::ashmem::AshmemShMemProvider>;
|
pub type StdShMemService = ShMemService<unix_shmem::ashmem::AshmemShMemProvider>;
|
||||||
|
|
||||||
|
/// The standard sharedmem
|
||||||
|
#[cfg(all(feature = "std", target_vendor = "apple"))]
|
||||||
|
pub type StdShMem = RcShMem<ServedShMem<MmapShMem>, ServedShMemProvider<MmapShMemProvider>>;
|
||||||
|
|
||||||
/// The standard sharedmem provider
|
/// The standard sharedmem provider
|
||||||
#[cfg(all(feature = "std", target_vendor = "apple"))]
|
#[cfg(all(feature = "std", target_vendor = "apple"))]
|
||||||
pub type StdShMemProvider = RcShMemProvider<ServedShMemProvider<MmapShMemProvider>>;
|
pub type StdShMemProvider = RcShMemProvider<ServedShMemProvider<MmapShMemProvider>>;
|
||||||
#[cfg(all(feature = "std", target_vendor = "apple"))]
|
#[cfg(all(feature = "std", target_vendor = "apple"))]
|
||||||
/// The standard sharedmem service
|
/// The standard sharedmem service
|
||||||
pub type StdShMemService = ShMemService<MmapShMemProvider>;
|
pub type StdShMemService = ShMemService<MmapShMemProvider>;
|
||||||
|
|
||||||
|
/// The default [`ShMem`].
|
||||||
|
#[cfg(all(
|
||||||
|
feature = "std",
|
||||||
|
unix,
|
||||||
|
not(any(target_os = "android", target_vendor = "apple", target_os = "haiku"))
|
||||||
|
))]
|
||||||
|
pub type StdShMem = UnixShMem;
|
||||||
/// The default [`ShMemProvider`] for this os.
|
/// The default [`ShMemProvider`] for this os.
|
||||||
#[cfg(all(
|
#[cfg(all(
|
||||||
feature = "std",
|
feature = "std",
|
||||||
@ -392,15 +417,19 @@ impl Deref for NopShMem {
|
|||||||
/// Useful if the `ShMemProvider` needs to keep local state.
|
/// Useful if the `ShMemProvider` needs to keep local state.
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub struct RcShMem<T: ShMemProvider> {
|
pub struct RcShMem<SHM, SP>
|
||||||
internal: ManuallyDrop<T::ShMem>,
|
where
|
||||||
provider: Rc<RefCell<T>>,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
|
{
|
||||||
|
internal: ManuallyDrop<SHM>,
|
||||||
|
provider: Rc<RefCell<SP>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
impl<T> ShMem for RcShMem<T>
|
impl<SP> ShMem for RcShMem<SP::ShMem, SP>
|
||||||
where
|
where
|
||||||
T: ShMemProvider + Debug,
|
SP: ShMemProvider,
|
||||||
{
|
{
|
||||||
fn id(&self) -> ShMemId {
|
fn id(&self) -> ShMemId {
|
||||||
self.internal.id()
|
self.internal.id()
|
||||||
@ -408,9 +437,10 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
impl<T> Deref for RcShMem<T>
|
impl<SHM, SP> Deref for RcShMem<SHM, SP>
|
||||||
where
|
where
|
||||||
T: ShMemProvider + Debug,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
type Target = [u8];
|
type Target = [u8];
|
||||||
|
|
||||||
@ -420,9 +450,10 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
impl<T> DerefMut for RcShMem<T>
|
impl<SHM, SP> DerefMut for RcShMem<SHM, SP>
|
||||||
where
|
where
|
||||||
T: ShMemProvider + Debug,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
fn deref_mut(&mut self) -> &mut [u8] {
|
fn deref_mut(&mut self) -> &mut [u8] {
|
||||||
&mut self.internal
|
&mut self.internal
|
||||||
@ -430,7 +461,11 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
impl<T: ShMemProvider> Drop for RcShMem<T> {
|
impl<SHM, SP> Drop for RcShMem<SHM, SP>
|
||||||
|
where
|
||||||
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
|
{
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
self.provider.borrow_mut().release_shmem(&mut self.internal);
|
self.provider.borrow_mut().release_shmem(&mut self.internal);
|
||||||
}
|
}
|
||||||
@ -441,10 +476,7 @@ impl<T: ShMemProvider> Drop for RcShMem<T> {
|
|||||||
/// Useful if the `ShMemProvider` needs to keep local state.
|
/// Useful if the `ShMemProvider` needs to keep local state.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
#[cfg(all(unix, feature = "std", not(target_os = "haiku")))]
|
#[cfg(all(unix, feature = "std", not(target_os = "haiku")))]
|
||||||
pub struct RcShMemProvider<SP>
|
pub struct RcShMemProvider<SP> {
|
||||||
where
|
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
|
||||||
/// The wrapped [`ShMemProvider`].
|
/// The wrapped [`ShMemProvider`].
|
||||||
internal: Rc<RefCell<SP>>,
|
internal: Rc<RefCell<SP>>,
|
||||||
/// A pipe the child uses to communicate progress to the parent after fork.
|
/// A pipe the child uses to communicate progress to the parent after fork.
|
||||||
@ -457,15 +489,12 @@ where
|
|||||||
parent_child_pipe: Option<Pipe>,
|
parent_child_pipe: Option<Pipe>,
|
||||||
}
|
}
|
||||||
|
|
||||||
//#[cfg(all(unix, feature = "std"))]
|
|
||||||
//unsafe impl<SP: ShMemProvider> Send for RcShMemProvider<SP> {}
|
|
||||||
|
|
||||||
#[cfg(all(unix, feature = "std", not(target_os = "haiku")))]
|
#[cfg(all(unix, feature = "std", not(target_os = "haiku")))]
|
||||||
impl<SP> ShMemProvider for RcShMemProvider<SP>
|
impl<SP> ShMemProvider for RcShMemProvider<SP>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider + Debug,
|
SP: ShMemProvider + Debug,
|
||||||
{
|
{
|
||||||
type ShMem = RcShMem<SP>;
|
type ShMem = RcShMem<SP::ShMem, SP>;
|
||||||
|
|
||||||
fn new() -> Result<Self, Error> {
|
fn new() -> Result<Self, Error> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
@ -535,10 +564,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(unix, feature = "std", not(target_os = "haiku")))]
|
#[cfg(all(unix, feature = "std", not(target_os = "haiku")))]
|
||||||
impl<SP> RcShMemProvider<SP>
|
impl<SP> RcShMemProvider<SP> {
|
||||||
where
|
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
|
||||||
/// "set" the "latch"
|
/// "set" the "latch"
|
||||||
/// (we abuse `pipes` as `semaphores`, as they don't need an additional shared mem region.)
|
/// (we abuse `pipes` as `semaphores`, as they don't need an additional shared mem region.)
|
||||||
fn pipe_set(pipe: &mut Option<Pipe>) -> Result<(), Error> {
|
fn pipe_set(pipe: &mut Option<Pipe>) -> Result<(), Error> {
|
||||||
@ -599,7 +625,7 @@ where
|
|||||||
#[cfg(all(unix, feature = "std", not(target_os = "haiku")))]
|
#[cfg(all(unix, feature = "std", not(target_os = "haiku")))]
|
||||||
impl<SP> Default for RcShMemProvider<SP>
|
impl<SP> Default for RcShMemProvider<SP>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider + Debug,
|
SP: ShMemProvider,
|
||||||
{
|
{
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::new().unwrap()
|
Self::new().unwrap()
|
||||||
@ -607,10 +633,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(unix, feature = "std", not(target_os = "haiku")))]
|
#[cfg(all(unix, feature = "std", not(target_os = "haiku")))]
|
||||||
impl<SP> RcShMemProvider<ServedShMemProvider<SP>>
|
impl<SP> RcShMemProvider<ServedShMemProvider<SP>> {
|
||||||
where
|
|
||||||
SP: ShMemProvider + Debug,
|
|
||||||
{
|
|
||||||
/// Forward to `ServedShMemProvider::on_restart`
|
/// Forward to `ServedShMemProvider::on_restart`
|
||||||
pub fn on_restart(&mut self) {
|
pub fn on_restart(&mut self) {
|
||||||
self.internal.borrow_mut().on_restart();
|
self.internal.borrow_mut().on_restart();
|
||||||
@ -1010,16 +1033,15 @@ pub mod unix_shmem {
|
|||||||
|
|
||||||
impl CommonUnixShMem {
|
impl CommonUnixShMem {
|
||||||
/// Create a new shared memory mapping, using shmget/shmat
|
/// Create a new shared memory mapping, using shmget/shmat
|
||||||
#[expect(unused_qualifications)]
|
|
||||||
pub fn new(map_size: usize) -> Result<Self, Error> {
|
pub fn new(map_size: usize) -> Result<Self, Error> {
|
||||||
#[cfg(any(target_os = "solaris", target_os = "illumos"))]
|
#[cfg(any(target_os = "solaris", target_os = "illumos"))]
|
||||||
const SHM_R: libc::c_int = 0o400;
|
const SHM_R: c_int = 0o400;
|
||||||
#[cfg(not(any(target_os = "solaris", target_os = "illumos")))]
|
#[cfg(not(any(target_os = "solaris", target_os = "illumos")))]
|
||||||
const SHM_R: libc::c_int = libc::SHM_R;
|
const SHM_R: c_int = libc::SHM_R;
|
||||||
#[cfg(any(target_os = "solaris", target_os = "illumos"))]
|
#[cfg(any(target_os = "solaris", target_os = "illumos"))]
|
||||||
const SHM_W: libc::c_int = 0o200;
|
const SHM_W: c_int = 0o200;
|
||||||
#[cfg(not(any(target_os = "solaris", target_os = "illumos")))]
|
#[cfg(not(any(target_os = "solaris", target_os = "illumos")))]
|
||||||
const SHM_W: libc::c_int = libc::SHM_W;
|
const SHM_W: c_int = libc::SHM_W;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let os_id = shmget(
|
let os_id = shmget(
|
||||||
@ -1206,7 +1228,7 @@ pub mod unix_shmem {
|
|||||||
//return Err(Error::unknown("Failed to set the ashmem mapping's name".to_string()));
|
//return Err(Error::unknown("Failed to set the ashmem mapping's name".to_string()));
|
||||||
//};
|
//};
|
||||||
|
|
||||||
#[expect(trivial_numeric_casts)]
|
#[allow(trivial_numeric_casts)]
|
||||||
if ioctl(fd, ASHMEM_SET_SIZE as _, map_size) != 0 {
|
if ioctl(fd, ASHMEM_SET_SIZE as _, map_size) != 0 {
|
||||||
close(fd);
|
close(fd);
|
||||||
return Err(Error::unknown(
|
return Err(Error::unknown(
|
||||||
@ -1241,7 +1263,8 @@ pub mod unix_shmem {
|
|||||||
pub fn shmem_from_id_and_size(id: ShMemId, map_size: usize) -> Result<Self, Error> {
|
pub fn shmem_from_id_and_size(id: ShMemId, map_size: usize) -> Result<Self, Error> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let fd: i32 = id.to_string().parse().unwrap();
|
let fd: i32 = id.to_string().parse().unwrap();
|
||||||
#[expect(trivial_numeric_casts, clippy::cast_sign_loss)]
|
#[allow(trivial_numeric_casts)]
|
||||||
|
#[expect(clippy::cast_sign_loss)]
|
||||||
if ioctl(fd, ASHMEM_GET_SIZE as _) as u32 as usize != map_size {
|
if ioctl(fd, ASHMEM_GET_SIZE as _) as u32 as usize != map_size {
|
||||||
return Err(Error::unknown(
|
return Err(Error::unknown(
|
||||||
"The mapping's size differs from the requested size".to_string(),
|
"The mapping's size differs from the requested size".to_string(),
|
||||||
@ -1294,12 +1317,12 @@ pub mod unix_shmem {
|
|||||||
|
|
||||||
/// [`Drop`] implementation for [`AshmemShMem`], which cleans up the mapping.
|
/// [`Drop`] implementation for [`AshmemShMem`], which cleans up the mapping.
|
||||||
impl Drop for AshmemShMem {
|
impl Drop for AshmemShMem {
|
||||||
#[expect(trivial_numeric_casts)]
|
#[allow(trivial_numeric_casts)]
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let fd: i32 = self.id.to_string().parse().unwrap();
|
let fd: i32 = self.id.to_string().parse().unwrap();
|
||||||
|
|
||||||
#[expect(trivial_numeric_casts)]
|
#[allow(trivial_numeric_casts)]
|
||||||
#[expect(clippy::cast_sign_loss)]
|
#[expect(clippy::cast_sign_loss)]
|
||||||
let length = ioctl(fd, ASHMEM_GET_SIZE as _) as u32;
|
let length = ioctl(fd, ASHMEM_GET_SIZE as _) as u32;
|
||||||
|
|
||||||
@ -1729,15 +1752,15 @@ impl DummyShMemService {
|
|||||||
/// A cursor around [`ShMem`] that immitates [`std::io::Cursor`]. Notably, this implements [`Write`] for [`ShMem`] in std environments.
|
/// A cursor around [`ShMem`] that immitates [`std::io::Cursor`]. Notably, this implements [`Write`] for [`ShMem`] in std environments.
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ShMemCursor<T: ShMem> {
|
pub struct ShMemCursor<SHM> {
|
||||||
inner: T,
|
inner: SHM,
|
||||||
pos: usize,
|
pos: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "std", not(target_os = "haiku")))]
|
#[cfg(all(feature = "std", not(target_os = "haiku")))]
|
||||||
impl<T: ShMem> ShMemCursor<T> {
|
impl<SHM> ShMemCursor<SHM> {
|
||||||
/// Create a new [`ShMemCursor`] around [`ShMem`]
|
/// Create a new [`ShMemCursor`] around [`ShMem`]
|
||||||
pub fn new(shmem: T) -> Self {
|
pub fn new(shmem: SHM) -> Self {
|
||||||
Self {
|
Self {
|
||||||
inner: shmem,
|
inner: shmem,
|
||||||
pos: 0,
|
pos: 0,
|
||||||
@ -1745,14 +1768,20 @@ impl<T: ShMem> ShMemCursor<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Slice from the current location on this map to the end, mutable
|
/// Slice from the current location on this map to the end, mutable
|
||||||
fn empty_slice_mut(&mut self) -> &mut [u8] {
|
fn empty_slice_mut(&mut self) -> &mut [u8]
|
||||||
|
where
|
||||||
|
SHM: DerefMut<Target = [u8]>,
|
||||||
|
{
|
||||||
use crate::AsSliceMut;
|
use crate::AsSliceMut;
|
||||||
&mut (self.inner.as_slice_mut()[self.pos..])
|
&mut (self.inner.as_slice_mut()[self.pos..])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "std", not(target_os = "haiku")))]
|
#[cfg(all(feature = "std", not(target_os = "haiku")))]
|
||||||
impl<T: ShMem> Write for ShMemCursor<T> {
|
impl<SHM> Write for ShMemCursor<SHM>
|
||||||
|
where
|
||||||
|
SHM: DerefMut<Target = [u8]>,
|
||||||
|
{
|
||||||
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
|
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
|
||||||
match self.empty_slice_mut().write(buf) {
|
match self.empty_slice_mut().write(buf) {
|
||||||
Ok(w) => {
|
Ok(w) => {
|
||||||
@ -1763,10 +1792,6 @@ impl<T: ShMem> Write for ShMemCursor<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flush(&mut self) -> std::io::Result<()> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_vectored(&mut self, bufs: &[std::io::IoSlice<'_>]) -> std::io::Result<usize> {
|
fn write_vectored(&mut self, bufs: &[std::io::IoSlice<'_>]) -> std::io::Result<usize> {
|
||||||
match self.empty_slice_mut().write_vectored(bufs) {
|
match self.empty_slice_mut().write_vectored(bufs) {
|
||||||
Ok(w) => {
|
Ok(w) => {
|
||||||
@ -1777,6 +1802,10 @@ impl<T: ShMem> Write for ShMemCursor<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn flush(&mut self) -> std::io::Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()> {
|
fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()> {
|
||||||
match self.empty_slice_mut().write_all(buf) {
|
match self.empty_slice_mut().write_all(buf) {
|
||||||
Ok(w) => {
|
Ok(w) => {
|
||||||
@ -1789,7 +1818,10 @@ impl<T: ShMem> Write for ShMemCursor<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
impl<T: ShMem> std::io::Seek for ShMemCursor<T> {
|
impl<SHM> std::io::Seek for ShMemCursor<SHM>
|
||||||
|
where
|
||||||
|
SHM: DerefMut<Target = [u8]>,
|
||||||
|
{
|
||||||
fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> {
|
fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> {
|
||||||
let effective_new_pos = match pos {
|
let effective_new_pos = match pos {
|
||||||
std::io::SeekFrom::Start(s) => s,
|
std::io::SeekFrom::Start(s) => s,
|
||||||
|
@ -65,17 +65,15 @@ impl StateShMemContent {
|
|||||||
/// it will instead write to disk, and store the file name into the map.
|
/// it will instead write to disk, and store the file name into the map.
|
||||||
/// Writing to [`StateRestorer`] multiple times is not allowed.
|
/// Writing to [`StateRestorer`] multiple times is not allowed.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct StateRestorer<SP>
|
pub struct StateRestorer<SHM, SP> {
|
||||||
where
|
shmem: SHM,
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
|
||||||
shmem: SP::ShMem,
|
|
||||||
phantom: PhantomData<*const SP>,
|
phantom: PhantomData<*const SP>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<SP> StateRestorer<SP>
|
impl<SHM, SP> StateRestorer<SHM, SP>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
|
SP: ShMemProvider<ShMem = SHM>,
|
||||||
{
|
{
|
||||||
/// Get the map size backing this [`StateRestorer`].
|
/// Get the map size backing this [`StateRestorer`].
|
||||||
pub fn mapsize(&self) -> usize {
|
pub fn mapsize(&self) -> usize {
|
||||||
@ -96,7 +94,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new [`StateRestorer`].
|
/// Create a new [`StateRestorer`].
|
||||||
pub fn new(shmem: SP::ShMem) -> Self {
|
pub fn new(shmem: SHM) -> Self {
|
||||||
let mut ret = Self {
|
let mut ret = Self {
|
||||||
shmem,
|
shmem,
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
@ -268,7 +266,7 @@ where
|
|||||||
File::open(tmpfile)?.read_to_end(&mut file_content)?;
|
File::open(tmpfile)?.read_to_end(&mut file_content)?;
|
||||||
if file_content.is_empty() {
|
if file_content.is_empty() {
|
||||||
return Err(Error::illegal_state(format!(
|
return Err(Error::illegal_state(format!(
|
||||||
"Colud not restore state from file {}",
|
"Could not restore state from file {}",
|
||||||
&filename
|
&filename
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
@ -296,7 +294,7 @@ mod tests {
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
shmem::{ShMemProvider, StdShMemProvider},
|
shmem::{ShMemProvider, StdShMem, StdShMemProvider},
|
||||||
staterestore::StateRestorer,
|
staterestore::StateRestorer,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -304,7 +302,7 @@ mod tests {
|
|||||||
|
|
||||||
let mut shmem_provider = StdShMemProvider::new().unwrap();
|
let mut shmem_provider = StdShMemProvider::new().unwrap();
|
||||||
let shmem = shmem_provider.new_shmem(TESTMAP_SIZE).unwrap();
|
let shmem = shmem_provider.new_shmem(TESTMAP_SIZE).unwrap();
|
||||||
let mut state_restorer = StateRestorer::<StdShMemProvider>::new(shmem);
|
let mut state_restorer = StateRestorer::<StdShMem, StdShMemProvider>::new(shmem);
|
||||||
|
|
||||||
let state = "hello world".to_string();
|
let state = "hello world".to_string();
|
||||||
|
|
||||||
|
@ -46,6 +46,7 @@ pub mod cpp_runtime {
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub use ctor::ctor;
|
pub use ctor::ctor;
|
||||||
use libafl::observers::concolic;
|
use libafl::observers::concolic;
|
||||||
|
pub use libafl_bolts::shmem::StdShMem;
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub use libc::atexit;
|
pub use libc::atexit;
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
@ -2,23 +2,30 @@
|
|||||||
|
|
||||||
pub use libafl::observers::concolic::serialization_format::StdShMemMessageFileWriter;
|
pub use libafl::observers::concolic::serialization_format::StdShMemMessageFileWriter;
|
||||||
use libafl::observers::concolic::SymExpr;
|
use libafl::observers::concolic::SymExpr;
|
||||||
|
use libafl_bolts::shmem::ShMem;
|
||||||
|
|
||||||
use crate::{RSymExpr, Runtime};
|
use crate::{RSymExpr, Runtime};
|
||||||
|
|
||||||
/// Traces the expressions according to the format described in [`libafl::observers::concolic::serialization_format`].
|
/// Traces the expressions according to the format described in [`libafl::observers::concolic::serialization_format`].
|
||||||
///
|
///
|
||||||
/// The format can be read from elsewhere to perform processing of the expressions outside of the runtime.
|
/// The format can be read from elsewhere to perform processing of the expressions outside of the runtime.
|
||||||
pub struct TracingRuntime {
|
pub struct TracingRuntime<SHM>
|
||||||
writer: StdShMemMessageFileWriter,
|
where
|
||||||
|
SHM: ShMem,
|
||||||
|
{
|
||||||
|
writer: StdShMemMessageFileWriter<SHM>,
|
||||||
trace_locations: bool,
|
trace_locations: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TracingRuntime {
|
impl<SHM> TracingRuntime<SHM>
|
||||||
|
where
|
||||||
|
SHM: ShMem,
|
||||||
|
{
|
||||||
/// Creates the runtime, tracing using the given writer.
|
/// Creates the runtime, tracing using the given writer.
|
||||||
/// When `trace_locations` is true, location information for calls, returns and basic blocks will also be part of the trace.
|
/// When `trace_locations` is true, location information for calls, returns and basic blocks will also be part of the trace.
|
||||||
/// Tracing location information can drastically increase trace size. It is therefore recommended to not active this if not needed.
|
/// Tracing location information can drastically increase trace size. It is therefore recommended to not active this if not needed.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new(writer: StdShMemMessageFileWriter, trace_locations: bool) -> Self {
|
pub fn new(writer: StdShMemMessageFileWriter<SHM>, trace_locations: bool) -> Self {
|
||||||
Self {
|
Self {
|
||||||
writer,
|
writer,
|
||||||
trace_locations,
|
trace_locations,
|
||||||
@ -62,7 +69,10 @@ macro_rules! binary_expression_builder {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Runtime for TracingRuntime {
|
impl<SHM> Runtime for TracingRuntime<SHM>
|
||||||
|
where
|
||||||
|
SHM: ShMem,
|
||||||
|
{
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
fn build_integer_from_buffer(
|
fn build_integer_from_buffer(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -201,7 +211,10 @@ impl Runtime for TracingRuntime {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for TracingRuntime {
|
impl<SHM> Drop for TracingRuntime<SHM>
|
||||||
|
where
|
||||||
|
SHM: ShMem,
|
||||||
|
{
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
// manually end the writer to update the length prefix
|
// manually end the writer to update the length prefix
|
||||||
self.writer
|
self.writer
|
||||||
|
@ -7,9 +7,11 @@ use symcc_runtime::{
|
|||||||
export_runtime,
|
export_runtime,
|
||||||
filter::NoFloat,
|
filter::NoFloat,
|
||||||
tracing::{self, StdShMemMessageFileWriter},
|
tracing::{self, StdShMemMessageFileWriter},
|
||||||
Runtime,
|
Runtime, StdShMem,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// use libafl_bolts::StdShmem;
|
||||||
|
|
||||||
export_runtime!(
|
export_runtime!(
|
||||||
NoFloat => NoFloat;
|
NoFloat => NoFloat;
|
||||||
tracing::TracingRuntime::new(
|
tracing::TracingRuntime::new(
|
||||||
@ -17,5 +19,5 @@ export_runtime!(
|
|||||||
.expect("unable to construct tracing runtime writer. (missing env?)"),
|
.expect("unable to construct tracing runtime writer. (missing env?)"),
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
=> tracing::TracingRuntime
|
=> tracing::TracingRuntime<StdShMem>
|
||||||
);
|
);
|
||||||
|
@ -111,7 +111,7 @@ where
|
|||||||
fuzz_with!(options, harness, do_fuzz, |fuzz_single| {
|
fuzz_with!(options, harness, do_fuzz, |fuzz_single| {
|
||||||
let (state, mgr): (
|
let (state, mgr): (
|
||||||
Option<StdState<_, _, _, _>>,
|
Option<StdState<_, _, _, _>>,
|
||||||
SimpleRestartingEventManager<_, _, StdState<_, _, _, _>, _>,
|
SimpleRestartingEventManager<_, _, StdState<_, _, _, _>, _, _>,
|
||||||
) = match SimpleRestartingEventManager::launch(monitor, &mut shmem_provider) {
|
) = match SimpleRestartingEventManager::launch(monitor, &mut shmem_provider) {
|
||||||
// The restarting state will spawn the same process again as child, then restarted it each time it crashes.
|
// The restarting state will spawn the same process again as child, then restarted it each time it crashes.
|
||||||
Ok(res) => res,
|
Ok(res) => res,
|
||||||
|
@ -69,7 +69,7 @@ pub fn merge(
|
|||||||
|
|
||||||
let (state, mut mgr): (
|
let (state, mut mgr): (
|
||||||
Option<StdState<_, _, _, _>>,
|
Option<StdState<_, _, _, _>>,
|
||||||
SimpleRestartingEventManager<_, _, StdState<_, _, _, _>, _>,
|
SimpleRestartingEventManager<_, _, StdState<_, _, _, _>, _, _>,
|
||||||
) = match SimpleRestartingEventManager::launch(monitor, &mut shmem_provider) {
|
) = match SimpleRestartingEventManager::launch(monitor, &mut shmem_provider) {
|
||||||
// The restarting state will spawn the same process again as child, then restarted it each time it crashes.
|
// The restarting state will spawn the same process again as child, then restarted it each time it crashes.
|
||||||
Ok(res) => res,
|
Ok(res) => res,
|
||||||
|
@ -43,7 +43,7 @@ use crate::Qemu;
|
|||||||
use crate::{command::CommandManager, modules::EmulatorModuleTuple, Emulator, EmulatorDriver};
|
use crate::{command::CommandManager, modules::EmulatorModuleTuple, Emulator, EmulatorDriver};
|
||||||
|
|
||||||
type EmulatorInProcessExecutor<'a, C, CM, ED, ET, H, I, OT, S, SM> =
|
type EmulatorInProcessExecutor<'a, C, CM, ED, ET, H, I, OT, S, SM> =
|
||||||
StatefulInProcessExecutor<'a, H, I, OT, S, Emulator<C, CM, ED, ET, I, S, SM>>;
|
StatefulInProcessExecutor<'a, Emulator<C, CM, ED, ET, I, S, SM>, H, I, OT, S>;
|
||||||
|
|
||||||
pub struct QemuExecutor<'a, C, CM, ED, ET, H, I, OT, S, SM> {
|
pub struct QemuExecutor<'a, C, CM, ED, ET, H, I, OT, S, SM> {
|
||||||
inner: EmulatorInProcessExecutor<'a, C, CM, ED, ET, H, I, OT, S, SM>,
|
inner: EmulatorInProcessExecutor<'a, C, CM, ED, ET, H, I, OT, S, SM>,
|
||||||
@ -207,7 +207,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
inner.inprocess_hooks_mut().timeout_handler = inproc_qemu_timeout_handler::<
|
inner.inprocess_hooks_mut().timeout_handler = inproc_qemu_timeout_handler::<
|
||||||
StatefulInProcessExecutor<'a, H, I, OT, S, Emulator<C, CM, ED, ET, I, S, SM>>,
|
StatefulInProcessExecutor<'a, Emulator<C, CM, ED, ET, I, S, SM>, H, I, OT, S>,
|
||||||
EM,
|
EM,
|
||||||
ET,
|
ET,
|
||||||
I,
|
I,
|
||||||
@ -299,9 +299,10 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub type QemuInProcessForkExecutor<'a, C, CM, ED, EM, ET, H, I, OT, S, SM, SP, Z> =
|
pub type QemuInProcessForkExecutor<'a, C, CM, ED, EM, ET, H, I, OT, S, SM, SP, Z> =
|
||||||
StatefulInProcessForkExecutor<'a, H, I, OT, S, SP, Emulator<C, CM, ED, ET, I, S, SM>, EM, Z>;
|
StatefulInProcessForkExecutor<'a, EM, Emulator<C, CM, ED, ET, I, S, SM>, H, I, OT, S, SP, Z>;
|
||||||
|
|
||||||
#[cfg(feature = "fork")]
|
#[cfg(feature = "fork")]
|
||||||
|
#[expect(clippy::type_complexity)]
|
||||||
pub struct QemuForkExecutor<'a, C, CM, ED, EM, ET, H, I, OT, S, SM, SP, Z> {
|
pub struct QemuForkExecutor<'a, C, CM, ED, EM, ET, H, I, OT, S, SM, SP, Z> {
|
||||||
inner: QemuInProcessForkExecutor<'a, C, CM, ED, EM, ET, H, I, OT, S, SM, SP, Z>,
|
inner: QemuInProcessForkExecutor<'a, C, CM, ED, EM, ET, H, I, OT, S, SM, SP, Z>,
|
||||||
}
|
}
|
||||||
@ -313,12 +314,13 @@ where
|
|||||||
C: Debug,
|
C: Debug,
|
||||||
CM: Debug,
|
CM: Debug,
|
||||||
ED: Debug,
|
ED: Debug,
|
||||||
|
EM: Debug,
|
||||||
ET: EmulatorModuleTuple<I, S> + Debug,
|
ET: EmulatorModuleTuple<I, S> + Debug,
|
||||||
OT: ObserversTuple<I, S> + Debug,
|
OT: ObserversTuple<I, S> + Debug,
|
||||||
I: Debug,
|
I: Debug,
|
||||||
S: Debug,
|
S: Debug,
|
||||||
SM: Debug,
|
SM: Debug,
|
||||||
SP: ShMemProvider,
|
SP: Debug,
|
||||||
{
|
{
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
f.debug_struct("QemuForkExecutor")
|
f.debug_struct("QemuForkExecutor")
|
||||||
@ -437,7 +439,6 @@ impl<C, CM, ED, EM, ET, H, I, OT, S, SM, SP, Z> HasObservers
|
|||||||
where
|
where
|
||||||
ET: EmulatorModuleTuple<I, S>,
|
ET: EmulatorModuleTuple<I, S>,
|
||||||
OT: ObserversTuple<I, S>,
|
OT: ObserversTuple<I, S>,
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
{
|
||||||
type Observers = OT;
|
type Observers = OT;
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -119,7 +119,7 @@ impl ForkserverBytesCoverageSugar<'_> {
|
|||||||
let time_ref = time_observer.handle();
|
let time_ref = time_observer.handle();
|
||||||
|
|
||||||
let mut run_client = |state: Option<_>,
|
let mut run_client = |state: Option<_>,
|
||||||
mut mgr: LlmpRestartingEventManager<_, _, _, _>,
|
mut mgr: LlmpRestartingEventManager<_, _, _, _, _>,
|
||||||
_core_id| {
|
_core_id| {
|
||||||
let time_observer = time_observer.clone();
|
let time_observer = time_observer.clone();
|
||||||
|
|
||||||
|
@ -147,7 +147,7 @@ where
|
|||||||
let time_ref = time_observer.handle();
|
let time_ref = time_observer.handle();
|
||||||
|
|
||||||
let mut run_client = |state: Option<_>,
|
let mut run_client = |state: Option<_>,
|
||||||
mut mgr: LlmpRestartingEventManager<_, _, _, _>,
|
mut mgr: LlmpRestartingEventManager<_, _, _, _, _>,
|
||||||
_core_id| {
|
_core_id| {
|
||||||
let time_observer = time_observer.clone();
|
let time_observer = time_observer.clone();
|
||||||
|
|
||||||
|
@ -150,7 +150,7 @@ where
|
|||||||
let time_ref = time_observer.handle();
|
let time_ref = time_observer.handle();
|
||||||
|
|
||||||
let mut run_client = |state: Option<_>,
|
let mut run_client = |state: Option<_>,
|
||||||
mut mgr: LlmpRestartingEventManager<_, _, _, _>,
|
mut mgr: LlmpRestartingEventManager<_, _, _, _, _>,
|
||||||
_core_id| {
|
_core_id| {
|
||||||
let time_observer = time_observer.clone();
|
let time_observer = time_observer.clone();
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use core::{marker::PhantomData, ptr, time::Duration};
|
use core::{marker::PhantomData, ptr, time::Duration};
|
||||||
|
use std::fmt::{Debug, Formatter};
|
||||||
|
|
||||||
use libafl::{
|
use libafl::{
|
||||||
executors::{Executor, ExitKind, HasObservers},
|
executors::{Executor, ExitKind, HasObservers},
|
||||||
@ -8,27 +9,24 @@ use libafl::{
|
|||||||
};
|
};
|
||||||
use libafl_bolts::{
|
use libafl_bolts::{
|
||||||
fs::{InputFile, INPUTFILE_STD},
|
fs::{InputFile, INPUTFILE_STD},
|
||||||
shmem::{NopShMemProvider, ShMem, ShMemProvider},
|
shmem::{NopShMem, NopShMemProvider, ShMem, ShMemProvider},
|
||||||
tuples::RefIndexable,
|
tuples::RefIndexable,
|
||||||
AsSlice, AsSliceMut,
|
AsSlice, AsSliceMut,
|
||||||
};
|
};
|
||||||
use tinyinst::tinyinst::{litecov::RunResult, TinyInst};
|
use tinyinst::tinyinst::{litecov::RunResult, TinyInst};
|
||||||
|
|
||||||
/// [`TinyInst`](https://github.com/googleprojectzero/TinyInst) executor
|
/// [`TinyInst`](https://github.com/googleprojectzero/TinyInst) executor
|
||||||
pub struct TinyInstExecutor<S, SP, OT>
|
pub struct TinyInstExecutor<S, SHM, OT> {
|
||||||
where
|
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
|
||||||
tinyinst: TinyInst,
|
tinyinst: TinyInst,
|
||||||
coverage_ptr: *mut Vec<u64>,
|
coverage_ptr: *mut Vec<u64>,
|
||||||
timeout: Duration,
|
timeout: Duration,
|
||||||
observers: OT,
|
observers: OT,
|
||||||
phantom: PhantomData<S>,
|
phantom: PhantomData<S>,
|
||||||
cur_input: InputFile,
|
cur_input: InputFile,
|
||||||
map: Option<<SP as ShMemProvider>::ShMem>,
|
map: Option<SHM>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TinyInstExecutor<(), NopShMemProvider, ()> {
|
impl TinyInstExecutor<(), NopShMem, ()> {
|
||||||
/// Create a builder for [`TinyInstExecutor`]
|
/// Create a builder for [`TinyInstExecutor`]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn builder<'a>() -> TinyInstExecutorBuilder<'a, NopShMemProvider> {
|
pub fn builder<'a>() -> TinyInstExecutorBuilder<'a, NopShMemProvider> {
|
||||||
@ -36,22 +34,19 @@ impl TinyInstExecutor<(), NopShMemProvider, ()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S, SP, OT> std::fmt::Debug for TinyInstExecutor<S, SP, OT>
|
impl<S, SHM, OT> Debug for TinyInstExecutor<S, SHM, OT> {
|
||||||
where
|
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
f.debug_struct("TinyInstExecutor")
|
f.debug_struct("TinyInstExecutor")
|
||||||
.field("timeout", &self.timeout)
|
.field("timeout", &self.timeout)
|
||||||
.finish_non_exhaustive()
|
.finish_non_exhaustive()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EM, I, OT, S, SP, Z> Executor<EM, I, S, Z> for TinyInstExecutor<S, SP, OT>
|
impl<EM, I, OT, S, SHM, Z> Executor<EM, I, S, Z> for TinyInstExecutor<S, SHM, OT>
|
||||||
where
|
where
|
||||||
S: HasExecutions,
|
S: HasExecutions,
|
||||||
I: HasTargetBytes,
|
I: HasTargetBytes,
|
||||||
SP: ShMemProvider,
|
SHM: ShMem,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn run_target(
|
fn run_target(
|
||||||
@ -133,10 +128,7 @@ impl<'a> TinyInstExecutorBuilder<'a, NopShMemProvider> {
|
|||||||
|
|
||||||
/// Use this to enable shmem testcase passing.
|
/// Use this to enable shmem testcase passing.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn shmem_provider<SP: ShMemProvider>(
|
pub fn shmem_provider<SP>(self, shmem_provider: &'a mut SP) -> TinyInstExecutorBuilder<'a, SP> {
|
||||||
self,
|
|
||||||
shmem_provider: &'a mut SP,
|
|
||||||
) -> TinyInstExecutorBuilder<'a, SP> {
|
|
||||||
TinyInstExecutorBuilder {
|
TinyInstExecutorBuilder {
|
||||||
tinyinst_args: self.tinyinst_args,
|
tinyinst_args: self.tinyinst_args,
|
||||||
program_args: self.program_args,
|
program_args: self.program_args,
|
||||||
@ -246,7 +238,10 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Build [`TinyInst`](https://github.com/googleprojectzero/TinyInst) executor
|
/// Build [`TinyInst`](https://github.com/googleprojectzero/TinyInst) executor
|
||||||
pub fn build<OT, S>(&mut self, observers: OT) -> Result<TinyInstExecutor<S, SP, OT>, Error> {
|
pub fn build<OT, S>(
|
||||||
|
&mut self,
|
||||||
|
observers: OT,
|
||||||
|
) -> Result<TinyInstExecutor<S, SP::ShMem, OT>, Error> {
|
||||||
if self.coverage_ptr.is_null() {
|
if self.coverage_ptr.is_null() {
|
||||||
return Err(Error::illegal_argument("Coverage pointer may not be null."));
|
return Err(Error::illegal_argument("Coverage pointer may not be null."));
|
||||||
}
|
}
|
||||||
@ -313,10 +308,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S, SP, OT> HasObservers for TinyInstExecutor<S, SP, OT>
|
impl<S, SHM, OT> HasObservers for TinyInstExecutor<S, SHM, OT> {
|
||||||
where
|
|
||||||
SP: ShMemProvider,
|
|
||||||
{
|
|
||||||
type Observers = OT;
|
type Observers = OT;
|
||||||
|
|
||||||
fn observers(&self) -> RefIndexable<&Self::Observers, Self::Observers> {
|
fn observers(&self) -> RefIndexable<&Self::Observers, Self::Observers> {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user