Add mute_inprocess_target fn, SimpleFdLogger::set_logger, and more (#1754)
* Add mute_inprocess_target fn, SimpleFdLogger::set_logger, set_error_print_panic_hook * Trying to fix #1753 * typo * More fix * Fix test? * more testcase fixes
This commit is contained in:
parent
38e16fbade
commit
a07563def0
@ -34,11 +34,11 @@ windows_alias = "unsupported"
|
||||
script_runner = "@shell"
|
||||
script='''
|
||||
timeout 30s ${CARGO_TARGET_DIR}/${PROFILE_DIR}/${FUZZER_NAME} >fuzz_stdout.log || true
|
||||
if [ -z "$(grep "objectives: 1" fuzz_stdout.log)" ]; then
|
||||
if grep -qa "objectives: 1" fuzz_stdout.log; then
|
||||
echo "Fuzzer is working"
|
||||
else
|
||||
echo "Fuzzer does not generate any testcases or any crashes"
|
||||
exit 1
|
||||
else
|
||||
echo "Fuzzer is working"
|
||||
fi
|
||||
'''
|
||||
dependencies = [ "fuzzer" ]
|
||||
|
@ -90,11 +90,11 @@ script='''
|
||||
rm -rf libafl_unix_shmem_server || true
|
||||
LD_PRELOAD=$CARGO_TARGET_DIR/${PROFILE_DIR}/libfrida_executable_fuzzer.so ./libpng-harness -i corpus -o out -H ./libpng-harness > fuzz_stdout.log &
|
||||
sleep 10s && pkill libpng-harness
|
||||
if [ -z "$(grep "corpus: 30" fuzz_stdout.log)" ]; then
|
||||
if grep -qa "corpus: 30" fuzz_stdout.log; then
|
||||
echo "Fuzzer is working"
|
||||
else
|
||||
echo "Fuzzer does not generate any testcases or any crashes"
|
||||
exit 1
|
||||
else
|
||||
echo "Fuzzer is working"
|
||||
fi
|
||||
'''
|
||||
dependencies = [ "fuzzer", "harness" ]
|
||||
|
@ -111,11 +111,11 @@ script_runner = "@shell"
|
||||
script='''
|
||||
rm -rf libafl_unix_shmem_server || true
|
||||
timeout 30s ./${FUZZER_NAME} -F LLVMFuzzerTestOneInput -H ./libpng-harness.so -l ./libpng-harness.so >fuzz_stdout.log 2>/dev/null || true
|
||||
if [ -z "$(grep "corpus: 30" fuzz_stdout.log)" ]; then
|
||||
if grep -qa "corpus: 30" fuzz_stdout.log; then
|
||||
echo "Fuzzer is working"
|
||||
else
|
||||
echo "Fuzzer does not generate any testcases or any crashes"
|
||||
exit 1
|
||||
else
|
||||
echo "Fuzzer is working"
|
||||
fi
|
||||
'''
|
||||
dependencies = [ "fuzzer", "harness" ]
|
||||
|
@ -83,11 +83,11 @@ mkdir in || true
|
||||
echo a > in/a
|
||||
# Allow sigterm as exit code
|
||||
timeout 31s ./${FUZZER_NAME} -o out -i in >fuzz_stdout.log || true
|
||||
if [ -z "$(grep "objectives: 1" fuzz_stdout.log)" ]; then
|
||||
if grep -qa "objectives: 1" fuzz_stdout.log; then
|
||||
echo "Fuzzer is working"
|
||||
else
|
||||
echo "Fuzzer does not generate any testcases or any crashes"
|
||||
exit 1
|
||||
else
|
||||
echo "Fuzzer is working"
|
||||
fi
|
||||
rm -rf out || true
|
||||
rm -rf in || true
|
||||
|
@ -381,12 +381,12 @@ fn fuzz(
|
||||
println!("We imported {} inputs from disk.", state.corpus().count());
|
||||
}
|
||||
|
||||
// Remove target ouput (logs still survive)
|
||||
// Remove target output (logs still survive)
|
||||
#[cfg(unix)]
|
||||
{
|
||||
let null_fd = file_null.as_raw_fd();
|
||||
dup2(null_fd, io::stdout().as_raw_fd())?;
|
||||
if !std::env::var("LIBAFL_FUZZBENCH_DEBUG").is_ok() {
|
||||
if std::env::var("LIBAFL_FUZZBENCH_DEBUG").is_err() {
|
||||
dup2(null_fd, io::stderr().as_raw_fd())?;
|
||||
}
|
||||
}
|
||||
|
@ -369,7 +369,7 @@ fn fuzz(
|
||||
// The order of the stages matter!
|
||||
let mut stages = tuple_list!(calibration, tracing, i2s, power);
|
||||
|
||||
// Remove target ouput (logs still survive)
|
||||
// Remove target output (logs still survive)
|
||||
#[cfg(unix)]
|
||||
{
|
||||
let null_fd = file_null.as_raw_fd();
|
||||
|
@ -387,7 +387,7 @@ fn fuzz(
|
||||
// The order of the stages matter!
|
||||
let mut stages = tuple_list!(calibration, tracing, i2s, power);
|
||||
|
||||
// Remove target ouput (logs still survive)
|
||||
// Remove target output (logs still survive)
|
||||
#[cfg(unix)]
|
||||
{
|
||||
let null_fd = file_null.as_raw_fd();
|
||||
|
@ -85,11 +85,11 @@ echo a > in/a
|
||||
# Allow sigterm as exit code
|
||||
timeout 31s ./${FUZZER_NAME} -o out -i in >fuzz_stdout.log || true
|
||||
cat fuzz_stdout.log
|
||||
if [ -z "$(grep "objectives: 1" fuzz_stdout.log)" ]; then
|
||||
if grep -qa "objectives: 1" fuzz_stdout.log; then
|
||||
echo "Fuzzer is working"
|
||||
else
|
||||
echo "Fuzzer does not generate any testcases or any crashes"
|
||||
exit 1
|
||||
else
|
||||
echo "Fuzzer is working"
|
||||
fi
|
||||
rm -rf out || true
|
||||
rm -rf in || true
|
||||
|
@ -448,7 +448,7 @@ fn fuzz_binary(
|
||||
println!("We imported {} inputs from disk.", state.corpus().count());
|
||||
}
|
||||
|
||||
// Remove target ouput (logs still survive)
|
||||
// Remove target output (logs still survive)
|
||||
#[cfg(unix)]
|
||||
{
|
||||
let null_fd = file_null.as_raw_fd();
|
||||
@ -675,7 +675,7 @@ fn fuzz_text(
|
||||
println!("We imported {} inputs from disk.", state.corpus().count());
|
||||
}
|
||||
|
||||
// Remove target ouput (logs still survive)
|
||||
// Remove target output (logs still survive)
|
||||
#[cfg(unix)]
|
||||
{
|
||||
let null_fd = file_null.as_raw_fd();
|
||||
|
@ -102,11 +102,11 @@ rm -rf libafl_unix_shmem_server || true
|
||||
(timeout 31s ./${FUZZER_NAME} >fuzz_stdout.log 2>/dev/null || true) &
|
||||
sleep 0.2
|
||||
timeout 30s ./${FUZZER_NAME} >/dev/null 2>/dev/null || true
|
||||
if [ -z "$(grep "corpus: 30" fuzz_stdout.log)" ]; then
|
||||
if grep -qa "corpus: 30" fuzz_stdout.log; then
|
||||
echo "Fuzzer is working"
|
||||
else
|
||||
echo "Fuzzer does not generate any testcases or any crashes"
|
||||
exit 1
|
||||
else
|
||||
echo "Fuzzer is working"
|
||||
fi
|
||||
'''
|
||||
dependencies = [ "fuzzer" ]
|
||||
|
@ -164,11 +164,11 @@ rm -rf libafl_unix_shmem_server || true
|
||||
(timeout 31s ./${FUZZER_NAME} >fuzz_stdout.log 2>/dev/null || true) &
|
||||
sleep 0.2
|
||||
timeout 30s ./${FUZZER_NAME} >/dev/null 2>/dev/null || true
|
||||
if [ -z "$(grep "corpus: 30" fuzz_stdout.log)" ]; then
|
||||
if grep -qa "corpus: 30" fuzz_stdout.log; then
|
||||
echo "Fuzzer is working"
|
||||
else
|
||||
echo "Fuzzer does not generate any testcases or any crashes"
|
||||
exit 1
|
||||
else
|
||||
echo "Fuzzer is working"
|
||||
fi
|
||||
'''
|
||||
dependencies = [ "fuzzer" ]
|
||||
|
@ -99,11 +99,11 @@ script_runner = "@shell"
|
||||
script='''
|
||||
rm -rf libafl_unix_shmem_server || true
|
||||
timeout 31s ./${FUZZER_NAME} --cores 0 --input ./corpus >fuzz_stdout.log 2>/dev/null || true
|
||||
if [ -z "$(grep "corpus: 30" fuzz_stdout.log)" ]; then
|
||||
if grep -qa "corpus: 30" fuzz_stdout.log; then
|
||||
echo "Fuzzer is working"
|
||||
else
|
||||
echo "Fuzzer does not generate any testcases or any crashes"
|
||||
exit 1
|
||||
else
|
||||
echo "Fuzzer is working"
|
||||
fi
|
||||
'''
|
||||
dependencies = [ "fuzzer" ]
|
||||
|
@ -99,11 +99,11 @@ script_runner = "@shell"
|
||||
script='''
|
||||
rm -rf libafl_unix_shmem_server || true
|
||||
timeout 31s ./${FUZZER_NAME} --cores 0 --input ./corpus 2>/dev/null >fuzz_stdout.log || true
|
||||
if [ -z "$(grep "corpus: 30" fuzz_stdout.log)" ]; then
|
||||
if grep -qa "corpus: 30" fuzz_stdout.log; then
|
||||
echo "Fuzzer is working"
|
||||
else
|
||||
echo "Fuzzer does not generate any testcases or any crashes"
|
||||
exit 1
|
||||
else
|
||||
echo "Fuzzer is working"
|
||||
fi
|
||||
'''
|
||||
dependencies = [ "fuzzer" ]
|
||||
|
@ -164,11 +164,11 @@ rm -rf libafl_unix_shmem_server || true
|
||||
timeout 31s ./${FUZZER_NAME} >fuzz_stdout.log &
|
||||
sleep 0.2
|
||||
timeout 30s ./${FUZZER_NAME} >/dev/null 2>/dev/null || true
|
||||
if [ -z "$(grep "corpus: 30" fuzz_stdout.log)" ]; then
|
||||
if grep -qa "corpus: 30" fuzz_stdout.log; then
|
||||
echo "Fuzzer is working"
|
||||
else
|
||||
echo "Fuzzer does not generate any testcases or any crashes"
|
||||
exit 1
|
||||
else
|
||||
echo "Fuzzer is working"
|
||||
fi
|
||||
'''
|
||||
dependencies = [ "fuzzer" ]
|
||||
|
@ -99,11 +99,11 @@ script_runner = "@shell"
|
||||
script='''
|
||||
rm -rf libafl_unix_shmem_server || true
|
||||
timeout 31s ./${FUZZER_NAME} --cores 0 --input ./corpus >fuzz_stdout.log 2>/dev/null || true
|
||||
if [ -z "$(grep "corpus: 30" fuzz_stdout.log)" ]; then
|
||||
if grep -qa "corpus: 30" fuzz_stdout.log; then
|
||||
echo "Fuzzer is working"
|
||||
else
|
||||
echo "Fuzzer does not generate any testcases or any crashes"
|
||||
exit 1
|
||||
else
|
||||
echo "Fuzzer is working"
|
||||
fi
|
||||
'''
|
||||
dependencies = [ "fuzzer" ]
|
||||
|
@ -100,11 +100,11 @@ script_runner = "@shell"
|
||||
script='''
|
||||
rm -rf libafl_unix_shmem_server || true
|
||||
timeout 31s ./${FUZZER_NAME}.coverage --broker-port 21337 --cores 0 --input ./corpus 2>/dev/null >fuzz_stdout.log || true
|
||||
if [ -z "$(grep "corpus: 30" fuzz_stdout.log)" ]; then
|
||||
if grep -qa "corpus: 30" fuzz_stdout.log; then
|
||||
echo "Fuzzer is working"
|
||||
else
|
||||
echo "Fuzzer does not generate any testcases or any crashes"
|
||||
exit 1
|
||||
else
|
||||
echo "Fuzzer is working"
|
||||
fi
|
||||
'''
|
||||
dependencies = [ "fuzzer" ]
|
||||
|
@ -105,11 +105,11 @@ rm -rf corpus/ || true
|
||||
mkdir corpus/ || true
|
||||
cp seeds/* corpus/ || true
|
||||
timeout 31s ./${FUZZER_NAME} --cores 0 --input ./corpus 2>/dev/null >fuzz_stdout.log || true
|
||||
if [ -z "$(grep "corpus: 30" fuzz_stdout.log)" ]; then
|
||||
if grep -qa "corpus: 30" fuzz_stdout.log; then
|
||||
echo "Fuzzer is working"
|
||||
else
|
||||
echo "Fuzzer does not generate any testcases or any crashes"
|
||||
exit 1
|
||||
else
|
||||
echo "Fuzzer is working"
|
||||
fi
|
||||
'''
|
||||
dependencies = [ "fuzzer" ]
|
||||
|
@ -164,11 +164,11 @@ rm -rf libafl_unix_shmem_server || true
|
||||
(timeout 31s ./${FUZZER_NAME} >fuzz_stdout.log 2>/dev/null || true) &
|
||||
sleep 0.2
|
||||
timeout 30s ./${FUZZER_NAME} >/dev/null 2>/dev/null || true
|
||||
if [ -z "$(grep "corpus: 30" fuzz_stdout.log)" ]; then
|
||||
if grep -qa "corpus: 30" fuzz_stdout.log; then
|
||||
echo "Fuzzer is working"
|
||||
else
|
||||
echo "Fuzzer does not generate any testcases or any crashes"
|
||||
exit 1
|
||||
else
|
||||
echo "Fuzzer is working"
|
||||
fi
|
||||
'''
|
||||
dependencies = [ "fuzzer" ]
|
||||
|
@ -65,11 +65,11 @@ rm -rf libafl_unix_shmem_server || true
|
||||
(timeout 31s ./${FUZZER_NAME} >fuzz_stdout.log 2>/dev/null || true) &
|
||||
sleep 0.2
|
||||
timeout 30s ./${FUZZER_NAME} >/dev/null 2>/dev/null || true
|
||||
if [ -z "$(grep "corpus: 30" fuzz_stdout.log)" ]; then
|
||||
if grep -qa "corpus: 30" fuzz_stdout.log; then
|
||||
echo "Fuzzer is working"
|
||||
else
|
||||
echo "Fuzzer does not generate any testcases or any crashes"
|
||||
exit 1
|
||||
else
|
||||
echo "Fuzzer is working"
|
||||
fi
|
||||
'''
|
||||
dependencies = [ "fuzzer" ]
|
||||
|
@ -107,11 +107,11 @@ script_runner = "@shell"
|
||||
script='''
|
||||
rm -rf libafl_unix_shmem_server || true
|
||||
timeout 31s ./${FUZZER_NAME} --cores 0 >fuzz_stdout.log 2>/dev/null || true
|
||||
if [ -z "$(grep "corpus: 8" fuzz_stdout.log)" ]; then
|
||||
if grep -qa "corpus: 8" fuzz_stdout.log; then
|
||||
echo "Fuzzer is working"
|
||||
else
|
||||
echo "Fuzzer does not generate any testcases or any crashes"
|
||||
exit 1
|
||||
else
|
||||
echo "Fuzzer is working"
|
||||
fi
|
||||
'''
|
||||
dependencies = [ "fuzzer" ]
|
||||
|
@ -95,10 +95,18 @@ where
|
||||
/// A file name to write all client output to
|
||||
#[builder(default = None)]
|
||||
stdout_file: Option<&'a str>,
|
||||
/// The actual, opened, stdout_file - so that we keep it open until the end
|
||||
#[cfg(all(unix, feature = "std", feature = "fork"))]
|
||||
#[builder(setter(skip), default = None)]
|
||||
opened_stdout_file: Option<File>,
|
||||
/// A file name to write all client stderr output to. If not specified, output is sent to
|
||||
/// `stdout_file`.
|
||||
#[builder(default = None)]
|
||||
stderr_file: Option<&'a str>,
|
||||
/// The actual, opened, stdout_file - so that we keep it open until the end
|
||||
#[cfg(all(unix, feature = "std", feature = "fork"))]
|
||||
#[builder(setter(skip), default = None)]
|
||||
opened_stderr_file: Option<File>,
|
||||
/// The `ip:port` address of another broker to connect our new broker to for multi-machine
|
||||
/// clusters.
|
||||
#[builder(default = None)]
|
||||
@ -166,12 +174,10 @@ where
|
||||
|
||||
log::info!("spawning on cores: {:?}", self.cores);
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
let stdout_file = self
|
||||
self.opened_stdout_file = self
|
||||
.stdout_file
|
||||
.map(|filename| File::create(filename).unwrap());
|
||||
#[cfg(feature = "std")]
|
||||
let stderr_file = self
|
||||
self.opened_stderr_file = self
|
||||
.stderr_file
|
||||
.map(|filename| File::create(filename).unwrap());
|
||||
|
||||
@ -204,9 +210,9 @@ where
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
if !debug_output {
|
||||
if let Some(file) = stdout_file {
|
||||
if let Some(file) = &self.opened_stdout_file {
|
||||
dup2(file.as_raw_fd(), libc::STDOUT_FILENO)?;
|
||||
if let Some(stderr) = stderr_file {
|
||||
if let Some(stderr) = &self.opened_stderr_file {
|
||||
dup2(stderr.as_raw_fd(), libc::STDERR_FILENO)?;
|
||||
} else {
|
||||
dup2(file.as_raw_fd(), libc::STDERR_FILENO)?;
|
||||
@ -423,12 +429,21 @@ where
|
||||
/// A file name to write all client output to
|
||||
#[builder(default = None)]
|
||||
stdout_file: Option<&'a str>,
|
||||
/// The actual, opened, stdout_file - so that we keep it open until the end
|
||||
#[cfg(all(unix, feature = "std", feature = "fork"))]
|
||||
#[builder(setter(skip), default = None)]
|
||||
opened_stdout_file: Option<File>,
|
||||
/// A file name to write all client stderr output to. If not specified, output is sent to
|
||||
/// `stdout_file`.
|
||||
#[builder(default = None)]
|
||||
stderr_file: Option<&'a str>,
|
||||
/// The actual, opened, stdout_file - so that we keep it open until the end
|
||||
#[cfg(all(unix, feature = "std", feature = "fork"))]
|
||||
#[builder(setter(skip), default = None)]
|
||||
opened_stderr_file: Option<File>,
|
||||
/// The `ip:port` address of another broker to connect our new broker to for multi-machine
|
||||
/// clusters.
|
||||
|
||||
#[builder(default = None)]
|
||||
remote_broker_addr: Option<SocketAddr>,
|
||||
/// If this launcher should spawn a new `broker` on `[Self::broker_port]` (default).
|
||||
@ -503,10 +518,10 @@ where
|
||||
|
||||
log::info!("spawning on cores: {:?}", self.cores);
|
||||
|
||||
let stdout_file = self
|
||||
self.opened_stdout_file = self
|
||||
.stdout_file
|
||||
.map(|filename| File::create(filename).unwrap());
|
||||
let stderr_file = self
|
||||
self.opened_stderr_file = self
|
||||
.stderr_file
|
||||
.map(|filename| File::create(filename).unwrap());
|
||||
|
||||
@ -556,9 +571,9 @@ where
|
||||
std::thread::sleep(std::time::Duration::from_millis(index * 10));
|
||||
|
||||
if !debug_output {
|
||||
if let Some(file) = stdout_file {
|
||||
if let Some(file) = &self.opened_stdout_file {
|
||||
dup2(file.as_raw_fd(), libc::STDOUT_FILENO)?;
|
||||
if let Some(stderr) = stderr_file {
|
||||
if let Some(stderr) = &self.opened_stderr_file {
|
||||
dup2(stderr.as_raw_fd(), libc::STDERR_FILENO)?;
|
||||
} else {
|
||||
dup2(file.as_raw_fd(), libc::STDERR_FILENO)?;
|
||||
|
@ -154,7 +154,7 @@ impl ConfigTarget for Command {
|
||||
if memlimit == 0 {
|
||||
return self;
|
||||
}
|
||||
// SAFETY
|
||||
// # Safety
|
||||
// This method does not do shady pointer foo.
|
||||
// It merely call libc functions.
|
||||
let func = move || {
|
||||
@ -181,7 +181,7 @@ impl ConfigTarget for Command {
|
||||
}
|
||||
Ok(())
|
||||
};
|
||||
// # SAFETY
|
||||
// # Safety
|
||||
// This calls our non-shady function from above.
|
||||
unsafe { self.pre_exec(func) }
|
||||
}
|
||||
@ -547,7 +547,7 @@ where
|
||||
self.executor.shmem_mut().is_some(),
|
||||
"The uses_shmem_testcase() bool can only exist when a map is set"
|
||||
);
|
||||
// # SAFETY
|
||||
// # Safety
|
||||
// Struct can never be created when uses_shmem_testcase is true and map is none.
|
||||
let map = unsafe { self.executor.shmem_mut().as_mut().unwrap_unchecked() };
|
||||
let target_bytes = input.target_bytes();
|
||||
@ -1237,7 +1237,7 @@ where
|
||||
self.map.is_some(),
|
||||
"The uses_shmem_testcase bool can only exist when a map is set"
|
||||
);
|
||||
// # SAFETY
|
||||
// # Safety
|
||||
// Struct can never be created when uses_shmem_testcase is true and map is none.
|
||||
let map = unsafe { self.map.as_mut().unwrap_unchecked() };
|
||||
let target_bytes = input.target_bytes();
|
||||
|
@ -1184,7 +1184,8 @@ pub mod pybind {
|
||||
EM: EventFirer<State = PythonStdState>,
|
||||
OT: ObserversTuple<PythonStdState>,
|
||||
{
|
||||
// SAFETY: We use this observer in Python ony when the ObserverTuple is PythonObserversTuple
|
||||
// # Safety
|
||||
// We use this observer in Python ony when the ObserverTuple is PythonObserversTuple
|
||||
let dont_look_at_this: &PythonObserversTuple =
|
||||
unsafe { &*(observers as *const OT as *const PythonObserversTuple) };
|
||||
let dont_look_at_this2: &PythonEventManager =
|
||||
@ -1217,7 +1218,8 @@ pub mod pybind {
|
||||
where
|
||||
OT: ObserversTuple<PythonStdState>,
|
||||
{
|
||||
// SAFETY: We use this observer in Python ony when the ObserverTuple is PythonObserversTuple
|
||||
// # Safety
|
||||
// We use this observer in Python ony when the ObserverTuple is PythonObserversTuple
|
||||
let dont_look_at_this: &PythonObserversTuple =
|
||||
unsafe { &*(observers as *const OT as *const PythonObserversTuple) };
|
||||
Python::with_gil(|py| -> PyResult<()> {
|
||||
|
@ -97,6 +97,7 @@ extern crate std;
|
||||
#[macro_use]
|
||||
#[doc(hidden)]
|
||||
pub extern crate alloc;
|
||||
|
||||
#[cfg(feature = "ctor")]
|
||||
#[doc(hidden)]
|
||||
pub use ctor::ctor;
|
||||
@ -159,6 +160,8 @@ pub mod bolts_prelude {
|
||||
pub use super::{cpu::*, os::*};
|
||||
}
|
||||
|
||||
#[cfg(all(unix, feature = "std"))]
|
||||
use alloc::boxed::Box;
|
||||
#[cfg(feature = "alloc")]
|
||||
use alloc::vec::Vec;
|
||||
#[cfg(all(not(feature = "xxh3"), feature = "alloc"))]
|
||||
@ -170,15 +173,17 @@ use std::time::{SystemTime, UNIX_EPOCH};
|
||||
#[cfg(all(unix, feature = "std"))]
|
||||
use std::{
|
||||
fs::File,
|
||||
io::Write,
|
||||
io::{stderr, stdout, Write},
|
||||
mem,
|
||||
os::fd::{FromRawFd, RawFd},
|
||||
os::fd::{AsRawFd, FromRawFd, RawFd},
|
||||
panic,
|
||||
};
|
||||
|
||||
// There's a bug in ahash that doesn't let it build in `alloc` without once_cell right now.
|
||||
// TODO: re-enable once <https://github.com/tkaitchuck/aHash/issues/155> is resolved.
|
||||
#[cfg(all(not(feature = "xxh3"), feature = "alloc"))]
|
||||
use ahash::RandomState;
|
||||
use log::SetLoggerError;
|
||||
use serde::{Deserialize, Serialize};
|
||||
#[cfg(feature = "xxh3")]
|
||||
use xxhash_rust::xxh3::xxh3_64;
|
||||
@ -570,6 +575,13 @@ impl From<TryFromSliceError> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SetLoggerError> for Error {
|
||||
#[allow(unused_variables)]
|
||||
fn from(err: SetLoggerError) -> Self {
|
||||
Self::illegal_state(format!("Failed to register logger: {err:?}"))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
impl From<windows::core::Error> for Error {
|
||||
#[allow(unused_variables)]
|
||||
@ -795,6 +807,10 @@ pub static LIBAFL_STDERR_LOGGER: SimpleStderrLogger = SimpleStderrLogger::new();
|
||||
#[cfg(feature = "std")]
|
||||
pub static LIBAFL_STDOUT_LOGGER: SimpleStdoutLogger = SimpleStdoutLogger::new();
|
||||
|
||||
/// A logger we can use log to raw fds.
|
||||
#[cfg(all(unix, feature = "std"))]
|
||||
static mut LIBAFL_RAWFD_LOGGER: SimpleFdLogger = unsafe { SimpleFdLogger::new(1) };
|
||||
|
||||
/// A simple logger struct that logs to stdout when used with [`log::set_logger`].
|
||||
#[derive(Debug)]
|
||||
#[cfg(feature = "std")]
|
||||
@ -817,8 +833,8 @@ impl SimpleStdoutLogger {
|
||||
|
||||
/// register stdout logger
|
||||
pub fn set_logger() -> Result<(), Error> {
|
||||
log::set_logger(&LIBAFL_STDOUT_LOGGER)
|
||||
.map_err(|_| Error::unknown("Failed to register logger"))
|
||||
log::set_logger(&LIBAFL_STDOUT_LOGGER)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@ -863,8 +879,8 @@ impl SimpleStderrLogger {
|
||||
|
||||
/// register stderr logger
|
||||
pub fn set_logger() -> Result<(), Error> {
|
||||
log::set_logger(&LIBAFL_STDERR_LOGGER)
|
||||
.map_err(|_| Error::unknown("Failed to register logger"))
|
||||
log::set_logger(&LIBAFL_STDERR_LOGGER)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@ -912,6 +928,22 @@ impl SimpleFdLogger {
|
||||
pub unsafe fn set_fd(&mut self, fd: RawFd) {
|
||||
self.fd = fd;
|
||||
}
|
||||
|
||||
/// Register this logger, logging to the given `fd`
|
||||
///
|
||||
/// # Safety
|
||||
/// This function may not be called multiple times concurrently.
|
||||
/// The passed-in `fd` has to be a legal file descriptor to log to.
|
||||
pub unsafe fn set_logger(log_fd: RawFd) -> Result<(), Error> {
|
||||
// # Safety
|
||||
// The passed-in `fd` has to be a legal file descriptor to log to.
|
||||
// We also access a shared variable here.
|
||||
unsafe {
|
||||
LIBAFL_RAWFD_LOGGER.set_fd(log_fd);
|
||||
log::set_logger(&LIBAFL_RAWFD_LOGGER)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "std", unix))]
|
||||
@ -937,6 +969,42 @@ impl log::Log for SimpleFdLogger {
|
||||
fn flush(&self) {}
|
||||
}
|
||||
|
||||
/// Closes `stdout` and `stderr` and returns a new `stdout` and `stderr`
|
||||
/// to be used in the fuzzer for further logging.
|
||||
///
|
||||
/// # Safety
|
||||
/// The function is arguably safe, but it might have undesirable side effects since it closes `stdout` and `stderr`.
|
||||
#[cfg(all(unix, feature = "std"))]
|
||||
pub unsafe fn dup_and_mute_outputs() -> Result<(RawFd, RawFd), Error> {
|
||||
let old_stdout = stdout().as_raw_fd();
|
||||
let old_stderr = stderr().as_raw_fd();
|
||||
let null_fd = crate::os::null_fd()?;
|
||||
|
||||
let new_stdout = crate::os::dup(old_stdout)?;
|
||||
let new_stderr = crate::os::dup(old_stderr)?;
|
||||
|
||||
crate::os::dup2(null_fd, old_stdout)?;
|
||||
crate::os::dup2(null_fd, old_stderr)?;
|
||||
|
||||
Ok((new_stdout, new_stderr))
|
||||
}
|
||||
|
||||
/// Set up an error print hook that will
|
||||
///
|
||||
/// # Safety
|
||||
/// Will fail if `new_stderr` is not a valid file descriptor.
|
||||
/// May not be called multiple times concurrently.
|
||||
#[cfg(all(unix, feature = "std"))]
|
||||
pub unsafe fn set_error_print_panic_hook(new_stderr: RawFd) {
|
||||
// Make sure potential errors get printed to the correct (non-closed) stderr
|
||||
panic::set_hook(Box::new(move |panic_info| {
|
||||
let mut f = unsafe { File::from_raw_fd(new_stderr) };
|
||||
writeln!(f, "{panic_info}",)
|
||||
.unwrap_or_else(|err| println!("Failed to log to fd {new_stderr}: {err}"));
|
||||
std::mem::forget(f);
|
||||
}));
|
||||
}
|
||||
|
||||
#[cfg(feature = "python")]
|
||||
#[allow(missing_docs)]
|
||||
pub mod pybind {
|
||||
@ -1083,19 +1151,16 @@ pub mod pybind {
|
||||
mod tests {
|
||||
|
||||
#[cfg(all(feature = "std", unix))]
|
||||
use crate::SimpleFdLogger;
|
||||
|
||||
#[cfg(all(feature = "std", unix))]
|
||||
pub static mut LOGGER: SimpleFdLogger = unsafe { SimpleFdLogger::new(1) };
|
||||
use crate::LIBAFL_RAWFD_LOGGER;
|
||||
|
||||
#[test]
|
||||
#[cfg(all(unix, feature = "std"))]
|
||||
fn test_logger() {
|
||||
use std::{io::stdout, os::fd::AsRawFd};
|
||||
|
||||
unsafe { LOGGER.fd = stdout().as_raw_fd() };
|
||||
unsafe { LIBAFL_RAWFD_LOGGER.fd = stdout().as_raw_fd() };
|
||||
unsafe {
|
||||
log::set_logger(&LOGGER).unwrap();
|
||||
log::set_logger(&LIBAFL_RAWFD_LOGGER).unwrap();
|
||||
}
|
||||
log::set_max_level(log::LevelFilter::Debug);
|
||||
log::info!("Test");
|
||||
|
@ -1,9 +1,6 @@
|
||||
//! Operating System specific abstractions
|
||||
//!
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use std::{env, process::Command};
|
||||
|
||||
#[cfg(any(unix, all(windows, feature = "std")))]
|
||||
use crate::Error;
|
||||
|
||||
@ -17,7 +14,15 @@ pub mod unix_signals;
|
||||
pub mod pipes;
|
||||
|
||||
#[cfg(all(unix, feature = "std"))]
|
||||
use std::ffi::CString;
|
||||
use alloc::borrow::Cow;
|
||||
#[cfg(all(unix, feature = "std"))]
|
||||
use core::ffi::CStr;
|
||||
#[cfg(feature = "std")]
|
||||
use std::{env, process::Command};
|
||||
#[cfg(all(unix, feature = "std"))]
|
||||
use std::{ffi::CString, os::fd::RawFd};
|
||||
#[cfg(all(unix, feature = "std"))]
|
||||
use std::{fs::File, os::fd::AsRawFd, sync::OnceLock};
|
||||
|
||||
// Allow a few extra features we need for the whole module
|
||||
#[cfg(all(windows, feature = "std"))]
|
||||
@ -27,6 +32,10 @@ pub mod windows_exceptions;
|
||||
#[cfg(unix)]
|
||||
use libc::pid_t;
|
||||
|
||||
/// A file that we keep open, pointing to /dev/null
|
||||
#[cfg(all(feature = "std", unix))]
|
||||
static NULL_FILE: OnceLock<File> = OnceLock::new();
|
||||
|
||||
/// Child Process Handle
|
||||
#[cfg(unix)]
|
||||
#[derive(Debug)]
|
||||
@ -91,11 +100,51 @@ pub fn startable_self() -> Result<Command, Error> {
|
||||
Ok(startable)
|
||||
}
|
||||
|
||||
/// "Safe" wrapper around dup2
|
||||
/// "Safe" wrapper around `dup`, duplicating the given file descriptor
|
||||
///
|
||||
/// # Safety
|
||||
/// The fd need to be a legal fd.
|
||||
#[cfg(all(unix, feature = "std"))]
|
||||
pub fn dup2(fd: i32, device: i32) -> Result<(), Error> {
|
||||
pub fn dup(fd: RawFd) -> Result<RawFd, Error> {
|
||||
match unsafe { libc::dup(fd) } {
|
||||
-1 => Err(Error::file(std::io::Error::last_os_error())),
|
||||
new_fd => Ok(new_fd),
|
||||
}
|
||||
}
|
||||
|
||||
/// "Safe" wrapper around dup2
|
||||
///
|
||||
/// # Safety
|
||||
/// The fds need to be legal fds.
|
||||
#[cfg(all(unix, feature = "std"))]
|
||||
pub fn dup2(fd: RawFd, device: RawFd) -> Result<(), Error> {
|
||||
match unsafe { libc::dup2(fd, device) } {
|
||||
-1 => Err(Error::file(std::io::Error::last_os_error())),
|
||||
_ => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the stringified version of the last `errno`.
|
||||
/// This is roughly equivalent to `strerror(errno)` in C.
|
||||
#[cfg(all(unix, feature = "std"))]
|
||||
#[must_use]
|
||||
pub fn last_error_str<'a>() -> Option<Cow<'a, str>> {
|
||||
std::io::Error::last_os_error().raw_os_error().map(|errno| {
|
||||
// # Safety
|
||||
//
|
||||
// Calling the `strerror` libc functions with the correct `errno`
|
||||
unsafe { CStr::from_ptr(libc::strerror(errno)).to_string_lossy() }
|
||||
})
|
||||
}
|
||||
|
||||
/// Get a file descriptor ([`RawFd`]) pointing to "/dev/null"
|
||||
#[cfg(all(unix, feature = "std"))]
|
||||
pub fn null_fd() -> Result<RawFd, Error> {
|
||||
// We don't care about opening the file twice here - races are ok.
|
||||
if let Some(file) = NULL_FILE.get() {
|
||||
Ok(file.as_raw_fd())
|
||||
} else {
|
||||
let null_file = File::open("/dev/null")?;
|
||||
Ok(NULL_FILE.get_or_init(move || null_file).as_raw_fd())
|
||||
}
|
||||
}
|
||||
|
@ -192,7 +192,8 @@ where
|
||||
#[allow(clippy::cast_possible_truncation)] // we cannot have more than usize elements..
|
||||
let hash = (self.build_hasher.hash_one(location) % usize::MAX as u64) as usize;
|
||||
let val = unsafe {
|
||||
// SAFETY: the index is modulo by the length, therefore it is always in bounds
|
||||
// # Safety
|
||||
// The index is modulo by the length, therefore it is always in bounds
|
||||
let len = self.hitcounts_map.len();
|
||||
self.hitcounts_map
|
||||
.as_mut_slice()
|
||||
|
@ -1,10 +1,11 @@
|
||||
use core::ffi::c_int;
|
||||
#[cfg(unix)]
|
||||
use std::io::Write;
|
||||
use std::io::{stderr, stdout, Write};
|
||||
use std::{
|
||||
fmt::Debug,
|
||||
fs::File,
|
||||
net::TcpListener,
|
||||
os::fd::AsRawFd,
|
||||
str::FromStr,
|
||||
time::{SystemTime, UNIX_EPOCH},
|
||||
};
|
||||
@ -35,23 +36,21 @@ use crate::{feedbacks::LibfuzzerCrashCauseMetadata, fuzz_with, options::Libfuzze
|
||||
fn destroy_output_fds(options: &LibfuzzerOptions) {
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use std::os::fd::AsRawFd;
|
||||
use libafl_bolts::os::{dup2, null_fd};
|
||||
|
||||
let null_fd = null_fd().unwrap();
|
||||
let stdout_fd = stdout().as_raw_fd();
|
||||
let stderr_fd = stderr().as_raw_fd();
|
||||
|
||||
if options.tui() {
|
||||
let file_null = File::open("/dev/null").unwrap();
|
||||
unsafe {
|
||||
libc::dup2(file_null.as_raw_fd(), 1);
|
||||
libc::dup2(file_null.as_raw_fd(), 2);
|
||||
}
|
||||
dup2(null_fd, stdout_fd).unwrap();
|
||||
dup2(null_fd, stderr_fd).unwrap();
|
||||
} else if options.close_fd_mask() != 0 {
|
||||
let file_null = File::open("/dev/null").unwrap();
|
||||
unsafe {
|
||||
if options.close_fd_mask() & 1 != 0 {
|
||||
libc::dup2(file_null.as_raw_fd(), 1);
|
||||
}
|
||||
if options.close_fd_mask() & 2 != 0 {
|
||||
libc::dup2(file_null.as_raw_fd(), 2);
|
||||
if options.close_fd_mask() & u8::try_from(stderr_fd).unwrap() != 0 {
|
||||
dup2(null_fd, stdout_fd).unwrap();
|
||||
}
|
||||
if options.close_fd_mask() & u8::try_from(stderr_fd).unwrap() != 0 {
|
||||
dup2(null_fd, stderr_fd).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user