Added heap feature (#3074)
* Added heap feature * Rename feature and add some more docs * Use document-features crate * Expose the patching API for more flexibility --------- Co-authored-by: Your Name <you@example.com>
This commit is contained in:
parent
e728df9843
commit
0154a3b930
@ -8,8 +8,11 @@ rust-version.workspace = true
|
||||
crate-type = ["rlib"]
|
||||
|
||||
[features]
|
||||
#! # Features
|
||||
default = [
|
||||
"dlmalloc",
|
||||
"document-features",
|
||||
"global_allocator",
|
||||
"guest",
|
||||
"hooks",
|
||||
"host",
|
||||
@ -19,14 +22,27 @@ default = [
|
||||
"test",
|
||||
"tracking",
|
||||
]
|
||||
## Enable support for the `dlmalloc` allocator backend
|
||||
dlmalloc = ["dep:dlmalloc"]
|
||||
## Enable documentation of features
|
||||
document-features = ["dep:document-features"]
|
||||
## Configure a global allocator (using dlmalloc or mimalloc as configured)
|
||||
global_allocator = []
|
||||
## Enable support for shadow memory and tracking in the guest
|
||||
guest = []
|
||||
## Enable support for hooking functions in the guest
|
||||
hooks = []
|
||||
## Enable support for shadow memory and tracking in the host
|
||||
host = ["dep:syscalls"]
|
||||
## Enable use of the `libc` library to support creation of mappings, read/write, logging etc (more OS agnostic)
|
||||
libc = ["dep:libc"]
|
||||
## Enable the use of direct syscalls (supported by `rustix`) to interact with the operating system (Linux specific).
|
||||
linux = ["dep:rustix"]
|
||||
## Enable the `baby_mimalloc` allocator
|
||||
mimalloc = ["dep:baby-mimalloc"]
|
||||
## Disable the magic used to support `no_std` environments for running unit and integration tests
|
||||
test = []
|
||||
## Enable support for memory tracking
|
||||
tracking = []
|
||||
|
||||
[dependencies]
|
||||
@ -34,6 +50,7 @@ baby-mimalloc = { version = "0.2.1", default-features = false, features = [
|
||||
"spin_mutex",
|
||||
], optional = true }
|
||||
bitflags = { version = "2.8.0", default-features = false }
|
||||
document-features = { version = "0.2.11", optional = true }
|
||||
dlmalloc = { version = "0.2.7", default-features = false, optional = true }
|
||||
itertools = { version = "0.14.0", default-features = false }
|
||||
log = { version = "0.4.22", default-features = false, features = [
|
||||
|
@ -73,7 +73,7 @@ pub struct PatchedHook {
|
||||
}
|
||||
|
||||
impl PatchedHook {
|
||||
const fn new<F: Copy>(name: &'static CStr, func: F) -> Self {
|
||||
pub const fn new<F: Copy>(name: &'static CStr, func: F) -> Self {
|
||||
let pf = (&func) as *const F as *const GuestAddr;
|
||||
let destination = unsafe { *pf };
|
||||
Self { name, destination }
|
||||
|
@ -29,21 +29,9 @@
|
||||
//! The componentized nature of the design is intended to permit the user to
|
||||
//! adapt `asan` to their needs with minimal modification by selecting and
|
||||
//! combining alternative implementations of the various key components.
|
||||
//!
|
||||
//! ## Features
|
||||
//! - `dlmalloc` - Enable support for the dlmalloc allocator backend.
|
||||
//! - `guest` - Enable support for shadow memory and tracking in the guest
|
||||
//! - `hooks` - Enable support for hooking functions in the guest
|
||||
//! - `host` - Enable support for shadow memory and tracking in the host
|
||||
//! - `libc` - Enable use of the `libc` library to support creation of mappings,
|
||||
//! read/write, logging etc (more OS agnostic)
|
||||
//! - `linux` - Enable the use of direct syscalls (supported by `rustix`) to
|
||||
//! interact with the operating system (Linux specific).
|
||||
//! - `test` - Disable the magic used to support `no_std` environments for
|
||||
//! running unit and integration tests
|
||||
//! - `tracking` - Enable support for memory tracking.
|
||||
#![cfg_attr(not(feature = "test"), no_std)]
|
||||
#![cfg_attr(target_arch = "powerpc", feature(asm_experimental_arch))]
|
||||
#![cfg_attr(feature = "document-features", doc = document_features::document_features!())]
|
||||
|
||||
pub mod allocator;
|
||||
|
||||
|
@ -3,10 +3,10 @@ use core::{
|
||||
slice::{from_raw_parts, from_raw_parts_mut},
|
||||
};
|
||||
|
||||
#[cfg(feature = "dlmalloc")]
|
||||
#[cfg(all(feature = "global_allocator", feature = "dlmalloc"))]
|
||||
use crate::allocator::backend::dlmalloc::DlmallocBackend;
|
||||
|
||||
#[cfg(all(feature = "linux", not(feature = "libc")))]
|
||||
#[cfg(all(feature = "global_allocator", feature = "linux", not(feature = "libc")))]
|
||||
type Mmap = crate::mmap::linux::LinuxMmap;
|
||||
|
||||
#[cfg(feature = "libc")]
|
||||
@ -14,14 +14,23 @@ type Mmap = crate::mmap::libc::LibcMmap<
|
||||
crate::symbols::dlsym::DlSymSymbols<crate::symbols::dlsym::LookupTypeNext>,
|
||||
>;
|
||||
|
||||
#[cfg(all(feature = "global_allocator"))]
|
||||
const PAGE_SIZE: usize = 4096;
|
||||
|
||||
#[global_allocator]
|
||||
#[cfg(all(feature = "dlmalloc", not(feature = "mimalloc")))]
|
||||
#[cfg(all(
|
||||
feature = "global_allocator",
|
||||
feature = "dlmalloc",
|
||||
not(feature = "mimalloc")
|
||||
))]
|
||||
static GLOBAL_ALLOCATOR: DlmallocBackend<Mmap> = DlmallocBackend::new(PAGE_SIZE);
|
||||
|
||||
#[global_allocator]
|
||||
#[cfg(all(feature = "dlmalloc", feature = "mimalloc"))]
|
||||
#[cfg(all(
|
||||
feature = "global_allocator",
|
||||
feature = "dlmalloc",
|
||||
feature = "mimalloc"
|
||||
))]
|
||||
static GLOBAL_ALLOCATOR: baby_mimalloc::MimallocMutexWrapper<DlmallocBackend<Mmap>> =
|
||||
baby_mimalloc::MimallocMutexWrapper::with_os_allocator(DlmallocBackend::new(PAGE_SIZE));
|
||||
|
||||
|
@ -23,26 +23,32 @@ impl PatchedHooks {
|
||||
pub fn init<S: Symbols, P: Patch, R: MapReader, M: Mmap>()
|
||||
-> Result<(), PatchesError<S, P, R, M>> {
|
||||
debug!("Installing patches");
|
||||
let reader = R::new().map_err(|e| PatchesError::MapReaderError(e))?;
|
||||
let mappings = MapIterator::new(reader).collect::<Vec<MapEntry>>();
|
||||
let mappings = Self::get_mappings()?;
|
||||
mappings.iter().for_each(|m| trace!("{m:?}"));
|
||||
let patches = PatchedHook::all()
|
||||
.into_iter()
|
||||
.map(|p| Self::apply_patch(p, &mappings))
|
||||
.collect::<Result<BTreeMap<GuestAddr, PatchedHook>, PatchesError<S, P, R, M>>>()?;
|
||||
PATCHED.lock().replace(patches);
|
||||
for patch in PatchedHook::all() {
|
||||
Self::patch(patch, &mappings)?;
|
||||
}
|
||||
debug!("Patching complete");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn apply_patch<S: Symbols, P: Patch, R: MapReader, M: Mmap>(
|
||||
p: PatchedHook,
|
||||
pub fn get_mappings<S: Symbols, P: Patch, R: MapReader, M: Mmap>()
|
||||
-> Result<Vec<MapEntry>, PatchesError<S, P, R, M>> {
|
||||
let reader = R::new().map_err(|e| PatchesError::MapReaderError(e))?;
|
||||
Ok(MapIterator::new(reader).collect::<Vec<MapEntry>>())
|
||||
}
|
||||
|
||||
pub fn patch<S: Symbols, P: Patch, R: MapReader, M: Mmap>(
|
||||
patch: PatchedHook,
|
||||
mappings: &[MapEntry],
|
||||
) -> Result<(GuestAddr, PatchedHook), PatchesError<S, P, R, M>> {
|
||||
trace!("patch: {:?}, destination: {:#x}", p.name, p.destination);
|
||||
let target = S::lookup(p.name.as_ptr() as *const c_char)
|
||||
) -> Result<(), PatchesError<S, P, R, M>> {
|
||||
trace!(
|
||||
"patch: {:?}, destination: {:#x}",
|
||||
patch.name, patch.destination
|
||||
);
|
||||
let target = S::lookup(patch.name.as_ptr() as *const c_char)
|
||||
.map_err(|e| PatchesError::SymbolsError(e))?;
|
||||
trace!("patching: {:#x} -> {:#x}", target, p.destination);
|
||||
trace!("patching: {:#x} -> {:#x}", target, patch.destination);
|
||||
let mapping = mappings
|
||||
.iter()
|
||||
.filter(|m| m.contains(target))
|
||||
@ -51,9 +57,10 @@ impl PatchedHooks {
|
||||
let prot = mapping
|
||||
.writeable::<M>()
|
||||
.map_err(|e| PatchesError::MmapError(e))?;
|
||||
P::patch(target, p.destination).map_err(|e| PatchesError::PatchError(e))?;
|
||||
P::patch(target, patch.destination).map_err(|e| PatchesError::PatchError(e))?;
|
||||
drop(prot);
|
||||
Ok((target, p))
|
||||
PATCHED.lock().get_or_insert_default().insert(target, patch);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn check_patched(addr: GuestAddr) -> Result<(), PatchesCheckError> {
|
||||
|
@ -14,6 +14,7 @@ test = ["asan/test", "dummy_libc/test"]
|
||||
[dependencies]
|
||||
asan = { path = "../asan", default-features = false, features = [
|
||||
"dlmalloc",
|
||||
"global_allocator",
|
||||
"guest",
|
||||
"hooks",
|
||||
"libc",
|
||||
|
@ -14,6 +14,7 @@ test = ["asan/test", "dummy_libc/test"]
|
||||
[dependencies]
|
||||
asan = { path = "../asan", default-features = false, features = [
|
||||
"dlmalloc",
|
||||
"global_allocator",
|
||||
"hooks",
|
||||
"host",
|
||||
"libc",
|
||||
|
@ -14,6 +14,7 @@ test = ["asan/test"]
|
||||
[dependencies]
|
||||
asan = { path = "../asan", default-features = false, features = [
|
||||
"dlmalloc",
|
||||
"global_allocator",
|
||||
"guest",
|
||||
"hooks",
|
||||
"host",
|
||||
|
Loading…
x
Reference in New Issue
Block a user