emu::current_cpu() is now the CPU that hitted the breakpoint in fullsystem (#910)

* emu::current_cpu() is now kept after vm stop and it is the CPU that hitted the breakpoint

* clippy

* uninit

* clippy

* clippy

* clippy

* clippy

* nightly override in CI

* nightly override in CI

* components

* components

* targets

* targets

* clippy

* clippy

* clippy

* clippy

* clippy (again)

* MaybeUninit

Co-authored-by: Dominik Maier <dmnk@google.com>
This commit is contained in:
Andrea Fioraldi 2022-11-25 11:57:08 +01:00 committed by GitHub
parent bc85129cd9
commit c2776e117a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 64 additions and 109 deletions

View File

@ -20,6 +20,7 @@ jobs:
with:
profile: minimal
toolchain: nightly
override: true
- name: install mdbook
uses: baptiste0928/cargo-install@v1.3.0
with:
@ -193,10 +194,12 @@ jobs:
with:
profile: minimal
toolchain: nightly
- name: Add nightly rustfmt and clippy
run: rustup toolchain install nightly && rustup target add --toolchain nightly aarch64-unknown-none && rustup component add --toolchain nightly rust-src && rustup target add thumbv6m-none-eabi
override: true
components: rustfmt, clippy, rust-src
- uses: actions/checkout@v3
- uses: Swatinem/rust-cache@v2
- name: Add targets
run: rustup target add arm-linux-androideabi && rustup target add thumbv6m-none-eabi
- name: Build aarch64-unknown-none
run: cd ./fuzzers/baby_no_std && cargo +nightly build -Zbuild-std=core,alloc --target aarch64-unknown-none -v --release && cd ../..
- name: run x86_64 until panic!

View File

@ -31,10 +31,7 @@ fn adder_loop(port: u16) -> ! {
loop {
let mut msg_counter = 0;
loop {
let (sender, tag, buf) = match client.recv_buf().unwrap() {
None => break,
Some(msg) => msg,
};
let Some((sender, tag, buf)) = client.recv_buf().unwrap() else { break };
msg_counter += 1;
match tag {
_TAG_SIMPLE_U32_V1 => {

View File

@ -41,7 +41,7 @@ macro_rules! impl_asany {
/// Get a `type_id` from its previously unpacked `u64`.
/// Opposite of [`unpack_type_id(id)`].
///
/// # Safety
/// # Note
/// Probably not safe for future compilers, fine for now.
#[must_use]
pub fn pack_type_id(id: u64) -> TypeId {
@ -52,7 +52,7 @@ pub fn pack_type_id(id: u64) -> TypeId {
/// Unpack a `type_id` to an `u64`
/// Opposite of [`pack_type_id(id)`].
///
/// # Safety
/// # Note
/// Probably not safe for future compilers, fine for now.
#[must_use]
pub fn unpack_type_id(id: TypeId) -> u64 {

View File

@ -8,7 +8,7 @@ use core::cell::RefCell;
use std::os::unix::prelude::{AsRawFd, RawFd};
use std::{
fs::{self, remove_file, File, OpenOptions},
io::{Seek, SeekFrom, Write},
io::{Seek, Write},
path::{Path, PathBuf},
};
@ -124,7 +124,7 @@ impl InputFile {
/// Rewinds the file to the beginning
#[inline]
pub fn rewind(&mut self) -> Result<(), Error> {
if let Err(err) = self.file.seek(SeekFrom::Start(0)) {
if let Err(err) = self.file.rewind() {
Err(err.into())
} else {
Ok(())

View File

@ -2681,17 +2681,14 @@ where
};
println!("Connected to port {port}");
let broker_shmem_description = if let TcpResponse::BrokerConnectHello {
let TcpResponse::BrokerConnectHello {
broker_shmem_description,
hostname: _,
} = recv_tcp_msg(&mut stream)?.try_into()?
{
broker_shmem_description
} else {
} = recv_tcp_msg(&mut stream)?.try_into()? else {
return Err(Error::illegal_state(
"Received unexpected Broker Hello".to_string(),
));
};
};
let map = LlmpSharedMap::existing(
shmem_provider.shmem_from_description(broker_shmem_description)?,
@ -2706,15 +2703,11 @@ where
send_tcp_msg(&mut stream, &client_hello_req)?;
let client_id = if let TcpResponse::LocalClientAccepted { client_id } =
recv_tcp_msg(&mut stream)?.try_into()?
{
client_id
} else {
return Err(Error::illegal_state(
"Unexpected Response from Broker".to_string(),
let TcpResponse::LocalClientAccepted { client_id } = recv_tcp_msg(&mut stream)?.try_into()? else {
return Err(Error::illegal_state(
"Unexpected Response from Broker".to_string(),
));
};
};
// Set our ID to the one the broker sent us..
// This is mainly so we can filter out our own msgs later.

View File

@ -348,12 +348,9 @@ impl Drop for ShMemServiceThread {
fn drop(&mut self) {
if self.join_handle.is_some() {
println!("Stopping ShMemService");
let mut stream = match UnixStream::connect_to_unix_addr(
let Ok(mut stream) = UnixStream::connect_to_unix_addr(
&UnixSocketAddr::new(UNIX_SERVER_NAME).unwrap(),
) {
Ok(stream) => stream,
Err(_) => return, // ignoring non-started server
};
) else { return };
let body = postcard::to_allocvec(&ServedShMemRequest::Exit).unwrap();

View File

@ -234,7 +234,7 @@ where
/// Match for a name and return the value
///
/// # Safety
/// # Note
/// This operation is unsafe with Rust stable, wait for [specialization](https://stackoverflow.com/a/60138532/7658998).
pub trait MatchName {
/// Match for a name and return the borrowed value

View File

@ -535,13 +535,12 @@ impl CommandExecutorBuilder {
OT: Debug + MatchName + ObserversTuple<S>,
S: UsesInput,
{
let program = if let Some(program) = &self.program {
program
} else {
return Err(Error::illegal_argument(
let Some(program) = &self.program else {
return Err(Error::illegal_argument(
"ComandExecutor::builder: no program set!",
));
));
};
let mut command = Command::new(program);
match &self.input_location {
InputLocation::StdIn => {

View File

@ -328,15 +328,13 @@ impl Forkserver {
/// Read a message from the child process.
pub fn read_st_timed(&mut self, timeout: &TimeSpec) -> Result<Option<i32>, Error> {
let mut buf: [u8; 4] = [0_u8; 4];
let st_read = match self.st_pipe.read_end() {
Some(fd) => fd,
None => {
return Err(Error::file(io::Error::new(
ErrorKind::BrokenPipe,
let Some(st_read) = self.st_pipe.read_end() else {
return Err(Error::file(io::Error::new(
ErrorKind::BrokenPipe,
"Read pipe end was already closed",
)));
}
};
};
let mut readfds = FdSet::new();
readfds.insert(st_read);
// We'll pass a copied timeout to keep the original timeout intact, because select updates timeout to indicate how much time was left. See select(2)

View File

@ -169,19 +169,13 @@ impl Tokens {
if line.is_empty() || start == Some('#') {
continue;
}
let pos_quote = match line.find('\"') {
Some(x) => x,
None => return Err(Error::illegal_argument(format!("Illegal line: {line}"))),
};
let Some(pos_quote) = line.find('\"') else { return Err(Error::illegal_argument(format!("Illegal line: {line}"))) };
if line.chars().nth(line.len() - 1) != Some('"') {
return Err(Error::illegal_argument(format!("Illegal line: {line}")));
}
// extract item
let item = match line.get(pos_quote + 1..line.len() - 1) {
Some(x) => x,
None => return Err(Error::illegal_argument(format!("Illegal line: {line}"))),
};
let Some(item) = line.get(pos_quote + 1..line.len() - 1) else { return Err(Error::illegal_argument(format!("Illegal line: {line}"))) };
if item.is_empty() {
continue;
}

View File

@ -548,7 +548,7 @@ where
/// Creates a new [`MapObserver`] from an [`OwnedSliceMut`] map.
///
/// # Safety
/// # Note
/// Will dereference the owned slice with up to len elements.
#[must_use]
pub fn new_from_ownedref<S>(name: S, map: OwnedSliceMut<'a, T>) -> Self
@ -594,7 +594,7 @@ where
/// Creates a new [`MapObserver`] from an [`OwnedSliceMut`] map in differential mode.
///
/// # Safety
/// # Note
/// Will dereference the owned slice with up to len elements.
#[must_use]
pub fn differential_from_ownedref<S>(name: S, map: OwnedSliceMut<'a, T>) -> Self

View File

@ -264,10 +264,7 @@ where
/// Cull the `Corpus`
#[allow(clippy::unused_self)]
pub fn accounting_cull(&self, state: &mut CS::State) -> Result<(), Error> {
let top_rated = match state.metadata().get::<TopAccountingMetadata>() {
None => return Ok(()),
Some(val) => val,
};
let Some(top_rated) = state.metadata().get::<TopAccountingMetadata>() else { return Ok(()) };
for (_key, idx) in &top_rated.map {
let mut entry = state.corpus().get(*idx)?.borrow_mut();

View File

@ -273,10 +273,7 @@ where
/// Cull the `Corpus` using the `MinimizerScheduler`
#[allow(clippy::unused_self)]
pub fn cull(&self, state: &mut CS::State) -> Result<(), Error> {
let top_rated = match state.metadata().get::<TopRatedsMetadata>() {
None => return Ok(()),
Some(val) => val,
};
let Some(top_rated) = state.metadata().get::<TopRatedsMetadata>() else { return Ok(()) };
let mut acc = HashSet::new();

View File

@ -349,15 +349,13 @@ impl Allocator {
#[allow(clippy::missing_safety_doc)]
pub unsafe fn release(&mut self, ptr: *mut c_void) {
//println!("freeing address: {:?}", ptr);
let mut metadata = if let Some(metadata) = self.allocations.get_mut(&(ptr as usize)) {
metadata
} else {
let Some(metadata) = self.allocations.get_mut(&(ptr as usize)) else {
if !ptr.is_null() {
AsanErrors::get_mut()
AsanErrors::get_mut()
.report_error(AsanError::UnallocatedFree((ptr as usize, Backtrace::new())));
}
return;
};
}
return;
};
if metadata.freed {
AsanErrors::get_mut().report_error(AsanError::DoubleFree((

View File

@ -60,21 +60,15 @@ impl NyxHelper {
parent_cpu_id: Option<u32>,
initial_timeout: Duration,
) -> Result<Self, Error> {
let sharedir = match target_dir.to_str() {
Some(x) => x,
None => return Err(Error::illegal_argument("can't convert sharedir to str")),
};
let Some(sharedir) = target_dir.to_str() else { return Err(Error::illegal_argument("can't convert sharedir to str")) };
let work_dir = target_dir.join("workdir");
let work_dir = work_dir.to_str().expect("unable to convert workdir to str");
let nyx_type = if parallel_mode {
let parent_cpu_id = match parent_cpu_id {
None => {
return Err(Error::illegal_argument(
"please set parent_cpu_id in nyx parallel mode",
))
}
Some(x) => x,
};
let Some(parent_cpu_id) = parent_cpu_id else {
return Err(Error::illegal_argument(
"please set parent_cpu_id in nyx parallel mode",
))
};
if cpu_id == parent_cpu_id {
NyxProcessType::PARENT
} else {

View File

@ -4,7 +4,7 @@ use which::which;
const QEMU_URL: &str = "https://github.com/AFLplusplus/qemu-libafl-bridge";
const QEMU_DIRNAME: &str = "qemu-libafl-bridge";
const QEMU_REVISION: &str = "f26a5ca6137bb5d4d0dcfe5451fb16d4c0551c4e";
const QEMU_REVISION: &str = "6db12fe4df0eb1305261cf07d1995f21eb262392";
fn build_dep_check(tools: &[&str]) {
for tool in tools {

View File

@ -50,7 +50,7 @@ impl<S> QemuHelper<S> for QemuCallTracerHelper
where
S: UsesInput,
{
fn init_hooks<'a, QT>(&self, hooks: &QemuHooks<'a, QT, S>)
fn init_hooks<QT>(&self, hooks: &QemuHooks<'_, QT, S>)
where
QT: QemuHelperTuple<S>,
{

View File

@ -1,13 +1,14 @@
//! Expose QEMU user `LibAFL` C api to Rust
#[cfg(emulation_mode = "usermode")]
use core::mem::MaybeUninit;
use core::{
convert::Into,
ffi::c_void,
ptr::{addr_of, addr_of_mut, copy_nonoverlapping, null},
ptr::{addr_of, copy_nonoverlapping, null},
};
use std::{ffi::CString, slice::from_raw_parts, str::from_utf8_unchecked};
#[cfg(emulation_mode = "systemmode")]
use std::ffi::CString;
use std::{slice::from_raw_parts, str::from_utf8_unchecked};
#[cfg(emulation_mode = "usermode")]
use libc::c_int;
@ -539,7 +540,6 @@ impl CPU {
pub fn write_reg<R, T>(&self, reg: R, val: T) -> Result<(), String>
where
T: Num + PartialOrd + Copy,
R: Into<i32>,
{
let reg = reg.into();
@ -553,16 +553,17 @@ impl CPU {
pub fn read_reg<R, T>(&self, reg: R) -> Result<T, String>
where
T: Num + PartialOrd + Copy,
R: Into<i32>,
{
let reg = reg.into();
let mut val = T::zero();
let success = unsafe { libafl_qemu_read_reg(self.ptr, reg, addr_of_mut!(val) as *mut u8) };
if success == 0 {
Err(format!("Failed to read register {reg}"))
} else {
Ok(val)
unsafe {
let reg = reg.into();
let mut val = MaybeUninit::uninit();
let success = libafl_qemu_read_reg(self.ptr, reg, val.as_mut_ptr() as *mut u8);
if success == 0 {
Err(format!("Failed to read register {reg}"))
} else {
Ok(val.assume_init())
}
}
}
@ -794,12 +795,6 @@ impl Emulator {
pub fn load_addr(&self) -> GuestAddr {
unsafe { libafl_load_addr() as GuestAddr }
}
#[cfg(emulation_mode = "systemmode")]
#[must_use]
pub fn load_addr(&self) -> GuestAddr {
// Only work if the binary is linked to the correct address and not pie
return 0x0 as GuestAddr;
}
#[cfg(emulation_mode = "usermode")]
#[must_use]

View File

@ -37,10 +37,6 @@ pub use __afl_acc_memop_ptr as ACCOUNTING_MEMOP_MAP_PTR;
pub use __afl_area_ptr as EDGES_MAP_PTR;
/// Return Tokens from the compile-time token section
///
/// # Safety
///
/// This fn is safe to call, as long as the compilation did not break, previously
#[cfg(any(target_os = "linux", target_vendor = "apple"))]
pub fn autotokens() -> Result<Tokens, Error> {
unsafe {

View File

@ -7,7 +7,7 @@ extern "C" {
/// Start the forkserver from this point. Any shared memory must be created before.
///
/// # Safety
/// # Note
///
/// The forkserver logic is written in C and this code is a wrapper.
pub fn start_forkserver() -> ! {

View File

@ -14,7 +14,7 @@ extern "C" {
/// Calls the (native) libfuzzer initialize function.
/// Returns the value returned by the init function.
/// # Safety
/// # Note
/// Calls the libfuzzer-style init function which is native code.
#[allow(clippy::similar_names)]
#[allow(clippy::must_use_candidate)] // nobody uses that return code...
@ -31,7 +31,7 @@ pub fn libfuzzer_initialize(args: &[String]) -> i32 {
}
/// Call a single input of a libfuzzer-style cpp-harness
/// # Safety
/// # Note
/// Calls the libfuzzer harness. We actually think the target is unsafe and crashes eventually, that's why we do all this fuzzing.
#[allow(clippy::must_use_candidate)]
pub fn libfuzzer_test_one_input(buf: &[u8]) -> i32 {

View File

@ -7,9 +7,6 @@ use core::slice::from_raw_parts_mut;
pub static mut COUNTERS_MAPS: Vec<&'static mut [u8]> = Vec::new();
/// Initialize the sancov `8-bit-counters` - usually called by `llvm`.
///
/// # Safety
/// Set up our coverage maps.
#[no_mangle]
#[allow(clippy::cast_sign_loss)]
#[allow(clippy::not_unsafe_ptr_arg_deref)]