Allow setting stdout_file in non-fork launcher (#2127)
* fix(launcher.rs): hide file output behind appropriate feature flag discovered while debugging #2111 * fix(launcher.rs): implement stdout/stderr piping for non-forking unix * hide all accesses to stdout_file in cfg blocks * Conditionally add stdout_file config in frida_gdiplus
This commit is contained in:
parent
2302f1b35c
commit
ec944a0ea4
@ -473,15 +473,22 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Launcher::builder()
|
let builder = Launcher::builder()
|
||||||
.configuration(EventConfig::AlwaysUnique)
|
.configuration(EventConfig::AlwaysUnique)
|
||||||
.shmem_provider(shmem_provider)
|
.shmem_provider(shmem_provider)
|
||||||
.monitor(monitor)
|
.monitor(monitor)
|
||||||
.run_client(&mut run_client)
|
.run_client(&mut run_client)
|
||||||
.cores(&options.cores)
|
.cores(&options.cores)
|
||||||
.broker_port(options.broker_port)
|
.broker_port(options.broker_port)
|
||||||
.stdout_file(Some(&options.stdout))
|
.remote_broker_addr(options.remote_broker_addr);
|
||||||
.remote_broker_addr(options.remote_broker_addr)
|
|
||||||
.build()
|
#[cfg(all(unix, feature = "std"))]
|
||||||
.launch()
|
{
|
||||||
|
return builder.stdout_file(Some(&options.stdout)).build().launch();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(all(unix, feature = "std")))]
|
||||||
|
{
|
||||||
|
return builder.build().launch();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,9 +25,11 @@ use core::{
|
|||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
#[cfg(all(feature = "std", any(windows, not(feature = "fork"))))]
|
#[cfg(all(feature = "std", any(windows, not(feature = "fork"))))]
|
||||||
use std::process::Stdio;
|
use std::process::Stdio;
|
||||||
#[cfg(all(unix, feature = "std", feature = "fork"))]
|
#[cfg(all(unix, feature = "std"))]
|
||||||
use std::{fs::File, os::unix::io::AsRawFd};
|
use std::{fs::File, os::unix::io::AsRawFd};
|
||||||
|
|
||||||
|
#[cfg(all(unix, feature = "std"))]
|
||||||
|
use libafl_bolts::os::dup2;
|
||||||
#[cfg(all(feature = "std", any(windows, not(feature = "fork"))))]
|
#[cfg(all(feature = "std", any(windows, not(feature = "fork"))))]
|
||||||
use libafl_bolts::os::startable_self;
|
use libafl_bolts::os::startable_self;
|
||||||
#[cfg(feature = "adaptive_serialization")]
|
#[cfg(feature = "adaptive_serialization")]
|
||||||
@ -35,7 +37,7 @@ use libafl_bolts::tuples::{Reference, Referenceable};
|
|||||||
#[cfg(all(unix, feature = "std", feature = "fork"))]
|
#[cfg(all(unix, feature = "std", feature = "fork"))]
|
||||||
use libafl_bolts::{
|
use libafl_bolts::{
|
||||||
core_affinity::get_core_ids,
|
core_affinity::get_core_ids,
|
||||||
os::{dup2, fork, ForkResult},
|
os::{fork, ForkResult},
|
||||||
};
|
};
|
||||||
use libafl_bolts::{
|
use libafl_bolts::{
|
||||||
core_affinity::{CoreId, Cores},
|
core_affinity::{CoreId, Cores},
|
||||||
@ -102,6 +104,7 @@ where
|
|||||||
/// The list of cores to run on
|
/// The list of cores to run on
|
||||||
cores: &'a Cores,
|
cores: &'a Cores,
|
||||||
/// A file name to write all client output to
|
/// A file name to write all client output to
|
||||||
|
#[cfg(all(unix, feature = "std"))]
|
||||||
#[builder(default = None)]
|
#[builder(default = None)]
|
||||||
stdout_file: Option<&'a str>,
|
stdout_file: Option<&'a str>,
|
||||||
/// The actual, opened, `stdout_file` - so that we keep it open until the end
|
/// The actual, opened, `stdout_file` - so that we keep it open until the end
|
||||||
@ -110,6 +113,7 @@ where
|
|||||||
opened_stdout_file: Option<File>,
|
opened_stdout_file: Option<File>,
|
||||||
/// A file name to write all client stderr output to. If not specified, output is sent to
|
/// A file name to write all client stderr output to. If not specified, output is sent to
|
||||||
/// `stdout_file`.
|
/// `stdout_file`.
|
||||||
|
#[cfg(all(unix, feature = "std"))]
|
||||||
#[builder(default = None)]
|
#[builder(default = None)]
|
||||||
stderr_file: Option<&'a str>,
|
stderr_file: Option<&'a str>,
|
||||||
/// The actual, opened, `stdout_file` - so that we keep it open until the end
|
/// The actual, opened, `stdout_file` - so that we keep it open until the end
|
||||||
@ -144,15 +148,21 @@ where
|
|||||||
S: State,
|
S: State,
|
||||||
{
|
{
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
f.debug_struct("Launcher")
|
let mut dbg_struct = f.debug_struct("Launcher");
|
||||||
|
dbg_struct
|
||||||
.field("configuration", &self.configuration)
|
.field("configuration", &self.configuration)
|
||||||
.field("broker_port", &self.broker_port)
|
.field("broker_port", &self.broker_port)
|
||||||
.field("core", &self.cores)
|
.field("core", &self.cores)
|
||||||
.field("spawn_broker", &self.spawn_broker)
|
.field("spawn_broker", &self.spawn_broker)
|
||||||
.field("remote_broker_addr", &self.remote_broker_addr)
|
.field("remote_broker_addr", &self.remote_broker_addr);
|
||||||
.field("stdout_file", &self.stdout_file)
|
#[cfg(all(unix, feature = "std"))]
|
||||||
.field("stderr_file", &self.stderr_file)
|
{
|
||||||
.finish_non_exhaustive()
|
dbg_struct
|
||||||
|
.field("stdout_file", &self.stdout_file)
|
||||||
|
.field("stderr_file", &self.stderr_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
dbg_struct.finish_non_exhaustive()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,10 +341,6 @@ where
|
|||||||
let mut handles = match is_client {
|
let mut handles = match is_client {
|
||||||
Ok(core_conf) => {
|
Ok(core_conf) => {
|
||||||
let core_id = core_conf.parse()?;
|
let core_id = core_conf.parse()?;
|
||||||
|
|
||||||
// TODO: silence stdout and stderr for clients
|
|
||||||
// let debug_output = std::env::var(LIBAFL_DEBUG_OUTPUT).is_ok();
|
|
||||||
|
|
||||||
// the actual client. do the fuzzing
|
// the actual client. do the fuzzing
|
||||||
let (state, mgr) = RestartingMgr::<EMH, MT, S, SP>::builder()
|
let (state, mgr) = RestartingMgr::<EMH, MT, S, SP>::builder()
|
||||||
.shmem_provider(self.shmem_provider.clone())
|
.shmem_provider(self.shmem_provider.clone())
|
||||||
@ -354,11 +360,6 @@ where
|
|||||||
// I am a broker
|
// I am a broker
|
||||||
// before going to the broker loop, spawn n clients
|
// before going to the broker loop, spawn n clients
|
||||||
|
|
||||||
#[cfg(windows)]
|
|
||||||
if self.stdout_file.is_some() {
|
|
||||||
log::info!("Child process file stdio is not supported on Windows yet. Dumping to stdout instead...");
|
|
||||||
}
|
|
||||||
|
|
||||||
let core_ids = core_affinity::get_core_ids().unwrap();
|
let core_ids = core_affinity::get_core_ids().unwrap();
|
||||||
let num_cores = core_ids.len();
|
let num_cores = core_ids.len();
|
||||||
let mut handles = vec![];
|
let mut handles = vec![];
|
||||||
@ -366,22 +367,45 @@ where
|
|||||||
log::info!("spawning on cores: {:?}", self.cores);
|
log::info!("spawning on cores: {:?}", self.cores);
|
||||||
|
|
||||||
let debug_output = std::env::var("LIBAFL_DEBUG_OUTPUT").is_ok();
|
let debug_output = std::env::var("LIBAFL_DEBUG_OUTPUT").is_ok();
|
||||||
|
#[cfg(all(feature = "std", unix))]
|
||||||
|
{
|
||||||
|
// Set own stdout and stderr as set by the user
|
||||||
|
if !debug_output {
|
||||||
|
let opened_stdout_file = self
|
||||||
|
.stdout_file
|
||||||
|
.map(|filename| File::create(filename).unwrap());
|
||||||
|
let opened_stderr_file = self
|
||||||
|
.stderr_file
|
||||||
|
.map(|filename| File::create(filename).unwrap());
|
||||||
|
if let Some(file) = opened_stdout_file {
|
||||||
|
dup2(file.as_raw_fd(), libc::STDOUT_FILENO)?;
|
||||||
|
if let Some(stderr) = opened_stderr_file {
|
||||||
|
dup2(stderr.as_raw_fd(), libc::STDERR_FILENO)?;
|
||||||
|
} else {
|
||||||
|
dup2(file.as_raw_fd(), libc::STDERR_FILENO)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
//spawn clients
|
//spawn clients
|
||||||
for (id, _) in core_ids.iter().enumerate().take(num_cores) {
|
for (id, _) in core_ids.iter().enumerate().take(num_cores) {
|
||||||
if self.cores.ids.iter().any(|&x| x == id.into()) {
|
if self.cores.ids.iter().any(|&x| x == id.into()) {
|
||||||
let stdio = if self.stdout_file.is_some() {
|
// Forward own stdio to child processes, if requested by user
|
||||||
Stdio::inherit()
|
let (mut stdout, mut stderr) = (Stdio::null(), Stdio::null());
|
||||||
} else {
|
#[cfg(all(feature = "std", unix))]
|
||||||
Stdio::null()
|
{
|
||||||
};
|
if self.stdout_file.is_some() || self.stderr_file.is_some() {
|
||||||
|
stdout = Stdio::inherit();
|
||||||
|
stderr = Stdio::inherit();
|
||||||
|
};
|
||||||
|
}
|
||||||
std::env::set_var(_AFL_LAUNCHER_CLIENT, id.to_string());
|
std::env::set_var(_AFL_LAUNCHER_CLIENT, id.to_string());
|
||||||
let mut child = startable_self()?;
|
let mut child = startable_self()?;
|
||||||
let child = (if debug_output {
|
let child = (if debug_output {
|
||||||
&mut child
|
&mut child
|
||||||
} else {
|
} else {
|
||||||
child.stdout(stdio)
|
child.stdout(stdout);
|
||||||
|
child.stderr(stderr)
|
||||||
})
|
})
|
||||||
.spawn()?;
|
.spawn()?;
|
||||||
handles.push(child);
|
handles.push(child);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user