@@ -6,27 +6,29 @@ use libafl::events::SimpleEventManager;
66#[ cfg( not( feature = "simplemgr" ) ) ]
77use libafl:: events:: { LlmpRestartingEventManager , MonitorTypedEventManager } ;
88use libafl:: {
9- corpus:: { Corpus , InMemoryOnDiskCorpus , OnDiskCorpus } ,
9+ corpus:: { Corpus , HasCurrentCorpusId , InMemoryOnDiskCorpus , OnDiskCorpus } ,
1010 events:: { ClientDescription , EventRestarter } ,
11- executors:: { Executor , ShadowExecutor } ,
11+ executors:: { Executor , ExitKind , ShadowExecutor } ,
1212 feedback_or, feedback_or_fast,
1313 feedbacks:: { CrashFeedback , MaxMapFeedback , TimeFeedback , TimeoutFeedback } ,
1414 fuzzer:: { Evaluator , Fuzzer , StdFuzzer } ,
15- inputs:: BytesInput ,
15+ inputs:: { BytesInput , Input } ,
1616 monitors:: Monitor ,
1717 mutators:: {
1818 havoc_mutations, token_mutations:: I2SRandReplace , tokens_mutations, StdMOptMutator ,
1919 StdScheduledMutator , Tokens ,
2020 } ,
21- observers:: { CanTrack , HitcountsMapObserver , TimeObserver , VariableMapObserver } ,
21+ observers:: {
22+ CanTrack , HitcountsMapObserver , ObserversTuple , TimeObserver , VariableMapObserver ,
23+ } ,
2224 schedulers:: {
2325 powersched:: PowerSchedule , IndexesLenTimeMinimizerScheduler , PowerQueueScheduler ,
2426 } ,
2527 stages:: {
2628 calibrate:: CalibrationStage , power:: StdPowerMutationalStage , AflStatsStage , IfStage ,
2729 ShadowTracingStage , StagesTuple , StdMutationalStage ,
2830 } ,
29- state:: { HasCorpus , StdState } ,
31+ state:: { HasCorpus , HasExecutions , HasSolutions , StdState } ,
3032 Error , HasMetadata ,
3133} ;
3234#[ cfg( not( feature = "simplemgr" ) ) ]
@@ -42,7 +44,7 @@ use libafl_qemu::{
4244 cmplog:: CmpLogObserver ,
4345 edges:: EdgeCoverageFullVariant ,
4446 utils:: filters:: { HasAddressFilter , NopPageFilter , StdAddressFilter } ,
45- EdgeCoverageModule , EmulatorModuleTuple , StdEdgeCoverageModule ,
47+ EdgeCoverageModule , EmulatorModuleTuple , SnapshotModule , StdEdgeCoverageModule ,
4648 } ,
4749 Emulator , GuestAddr , Qemu , QemuExecutor ,
4850} ;
@@ -62,6 +64,27 @@ pub type ClientMgr<M> = MonitorTypedEventManager<
6264 M ,
6365> ;
6466
67+ /*
68+ * The snapshot and iterations options interact as follows:
69+ *
70+ * +----------+------------+-------------------------------------------+
71+ * | snapshot | iterations | Functionality |
72+ * +----------+------------+-------------------------------------------+
73+ * | N | N | We set the snapshot module into manual |
74+ * | | | mode and never reset it. |
75+ * +----------+------------+-------------------------------------------+
76+ * | N | Y | We set the snapshot module into manual |
77+ * | | | mode and never reset it. |
78+ * +----------+------------+-------------------------------------------+
79+ * | Y | N | We set the snapshot module into automatic |
80+ * | | | mode so it resets after every iteration. |
81+ * +----------+------------+-------------------------------------------+
82+ * | Y | Y | We set the snapshot module into manual |
83+ * | | | mode and manually reset it after the |
84+ * | | | required number of iterations are done. |
85+ * +----------+------------+-------------------------------------------+
86+ */
87+
6588#[ derive( TypedBuilder ) ]
6689pub struct Instance < ' a , M : Monitor > {
6790 options : & ' a FuzzerOptions ,
@@ -131,7 +154,22 @@ impl<M: Monitor> Instance<'_, M> {
131154 . map_observer ( edges_observer. as_mut ( ) )
132155 . build ( ) ?;
133156
134- let modules = modules. prepend ( edge_coverage_module) ;
157+ let mut snapshot_module = SnapshotModule :: new ( ) ;
158+
159+ /*
160+ * Since the generics for the modules are already excessive when taking
161+ * into accout asan, asan guest mode, cmplog, and injection, we will
162+ * always include the SnapshotModule in all configurations, but simply
163+ * not use it when it is not required. See the table at the top of this
164+ * file for details.
165+ */
166+ if !self . options . snapshots || self . options . iterations . is_some ( ) {
167+ snapshot_module. use_manual_reset ( ) ;
168+ }
169+
170+ let modules = modules
171+ . prepend ( edge_coverage_module)
172+ . prepend ( snapshot_module) ;
135173 let mut emulator = Emulator :: empty ( )
136174 . qemu_parameters ( args)
137175 . modules ( modules)
@@ -266,9 +304,9 @@ impl<M: Monitor> Instance<'_, M> {
266304 // Create an observation channel using cmplog map
267305 let cmplog_observer = CmpLogObserver :: new ( "cmplog" , true ) ;
268306
269- let mut executor = ShadowExecutor :: new ( executor, tuple_list ! ( cmplog_observer) ) ;
307+ let mut shadow_executor = ShadowExecutor :: new ( executor, tuple_list ! ( cmplog_observer) ) ;
270308
271- let tracing = ShadowTracingStage :: new ( & mut executor ) ;
309+ let tracing = ShadowTracingStage :: new ( & mut shadow_executor ) ;
272310
273311 // Setup a randomic Input2State stage
274312 let i2s = StdMutationalStage :: new ( StdScheduledMutator :: new ( tuple_list ! (
@@ -289,7 +327,14 @@ impl<M: Monitor> Instance<'_, M> {
289327 // The order of the stages matter!
290328 let mut stages = tuple_list ! ( calibration, tracing, i2s, power, stats_stage) ;
291329
292- self . fuzz ( & mut state, & mut fuzzer, & mut executor, & mut stages)
330+ self . fuzz (
331+ & mut state,
332+ & mut fuzzer,
333+ & mut shadow_executor,
334+ Self :: reset_shadow_executor_snapshot_module,
335+ qemu,
336+ & mut stages,
337+ )
293338 } else {
294339 // Create a QEMU in-process executor
295340 let mut executor = QemuExecutor :: new (
@@ -306,25 +351,88 @@ impl<M: Monitor> Instance<'_, M> {
306351 let mutator = StdScheduledMutator :: new ( havoc_mutations ( ) . merge ( tokens_mutations ( ) ) ) ;
307352 let mut stages = tuple_list ! ( StdMutationalStage :: new( mutator) ) ;
308353
309- self . fuzz ( & mut state, & mut fuzzer, & mut executor, & mut stages)
354+ self . fuzz (
355+ & mut state,
356+ & mut fuzzer,
357+ & mut executor,
358+ Self :: reset_executor_snapshot_module,
359+ qemu,
360+ & mut stages,
361+ )
310362 }
311363 }
312364
313- fn fuzz < Z , E , ST > (
365+ fn reset_executor_snapshot_module < ' a , C , CM , ED , EM , ET , H , I , OT , S , SM , Z > (
366+ executor : & mut QemuExecutor < ' a , C , CM , ED , EM , ( SnapshotModule , ET ) , H , I , OT , S , SM , Z > ,
367+ qemu : Qemu ,
368+ ) where
369+ I : Input + Unpin ,
370+ ET : EmulatorModuleTuple < I , S > ,
371+ S : HasCorpus < I > + HasCurrentCorpusId + HasSolutions < I > + HasExecutions + Unpin ,
372+ H : for <' e , ' s , ' i > FnMut (
373+ & ' e mut Emulator < C , CM , ED , ( SnapshotModule , ET ) , I , S , SM > ,
374+ & ' s mut S ,
375+ & ' i I ,
376+ ) -> ExitKind ,
377+ OT : ObserversTuple < I , S > ,
378+ {
379+ executor
380+ . inner_mut ( )
381+ . exposed_executor_state_mut ( )
382+ . modules_mut ( )
383+ . modules_mut ( )
384+ . 0
385+ . reset ( qemu) ;
386+ }
387+
388+ fn reset_shadow_executor_snapshot_module < ' a , C , CM , ED , EM , ET , H , I , OT , S , SM , SOT , Z > (
389+ executor : & mut ShadowExecutor <
390+ QemuExecutor < ' a , C , CM , ED , EM , ( SnapshotModule , ET ) , H , I , OT , S , SM , Z > ,
391+ I ,
392+ S ,
393+ SOT ,
394+ > ,
395+ qemu : Qemu ,
396+ ) where
397+ I : Input + Unpin ,
398+ ET : EmulatorModuleTuple < I , S > ,
399+ S : HasCorpus < I > + HasCurrentCorpusId + HasSolutions < I > + HasExecutions + Unpin ,
400+ H : for <' e , ' s , ' i > FnMut (
401+ & ' e mut Emulator < C , CM , ED , ( SnapshotModule , ET ) , I , S , SM > ,
402+ & ' s mut S ,
403+ & ' i I ,
404+ ) -> ExitKind ,
405+ OT : ObserversTuple < I , S > ,
406+ SOT : ObserversTuple < I , S > ,
407+ {
408+ executor
409+ . executor_mut ( )
410+ . inner_mut ( )
411+ . exposed_executor_state_mut ( )
412+ . modules_mut ( )
413+ . modules_mut ( )
414+ . 0
415+ . reset ( qemu) ;
416+ }
417+
418+ fn fuzz < Z , E , ST , RSM > (
314419 & mut self ,
315420 state : & mut ClientState ,
316421 fuzzer : & mut Z ,
317422 executor : & mut E ,
423+ reset_snapshot_module : RSM ,
424+ qemu : Qemu ,
318425 stages : & mut ST ,
319426 ) -> Result < ( ) , Error >
320427 where
321428 Z : Fuzzer < E , ClientMgr < M > , BytesInput , ClientState , ST >
322429 + Evaluator < E , ClientMgr < M > , BytesInput , ClientState > ,
323430 ST : StagesTuple < E , ClientMgr < M > , ClientState , Z > ,
431+ RSM : Fn ( & mut E , Qemu ) ,
324432 {
325- let corpus_dirs = [ self . options . input_dir ( ) ] ;
326-
327433 if state. must_load_initial_inputs ( ) {
434+ let corpus_dirs = [ self . options . input_dir ( ) ] ;
435+
328436 state
329437 . load_initial_inputs ( fuzzer, executor, & mut self . mgr , & corpus_dirs)
330438 . unwrap_or_else ( |_| {
@@ -334,12 +442,23 @@ impl<M: Monitor> Instance<'_, M> {
334442 println ! ( "We imported {} inputs from disk." , state. corpus( ) . count( ) ) ;
335443 }
336444
445+ /*
446+ * See the table a the top of this file for details on how the snapshot
447+ * and iterations options interact.
448+ */
337449 if let Some ( iters) = self . options . iterations {
338- fuzzer. fuzz_loop_for ( stages, executor, state, & mut self . mgr , iters) ?;
339-
340- // It's important, that we store the state before restarting!
341- // Else, the parent will not respawn a new child and quit.
342- self . mgr . on_restart ( state) ?;
450+ if self . options . snapshots {
451+ loop {
452+ reset_snapshot_module ( executor, qemu) ;
453+ fuzzer. fuzz_loop_for ( stages, executor, state, & mut self . mgr , iters) ?;
454+ }
455+ } else {
456+ fuzzer. fuzz_loop_for ( stages, executor, state, & mut self . mgr , iters) ?;
457+
458+ // It's important, that we store the state before restarting!
459+ // Else, the parent will not respawn a new child and quit.
460+ self . mgr . on_restart ( state) ?;
461+ }
343462 } else {
344463 fuzzer. fuzz_loop ( stages, executor, state, & mut self . mgr ) ?;
345464 }
0 commit comments