125 lines
3.8 KiB
Rust
125 lines
3.8 KiB
Rust
extern crate alloc;
|
|
|
|
#[cfg(test)]
|
|
#[cfg(feature = "linux")]
|
|
mod tests {
|
|
use alloc::alloc::{GlobalAlloc, Layout};
|
|
|
|
use asan::{
|
|
GuestAddr,
|
|
allocator::frontend::{AllocatorFrontend, default::DefaultFrontend},
|
|
mmap::{Mmap, linux::LinuxMmap},
|
|
shadow::{
|
|
Shadow,
|
|
guest::{DefaultShadowLayout, GuestShadow},
|
|
},
|
|
tracking::guest::GuestTracking,
|
|
};
|
|
use log::{debug, info};
|
|
use mockall::mock;
|
|
use spin::{Lazy, Mutex, MutexGuard};
|
|
use thiserror::Error;
|
|
|
|
const MAX_ADDR: GuestAddr = 64 << 20;
|
|
|
|
// We can't mock GlobalAlloc since `*mut u8` isn't Send and Sync, so we will
|
|
// create a trivial implementation of it which converts the types and calls this
|
|
// substititue mockable trait instead.
|
|
trait BackendTrait {
|
|
fn do_alloc(&self, layout: Layout) -> GuestAddr;
|
|
fn do_dealloc(&self, addr: GuestAddr, layout: Layout);
|
|
}
|
|
|
|
mock! {
|
|
#[derive(Debug)]
|
|
pub Backend {}
|
|
|
|
impl BackendTrait for Backend {
|
|
fn do_alloc(&self, layout: Layout) -> GuestAddr;
|
|
fn do_dealloc(&self, addr: GuestAddr, layout: Layout);
|
|
}
|
|
}
|
|
|
|
unsafe impl GlobalAlloc for MockBackend {
|
|
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
|
self.do_alloc(layout) as *mut u8
|
|
}
|
|
|
|
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
|
|
self.do_dealloc(ptr as GuestAddr, layout)
|
|
}
|
|
}
|
|
|
|
#[derive(Error, Debug, PartialEq)]
|
|
pub enum MockBackendError {}
|
|
|
|
static INIT_ONCE: Lazy<Mutex<DF>> = Lazy::new(|| {
|
|
Mutex::new({
|
|
env_logger::init();
|
|
let backend = MockBackend::new();
|
|
let shadow = GuestShadow::<LinuxMmap, DefaultShadowLayout>::new().unwrap();
|
|
let tracking = GuestTracking::new().unwrap();
|
|
DF::new(
|
|
backend,
|
|
shadow,
|
|
tracking,
|
|
DF::DEFAULT_REDZONE_SIZE,
|
|
DF::DEFAULT_QUARANTINE_SIZE,
|
|
)
|
|
.unwrap()
|
|
})
|
|
});
|
|
|
|
static MAP: Lazy<LinuxMmap> = Lazy::new(|| LinuxMmap::map(MAX_ADDR).unwrap());
|
|
|
|
type DF =
|
|
DefaultFrontend<MockBackend, GuestShadow<LinuxMmap, DefaultShadowLayout>, GuestTracking>;
|
|
|
|
fn frontend() -> MutexGuard<'static, DF> {
|
|
INIT_ONCE.lock()
|
|
}
|
|
|
|
#[test]
|
|
fn test_allocate_is_poisoned() {
|
|
let mut frontend = frontend();
|
|
|
|
let base = MAP.as_slice().as_ptr() as GuestAddr;
|
|
info!("base: 0x{:x}", base);
|
|
|
|
let inputs = [[4, 8, 0], [0x3ff, 0, 0]];
|
|
for [len, align, addr] in inputs {
|
|
frontend
|
|
.backend_mut()
|
|
.expect_do_alloc()
|
|
.returning(move |layout| {
|
|
debug!(
|
|
"mock - len: 0x{:x}, align: 0x{:x}",
|
|
layout.size(),
|
|
layout.align()
|
|
);
|
|
base + addr
|
|
});
|
|
frontend
|
|
.backend_mut()
|
|
.expect_do_dealloc()
|
|
.returning(|addr, layout| {
|
|
debug!(
|
|
"mock - addr: 0x{:x}, len: 0x{:x}, align: 0x{:x}",
|
|
addr,
|
|
layout.size(),
|
|
layout.align()
|
|
);
|
|
});
|
|
|
|
let buf = frontend.alloc(len, align).unwrap();
|
|
info!("buf: 0x{:x}", buf);
|
|
for i in buf - DF::DEFAULT_REDZONE_SIZE..buf + len + DF::DEFAULT_REDZONE_SIZE {
|
|
let expected = i < buf || i >= buf + len;
|
|
let poisoned = frontend.shadow().is_poison(i, 1).unwrap();
|
|
assert_eq!(expected, poisoned);
|
|
}
|
|
frontend.dealloc(buf).unwrap();
|
|
}
|
|
}
|
|
}
|