No more (direct) mutable references to mutable statics (#2550)
* No more (direct) mutable references to mutable statics * More * Fix build, but it's unsafe dude * more * fmt * More fix * more?
This commit is contained in:
parent
691fd1f8cb
commit
f0d85aaaa5
@ -938,7 +938,7 @@ pub trait AdaptiveSerializer {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
||||||
use core::ptr::addr_of_mut;
|
use core::ptr::{addr_of, addr_of_mut};
|
||||||
|
|
||||||
use libafl_bolts::{current_time, tuples::tuple_list, Named};
|
use libafl_bolts::{current_time, tuples::tuple_list, Named};
|
||||||
use tuple_list::tuple_list_type;
|
use tuple_list::tuple_list_type;
|
||||||
@ -955,7 +955,8 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_event_serde() {
|
fn test_event_serde() {
|
||||||
let obv = unsafe {
|
let obv = unsafe {
|
||||||
StdMapObserver::from_mut_ptr("test", addr_of_mut!(MAP) as *mut u32, MAP.len())
|
let len = (*addr_of!(MAP)).len();
|
||||||
|
StdMapObserver::from_mut_ptr("test", addr_of_mut!(MAP) as *mut u32, len)
|
||||||
};
|
};
|
||||||
let map = tuple_list!(obv);
|
let map = tuple_list!(obv);
|
||||||
let observers_buf = postcard::to_allocvec(&map).unwrap();
|
let observers_buf = postcard::to_allocvec(&map).unwrap();
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
//! Hitcount map observer is for implementing AFL's hit count bucket
|
//! Hitcount map observer is for implementing AFL's hit count bucket
|
||||||
use alloc::{borrow::Cow, vec::Vec};
|
use alloc::{borrow::Cow, vec::Vec};
|
||||||
use core::{fmt::Debug, hash::Hash, mem::size_of, slice};
|
use core::{
|
||||||
|
fmt::Debug,
|
||||||
|
hash::Hash,
|
||||||
|
mem::size_of,
|
||||||
|
ptr::{addr_of, addr_of_mut},
|
||||||
|
slice,
|
||||||
|
};
|
||||||
|
|
||||||
use libafl_bolts::{AsIter, AsIterMut, AsSlice, AsSliceMut, HasLen, Named, Truncate};
|
use libafl_bolts::{AsIter, AsIterMut, AsSlice, AsSliceMut, HasLen, Named, Truncate};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@ -35,17 +41,19 @@ static mut COUNT_CLASS_LOOKUP_16: Vec<u16> = vec![];
|
|||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// Calling this from multiple threads may be racey and hence leak 65k mem
|
/// Calling this from multiple threads may be racey and hence leak 65k mem or even create a broken lookup vec.
|
||||||
fn init_count_class_16() {
|
fn init_count_class_16() {
|
||||||
unsafe {
|
unsafe {
|
||||||
if !COUNT_CLASS_LOOKUP_16.is_empty() {
|
let count_class_lookup_16 = &mut *addr_of_mut!(COUNT_CLASS_LOOKUP_16);
|
||||||
|
|
||||||
|
if !count_class_lookup_16.is_empty() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
COUNT_CLASS_LOOKUP_16 = vec![0; 65536];
|
*count_class_lookup_16 = vec![0; 65536];
|
||||||
for i in 0..256 {
|
for i in 0..256 {
|
||||||
for j in 0..256 {
|
for j in 0..256 {
|
||||||
COUNT_CLASS_LOOKUP_16[(i << 8) + j] =
|
count_class_lookup_16[(i << 8) + j] =
|
||||||
(u16::from(COUNT_CLASS_LOOKUP[i]) << 8) | u16::from(COUNT_CLASS_LOOKUP[j]);
|
(u16::from(COUNT_CLASS_LOOKUP[i]) << 8) | u16::from(COUNT_CLASS_LOOKUP[j]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -117,7 +125,7 @@ where
|
|||||||
#[allow(clippy::unused_enumerate_index)]
|
#[allow(clippy::unused_enumerate_index)]
|
||||||
for (_i, item) in map16[0..cnt].iter_mut().enumerate() {
|
for (_i, item) in map16[0..cnt].iter_mut().enumerate() {
|
||||||
unsafe {
|
unsafe {
|
||||||
*item = *COUNT_CLASS_LOOKUP_16.get_unchecked(*item as usize);
|
*item = *(*addr_of!(COUNT_CLASS_LOOKUP_16)).get_unchecked(*item as usize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -446,7 +446,7 @@ where
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
||||||
use core::ptr::addr_of_mut;
|
use core::ptr::{addr_of, addr_of_mut};
|
||||||
|
|
||||||
use libafl_bolts::{
|
use libafl_bolts::{
|
||||||
ownedref::OwnedMutSlice,
|
ownedref::OwnedMutSlice,
|
||||||
@ -461,9 +461,10 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_observer_serde() {
|
fn test_observer_serde() {
|
||||||
let obv = tuple_list!(TimeObserver::new("time"), unsafe {
|
let obv = tuple_list!(TimeObserver::new("time"), unsafe {
|
||||||
|
let len = (*addr_of!(MAP)).len();
|
||||||
StdMapObserver::from_ownedref(
|
StdMapObserver::from_ownedref(
|
||||||
"map",
|
"map",
|
||||||
OwnedMutSlice::from_raw_parts_mut(addr_of_mut!(MAP) as *mut u32, MAP.len()),
|
OwnedMutSlice::from_raw_parts_mut(addr_of_mut!(MAP) as *mut u32, len),
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
let vec = postcard::to_allocvec(&obv).unwrap();
|
let vec = postcard::to_allocvec(&obv).unwrap();
|
||||||
|
@ -992,7 +992,7 @@ impl SimpleFdLogger {
|
|||||||
// The passed-in `fd` has to be a legal file descriptor to log to.
|
// The passed-in `fd` has to be a legal file descriptor to log to.
|
||||||
// We also access a shared variable here.
|
// We also access a shared variable here.
|
||||||
unsafe {
|
unsafe {
|
||||||
LIBAFL_RAWFD_LOGGER.set_fd(log_fd);
|
(*ptr::addr_of_mut!(LIBAFL_RAWFD_LOGGER)).set_fd(log_fd);
|
||||||
log::set_logger(&*ptr::addr_of!(LIBAFL_RAWFD_LOGGER))?;
|
log::set_logger(&*ptr::addr_of!(LIBAFL_RAWFD_LOGGER))?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -118,7 +118,12 @@ pub mod serdeany_registry {
|
|||||||
boxed::Box,
|
boxed::Box,
|
||||||
string::{String, ToString},
|
string::{String, ToString},
|
||||||
};
|
};
|
||||||
use core::{any::TypeId, fmt, hash::BuildHasherDefault};
|
use core::{
|
||||||
|
any::TypeId,
|
||||||
|
fmt,
|
||||||
|
hash::BuildHasherDefault,
|
||||||
|
ptr::{addr_of, addr_of_mut},
|
||||||
|
};
|
||||||
|
|
||||||
use hashbrown::{
|
use hashbrown::{
|
||||||
hash_map::{Values, ValuesMut},
|
hash_map::{Values, ValuesMut},
|
||||||
@ -156,7 +161,7 @@ pub mod serdeany_registry {
|
|||||||
let id: TypeRepr = visitor.next_element()?.unwrap();
|
let id: TypeRepr = visitor.next_element()?.unwrap();
|
||||||
|
|
||||||
let cb = unsafe {
|
let cb = unsafe {
|
||||||
REGISTRY
|
(*addr_of!(REGISTRY))
|
||||||
.deserializers
|
.deserializers
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.ok_or_else(||
|
.ok_or_else(||
|
||||||
@ -228,7 +233,7 @@ pub mod serdeany_registry {
|
|||||||
T: crate::serdeany::SerdeAny + Serialize + serde::de::DeserializeOwned,
|
T: crate::serdeany::SerdeAny + Serialize + serde::de::DeserializeOwned,
|
||||||
{
|
{
|
||||||
unsafe {
|
unsafe {
|
||||||
REGISTRY.register::<T>();
|
(*addr_of_mut!(REGISTRY)).register::<T>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,7 +244,7 @@ pub mod serdeany_registry {
|
|||||||
/// It dereferences the `REGISTRY` hashmap and adds the given type to it.
|
/// It dereferences the `REGISTRY` hashmap and adds the given type to it.
|
||||||
pub fn finalize() {
|
pub fn finalize() {
|
||||||
unsafe {
|
unsafe {
|
||||||
REGISTRY.finalize();
|
(*addr_of_mut!(REGISTRY)).finalize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -366,7 +371,7 @@ pub mod serdeany_registry {
|
|||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
unsafe {
|
unsafe {
|
||||||
REGISTRY
|
(*addr_of!(REGISTRY))
|
||||||
.deserializers
|
.deserializers
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.expect(super::ERR_EMPTY_TYPES_REGISTER)
|
.expect(super::ERR_EMPTY_TYPES_REGISTER)
|
||||||
@ -629,7 +634,7 @@ pub mod serdeany_registry {
|
|||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
unsafe {
|
unsafe {
|
||||||
REGISTRY
|
(*addr_of!(REGISTRY))
|
||||||
.deserializers
|
.deserializers
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.expect(super::ERR_EMPTY_TYPES_REGISTER)
|
.expect(super::ERR_EMPTY_TYPES_REGISTER)
|
||||||
|
@ -58,9 +58,8 @@ where
|
|||||||
|
|
||||||
impl BreakpointId {
|
impl BreakpointId {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
static mut BREAKPOINT_ID_COUNTER: OnceLock<AtomicU64> = OnceLock::new();
|
static BREAKPOINT_ID_COUNTER: OnceLock<AtomicU64> = OnceLock::new();
|
||||||
|
let counter = BREAKPOINT_ID_COUNTER.get_or_init(|| AtomicU64::new(0));
|
||||||
let counter = unsafe { BREAKPOINT_ID_COUNTER.get_or_init(|| AtomicU64::new(0)) };
|
|
||||||
|
|
||||||
BreakpointId(counter.fetch_add(1, Ordering::SeqCst))
|
BreakpointId(counter.fetch_add(1, Ordering::SeqCst))
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ use std::fmt::Debug;
|
|||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use libafl::{
|
use libafl::{
|
||||||
inputs::{HasTargetBytes, UsesInput},
|
inputs::{HasTargetBytes, UsesInput},
|
||||||
prelude::{HasExecutions, State},
|
state::{HasExecutions, State},
|
||||||
};
|
};
|
||||||
use libafl_qemu_sys::GuestPhysAddr;
|
use libafl_qemu_sys::GuestPhysAddr;
|
||||||
|
|
||||||
|
@ -100,6 +100,7 @@ pub fn python_module(m: &Bound<'_, PyModule>) -> PyResult<()> {
|
|||||||
}
|
}
|
||||||
m.add_submodule(&mmapm)?;
|
m.add_submodule(&mmapm)?;
|
||||||
|
|
||||||
|
#[cfg(emulation_mode = "usermode")]
|
||||||
m.add_class::<sys::MapInfo>()?;
|
m.add_class::<sys::MapInfo>()?;
|
||||||
|
|
||||||
#[cfg(emulation_mode = "usermode")]
|
#[cfg(emulation_mode = "usermode")]
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use core::{cell::UnsafeCell, fmt::Debug};
|
use core::{cell::UnsafeCell, fmt::Debug, ptr::addr_of_mut};
|
||||||
|
|
||||||
use capstone::prelude::*;
|
use capstone::prelude::*;
|
||||||
use libafl::{
|
use libafl::{
|
||||||
@ -541,13 +541,13 @@ impl Default for FullBacktraceCollector {
|
|||||||
|
|
||||||
impl FullBacktraceCollector {
|
impl FullBacktraceCollector {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
unsafe { CALLSTACKS = Some(ThreadLocal::new()) };
|
unsafe { *(&mut *addr_of_mut!(CALLSTACKS)) = Some(ThreadLocal::new()) };
|
||||||
Self {}
|
Self {}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset(&mut self) {
|
pub fn reset(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
for tls in CALLSTACKS.as_mut().unwrap().iter_mut() {
|
for tls in (*addr_of_mut!(CALLSTACKS)).as_mut().unwrap().iter_mut() {
|
||||||
(*tls.get()).clear();
|
(*tls.get()).clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -555,7 +555,7 @@ impl FullBacktraceCollector {
|
|||||||
|
|
||||||
pub fn backtrace() -> Option<&'static [GuestAddr]> {
|
pub fn backtrace() -> Option<&'static [GuestAddr]> {
|
||||||
unsafe {
|
unsafe {
|
||||||
if let Some(c) = CALLSTACKS.as_mut() {
|
if let Some(c) = (*addr_of_mut!(CALLSTACKS)).as_mut() {
|
||||||
Some(&*c.get_or_default().get())
|
Some(&*c.get_or_default().get())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -578,7 +578,12 @@ impl CallTraceCollector for FullBacktraceCollector {
|
|||||||
{
|
{
|
||||||
// TODO handle Thumb
|
// TODO handle Thumb
|
||||||
unsafe {
|
unsafe {
|
||||||
(*CALLSTACKS.as_mut().unwrap().get_or_default().get()).push(pc + call_len as GuestAddr);
|
(*(*addr_of_mut!(CALLSTACKS))
|
||||||
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
|
.get_or_default()
|
||||||
|
.get())
|
||||||
|
.push(pc + call_len as GuestAddr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -594,7 +599,11 @@ impl CallTraceCollector for FullBacktraceCollector {
|
|||||||
S: Unpin + UsesInput,
|
S: Unpin + UsesInput,
|
||||||
{
|
{
|
||||||
unsafe {
|
unsafe {
|
||||||
let v = &mut *CALLSTACKS.as_mut().unwrap().get_or_default().get();
|
let v = &mut *(*addr_of_mut!(CALLSTACKS))
|
||||||
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
|
.get_or_default()
|
||||||
|
.get();
|
||||||
if !v.is_empty() {
|
if !v.is_empty() {
|
||||||
// if *v.last().unwrap() == ret_addr {
|
// if *v.last().unwrap() == ret_addr {
|
||||||
// v.pop();
|
// v.pop();
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use core::{fmt::Debug, ops::Range};
|
use core::{cell::UnsafeCell, fmt::Debug, hash::BuildHasher, ops::Range, ptr::addr_of_mut};
|
||||||
use std::{cell::UnsafeCell, hash::BuildHasher};
|
|
||||||
|
|
||||||
use hashbrown::HashSet;
|
use hashbrown::HashSet;
|
||||||
use libafl::{executors::ExitKind, inputs::UsesInput, observers::ObserversTuple};
|
use libafl::{executors::ExitKind, inputs::UsesInput, observers::ObserversTuple};
|
||||||
@ -311,7 +310,7 @@ impl HasInstrumentationFilter<QemuInstrumentationAddressRangeFilter> for () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn filter_mut(&mut self) -> &mut QemuInstrumentationAddressRangeFilter {
|
fn filter_mut(&mut self) -> &mut QemuInstrumentationAddressRangeFilter {
|
||||||
unsafe { EMPTY_ADDRESS_FILTER.get_mut() }
|
unsafe { (*addr_of_mut!(EMPTY_ADDRESS_FILTER)).get_mut() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -321,7 +320,7 @@ impl HasInstrumentationFilter<QemuInstrumentationPagingFilter> for () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn filter_mut(&mut self) -> &mut QemuInstrumentationPagingFilter {
|
fn filter_mut(&mut self) -> &mut QemuInstrumentationPagingFilter {
|
||||||
unsafe { EMPTY_PAGING_FILTER.get_mut() }
|
unsafe { (*addr_of_mut!(EMPTY_PAGING_FILTER)).get_mut() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,16 +3,18 @@
|
|||||||
//! This module exposes the low-level QEMU library through [`Qemu`].
|
//! This module exposes the low-level QEMU library through [`Qemu`].
|
||||||
//! To access higher-level features of QEMU, it is recommended to use [`crate::Emulator`] instead.
|
//! To access higher-level features of QEMU, it is recommended to use [`crate::Emulator`] instead.
|
||||||
|
|
||||||
use core::fmt;
|
use core::{
|
||||||
use std::{
|
|
||||||
cmp::{Ordering, PartialOrd},
|
cmp::{Ordering, PartialOrd},
|
||||||
|
fmt,
|
||||||
|
ptr::{self, addr_of_mut},
|
||||||
|
};
|
||||||
|
use std::{
|
||||||
ffi::{c_void, CString},
|
ffi::{c_void, CString},
|
||||||
fmt::{Display, Formatter},
|
fmt::{Display, Formatter},
|
||||||
intrinsics::{copy_nonoverlapping, transmute},
|
intrinsics::{copy_nonoverlapping, transmute},
|
||||||
mem::MaybeUninit,
|
mem::MaybeUninit,
|
||||||
ops::Range,
|
ops::Range,
|
||||||
pin::Pin,
|
pin::Pin,
|
||||||
ptr,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use libafl_bolts::os::unix_signals::Signal;
|
use libafl_bolts::os::unix_signals::Signal;
|
||||||
@ -141,7 +143,7 @@ pub struct QemuMemoryChunk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::vec_box)]
|
#[allow(clippy::vec_box)]
|
||||||
static mut GDB_COMMANDS: Vec<Box<FatPtr>> = vec![];
|
static mut GDB_COMMANDS: Vec<Box<FatPtr>> = Vec::new();
|
||||||
|
|
||||||
unsafe extern "C" fn gdb_cmd(data: *mut c_void, buf: *mut u8, len: usize) -> bool {
|
unsafe extern "C" fn gdb_cmd(data: *mut c_void, buf: *mut u8, len: usize) -> bool {
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -768,16 +770,16 @@ impl Qemu {
|
|||||||
id.remove(invalidate_block)
|
id.remove(invalidate_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// # Safety
|
||||||
|
// Calling this multiple times concurrently will access static variables and is unsafe.
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
pub fn add_gdb_cmd(&self, callback: Box<dyn FnMut(&Self, &str) -> bool>) {
|
pub unsafe fn add_gdb_cmd(&self, callback: Box<dyn FnMut(&Self, &str) -> bool>) {
|
||||||
unsafe {
|
|
||||||
let fat: Box<FatPtr> = Box::new(transmute::<
|
let fat: Box<FatPtr> = Box::new(transmute::<
|
||||||
Box<dyn for<'a, 'b> FnMut(&'a Qemu, &'b str) -> bool>,
|
Box<dyn for<'a, 'b> FnMut(&'a Qemu, &'b str) -> bool>,
|
||||||
FatPtr,
|
FatPtr,
|
||||||
>(callback));
|
>(callback));
|
||||||
libafl_qemu_add_gdb_cmd(Some(gdb_cmd), ptr::from_ref(&*fat) as *mut c_void);
|
libafl_qemu_add_gdb_cmd(Some(gdb_cmd), ptr::from_ref(&*fat) as *mut c_void);
|
||||||
GDB_COMMANDS.push(fat);
|
(*addr_of_mut!(GDB_COMMANDS)).push(fat);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gdb_reply(&self, output: &str) {
|
pub fn gdb_reply(&self, output: &str) {
|
||||||
@ -956,7 +958,10 @@ pub mod pybind {
|
|||||||
static mut PY_GENERIC_HOOKS: Vec<(GuestAddr, PyObject)> = vec![];
|
static mut PY_GENERIC_HOOKS: Vec<(GuestAddr, PyObject)> = vec![];
|
||||||
|
|
||||||
extern "C" fn py_generic_hook_wrapper(idx: u64, _pc: GuestAddr) {
|
extern "C" fn py_generic_hook_wrapper(idx: u64, _pc: GuestAddr) {
|
||||||
let obj = unsafe { &PY_GENERIC_HOOKS[idx as usize].1 };
|
let obj = unsafe {
|
||||||
|
let hooks = &mut *core::ptr::addr_of_mut!(PY_GENERIC_HOOKS);
|
||||||
|
&hooks[idx as usize].1
|
||||||
|
};
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
obj.call0(py).expect("Error in the hook");
|
obj.call0(py).expect("Error in the hook");
|
||||||
});
|
});
|
||||||
@ -1032,8 +1037,9 @@ pub mod pybind {
|
|||||||
|
|
||||||
fn set_hook(&self, addr: GuestAddr, hook: PyObject) {
|
fn set_hook(&self, addr: GuestAddr, hook: PyObject) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let idx = PY_GENERIC_HOOKS.len();
|
let hooks = &mut *core::ptr::addr_of_mut!(PY_GENERIC_HOOKS);
|
||||||
PY_GENERIC_HOOKS.push((addr, hook));
|
let idx = hooks.len();
|
||||||
|
hooks.push((addr, hook));
|
||||||
self.qemu.hooks().add_instruction_hooks(
|
self.qemu.hooks().add_instruction_hooks(
|
||||||
idx as u64,
|
idx as u64,
|
||||||
addr,
|
addr,
|
||||||
@ -1045,7 +1051,8 @@ pub mod pybind {
|
|||||||
|
|
||||||
fn remove_hooks_at(&self, addr: GuestAddr) -> usize {
|
fn remove_hooks_at(&self, addr: GuestAddr) -> usize {
|
||||||
unsafe {
|
unsafe {
|
||||||
PY_GENERIC_HOOKS.retain(|(a, _)| *a != addr);
|
let hooks = &mut *core::ptr::addr_of_mut!(PY_GENERIC_HOOKS);
|
||||||
|
hooks.retain(|(a, _)| *a != addr);
|
||||||
}
|
}
|
||||||
self.qemu.hooks().remove_instruction_hooks_at(addr, true)
|
self.qemu.hooks().remove_instruction_hooks_at(addr, true)
|
||||||
}
|
}
|
||||||
|
@ -261,7 +261,7 @@ pub mod pybind {
|
|||||||
a6: u64,
|
a6: u64,
|
||||||
a7: u64,
|
a7: u64,
|
||||||
) -> SyscallHookResult {
|
) -> SyscallHookResult {
|
||||||
unsafe { PY_SYSCALL_HOOK.as_ref() }.map_or_else(
|
unsafe { (*core::ptr::addr_of!(PY_SYSCALL_HOOK)).as_ref() }.map_or_else(
|
||||||
|| SyscallHookResult::new(None),
|
|| SyscallHookResult::new(None),
|
||||||
|obj| {
|
|obj| {
|
||||||
let args = (sys_num, a0, a1, a2, a3, a4, a5, a6, a7);
|
let args = (sys_num, a0, a1, a2, a3, a4, a5, a6, a7);
|
||||||
@ -340,7 +340,7 @@ pub mod pybind {
|
|||||||
|
|
||||||
fn set_syscall_hook(&self, hook: PyObject) {
|
fn set_syscall_hook(&self, hook: PyObject) {
|
||||||
unsafe {
|
unsafe {
|
||||||
PY_SYSCALL_HOOK = Some(hook);
|
*(&mut *core::ptr::addr_of_mut!(PY_SYSCALL_HOOK)) = Some(hook);
|
||||||
}
|
}
|
||||||
self.qemu
|
self.qemu
|
||||||
.hooks()
|
.hooks()
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use core::marker::PhantomData;
|
use core::{marker::PhantomData, ptr::addr_of_mut};
|
||||||
|
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use libafl::{
|
use libafl::{
|
||||||
@ -12,9 +12,11 @@ pub static mut FUNCTION_LIST: Lazy<HashMap<usize, usize>> = Lazy::new(HashMap::n
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
/// The runtime code inserted at every callinst invokation (if you used the function-logging.cc)
|
/// The runtime code inserted at every callinst invokation (if you used the function-logging.cc)
|
||||||
/// # Safety
|
/// # Safety
|
||||||
/// unsafe because it touches pub static mut
|
/// unsafe because it touches the pub static mut `FUNCTION_LIST`.
|
||||||
|
/// May not be called concurrently.
|
||||||
pub unsafe extern "C" fn __libafl_target_call_hook(id: usize) {
|
pub unsafe extern "C" fn __libafl_target_call_hook(id: usize) {
|
||||||
*FUNCTION_LIST.entry(id).or_insert(0) += 1;
|
let function_list = &mut *addr_of_mut!(FUNCTION_LIST);
|
||||||
|
*function_list.entry(id).or_insert(0) += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The empty struct to clear the `FUNCTION_LIST` before the execution
|
/// The empty struct to clear the `FUNCTION_LIST` before the execution
|
||||||
@ -41,7 +43,13 @@ where
|
|||||||
|
|
||||||
fn pre_exec(&mut self, _state: &mut S, _input: &<S as UsesInput>::Input) {
|
fn pre_exec(&mut self, _state: &mut S, _input: &<S as UsesInput>::Input) {
|
||||||
// clear it before the execution
|
// clear it before the execution
|
||||||
unsafe { FUNCTION_LIST.clear() }
|
// # Safety
|
||||||
|
// This typically happens while no other execution happens.
|
||||||
|
// In theory there is a race, but we can ignore it _for this use case_.
|
||||||
|
unsafe {
|
||||||
|
let function_list = &mut *addr_of_mut!(FUNCTION_LIST);
|
||||||
|
function_list.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn post_exec(&mut self, _state: &mut S, _input: &<S as UsesInput>::Input) {}
|
fn post_exec(&mut self, _state: &mut S, _input: &<S as UsesInput>::Input) {}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
feature = "sancov_ctx"
|
feature = "sancov_ctx"
|
||||||
))]
|
))]
|
||||||
use alloc::borrow::Cow;
|
use alloc::borrow::Cow;
|
||||||
|
use core::ptr::addr_of_mut;
|
||||||
|
|
||||||
#[cfg(any(target_os = "linux", target_vendor = "apple"))]
|
#[cfg(any(target_os = "linux", target_vendor = "apple"))]
|
||||||
use libafl::{mutators::Tokens, Error};
|
use libafl::{mutators::Tokens, Error};
|
||||||
@ -157,7 +158,7 @@ pub fn edges_map_mut_ptr() -> *mut u8 {
|
|||||||
assert!(!EDGES_MAP_PTR.is_null());
|
assert!(!EDGES_MAP_PTR.is_null());
|
||||||
EDGES_MAP_PTR
|
EDGES_MAP_PTR
|
||||||
} else {
|
} else {
|
||||||
EDGES_MAP.as_mut_ptr()
|
addr_of_mut!(EDGES_MAP) as *mut u8
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
//! [`LLVM` `8-bit-counters`](https://clang.llvm.org/docs/SanitizerCoverage.html#tracing-pcs-with-guards) runtime for `LibAFL`.
|
//! [`LLVM` `8-bit-counters`](https://clang.llvm.org/docs/SanitizerCoverage.html#tracing-pcs-with-guards) runtime for `LibAFL`.
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use core::ptr::addr_of_mut;
|
use core::ptr::{addr_of, addr_of_mut};
|
||||||
|
|
||||||
use libafl_bolts::{ownedref::OwnedMutSlice, AsSlice, AsSliceMut};
|
use libafl_bolts::{ownedref::OwnedMutSlice, AsSlice, AsSliceMut};
|
||||||
|
|
||||||
@ -14,7 +14,8 @@ pub static mut COUNTERS_MAPS: Vec<OwnedMutSlice<'static, u8>> = Vec::new();
|
|||||||
/// You are responsible for ensuring there is no multi-mutability!
|
/// You are responsible for ensuring there is no multi-mutability!
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub unsafe fn extra_counters() -> Vec<OwnedMutSlice<'static, u8>> {
|
pub unsafe fn extra_counters() -> Vec<OwnedMutSlice<'static, u8>> {
|
||||||
COUNTERS_MAPS
|
let counter_maps = &*addr_of!(COUNTERS_MAPS);
|
||||||
|
counter_maps
|
||||||
.iter()
|
.iter()
|
||||||
.map(|counters| {
|
.map(|counters| {
|
||||||
OwnedMutSlice::from_raw_parts_mut(
|
OwnedMutSlice::from_raw_parts_mut(
|
||||||
@ -31,7 +32,8 @@ pub unsafe fn extra_counters() -> Vec<OwnedMutSlice<'static, u8>> {
|
|||||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
||||||
pub extern "C" fn __sanitizer_cov_8bit_counters_init(start: *mut u8, stop: *mut u8) {
|
pub extern "C" fn __sanitizer_cov_8bit_counters_init(start: *mut u8, stop: *mut u8) {
|
||||||
unsafe {
|
unsafe {
|
||||||
for existing in &mut *addr_of_mut!(COUNTERS_MAPS) {
|
let counter_maps = &mut *addr_of_mut!(COUNTERS_MAPS);
|
||||||
|
for existing in counter_maps {
|
||||||
let range = existing.as_slice_mut().as_mut_ptr()
|
let range = existing.as_slice_mut().as_mut_ptr()
|
||||||
..=existing
|
..=existing
|
||||||
.as_slice_mut()
|
.as_slice_mut()
|
||||||
@ -46,8 +48,10 @@ pub extern "C" fn __sanitizer_cov_8bit_counters_init(start: *mut u8, stop: *mut
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let counter_maps = &mut *addr_of_mut!(COUNTERS_MAPS);
|
||||||
// we didn't overlap; keep going
|
// we didn't overlap; keep going
|
||||||
COUNTERS_MAPS.push(OwnedMutSlice::from_raw_parts_mut(
|
counter_maps.push(OwnedMutSlice::from_raw_parts_mut(
|
||||||
start,
|
start,
|
||||||
stop.offset_from(start) as usize,
|
stop.offset_from(start) as usize,
|
||||||
));
|
));
|
||||||
@ -327,7 +331,10 @@ mod observers {
|
|||||||
type IntoIter = Flatten<Iter<'it, OwnedMutSlice<'static, u8>>>;
|
type IntoIter = Flatten<Iter<'it, OwnedMutSlice<'static, u8>>>;
|
||||||
|
|
||||||
fn as_iter(&'it self) -> Self::IntoIter {
|
fn as_iter(&'it self) -> Self::IntoIter {
|
||||||
unsafe { COUNTERS_MAPS.iter().flatten() }
|
unsafe {
|
||||||
|
let counters_maps = &*addr_of!(COUNTERS_MAPS);
|
||||||
|
counters_maps.iter().flatten()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -336,7 +343,10 @@ mod observers {
|
|||||||
type IntoIterMut = Flatten<IterMut<'it, OwnedMutSlice<'static, u8>>>;
|
type IntoIterMut = Flatten<IterMut<'it, OwnedMutSlice<'static, u8>>>;
|
||||||
|
|
||||||
fn as_iter_mut(&'it mut self) -> Self::IntoIterMut {
|
fn as_iter_mut(&'it mut self) -> Self::IntoIterMut {
|
||||||
unsafe { COUNTERS_MAPS.iter_mut().flatten() }
|
unsafe {
|
||||||
|
let counters_maps = &mut *addr_of_mut!(COUNTERS_MAPS);
|
||||||
|
counters_maps.iter_mut().flatten()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,6 +65,8 @@ pub static SHR_4: Ngram4 = Ngram4::from_array([1, 1, 1, 1]);
|
|||||||
#[rustversion::nightly]
|
#[rustversion::nightly]
|
||||||
pub static SHR_8: Ngram8 = Ngram8::from_array([1, 1, 1, 1, 1, 1, 1, 1]);
|
pub static SHR_8: Ngram8 = Ngram8::from_array([1, 1, 1, 1, 1, 1, 1, 1]);
|
||||||
|
|
||||||
|
static mut PC_TABLES: Vec<&'static [PcTableEntry]> = Vec::new();
|
||||||
|
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
feature = "sancov_ngram4",
|
feature = "sancov_ngram4",
|
||||||
@ -184,17 +186,19 @@ unsafe fn update_ngram(pos: usize) -> usize {
|
|||||||
let mut reduced = pos;
|
let mut reduced = pos;
|
||||||
#[cfg(feature = "sancov_ngram4")]
|
#[cfg(feature = "sancov_ngram4")]
|
||||||
{
|
{
|
||||||
PREV_ARRAY_4 = PREV_ARRAY_4.rotate_elements_right::<1>();
|
let prev_array_4 = &mut *core::ptr::addr_of_mut!(PREV_ARRAY_4);
|
||||||
PREV_ARRAY_4.shl_assign(SHR_4);
|
*prev_array_4 = prev_array_4.rotate_elements_right::<1>();
|
||||||
PREV_ARRAY_4.as_mut_array()[0] = pos as u32;
|
prev_array_4.shl_assign(SHR_4);
|
||||||
reduced = PREV_ARRAY_4.reduce_xor() as usize;
|
prev_array_4.as_mut_array()[0] = pos as u32;
|
||||||
|
reduced = prev_array_4.reduce_xor() as usize;
|
||||||
}
|
}
|
||||||
#[cfg(feature = "sancov_ngram8")]
|
#[cfg(feature = "sancov_ngram8")]
|
||||||
{
|
{
|
||||||
PREV_ARRAY_8 = PREV_ARRAY_8.rotate_elements_right::<1>();
|
let prev_array_8 = &mut *core::ptr::addr_of_mut!(PREV_ARRAY_8);
|
||||||
PREV_ARRAY_8.shl_assign(SHR_8);
|
*prev_array_8 = prev_array_8.rotate_elements_right::<1>();
|
||||||
PREV_ARRAY_8.as_mut_array()[0] = pos as u32;
|
prev_array_8.shl_assign(SHR_8);
|
||||||
reduced = PREV_ARRAY_8.reduce_xor() as usize;
|
prev_array_8.as_mut_array()[0] = pos as u32;
|
||||||
|
reduced = prev_array_8.reduce_xor() as usize;
|
||||||
}
|
}
|
||||||
reduced %= EDGES_MAP_SIZE_IN_USE;
|
reduced %= EDGES_MAP_SIZE_IN_USE;
|
||||||
reduced
|
reduced
|
||||||
@ -269,7 +273,7 @@ pub unsafe extern "C" fn __sanitizer_cov_trace_pc_guard(guard: *mut u32) {
|
|||||||
pub unsafe extern "C" fn __sanitizer_cov_trace_pc_guard_init(mut start: *mut u32, stop: *mut u32) {
|
pub unsafe extern "C" fn __sanitizer_cov_trace_pc_guard_init(mut start: *mut u32, stop: *mut u32) {
|
||||||
#[cfg(feature = "pointer_maps")]
|
#[cfg(feature = "pointer_maps")]
|
||||||
if EDGES_MAP_PTR.is_null() {
|
if EDGES_MAP_PTR.is_null() {
|
||||||
EDGES_MAP_PTR = EDGES_MAP.as_mut_ptr();
|
EDGES_MAP_PTR = core::ptr::addr_of_mut!(EDGES_MAP) as *mut u8;
|
||||||
}
|
}
|
||||||
|
|
||||||
if start == stop || *start != 0 {
|
if start == stop || *start != 0 {
|
||||||
@ -292,8 +296,6 @@ pub unsafe extern "C" fn __sanitizer_cov_trace_pc_guard_init(mut start: *mut u32
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static mut PC_TABLES: Vec<&'static [PcTableEntry]> = Vec::new();
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
unsafe extern "C" fn __sanitizer_cov_pcs_init(pcs_beg: *const usize, pcs_end: *const usize) {
|
unsafe extern "C" fn __sanitizer_cov_pcs_init(pcs_beg: *const usize, pcs_end: *const usize) {
|
||||||
// "The Unsafe Code Guidelines also notably defines that usize and isize are respectively compatible with uintptr_t and intptr_t defined in C."
|
// "The Unsafe Code Guidelines also notably defines that usize and isize are respectively compatible with uintptr_t and intptr_t defined in C."
|
||||||
@ -312,7 +314,8 @@ unsafe extern "C" fn __sanitizer_cov_pcs_init(pcs_beg: *const usize, pcs_end: *c
|
|||||||
"Unaligned PC Table - start: {pcs_beg:x?} end: {pcs_end:x?}"
|
"Unaligned PC Table - start: {pcs_beg:x?} end: {pcs_end:x?}"
|
||||||
);
|
);
|
||||||
|
|
||||||
PC_TABLES.push(slice::from_raw_parts(pcs_beg as *const PcTableEntry, len));
|
let pc_tables = &mut *core::ptr::addr_of_mut!(PC_TABLES);
|
||||||
|
pc_tables.push(slice::from_raw_parts(pcs_beg as *const PcTableEntry, len));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An entry to the `sanitizer_cov` `pc_table`
|
/// An entry to the `sanitizer_cov` `pc_table`
|
||||||
@ -338,8 +341,11 @@ impl PcTableEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an iterator over the PC tables. If no tables were registered, this will be empty.
|
/// Returns an iterator over the PC tables. If no tables were registered, this will be empty.
|
||||||
pub fn sanitizer_cov_pc_table() -> impl Iterator<Item = &'static [PcTableEntry]> {
|
pub fn sanitizer_cov_pc_table<'a>() -> impl Iterator<Item = &'a [PcTableEntry]> {
|
||||||
// SAFETY: Once PCS_BEG and PCS_END have been initialized, will not be written to again. So
|
// SAFETY: Once PCS_BEG and PCS_END have been initialized, will not be written to again. So
|
||||||
// there's no TOCTOU issue.
|
// there's no TOCTOU issue.
|
||||||
unsafe { PC_TABLES.iter().copied() }
|
unsafe {
|
||||||
|
let pc_tables = &*core::ptr::addr_of!(PC_TABLES);
|
||||||
|
pc_tables.iter().copied()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user