Skip to content

Commit 5710c8b

Browse files
authoredAug 29, 2023
Document LIBAFL_DEBUG_OUTPUT in Launcher (#1485)
* Document LIBAFL_DEBUG_OUTPUT in Launcher * fmt * more doc * fork * unix
1 parent 51e4d81 commit 5710c8b

File tree

4 files changed

+21
-8
lines changed

4 files changed

+21
-8
lines changed
 

‎docs/src/introduction.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,6 @@ feel free to use and mutate an Abstract Syntax Tree instead, for structured fuzz
2929
- `scalable`: As part of LibAFL, we developed `Low Level Message Passing`, `LLMP` for short, which allows LibAFL to scale almost linearly over cores. That is, if you chose to use this feature - it is your fuzzer, after all.
3030
Scaling to multiple machines over TCP is also possible, using LLMP's `broker2broker` feature.
3131
- `fast`: We do everything we can at compile time so that the runtime overhead is as minimal as it can get.
32-
- `bring your own target`: We support binary-only modes, like QEMU-Mode and Frida-Mode with ASAN and CmpLog, as well as multiple compilation passes for sourced-based instrumentation.
32+
- `bring your own target`: We support binary-only modes, like (full-system) QEMU-Mode and Frida-Mode with ASan and CmpLog, as well as multiple compilation passes for sourced-based instrumentation.
3333
Of course, we also support custom instrumentation, as you can see in the Python example based on Google's Atheris.
3434
- `usable`: This one is on you to decide. Dig right in!

‎docs/src/message_passing/configurations.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
Configurations for individual fuzzer nodes are relevant for multi node fuzzing.
44
The chapter describes how to run nodes with different configurations
55
in one fuzzing cluster.
6-
This allows, for example, a node compiled with ASAN, to know that it needs to rerun new testcases for a node without ASAN, while the same binary/configuration does not.
6+
This allows, for example, a node compiled with ASan, to know that it needs to rerun new testcases for a node without ASan, while the same binary/configuration does not.
77

88
Fuzzers with the same configuration can exchange Observers for new testcases and reuse them without rerunning the input.
99
A different configuration indicates, that only the raw input can be exchanged, it must be rerun on the other node to capture relevant observations.

‎docs/src/message_passing/spawn_instances.md

+6-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Multiple fuzzer instances can be spawned using different ways.
44

55
## Manually, via a TCP port
66

7-
The straightforward way to do Multi-Threading is to use the `LlmpRestartingEventManager`, specifically to use `setup_restarting_mgr_std`.
7+
The straightforward way to do Multi-Threading is to use the [`LlmpRestartingEventManager`](https://docs.rs/libafl/latest/libafl/events/llmp/struct.LlmpRestartingEventManager.html), specifically to use [`setup_restarting_mgr_std`](https://docs.rs/libafl/latest/libafl/events/llmp/fn.setup_restarting_mgr_std.html).
88
It abstracts away all the pesky details about restarts on crash handling (for in-memory fuzzers) and multi-threading.
99
With it, every instance you launch manually tries to connect to a TCP port on the local machine.
1010

@@ -13,7 +13,7 @@ If the port is not yet bound, this instance becomes the broker, binding itself t
1313
If the port is already bound, the EventManager will try to connect to it.
1414
The instance becomes a client and can now communicate with all other nodes.
1515

16-
Launching nodes manually has the benefit that you can have multiple nodes with different configurations, such as clients fuzzing with and without ASAN.
16+
Launching nodes manually has the benefit that you can have multiple nodes with different configurations, such as clients fuzzing with and without `ASan``.
1717

1818
While it's called "restarting" manager, it uses `fork` on Unix-like operating systems as optimization and only actually restarts from scratch on Windows.
1919

@@ -42,13 +42,17 @@ To use launcher, first you need to write an anonymous function `let mut run_clie
4242
This first starts a broker, then spawns `n` clients, according to the value passed to `cores`.
4343
The value is a string indicating the cores to bind to, for example, `0,2,5` or `0-3`.
4444
For each client, `run_client` will be called.
45+
If the launcher uses `fork`, it will hide child output, unless the settings indicate otherwise, or the `LIBAFL_DEBUG_OUTPUT` env variable is set.
4546
On Windows, the Launcher will restart each client, while on Unix-alikes, it will use `fork`.
4647

4748
Advanced use-cases:
4849

4950
1. To connect multiple nodes together via TCP, you can use the `remote_broker_addr`. this requires the `llmp_bind_public` compile-time feature for `LibAFL`.
5051
2. To use multiple launchers for individual configurations, you can set `spawn_broker` to `false` on all instances but one.
5152
3. Launcher will not select the cores automatically, so you need to specify the `cores` that you want.
53+
4. On `Unix`, you can chose between a forking and non-forking version of Launcher by setting the `fork` feature in LibAFL. Some targets may not like forking, but it is faster than restarting processes from scratch. Windows will never fork.
54+
5. For simple debugging, first set the `LIBAFL_DEBUG_OUTPUT` env variable to see if a child process printed anything.
55+
6. For further debugging of fuzzer failures, it may make sense to replace `Launcher` temporarily with a [`SimpleEventManager`](https://docs.rs/libafl/latest/libafl/events/simple/struct.SimpleEventManager.html#method.new) and call your harness fn (`run_client(None, mgr, 0);`) directly, so that fuzzing runs in the same thread and is easier to debug, before moving back to `Launcher` after the bugfix.
5256

5357
For more examples, you can check out `qemu_launcher` and `libfuzzer_libpng_launcher` in [`./fuzzers/`](https://github.com/AFLplusplus/LibAFL/tree/main/fuzzers).
5458

‎libafl/src/events/launcher.rs

+13-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
//! The [`Launcher`] launches multiple fuzzer instances in parallel.
22
//! Thanks to it, we won't need a `for` loop in a shell script...
33
//!
4+
//! It will hide child output, unless the settings indicate otherwise, or the `LIBAFL_DEBUG_OUTPUT` env variable is set.
5+
//!
46
//! To use multiple [`Launcher`]`s` for individual configurations,
57
//! we can set `spawn_broker` to `false` on all but one.
68
//!
@@ -54,7 +56,13 @@ use crate::{
5456
/// The (internal) `env` that indicates we're running as client.
5557
const _AFL_LAUNCHER_CLIENT: &str = "AFL_LAUNCHER_CLIENT";
5658

57-
/// Provides a Launcher, which can be used to launch a fuzzing run on a specified list of cores
59+
/// The env variable to set in order to enable child output
60+
#[cfg(all(feature = "fork", unix))]
61+
const LIBAFL_DEBUG_OUTPUT: &str = "LIBAFL_DEBUG_OUTPUT";
62+
63+
/// Provides a [`Launcher`], which can be used to launch a fuzzing run on a specified list of cores
64+
///
65+
/// Will hide child output, unless the settings indicate otherwise, or the `LIBAFL_DEBUG_OUTPUT` env variable is set.
5866
#[cfg(feature = "std")]
5967
#[allow(
6068
clippy::type_complexity,
@@ -168,7 +176,7 @@ where
168176
.map(|filename| File::create(filename).unwrap());
169177

170178
#[cfg(feature = "std")]
171-
let debug_output = std::env::var("LIBAFL_DEBUG_OUTPUT").is_ok();
179+
let debug_output = std::env::var(LIBAFL_DEBUG_OUTPUT).is_ok();
172180

173181
// Spawn clients
174182
let mut index = 0_u64;
@@ -277,7 +285,8 @@ where
277285
Ok(core_conf) => {
278286
let core_id = core_conf.parse()?;
279287

280-
//todo: silence stdout and stderr for clients
288+
// TODO: silence stdout and stderr for clients
289+
// let debug_output = std::env::var(LIBAFL_DEBUG_OUTPUT).is_ok();
281290

282291
// the actual client. do the fuzzing
283292
let (state, mgr) = RestartingMgr::<MT, S, SP>::builder()
@@ -493,7 +502,7 @@ where
493502
.stderr_file
494503
.map(|filename| File::create(filename).unwrap());
495504

496-
let debug_output = std::env::var("LIBAFL_DEBUG_OUTPUT").is_ok();
505+
let debug_output = std::env::var(LIBAFL_DEBUG_OUTPUT).is_ok();
497506

498507
// Spawn centralized broker
499508
self.shmem_provider.pre_fork()?;

0 commit comments

Comments
 (0)