Various updates to librasan
(#3106)
* Add rawmemchr * Add stpncpy * Add strchrnul * Fix strcat * Added strncat * Add wcschr * Minor tweak * Add wcsncmp * Add wcsnlen * Add wcsrchr * Add wmemchr * Fix asan load/store sizes for wide string functions * Refactor patches * Rename tracking functions to prevent collision with allocator * Change return type of asan_sym to make it consistent with the other native functions * Fix mutex re-entrancy issue in Patches by splitting locks * Fix tests on 32-bit platforms --------- Co-authored-by: Your Name <you@example.com>
This commit is contained in:
parent
58607dc333
commit
869edd068d
@ -94,7 +94,7 @@ impl<B: GlobalAlloc + Send, S: Shadow, T: Tracking> AllocatorFrontend for Defaul
|
|||||||
);
|
);
|
||||||
|
|
||||||
self.tracking
|
self.tracking
|
||||||
.alloc(data, len)
|
.track(data, len)
|
||||||
.map_err(|e| DefaultFrontendError::TrackingError(e))?;
|
.map_err(|e| DefaultFrontendError::TrackingError(e))?;
|
||||||
self.shadow
|
self.shadow
|
||||||
.poison(orig, data - orig, PoisonType::AsanHeapLeftRz)
|
.poison(orig, data - orig, PoisonType::AsanHeapLeftRz)
|
||||||
@ -130,7 +130,7 @@ impl<B: GlobalAlloc + Send, S: Shadow, T: Tracking> AllocatorFrontend for Defaul
|
|||||||
)
|
)
|
||||||
.map_err(|e| DefaultFrontendError::ShadowError(e))?;
|
.map_err(|e| DefaultFrontendError::ShadowError(e))?;
|
||||||
self.tracking
|
self.tracking
|
||||||
.dealloc(addr)
|
.untrack(addr)
|
||||||
.map_err(|e| DefaultFrontendError::TrackingError(e))?;
|
.map_err(|e| DefaultFrontendError::TrackingError(e))?;
|
||||||
self.quaratine_used += alloc.backend_len;
|
self.quaratine_used += alloc.backend_len;
|
||||||
self.quarantine.push_back(alloc);
|
self.quarantine.push_back(alloc);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use core::ffi::{CStr, c_char, c_int};
|
use core::ffi::{CStr, c_char, c_int, c_void};
|
||||||
|
|
||||||
use libc::{SIGABRT, pid_t};
|
use libc::{SIGABRT, pid_t};
|
||||||
|
|
||||||
@ -32,15 +32,15 @@ impl Function for FunctionExit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsafe extern "C" {
|
unsafe extern "C" {
|
||||||
fn asan_sym(name: *const c_char) -> GuestAddr;
|
fn asan_sym(name: *const c_char) -> *const c_void;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn abort() -> ! {
|
pub fn abort() -> ! {
|
||||||
let getpid_addr = unsafe { asan_sym(FunctionGetpid::NAME.as_ptr() as *const c_char) };
|
let getpid_addr = unsafe { asan_sym(FunctionGetpid::NAME.as_ptr() as *const c_char) };
|
||||||
let fn_getpid = FunctionGetpid::as_ptr(getpid_addr).unwrap();
|
let fn_getpid = FunctionGetpid::as_ptr(getpid_addr as GuestAddr).unwrap();
|
||||||
|
|
||||||
let kill_addr = unsafe { asan_sym(FunctionKill::NAME.as_ptr() as *const c_char) };
|
let kill_addr = unsafe { asan_sym(FunctionKill::NAME.as_ptr() as *const c_char) };
|
||||||
let fn_kill = FunctionKill::as_ptr(kill_addr).unwrap();
|
let fn_kill = FunctionKill::as_ptr(kill_addr as GuestAddr).unwrap();
|
||||||
|
|
||||||
unsafe { asan_swap(false) };
|
unsafe { asan_swap(false) };
|
||||||
let pid = unsafe { fn_getpid() };
|
let pid = unsafe { fn_getpid() };
|
||||||
@ -50,7 +50,7 @@ pub fn abort() -> ! {
|
|||||||
|
|
||||||
pub fn exit(status: c_int) -> ! {
|
pub fn exit(status: c_int) -> ! {
|
||||||
let exit_addr = unsafe { asan_sym(FunctionExit::NAME.as_ptr() as *const c_char) };
|
let exit_addr = unsafe { asan_sym(FunctionExit::NAME.as_ptr() as *const c_char) };
|
||||||
let fn_exit = FunctionExit::as_ptr(exit_addr).unwrap();
|
let fn_exit = FunctionExit::as_ptr(exit_addr as GuestAddr).unwrap();
|
||||||
unsafe { asan_swap(false) };
|
unsafe { asan_swap(false) };
|
||||||
unsafe { fn_exit(status) };
|
unsafe { fn_exit(status) };
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ use libc::FILE;
|
|||||||
use log::trace;
|
use log::trace;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
asan_load, asan_panic, asan_store, asan_swap, asan_sym,
|
GuestAddr, asan_load, asan_panic, asan_store, asan_swap, asan_sym,
|
||||||
symbols::{AtomicGuestAddr, Function, FunctionPointer},
|
symbols::{AtomicGuestAddr, Function, FunctionPointer},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -36,8 +36,9 @@ pub unsafe extern "C" fn fgets(buf: *mut c_char, n: c_int, stream: *mut FILE) ->
|
|||||||
|
|
||||||
asan_store(buf as *const c_void, n as usize);
|
asan_store(buf as *const c_void, n as usize);
|
||||||
asan_load(stream as *const c_void, size_of::<FILE>());
|
asan_load(stream as *const c_void, size_of::<FILE>());
|
||||||
let addr = FGETS_ADDR
|
let addr = FGETS_ADDR.get_or_insert_with(|| {
|
||||||
.get_or_insert_with(|| asan_sym(FunctionFgets::NAME.as_ptr() as *const c_char));
|
asan_sym(FunctionFgets::NAME.as_ptr() as *const c_char) as GuestAddr
|
||||||
|
});
|
||||||
let fn_fgets = FunctionFgets::as_ptr(addr).unwrap();
|
let fn_fgets = FunctionFgets::as_ptr(addr).unwrap();
|
||||||
asan_swap(false);
|
asan_swap(false);
|
||||||
let ret = fn_fgets(buf, n, stream);
|
let ret = fn_fgets(buf, n, stream);
|
||||||
|
@ -4,7 +4,7 @@ use libc::{c_int, c_void};
|
|||||||
use log::trace;
|
use log::trace;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
asan_swap, asan_sym, asan_track, asan_unpoison, off_t, size_t,
|
GuestAddr, asan_swap, asan_sym, asan_track, asan_unpoison, off_t, size_t,
|
||||||
symbols::{AtomicGuestAddr, Function, FunctionPointer},
|
symbols::{AtomicGuestAddr, Function, FunctionPointer},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -41,8 +41,9 @@ pub unsafe extern "C" fn mmap(
|
|||||||
"mmap - addr: {:p}, len: {:#x}, prot: {:#x}, flags: {:#x}, fd: {:#x}, offset: {:#x}",
|
"mmap - addr: {:p}, len: {:#x}, prot: {:#x}, flags: {:#x}, fd: {:#x}, offset: {:#x}",
|
||||||
addr, len, prot, flags, fd, offset
|
addr, len, prot, flags, fd, offset
|
||||||
);
|
);
|
||||||
let mmap_addr =
|
let mmap_addr = MMAP_ADDR.get_or_insert_with(|| {
|
||||||
MMAP_ADDR.get_or_insert_with(|| asan_sym(FunctionMmap::NAME.as_ptr() as *const c_char));
|
asan_sym(FunctionMmap::NAME.as_ptr() as *const c_char) as GuestAddr
|
||||||
|
});
|
||||||
asan_swap(false);
|
asan_swap(false);
|
||||||
let fn_mmap = FunctionMmap::as_ptr(mmap_addr).unwrap();
|
let fn_mmap = FunctionMmap::as_ptr(mmap_addr).unwrap();
|
||||||
asan_swap(true);
|
asan_swap(true);
|
||||||
|
@ -28,19 +28,23 @@ pub mod mmap;
|
|||||||
pub mod munmap;
|
pub mod munmap;
|
||||||
pub mod posix_memalign;
|
pub mod posix_memalign;
|
||||||
pub mod pvalloc;
|
pub mod pvalloc;
|
||||||
|
pub mod rawmemchr;
|
||||||
pub mod read;
|
pub mod read;
|
||||||
pub mod realloc;
|
pub mod realloc;
|
||||||
pub mod reallocarray;
|
pub mod reallocarray;
|
||||||
pub mod stpcpy;
|
pub mod stpcpy;
|
||||||
|
pub mod stpncpy;
|
||||||
pub mod strcasecmp;
|
pub mod strcasecmp;
|
||||||
pub mod strcasestr;
|
pub mod strcasestr;
|
||||||
pub mod strcat;
|
pub mod strcat;
|
||||||
pub mod strchr;
|
pub mod strchr;
|
||||||
|
pub mod strchrnul;
|
||||||
pub mod strcmp;
|
pub mod strcmp;
|
||||||
pub mod strcpy;
|
pub mod strcpy;
|
||||||
pub mod strdup;
|
pub mod strdup;
|
||||||
pub mod strlen;
|
pub mod strlen;
|
||||||
pub mod strncasecmp;
|
pub mod strncasecmp;
|
||||||
|
pub mod strncat;
|
||||||
pub mod strncmp;
|
pub mod strncmp;
|
||||||
pub mod strncpy;
|
pub mod strncpy;
|
||||||
pub mod strndup;
|
pub mod strndup;
|
||||||
@ -48,25 +52,30 @@ pub mod strnlen;
|
|||||||
pub mod strrchr;
|
pub mod strrchr;
|
||||||
pub mod strstr;
|
pub mod strstr;
|
||||||
pub mod valloc;
|
pub mod valloc;
|
||||||
|
pub mod wcschr;
|
||||||
pub mod wcscmp;
|
pub mod wcscmp;
|
||||||
pub mod wcscpy;
|
pub mod wcscpy;
|
||||||
pub mod wcslen;
|
pub mod wcslen;
|
||||||
|
pub mod wcsncmp;
|
||||||
|
pub mod wcsnlen;
|
||||||
|
pub mod wcsrchr;
|
||||||
|
pub mod wmemchr;
|
||||||
pub mod write;
|
pub mod write;
|
||||||
|
|
||||||
#[cfg(feature = "libc")]
|
#[cfg(feature = "libc")]
|
||||||
pub mod fgets;
|
pub mod fgets;
|
||||||
|
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::{IntoIter, Vec};
|
||||||
use core::ffi::{CStr, c_char, c_int, c_void};
|
use core::ffi::{CStr, c_char, c_int, c_void};
|
||||||
|
|
||||||
use crate::{GuestAddr, hooks, size_t, wchar_t};
|
use crate::{GuestAddr, hooks, size_t, symbols::Symbols, wchar_t};
|
||||||
|
|
||||||
unsafe extern "C" {
|
unsafe extern "C" {
|
||||||
pub fn asprintf(strp: *mut *mut c_char, fmt: *const c_char, ...) -> c_int;
|
pub fn asprintf(strp: *mut *mut c_char, fmt: *const c_char, ...) -> c_int;
|
||||||
pub fn vasprintf(strp: *mut *mut c_char, fmt: *const c_char, va: *const c_void) -> c_int;
|
pub fn vasprintf(strp: *mut *mut c_char, fmt: *const c_char, va: *const c_void) -> c_int;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct PatchedHook {
|
pub struct PatchedHook {
|
||||||
pub name: &'static CStr,
|
pub name: &'static CStr,
|
||||||
pub destination: GuestAddr,
|
pub destination: GuestAddr,
|
||||||
@ -79,8 +88,27 @@ impl PatchedHook {
|
|||||||
Self { name, destination }
|
Self { name, destination }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn all() -> Vec<Self> {
|
pub fn lookup<S: Symbols>(&self) -> Result<GuestAddr, S::Error> {
|
||||||
[
|
S::lookup(self.name.as_ptr() as *const c_char)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PatchedHooks {
|
||||||
|
hooks: Vec<PatchedHook>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoIterator for PatchedHooks {
|
||||||
|
type Item = PatchedHook;
|
||||||
|
type IntoIter = IntoIter<Self::Item>;
|
||||||
|
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
self.hooks.into_iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for PatchedHooks {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self { hooks: [
|
||||||
PatchedHook::new::<unsafe extern "C" fn(size_t, size_t) -> *mut c_void>(
|
PatchedHook::new::<unsafe extern "C" fn(size_t, size_t) -> *mut c_void>(
|
||||||
c"aligned_alloc",
|
c"aligned_alloc",
|
||||||
hooks::aligned_alloc::aligned_alloc,
|
hooks::aligned_alloc::aligned_alloc,
|
||||||
@ -124,10 +152,17 @@ impl PatchedHook {
|
|||||||
c"memrchr",
|
c"memrchr",
|
||||||
hooks::memrchr::memrchr,
|
hooks::memrchr::memrchr,
|
||||||
),
|
),
|
||||||
|
PatchedHook::new::<unsafe extern "C" fn(*const c_void, c_int) -> *mut c_void>(
|
||||||
|
c"rawmemchr",
|
||||||
|
hooks::rawmemchr::rawmemchr,
|
||||||
|
),
|
||||||
PatchedHook::new::<unsafe extern "C" fn(*mut c_char, *const c_char) -> *mut c_char>(
|
PatchedHook::new::<unsafe extern "C" fn(*mut c_char, *const c_char) -> *mut c_char>(
|
||||||
c"stpcpy",
|
c"stpcpy",
|
||||||
hooks::stpcpy::stpcpy,
|
hooks::stpcpy::stpcpy,
|
||||||
),
|
),
|
||||||
|
PatchedHook::new::<
|
||||||
|
unsafe extern "C" fn(*mut c_char, *const c_char, size_t) -> *mut c_char,
|
||||||
|
>(c"stpncpy", hooks::stpncpy::stpncpy),
|
||||||
PatchedHook::new::<unsafe extern "C" fn(*const c_char, *const c_char) -> c_int>(
|
PatchedHook::new::<unsafe extern "C" fn(*const c_char, *const c_char) -> c_int>(
|
||||||
c"strcasecmp",
|
c"strcasecmp",
|
||||||
hooks::strcasecmp::strcasecmp,
|
hooks::strcasecmp::strcasecmp,
|
||||||
@ -144,6 +179,10 @@ impl PatchedHook {
|
|||||||
c"strchr",
|
c"strchr",
|
||||||
hooks::strchr::strchr,
|
hooks::strchr::strchr,
|
||||||
),
|
),
|
||||||
|
PatchedHook::new::<unsafe extern "C" fn(*const c_char, c_int) -> *mut c_char>(
|
||||||
|
c"strchrnul",
|
||||||
|
hooks::strchrnul::strchrnul,
|
||||||
|
),
|
||||||
PatchedHook::new::<unsafe extern "C" fn(*const c_char, *const c_char) -> c_int>(
|
PatchedHook::new::<unsafe extern "C" fn(*const c_char, *const c_char) -> c_int>(
|
||||||
c"strcmp",
|
c"strcmp",
|
||||||
hooks::strcmp::strcmp,
|
hooks::strcmp::strcmp,
|
||||||
@ -164,6 +203,9 @@ impl PatchedHook {
|
|||||||
c"strncasecmp",
|
c"strncasecmp",
|
||||||
hooks::strncasecmp::strncasecmp,
|
hooks::strncasecmp::strncasecmp,
|
||||||
),
|
),
|
||||||
|
PatchedHook::new::<
|
||||||
|
unsafe extern "C" fn(*mut c_char, *const c_char, size_t) -> *mut c_char,
|
||||||
|
>(c"strncat", hooks::strncat::strncat),
|
||||||
PatchedHook::new::<unsafe extern "C" fn(*const c_char, *const c_char, size_t) -> c_int>(
|
PatchedHook::new::<unsafe extern "C" fn(*const c_char, *const c_char, size_t) -> c_int>(
|
||||||
c"strncmp",
|
c"strncmp",
|
||||||
hooks::strncmp::strncmp,
|
hooks::strncmp::strncmp,
|
||||||
@ -190,6 +232,10 @@ impl PatchedHook {
|
|||||||
PatchedHook::new::<
|
PatchedHook::new::<
|
||||||
unsafe extern "C" fn(*mut *mut c_char, *const c_char, *const c_void) -> c_int,
|
unsafe extern "C" fn(*mut *mut c_char, *const c_char, *const c_void) -> c_int,
|
||||||
>(c"vasprintf", hooks::vasprintf),
|
>(c"vasprintf", hooks::vasprintf),
|
||||||
|
PatchedHook::new::<unsafe extern "C" fn(*const wchar_t, c_int) -> *mut wchar_t>(
|
||||||
|
c"wcschr",
|
||||||
|
hooks::wcschr::wcschr,
|
||||||
|
),
|
||||||
PatchedHook::new::<unsafe extern "C" fn(*const wchar_t, *const wchar_t) -> c_int>(
|
PatchedHook::new::<unsafe extern "C" fn(*const wchar_t, *const wchar_t) -> c_int>(
|
||||||
c"wcscmp",
|
c"wcscmp",
|
||||||
hooks::wcscmp::wcscmp,
|
hooks::wcscmp::wcscmp,
|
||||||
@ -202,7 +248,24 @@ impl PatchedHook {
|
|||||||
c"wcslen",
|
c"wcslen",
|
||||||
hooks::wcslen::wcslen,
|
hooks::wcslen::wcslen,
|
||||||
),
|
),
|
||||||
|
PatchedHook::new::<unsafe extern "C" fn (*const wchar_t, *const wchar_t, size_t) -> c_int>(
|
||||||
|
c"wcsncmp",
|
||||||
|
hooks::wcsncmp::wcsncmp,
|
||||||
|
),
|
||||||
|
PatchedHook::new::<unsafe extern "C" fn ( *const wchar_t, size_t) -> size_t>(
|
||||||
|
c"wcsnlen",
|
||||||
|
hooks::wcsnlen::wcsnlen,
|
||||||
|
),
|
||||||
|
PatchedHook::new::<unsafe extern "C" fn ( *const wchar_t, c_int) -> *mut wchar_t >(
|
||||||
|
c"wcsrchr",
|
||||||
|
hooks::wcsrchr::wcsrchr,
|
||||||
|
),
|
||||||
|
PatchedHook::new::<unsafe extern "C" fn ( *const wchar_t, wchar_t, size_t) -> *mut wchar_t>(
|
||||||
|
c"wmemchr",
|
||||||
|
hooks::wmemchr::wmemchr,
|
||||||
|
),
|
||||||
|
|
||||||
]
|
]
|
||||||
.to_vec()
|
.to_vec() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ use libc::{c_int, c_void};
|
|||||||
use log::trace;
|
use log::trace;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
asan_swap, asan_sym, asan_untrack, size_t,
|
GuestAddr, asan_swap, asan_sym, asan_untrack, size_t,
|
||||||
symbols::{AtomicGuestAddr, Function, FunctionPointer},
|
symbols::{AtomicGuestAddr, Function, FunctionPointer},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -24,8 +24,9 @@ static MUNMAP_ADDR: AtomicGuestAddr = AtomicGuestAddr::new();
|
|||||||
pub unsafe extern "C" fn munmap(addr: *mut c_void, len: size_t) -> c_int {
|
pub unsafe extern "C" fn munmap(addr: *mut c_void, len: size_t) -> c_int {
|
||||||
unsafe {
|
unsafe {
|
||||||
trace!("munmap - addr: {:p}, len: {:#x}", addr, len);
|
trace!("munmap - addr: {:p}, len: {:#x}", addr, len);
|
||||||
let mmap_addr = MUNMAP_ADDR
|
let mmap_addr = MUNMAP_ADDR.get_or_insert_with(|| {
|
||||||
.get_or_insert_with(|| asan_sym(FunctionMunmap::NAME.as_ptr() as *const c_char));
|
asan_sym(FunctionMunmap::NAME.as_ptr() as *const c_char) as GuestAddr
|
||||||
|
});
|
||||||
asan_swap(false);
|
asan_swap(false);
|
||||||
let fn_munmap = FunctionMunmap::as_ptr(mmap_addr).unwrap();
|
let fn_munmap = FunctionMunmap::as_ptr(mmap_addr).unwrap();
|
||||||
asan_swap(true);
|
asan_swap(true);
|
||||||
|
26
libafl_qemu/librasan/asan/src/hooks/rawmemchr.rs
Normal file
26
libafl_qemu/librasan/asan/src/hooks/rawmemchr.rs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
use core::ffi::{c_char, c_int, c_void};
|
||||||
|
|
||||||
|
use log::trace;
|
||||||
|
|
||||||
|
use crate::{asan_load, asan_panic};
|
||||||
|
|
||||||
|
/// # Safety
|
||||||
|
/// See man pages
|
||||||
|
#[unsafe(export_name = "patch_rawmemchr")]
|
||||||
|
pub unsafe extern "C" fn rawmemchr(s: *const c_void, c: c_int) -> *mut c_void {
|
||||||
|
unsafe {
|
||||||
|
trace!("rawmemchr - s: {:p}, c: {:#x}", s, c);
|
||||||
|
|
||||||
|
if s.is_null() {
|
||||||
|
asan_panic(c"rawmemchr - s is null".as_ptr() as *const c_char);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut len = 0;
|
||||||
|
let pc = s as *const c_char;
|
||||||
|
while *pc.add(len) != c as c_char {
|
||||||
|
len += 1;
|
||||||
|
}
|
||||||
|
asan_load(s, len);
|
||||||
|
s.add(len) as *mut c_void
|
||||||
|
}
|
||||||
|
}
|
@ -4,7 +4,7 @@ use libc::{SYS_read, c_int, c_void};
|
|||||||
use log::trace;
|
use log::trace;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
asan_panic, asan_store, asan_swap, asan_sym, size_t, ssize_t,
|
GuestAddr, asan_panic, asan_store, asan_swap, asan_sym, size_t, ssize_t,
|
||||||
symbols::{AtomicGuestAddr, Function, FunctionPointer},
|
symbols::{AtomicGuestAddr, Function, FunctionPointer},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -30,8 +30,9 @@ pub unsafe extern "C" fn read(fd: c_int, buf: *mut c_void, count: size_t) -> ssi
|
|||||||
}
|
}
|
||||||
|
|
||||||
asan_store(buf, count);
|
asan_store(buf, count);
|
||||||
let addr = SYSCALL_ADDR
|
let addr = SYSCALL_ADDR.get_or_insert_with(|| {
|
||||||
.get_or_insert_with(|| asan_sym(FunctionSyscall::NAME.as_ptr() as *const c_char));
|
asan_sym(FunctionSyscall::NAME.as_ptr() as *const c_char) as GuestAddr
|
||||||
|
});
|
||||||
let fn_syscall = FunctionSyscall::as_ptr(addr).unwrap();
|
let fn_syscall = FunctionSyscall::as_ptr(addr).unwrap();
|
||||||
asan_swap(false);
|
asan_swap(false);
|
||||||
let ret = fn_syscall(SYS_read, fd, buf, count);
|
let ret = fn_syscall(SYS_read, fd, buf, count);
|
||||||
|
49
libafl_qemu/librasan/asan/src/hooks/stpncpy.rs
Normal file
49
libafl_qemu/librasan/asan/src/hooks/stpncpy.rs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
use core::{
|
||||||
|
cmp::min,
|
||||||
|
ffi::{c_char, c_void},
|
||||||
|
ptr::{copy, write_bytes},
|
||||||
|
};
|
||||||
|
|
||||||
|
use log::trace;
|
||||||
|
|
||||||
|
use crate::{asan_load, asan_panic, asan_store, size_t};
|
||||||
|
|
||||||
|
/// # Safety
|
||||||
|
/// See man pages
|
||||||
|
#[unsafe(export_name = "patch_stpncpy")]
|
||||||
|
pub unsafe extern "C" fn stpncpy(
|
||||||
|
dst: *mut c_char,
|
||||||
|
src: *const c_char,
|
||||||
|
dsize: size_t,
|
||||||
|
) -> *mut c_char {
|
||||||
|
unsafe {
|
||||||
|
trace!(
|
||||||
|
"stpncpy - dst: {:p}, src: {:p}, dsize: {:#x}",
|
||||||
|
dst, src, dsize
|
||||||
|
);
|
||||||
|
|
||||||
|
if dsize == 0 {
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
if dst.is_null() {
|
||||||
|
asan_panic(c"stpncpy - dst is null".as_ptr() as *const c_char);
|
||||||
|
}
|
||||||
|
|
||||||
|
if src.is_null() {
|
||||||
|
asan_panic(c"stpncpy - src is null".as_ptr() as *const c_char);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut len = 0;
|
||||||
|
while *src.add(len) != 0 {
|
||||||
|
len += 1;
|
||||||
|
}
|
||||||
|
asan_load(src as *const c_void, len + 1);
|
||||||
|
asan_store(dst as *const c_void, dsize);
|
||||||
|
|
||||||
|
let dlen = min(len + 1, dsize);
|
||||||
|
copy(src, dst, dlen);
|
||||||
|
write_bytes(dst.add(dlen), 0, dsize - dlen);
|
||||||
|
dst.add(dsize)
|
||||||
|
}
|
||||||
|
}
|
@ -5,7 +5,7 @@ use core::{
|
|||||||
|
|
||||||
use log::trace;
|
use log::trace;
|
||||||
|
|
||||||
use crate::{asan_load, asan_panic};
|
use crate::{asan_load, asan_panic, asan_store};
|
||||||
|
|
||||||
/// # Safety
|
/// # Safety
|
||||||
/// See man pages
|
/// See man pages
|
||||||
@ -30,7 +30,7 @@ pub unsafe extern "C" fn strcat(s: *mut c_char, ct: *const c_char) -> *mut c_cha
|
|||||||
while *ct.add(ct_len) != 0 {
|
while *ct.add(ct_len) != 0 {
|
||||||
ct_len += 1;
|
ct_len += 1;
|
||||||
}
|
}
|
||||||
asan_load(s as *const c_void, s_len + 1);
|
asan_store(s.add(s_len) as *const c_void, ct_len + 1);
|
||||||
asan_load(ct as *const c_void, ct_len + 1);
|
asan_load(ct as *const c_void, ct_len + 1);
|
||||||
copy(ct, s.add(s_len), ct_len + 1);
|
copy(ct, s.add(s_len), ct_len + 1);
|
||||||
s
|
s
|
||||||
|
33
libafl_qemu/librasan/asan/src/hooks/strchrnul.rs
Normal file
33
libafl_qemu/librasan/asan/src/hooks/strchrnul.rs
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
use core::{
|
||||||
|
ffi::{c_char, c_int, c_void},
|
||||||
|
slice::from_raw_parts,
|
||||||
|
};
|
||||||
|
|
||||||
|
use log::trace;
|
||||||
|
|
||||||
|
use crate::{asan_load, asan_panic};
|
||||||
|
|
||||||
|
/// # Safety
|
||||||
|
/// See man pages
|
||||||
|
#[unsafe(export_name = "patch_strchrnul")]
|
||||||
|
pub unsafe extern "C" fn strchrnul(cs: *const c_char, c: c_int) -> *mut c_char {
|
||||||
|
unsafe {
|
||||||
|
trace!("strchrnul - cs: {:p}, c: {:#x}", cs, c);
|
||||||
|
|
||||||
|
if cs.is_null() {
|
||||||
|
asan_panic(c"strchrnul - cs is null".as_ptr() as *const c_char);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut len = 0;
|
||||||
|
while *cs.add(len) != 0 {
|
||||||
|
len += 1;
|
||||||
|
}
|
||||||
|
asan_load(cs as *const c_void, len + 1);
|
||||||
|
let cs_slice = from_raw_parts(cs, len);
|
||||||
|
let pos = cs_slice.iter().position(|&x| x as c_int == c);
|
||||||
|
match pos {
|
||||||
|
Some(pos) => cs.add(pos) as *mut c_char,
|
||||||
|
None => cs.add(len) as *mut c_char,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
46
libafl_qemu/librasan/asan/src/hooks/strncat.rs
Normal file
46
libafl_qemu/librasan/asan/src/hooks/strncat.rs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
use core::{
|
||||||
|
ffi::{c_char, c_void},
|
||||||
|
ptr::copy,
|
||||||
|
};
|
||||||
|
|
||||||
|
use log::trace;
|
||||||
|
|
||||||
|
use crate::{asan_load, asan_panic, asan_store, size_t};
|
||||||
|
|
||||||
|
/// # Safety
|
||||||
|
/// See man pages
|
||||||
|
#[unsafe(export_name = "patch_strncat")]
|
||||||
|
pub unsafe extern "C" fn strncat(s: *mut c_char, ct: *const c_char, n: size_t) -> *mut c_char {
|
||||||
|
unsafe {
|
||||||
|
trace!("strcat - s: {:p}, ct: {:p}, n: {:#x}", s, ct, n);
|
||||||
|
|
||||||
|
if n == 0 {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.is_null() {
|
||||||
|
asan_panic(c"strcat - s is null".as_ptr() as *const c_char);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ct.is_null() {
|
||||||
|
asan_panic(c"strcat - ct is null".as_ptr() as *const c_char);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut s_len = 0;
|
||||||
|
while *s.add(s_len) != 0 {
|
||||||
|
s_len += 1;
|
||||||
|
}
|
||||||
|
let mut ct_len = 0;
|
||||||
|
while *ct.add(ct_len) != 0 {
|
||||||
|
ct_len += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
let c_len = ct_len.min(n);
|
||||||
|
|
||||||
|
asan_store(s.add(s_len) as *const c_void, c_len + 1);
|
||||||
|
asan_load(ct as *const c_void, c_len);
|
||||||
|
copy(ct, s.add(s_len), c_len);
|
||||||
|
*s.add(s_len + c_len + 1) = 0;
|
||||||
|
s
|
||||||
|
}
|
||||||
|
}
|
34
libafl_qemu/librasan/asan/src/hooks/wcschr.rs
Normal file
34
libafl_qemu/librasan/asan/src/hooks/wcschr.rs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
use core::{
|
||||||
|
ffi::{c_char, c_int, c_void},
|
||||||
|
ptr::null_mut,
|
||||||
|
slice::from_raw_parts,
|
||||||
|
};
|
||||||
|
|
||||||
|
use log::trace;
|
||||||
|
|
||||||
|
use crate::{asan_load, asan_panic, wchar_t};
|
||||||
|
|
||||||
|
/// # Safety
|
||||||
|
/// See man pages
|
||||||
|
#[unsafe(export_name = "patch_wcschr")]
|
||||||
|
pub unsafe extern "C" fn wcschr(cs: *const wchar_t, c: c_int) -> *mut wchar_t {
|
||||||
|
unsafe {
|
||||||
|
trace!("wcschr - cs: {:p}, c: {:#x}", cs, c);
|
||||||
|
|
||||||
|
if cs.is_null() {
|
||||||
|
asan_panic(c"wcschr - cs is null".as_ptr() as *const c_char);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut len = 0;
|
||||||
|
while *cs.add(len) != 0 {
|
||||||
|
len += 1;
|
||||||
|
}
|
||||||
|
asan_load(cs as *const c_void, (len + 1) * size_of::<wchar_t>());
|
||||||
|
let cs_slice = from_raw_parts(cs, len);
|
||||||
|
let pos = cs_slice.iter().position(|&x| x as c_int == c);
|
||||||
|
match pos {
|
||||||
|
Some(pos) => cs.add(pos) as *mut wchar_t,
|
||||||
|
None => null_mut(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
62
libafl_qemu/librasan/asan/src/hooks/wcsncmp.rs
Normal file
62
libafl_qemu/librasan/asan/src/hooks/wcsncmp.rs
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
use core::{
|
||||||
|
cmp::Ordering,
|
||||||
|
ffi::{c_char, c_int, c_void},
|
||||||
|
slice::from_raw_parts,
|
||||||
|
};
|
||||||
|
|
||||||
|
use log::trace;
|
||||||
|
|
||||||
|
use crate::{asan_load, asan_panic, size_t, wchar_t};
|
||||||
|
|
||||||
|
/// # Safety
|
||||||
|
/// See man pages
|
||||||
|
#[unsafe(export_name = "patch_wcsncmp")]
|
||||||
|
pub unsafe extern "C" fn wcsncmp(cs: *const wchar_t, ct: *const wchar_t, n: size_t) -> c_int {
|
||||||
|
unsafe {
|
||||||
|
trace!("wcsncmp - cs: {:p}, ct: {:p}, n: {:#x}", cs, ct, n);
|
||||||
|
|
||||||
|
if n == 0 {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if cs.is_null() {
|
||||||
|
asan_panic(c"wcsncmp - cs is null".as_ptr() as *const c_char);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ct.is_null() {
|
||||||
|
asan_panic(c"wcsncmp - ct is null".as_ptr() as *const c_char);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut cs_len = 0;
|
||||||
|
while cs_len < n && *cs.add(cs_len) != 0 {
|
||||||
|
cs_len += 1;
|
||||||
|
}
|
||||||
|
let mut ct_len = 0;
|
||||||
|
while ct_len < n && *ct.add(ct_len) != 0 {
|
||||||
|
ct_len += 1;
|
||||||
|
}
|
||||||
|
asan_load(cs as *const c_void, (cs_len + 1) * size_of::<wchar_t>());
|
||||||
|
asan_load(ct as *const c_void, (ct_len + 1) * size_of::<wchar_t>());
|
||||||
|
|
||||||
|
let slice1 = from_raw_parts(cs as *const u32, cs_len);
|
||||||
|
let slice2 = from_raw_parts(ct as *const u32, ct_len);
|
||||||
|
|
||||||
|
for i in 0..cs_len.max(ct_len) {
|
||||||
|
if i >= cs_len {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if i >= ct_len {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
match slice1[i].cmp(&slice2[i]) {
|
||||||
|
Ordering::Equal => (),
|
||||||
|
Ordering::Less => return -1,
|
||||||
|
Ordering::Greater => return 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
35
libafl_qemu/librasan/asan/src/hooks/wcsnlen.rs
Normal file
35
libafl_qemu/librasan/asan/src/hooks/wcsnlen.rs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
use core::ffi::{c_char, c_void};
|
||||||
|
|
||||||
|
use log::trace;
|
||||||
|
|
||||||
|
use crate::{asan_load, asan_panic, size_t, wchar_t};
|
||||||
|
|
||||||
|
/// # Safety
|
||||||
|
/// See man pages
|
||||||
|
#[unsafe(export_name = "patch_wcsnlen")]
|
||||||
|
pub unsafe extern "C" fn wcsnlen(cs: *const wchar_t, maxlen: size_t) -> size_t {
|
||||||
|
unsafe {
|
||||||
|
trace!("wcsnlen - cs: {:p}, maxlen: {:#x}", cs, maxlen);
|
||||||
|
|
||||||
|
if maxlen == 0 {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if cs.is_null() {
|
||||||
|
asan_panic(c"wcsnlen - cs is null".as_ptr() as *const c_char);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut len = 0;
|
||||||
|
while *cs.add(len) != 0 {
|
||||||
|
len += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if len < maxlen {
|
||||||
|
asan_load(cs as *const c_void, (len + 1) * size_of::<wchar_t>());
|
||||||
|
len
|
||||||
|
} else {
|
||||||
|
asan_load(cs as *const c_void, maxlen * size_of::<wchar_t>());
|
||||||
|
maxlen
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
34
libafl_qemu/librasan/asan/src/hooks/wcsrchr.rs
Normal file
34
libafl_qemu/librasan/asan/src/hooks/wcsrchr.rs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
use core::{
|
||||||
|
ffi::{c_char, c_int, c_void},
|
||||||
|
ptr::null_mut,
|
||||||
|
slice::from_raw_parts,
|
||||||
|
};
|
||||||
|
|
||||||
|
use log::trace;
|
||||||
|
|
||||||
|
use crate::{asan_load, asan_panic, wchar_t};
|
||||||
|
|
||||||
|
/// # Safety
|
||||||
|
/// See man pages
|
||||||
|
#[unsafe(export_name = "patch_wcsrchr")]
|
||||||
|
pub unsafe extern "C" fn wcsrchr(cs: *const wchar_t, c: c_int) -> *mut wchar_t {
|
||||||
|
unsafe {
|
||||||
|
trace!("wcsrchr - cs: {:p}, c: {:#x}", cs, c);
|
||||||
|
|
||||||
|
if cs.is_null() {
|
||||||
|
asan_panic(c"wcsrchr - cs is null".as_ptr() as *const c_char);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut len = 0;
|
||||||
|
while *cs.add(len) != 0 {
|
||||||
|
len += 1;
|
||||||
|
}
|
||||||
|
asan_load(cs as *const c_void, (len + 1) * size_of::<wchar_t>());
|
||||||
|
let cs_slice = from_raw_parts(cs, len);
|
||||||
|
let pos = cs_slice.iter().rev().position(|&x| x as c_int == c);
|
||||||
|
match pos {
|
||||||
|
Some(pos) => cs.add(len - pos - 1) as *mut wchar_t,
|
||||||
|
None => null_mut(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
34
libafl_qemu/librasan/asan/src/hooks/wmemchr.rs
Normal file
34
libafl_qemu/librasan/asan/src/hooks/wmemchr.rs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
use core::{
|
||||||
|
ffi::{c_char, c_void},
|
||||||
|
ptr::null_mut,
|
||||||
|
slice::from_raw_parts,
|
||||||
|
};
|
||||||
|
|
||||||
|
use log::trace;
|
||||||
|
|
||||||
|
use crate::{asan_load, asan_panic, size_t, wchar_t};
|
||||||
|
|
||||||
|
/// # Safety
|
||||||
|
/// See man pages
|
||||||
|
#[unsafe(export_name = "patch_wmemchr")]
|
||||||
|
pub unsafe extern "C" fn wmemchr(cx: *const wchar_t, c: wchar_t, n: size_t) -> *mut wchar_t {
|
||||||
|
unsafe {
|
||||||
|
trace!("wmemchr - cx: {:p}, c: {:#x}, n: {:#x}", cx, c, n);
|
||||||
|
|
||||||
|
if n == 0 {
|
||||||
|
return null_mut();
|
||||||
|
}
|
||||||
|
|
||||||
|
if cx.is_null() && n != 0 {
|
||||||
|
asan_panic(c"wmemchr - cx is null".as_ptr() as *const c_char);
|
||||||
|
}
|
||||||
|
|
||||||
|
asan_load(cx as *const c_void, n * size_of::<wchar_t>());
|
||||||
|
let slice = from_raw_parts(cx, n);
|
||||||
|
let pos = slice.iter().position(|&x| x == c);
|
||||||
|
match pos {
|
||||||
|
Some(pos) => cx.add(pos) as *mut wchar_t,
|
||||||
|
None => null_mut(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,7 +4,7 @@ use libc::{SYS_write, c_int, c_void};
|
|||||||
use log::trace;
|
use log::trace;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
asan_load, asan_panic, asan_swap, asan_sym, size_t, ssize_t,
|
GuestAddr, asan_load, asan_panic, asan_swap, asan_sym, size_t, ssize_t,
|
||||||
symbols::{AtomicGuestAddr, Function, FunctionPointer},
|
symbols::{AtomicGuestAddr, Function, FunctionPointer},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -30,8 +30,9 @@ pub unsafe extern "C" fn write(fd: c_int, buf: *const c_void, count: size_t) ->
|
|||||||
}
|
}
|
||||||
|
|
||||||
asan_load(buf, count);
|
asan_load(buf, count);
|
||||||
let addr = SYSCALL_ADDR
|
let addr = SYSCALL_ADDR.get_or_insert_with(|| {
|
||||||
.get_or_insert_with(|| asan_sym(FunctionSyscall::NAME.as_ptr() as *const c_char));
|
asan_sym(FunctionSyscall::NAME.as_ptr() as *const c_char) as GuestAddr
|
||||||
|
});
|
||||||
let fn_syscall = FunctionSyscall::as_ptr(addr).unwrap();
|
let fn_syscall = FunctionSyscall::as_ptr(addr).unwrap();
|
||||||
asan_swap(false);
|
asan_swap(false);
|
||||||
let ret = fn_syscall(SYS_write, fd, buf, count);
|
let ret = fn_syscall(SYS_write, fd, buf, count);
|
||||||
|
@ -111,7 +111,7 @@ impl<S: Symbols> Host for LibcHost<S> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alloc(start: GuestAddr, len: usize) -> Result<(), LibcHostError<S>> {
|
fn track(start: GuestAddr, len: usize) -> Result<(), LibcHostError<S>> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let syscall = Self::get_syscall()?;
|
let syscall = Self::get_syscall()?;
|
||||||
let ret = syscall(Self::SYSCALL_NO, HostAction::Alloc as usize, start, len);
|
let ret = syscall(Self::SYSCALL_NO, HostAction::Alloc as usize, start, len);
|
||||||
@ -122,7 +122,7 @@ impl<S: Symbols> Host for LibcHost<S> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dealloc(start: GuestAddr) -> Result<(), LibcHostError<S>> {
|
fn untrack(start: GuestAddr) -> Result<(), LibcHostError<S>> {
|
||||||
let syscall = Self::get_syscall()?;
|
let syscall = Self::get_syscall()?;
|
||||||
let ret = unsafe { syscall(Self::SYSCALL_NO, HostAction::Dealloc as usize, start) };
|
let ret = unsafe { syscall(Self::SYSCALL_NO, HostAction::Dealloc as usize, start) };
|
||||||
if ret != 0 {
|
if ret != 0 {
|
||||||
|
@ -66,14 +66,14 @@ impl Host for LinuxHost {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alloc(start: GuestAddr, len: usize) -> LinuxHostResult<()> {
|
fn track(start: GuestAddr, len: usize) -> LinuxHostResult<()> {
|
||||||
unsafe {
|
unsafe {
|
||||||
syscall3(Self::sysno(), HostAction::Alloc as usize, start, len)?;
|
syscall3(Self::sysno(), HostAction::Alloc as usize, start, len)?;
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dealloc(start: GuestAddr) -> LinuxHostResult<()> {
|
fn untrack(start: GuestAddr) -> LinuxHostResult<()> {
|
||||||
unsafe { syscall2(Self::sysno(), HostAction::Dealloc as usize, start)? };
|
unsafe { syscall2(Self::sysno(), HostAction::Dealloc as usize, start)? };
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,6 @@ pub trait Host: Debug + Send {
|
|||||||
fn unpoison(start: GuestAddr, len: usize) -> Result<(), Self::Error>;
|
fn unpoison(start: GuestAddr, len: usize) -> Result<(), Self::Error>;
|
||||||
fn is_poison(start: GuestAddr, len: usize) -> Result<bool, Self::Error>;
|
fn is_poison(start: GuestAddr, len: usize) -> Result<bool, Self::Error>;
|
||||||
fn swap(enabled: bool) -> Result<(), Self::Error>;
|
fn swap(enabled: bool) -> Result<(), Self::Error>;
|
||||||
fn alloc(start: GuestAddr, len: usize) -> Result<(), Self::Error>;
|
fn track(start: GuestAddr, len: usize) -> Result<(), Self::Error>;
|
||||||
fn dealloc(start: GuestAddr) -> Result<(), Self::Error>;
|
fn untrack(start: GuestAddr) -> Result<(), Self::Error>;
|
||||||
}
|
}
|
||||||
|
@ -118,8 +118,7 @@ unsafe extern "C" {
|
|||||||
pub fn asan_alloc(len: usize, align: usize) -> *mut c_void;
|
pub fn asan_alloc(len: usize, align: usize) -> *mut c_void;
|
||||||
pub fn asan_dealloc(addr: *const c_void);
|
pub fn asan_dealloc(addr: *const c_void);
|
||||||
pub fn asan_get_size(addr: *const c_void) -> usize;
|
pub fn asan_get_size(addr: *const c_void) -> usize;
|
||||||
#[cfg(feature = "libc")]
|
pub fn asan_sym(name: *const c_char) -> *const c_void;
|
||||||
pub fn asan_sym(name: *const c_char) -> GuestAddr;
|
|
||||||
pub fn asan_page_size() -> usize;
|
pub fn asan_page_size() -> usize;
|
||||||
pub fn asan_unpoison(addr: *mut c_void, len: usize);
|
pub fn asan_unpoison(addr: *mut c_void, len: usize);
|
||||||
pub fn asan_track(addr: *mut c_void, len: usize);
|
pub fn asan_track(addr: *mut c_void, len: usize);
|
||||||
|
@ -1,5 +1,18 @@
|
|||||||
|
use alloc::vec::{IntoIter, Vec};
|
||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
|
|
||||||
|
use itertools::Itertools;
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
GuestAddr,
|
||||||
|
maps::{
|
||||||
|
entry::{MapEntry, WriteableMapProtection},
|
||||||
|
iterator::MapIterator,
|
||||||
|
},
|
||||||
|
mmap::Mmap,
|
||||||
|
};
|
||||||
|
|
||||||
mod decode;
|
mod decode;
|
||||||
pub mod entry;
|
pub mod entry;
|
||||||
|
|
||||||
@ -15,4 +28,46 @@ pub trait MapReader: Sized {
|
|||||||
type Error: Debug;
|
type Error: Debug;
|
||||||
fn new() -> Result<Self, Self::Error>;
|
fn new() -> Result<Self, Self::Error>;
|
||||||
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error>;
|
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error>;
|
||||||
|
fn mappings() -> Result<Maps, Self::Error> {
|
||||||
|
let reader = Self::new()?;
|
||||||
|
let maps = MapIterator::new(reader).collect::<Vec<MapEntry>>();
|
||||||
|
Ok(Maps { maps })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Maps {
|
||||||
|
maps: Vec<MapEntry>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Maps {
|
||||||
|
pub fn writeable<M: Mmap>(
|
||||||
|
&self,
|
||||||
|
addr: GuestAddr,
|
||||||
|
) -> Result<WriteableMapProtection<M>, MapsError<M>> {
|
||||||
|
let mapping = self
|
||||||
|
.maps
|
||||||
|
.iter()
|
||||||
|
.filter(|m| m.contains(addr))
|
||||||
|
.exactly_one()
|
||||||
|
.map_err(|_e| MapsError::MappingNotFound(addr))?;
|
||||||
|
mapping
|
||||||
|
.writeable::<M>()
|
||||||
|
.map_err(|e| MapsError::MmapError(e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoIterator for Maps {
|
||||||
|
type Item = MapEntry;
|
||||||
|
type IntoIter = IntoIter<Self::Item>;
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
self.maps.into_iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Error, Debug)]
|
||||||
|
pub enum MapsError<M: Mmap> {
|
||||||
|
#[error("Mapping not found: {0}")]
|
||||||
|
MappingNotFound(GuestAddr),
|
||||||
|
#[error("Mmap error: {0:?}")]
|
||||||
|
MmapError(M::Error),
|
||||||
}
|
}
|
||||||
|
@ -1,92 +0,0 @@
|
|||||||
use alloc::{collections::BTreeMap, fmt::Debug, vec::Vec};
|
|
||||||
use core::ffi::{CStr, c_char};
|
|
||||||
|
|
||||||
use itertools::Itertools;
|
|
||||||
use log::{debug, trace};
|
|
||||||
use spin::Mutex;
|
|
||||||
use thiserror::Error;
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
GuestAddr,
|
|
||||||
hooks::PatchedHook,
|
|
||||||
maps::{MapReader, entry::MapEntry, iterator::MapIterator},
|
|
||||||
mmap::Mmap,
|
|
||||||
patch::Patch,
|
|
||||||
symbols::Symbols,
|
|
||||||
};
|
|
||||||
|
|
||||||
static PATCHED: Mutex<Option<BTreeMap<GuestAddr, PatchedHook>>> = Mutex::new(None);
|
|
||||||
|
|
||||||
pub struct PatchedHooks;
|
|
||||||
|
|
||||||
impl PatchedHooks {
|
|
||||||
pub fn init<S: Symbols, P: Patch, R: MapReader, M: Mmap>()
|
|
||||||
-> Result<(), PatchesError<S, P, R, M>> {
|
|
||||||
debug!("Installing patches");
|
|
||||||
let mappings = Self::get_mappings()?;
|
|
||||||
mappings.iter().for_each(|m| trace!("{m:?}"));
|
|
||||||
for patch in PatchedHook::all() {
|
|
||||||
Self::patch(patch, &mappings)?;
|
|
||||||
}
|
|
||||||
debug!("Patching complete");
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
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<(), 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, patch.destination);
|
|
||||||
let mapping = mappings
|
|
||||||
.iter()
|
|
||||||
.filter(|m| m.contains(target))
|
|
||||||
.exactly_one()
|
|
||||||
.map_err(|_e| PatchesError::MapError(target))?;
|
|
||||||
let prot = mapping
|
|
||||||
.writeable::<M>()
|
|
||||||
.map_err(|e| PatchesError::MmapError(e))?;
|
|
||||||
P::patch(target, patch.destination).map_err(|e| PatchesError::PatchError(e))?;
|
|
||||||
drop(prot);
|
|
||||||
PATCHED.lock().get_or_insert_default().insert(target, patch);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn check_patched(addr: GuestAddr) -> Result<(), PatchesCheckError> {
|
|
||||||
match PATCHED.lock().as_ref().and_then(|p| p.get(&addr)) {
|
|
||||||
Some(patch) => Err(PatchesCheckError::AddressPatchedError(addr, patch.name))?,
|
|
||||||
_ => Ok(()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Error, Debug, PartialEq, Clone)]
|
|
||||||
pub enum PatchesError<S: Symbols, P: Patch, R: MapReader, M: Mmap> {
|
|
||||||
#[error("Symbols error: {0:?}")]
|
|
||||||
SymbolsError(S::Error),
|
|
||||||
#[error("Patch error: {0:?}")]
|
|
||||||
PatchError(P::Error),
|
|
||||||
#[error("Map reader error: {0:?}")]
|
|
||||||
MapReaderError(R::Error),
|
|
||||||
#[error("Map error: {0:?}")]
|
|
||||||
MapError(GuestAddr),
|
|
||||||
#[error("Mmap error: {0:?}")]
|
|
||||||
MmapError(M::Error),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Error, Debug, PartialEq, Clone)]
|
|
||||||
pub enum PatchesCheckError {
|
|
||||||
#[error("Address: {0} is patched for {1:?}")]
|
|
||||||
AddressPatchedError(GuestAddr, &'static CStr),
|
|
||||||
}
|
|
@ -1,16 +1,65 @@
|
|||||||
//! # patch
|
//! # patch
|
||||||
//! This module provides implementations patching function prologues in order
|
//! This module provides implementations patching function prologues in order
|
||||||
//! to re-direct execution to an alternative address.
|
//! to re-direct execution to an alternative address.
|
||||||
use alloc::fmt::Debug;
|
|
||||||
|
|
||||||
use crate::GuestAddr;
|
|
||||||
|
|
||||||
#[cfg(feature = "hooks")]
|
|
||||||
pub mod hooks;
|
|
||||||
|
|
||||||
pub mod raw;
|
pub mod raw;
|
||||||
|
|
||||||
|
use alloc::{collections::BTreeMap, fmt::Debug};
|
||||||
|
|
||||||
|
use log::trace;
|
||||||
|
use spin::{Mutex, Once};
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
GuestAddr,
|
||||||
|
maps::{Maps, MapsError},
|
||||||
|
mmap::Mmap,
|
||||||
|
};
|
||||||
|
|
||||||
pub trait Patch: Debug {
|
pub trait Patch: Debug {
|
||||||
type Error: Debug;
|
type Error: Debug;
|
||||||
fn patch(target: GuestAddr, destination: GuestAddr) -> Result<(), Self::Error>;
|
fn patch(target: GuestAddr, destination: GuestAddr) -> Result<(), Self::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PATCHES: Once<Mutex<Patches>> = Once::new();
|
||||||
|
static PATCHED: Mutex<BTreeMap<GuestAddr, GuestAddr>> = Mutex::new(BTreeMap::new());
|
||||||
|
|
||||||
|
pub struct Patches {
|
||||||
|
maps: Maps,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Patches {
|
||||||
|
pub fn init(maps: Maps) {
|
||||||
|
let patches = Mutex::new(Patches { maps });
|
||||||
|
PATCHES.call_once(|| patches);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn apply<P: Patch, M: Mmap>(
|
||||||
|
target: GuestAddr,
|
||||||
|
destination: GuestAddr,
|
||||||
|
) -> Result<(), PatchesError<P, M>> {
|
||||||
|
trace!("patch: {:#x} -> {:#x}", target, destination);
|
||||||
|
let patches = PATCHES.get().ok_or(PatchesError::Uninitialized())?.lock();
|
||||||
|
let prot = patches
|
||||||
|
.maps
|
||||||
|
.writeable(target)
|
||||||
|
.map_err(PatchesError::MapsError)?;
|
||||||
|
P::patch(target, destination).map_err(|e| PatchesError::PatchError(e))?;
|
||||||
|
drop(prot);
|
||||||
|
PATCHED.lock().insert(target, destination);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_patched(addr: GuestAddr) -> bool {
|
||||||
|
PATCHED.lock().contains_key(&addr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Error, Debug)]
|
||||||
|
pub enum PatchesError<P: Patch, M: Mmap> {
|
||||||
|
#[error("Uninitialized")]
|
||||||
|
Uninitialized(),
|
||||||
|
#[error("Patch error: {0:?}")]
|
||||||
|
PatchError(P::Error),
|
||||||
|
#[error("Maps error: {0:?}")]
|
||||||
|
MapsError(MapsError<M>),
|
||||||
|
}
|
||||||
|
@ -12,9 +12,7 @@ use core::{
|
|||||||
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::GuestAddr;
|
use crate::{GuestAddr, patch::Patches};
|
||||||
#[cfg(feature = "hooks")]
|
|
||||||
use crate::patch::hooks::{PatchedHooks, PatchesCheckError};
|
|
||||||
|
|
||||||
#[cfg(feature = "libc")]
|
#[cfg(feature = "libc")]
|
||||||
pub mod dlsym;
|
pub mod dlsym;
|
||||||
@ -108,8 +106,9 @@ impl<T: Function> FunctionPointer for T {
|
|||||||
Err(FunctionPointerError::BadAddress(addr))?;
|
Err(FunctionPointerError::BadAddress(addr))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "hooks")]
|
if Patches::is_patched(addr) {
|
||||||
PatchedHooks::check_patched(addr).map_err(FunctionPointerError::PatchedAddress)?;
|
Err(FunctionPointerError::PatchedAddress(addr))?;
|
||||||
|
}
|
||||||
|
|
||||||
let pp_sym = (&addr) as *const GuestAddr as *const *mut c_void;
|
let pp_sym = (&addr) as *const GuestAddr as *const *mut c_void;
|
||||||
let p_f = pp_sym as *const Self::Func;
|
let p_f = pp_sym as *const Self::Func;
|
||||||
@ -122,7 +121,6 @@ impl<T: Function> FunctionPointer for T {
|
|||||||
pub enum FunctionPointerError {
|
pub enum FunctionPointerError {
|
||||||
#[error("Bad address: {0}")]
|
#[error("Bad address: {0}")]
|
||||||
BadAddress(GuestAddr),
|
BadAddress(GuestAddr),
|
||||||
#[cfg(feature = "hooks")]
|
|
||||||
#[error("Patched address: {0}")]
|
#[error("Patched address: {0}")]
|
||||||
PatchedAddress(PatchesCheckError),
|
PatchedAddress(GuestAddr),
|
||||||
}
|
}
|
||||||
|
@ -138,8 +138,8 @@ pub unsafe extern "C" fn asan_get_size(addr: *const c_void) -> usize {
|
|||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
/// # Safety
|
/// # Safety
|
||||||
pub unsafe extern "C" fn asan_sym(name: *const c_char) -> GuestAddr {
|
pub unsafe extern "C" fn asan_sym(name: *const c_char) -> *const c_void {
|
||||||
TestSyms::lookup(name).unwrap()
|
TestSyms::lookup(name).unwrap() as *const c_void
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
@ -166,7 +166,7 @@ pub unsafe extern "C" fn asan_track(addr: *const c_void, len: usize) {
|
|||||||
FRONTEND
|
FRONTEND
|
||||||
.lock()
|
.lock()
|
||||||
.tracking_mut()
|
.tracking_mut()
|
||||||
.alloc(addr as GuestAddr, len)
|
.track(addr as GuestAddr, len)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,7 +177,7 @@ pub unsafe extern "C" fn asan_untrack(addr: *const c_void) {
|
|||||||
FRONTEND
|
FRONTEND
|
||||||
.lock()
|
.lock()
|
||||||
.tracking_mut()
|
.tracking_mut()
|
||||||
.dealloc(addr as GuestAddr)
|
.untrack(addr as GuestAddr)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ pub struct GuestTracking {
|
|||||||
impl Tracking for GuestTracking {
|
impl Tracking for GuestTracking {
|
||||||
type Error = GuestTrackingError;
|
type Error = GuestTrackingError;
|
||||||
|
|
||||||
fn alloc(&mut self, start: GuestAddr, len: usize) -> Result<(), Self::Error> {
|
fn track(&mut self, start: GuestAddr, len: usize) -> Result<(), Self::Error> {
|
||||||
debug!("alloc - start: 0x{:x}, len: 0x{:x}", start, len);
|
debug!("alloc - start: 0x{:x}, len: 0x{:x}", start, len);
|
||||||
if Self::is_out_of_bounds(start, len) {
|
if Self::is_out_of_bounds(start, len) {
|
||||||
Err(GuestTrackingError::AddressRangeOverflow(start, len))?;
|
Err(GuestTrackingError::AddressRangeOverflow(start, len))?;
|
||||||
@ -85,7 +85,7 @@ impl Tracking for GuestTracking {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dealloc(&mut self, start: GuestAddr) -> Result<(), Self::Error> {
|
fn untrack(&mut self, start: GuestAddr) -> Result<(), Self::Error> {
|
||||||
debug!("dealloc - start: 0x{:x}", start);
|
debug!("dealloc - start: 0x{:x}", start);
|
||||||
let pos = self.ranges.binary_search_by(|item| item.start.cmp(&start));
|
let pos = self.ranges.binary_search_by(|item| item.start.cmp(&start));
|
||||||
match pos {
|
match pos {
|
||||||
|
@ -19,15 +19,15 @@ pub struct HostTracking<H> {
|
|||||||
impl<H: Host> Tracking for HostTracking<H> {
|
impl<H: Host> Tracking for HostTracking<H> {
|
||||||
type Error = HostTrackingError<H>;
|
type Error = HostTrackingError<H>;
|
||||||
|
|
||||||
fn alloc(&mut self, start: GuestAddr, len: usize) -> Result<(), Self::Error> {
|
fn track(&mut self, start: GuestAddr, len: usize) -> Result<(), Self::Error> {
|
||||||
debug!("alloc - start: 0x{:x}, len: 0x{:x}", start, len);
|
debug!("alloc - start: 0x{:x}, len: 0x{:x}", start, len);
|
||||||
/* Here QEMU expects a start and end, rather than start and length */
|
/* Here QEMU expects a start and end, rather than start and length */
|
||||||
H::alloc(start, start + len).map_err(|e| HostTrackingError::HostError(e))
|
H::track(start, start + len).map_err(|e| HostTrackingError::HostError(e))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dealloc(&mut self, start: GuestAddr) -> Result<(), Self::Error> {
|
fn untrack(&mut self, start: GuestAddr) -> Result<(), Self::Error> {
|
||||||
debug!("free - start: 0x{:x}", start);
|
debug!("free - start: 0x{:x}", start);
|
||||||
H::dealloc(start).map_err(|e| HostTrackingError::HostError(e))
|
H::untrack(start).map_err(|e| HostTrackingError::HostError(e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,6 @@ pub mod host;
|
|||||||
|
|
||||||
pub trait Tracking: Sized + Debug + Send {
|
pub trait Tracking: Sized + Debug + Send {
|
||||||
type Error: Debug;
|
type Error: Debug;
|
||||||
fn alloc(&mut self, start: GuestAddr, len: usize) -> Result<(), Self::Error>;
|
fn track(&mut self, start: GuestAddr, len: usize) -> Result<(), Self::Error>;
|
||||||
fn dealloc(&mut self, start: GuestAddr) -> Result<(), Self::Error>;
|
fn untrack(&mut self, start: GuestAddr) -> Result<(), Self::Error>;
|
||||||
}
|
}
|
||||||
|
@ -28,14 +28,14 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_max() {
|
fn test_max() {
|
||||||
let mut tracking = get_tracking();
|
let mut tracking = get_tracking();
|
||||||
assert_eq!(tracking.alloc(GuestAddr::MAX, 1), Ok(()));
|
assert_eq!(tracking.track(GuestAddr::MAX, 1), Ok(()));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_out_of_bounds() {
|
fn test_out_of_bounds() {
|
||||||
let mut tracking = get_tracking();
|
let mut tracking = get_tracking();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
tracking.alloc(GuestAddr::MAX, 2),
|
tracking.track(GuestAddr::MAX, 2),
|
||||||
Err(GuestTrackingError::AddressRangeOverflow(GuestAddr::MAX, 2))
|
Err(GuestTrackingError::AddressRangeOverflow(GuestAddr::MAX, 2))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -43,9 +43,9 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_track_identical() {
|
fn test_track_identical() {
|
||||||
let mut tracking = get_tracking();
|
let mut tracking = get_tracking();
|
||||||
assert_eq!(tracking.alloc(0x1000, 0x1000), Ok(()));
|
assert_eq!(tracking.track(0x1000, 0x1000), Ok(()));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
tracking.alloc(0x1000, 0x1000),
|
tracking.track(0x1000, 0x1000),
|
||||||
Err(GuestTrackingError::TrackingConflict(
|
Err(GuestTrackingError::TrackingConflict(
|
||||||
0x1000, 0x1000, 0x1000, 0x1000
|
0x1000, 0x1000, 0x1000, 0x1000
|
||||||
))
|
))
|
||||||
@ -55,23 +55,23 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_track_adjacent_after() {
|
fn test_track_adjacent_after() {
|
||||||
let mut tracking = get_tracking();
|
let mut tracking = get_tracking();
|
||||||
assert_eq!(tracking.alloc(0x1000, 0x1000), Ok(()));
|
assert_eq!(tracking.track(0x1000, 0x1000), Ok(()));
|
||||||
assert_eq!(tracking.alloc(0x2000, 0x1000), Ok(()));
|
assert_eq!(tracking.track(0x2000, 0x1000), Ok(()));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_track_adjacent_before() {
|
fn test_track_adjacent_before() {
|
||||||
let mut tracking = get_tracking();
|
let mut tracking = get_tracking();
|
||||||
assert_eq!(tracking.alloc(0x1000, 0x1000), Ok(()));
|
assert_eq!(tracking.track(0x1000, 0x1000), Ok(()));
|
||||||
assert_eq!(tracking.alloc(0x0000, 0x1000), Ok(()));
|
assert_eq!(tracking.track(0x0000, 0x1000), Ok(()));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_track_overlapping_start() {
|
fn test_track_overlapping_start() {
|
||||||
let mut tracking = get_tracking();
|
let mut tracking = get_tracking();
|
||||||
assert_eq!(tracking.alloc(0x1000, 0x1000), Ok(()));
|
assert_eq!(tracking.track(0x1000, 0x1000), Ok(()));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
tracking.alloc(0x0000, 0x1001),
|
tracking.track(0x0000, 0x1001),
|
||||||
Err(GuestTrackingError::TrackingConflict(
|
Err(GuestTrackingError::TrackingConflict(
|
||||||
0x1000, 0x1000, 0x0000, 0x1001
|
0x1000, 0x1000, 0x0000, 0x1001
|
||||||
))
|
))
|
||||||
@ -81,9 +81,9 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_track_overlapping_end() {
|
fn test_track_overlapping_end() {
|
||||||
let mut tracking = get_tracking();
|
let mut tracking = get_tracking();
|
||||||
assert_eq!(tracking.alloc(0x1000, 0x1000), Ok(()));
|
assert_eq!(tracking.track(0x1000, 0x1000), Ok(()));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
tracking.alloc(0x1fff, 0x1001),
|
tracking.track(0x1fff, 0x1001),
|
||||||
Err(GuestTrackingError::TrackingConflict(
|
Err(GuestTrackingError::TrackingConflict(
|
||||||
0x1000, 0x1000, 0x1fff, 0x1001
|
0x1000, 0x1000, 0x1fff, 0x1001
|
||||||
))
|
))
|
||||||
@ -96,9 +96,9 @@ mod tests {
|
|||||||
let mut tracking = get_tracking();
|
let mut tracking = get_tracking();
|
||||||
// alloc - start: 0xffffffffb5b5ff21, len: 0x3ff
|
// alloc - start: 0xffffffffb5b5ff21, len: 0x3ff
|
||||||
// alloc - start: 0xffffffffb5b60107, len: 0xdb
|
// alloc - start: 0xffffffffb5b60107, len: 0xdb
|
||||||
assert_eq!(tracking.alloc(0xffffffffb5b5ff21, 0x3ff), Ok(()));
|
assert_eq!(tracking.track(0xffffffffb5b5ff21, 0x3ff), Ok(()));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
tracking.alloc(0xffffffffb5b60107, 0xdb),
|
tracking.track(0xffffffffb5b60107, 0xdb),
|
||||||
Err(GuestTrackingError::TrackingConflict(
|
Err(GuestTrackingError::TrackingConflict(
|
||||||
0xffffffffb5b5ff21,
|
0xffffffffb5b5ff21,
|
||||||
0x3ff,
|
0x3ff,
|
||||||
|
51
libafl_qemu/librasan/asan/tests/hooks_rawmemchr.rs
Normal file
51
libafl_qemu/librasan/asan/tests/hooks_rawmemchr.rs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#[cfg(test)]
|
||||||
|
#[cfg(feature = "hooks")]
|
||||||
|
mod tests {
|
||||||
|
use core::{
|
||||||
|
ffi::{c_int, c_void},
|
||||||
|
ptr::null_mut,
|
||||||
|
};
|
||||||
|
|
||||||
|
use asan::{expect_panic, hooks::rawmemchr::rawmemchr};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_rawmemchr_null_buffer() {
|
||||||
|
expect_panic();
|
||||||
|
unsafe { rawmemchr(null_mut(), 0) };
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_rawmemchr_find_first() {
|
||||||
|
let data = "abcdefghij".as_bytes();
|
||||||
|
let c = 'a' as c_int;
|
||||||
|
let ret = unsafe { rawmemchr(data.as_ptr() as *const c_void, c) };
|
||||||
|
assert_eq!(ret, data.as_ptr() as *mut c_void);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_rawmemchr_find_last() {
|
||||||
|
let data = "abcdefghij".as_bytes();
|
||||||
|
let c = 'j' as c_int;
|
||||||
|
let ret = unsafe { rawmemchr(data.as_ptr() as *const c_void, c) };
|
||||||
|
assert_eq!(ret, unsafe {
|
||||||
|
data.as_ptr().add(data.len() - 1) as *mut c_void
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_rawmemchr_find_mid() {
|
||||||
|
let data = "abcdefghij".as_bytes();
|
||||||
|
let c = 'e' as c_int;
|
||||||
|
let ret = unsafe { rawmemchr(data.as_ptr() as *const c_void, c) };
|
||||||
|
assert_eq!(ret, unsafe { data.as_ptr().add(4) as *mut c_void });
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_rawmemchr_find_repeated() {
|
||||||
|
let data = "ababababab".as_bytes();
|
||||||
|
let c = 'b' as c_int;
|
||||||
|
let ret = unsafe { rawmemchr(data.as_ptr() as *const c_void, c) };
|
||||||
|
assert_eq!(ret, unsafe { data.as_ptr().add(1) as *mut c_void });
|
||||||
|
}
|
||||||
|
}
|
64
libafl_qemu/librasan/asan/tests/hooks_stpncpy.rs
Normal file
64
libafl_qemu/librasan/asan/tests/hooks_stpncpy.rs
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#[cfg(test)]
|
||||||
|
#[cfg(all(feature = "hooks"))]
|
||||||
|
mod tests {
|
||||||
|
use core::{ffi::c_char, ptr::null_mut};
|
||||||
|
|
||||||
|
use asan::{expect_panic, hooks::stpncpy::stpncpy};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_stpncpy_zero_length() {
|
||||||
|
let ret = unsafe { stpncpy(null_mut(), null_mut(), 0) };
|
||||||
|
assert_eq!(ret, null_mut());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_stpncpy_dst_null() {
|
||||||
|
let src = [0u8; 10];
|
||||||
|
expect_panic();
|
||||||
|
unsafe { stpncpy(null_mut(), src.as_ptr() as *const c_char, 10) };
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_stpncpy_src_null() {
|
||||||
|
let dst = [0u8; 10];
|
||||||
|
expect_panic();
|
||||||
|
unsafe { stpncpy(dst.as_ptr() as *mut c_char, null_mut(), dst.len()) };
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_stpncpy_full() {
|
||||||
|
let src = [0xffu8; 10];
|
||||||
|
let dst = [0u8; 10];
|
||||||
|
let ret = unsafe {
|
||||||
|
stpncpy(
|
||||||
|
dst.as_ptr() as *mut c_char,
|
||||||
|
src.as_ptr() as *const c_char,
|
||||||
|
dst.len(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
assert_eq!(ret, unsafe { dst.as_ptr().add(dst.len()) as *mut c_char });
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_stpncpy_partial() {
|
||||||
|
let mut vec = c"abcdefghijklmnopqrstuvwxyz".to_bytes().to_vec();
|
||||||
|
let dst = vec.as_mut_slice();
|
||||||
|
let src = c"uvwxyz".to_bytes();
|
||||||
|
let ret = unsafe {
|
||||||
|
stpncpy(
|
||||||
|
dst.as_ptr() as *mut c_char,
|
||||||
|
src.as_ptr() as *const c_char,
|
||||||
|
dst.len(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
assert_eq!(ret, unsafe { dst.as_ptr().add(dst.len()) as *mut c_char });
|
||||||
|
let expected = c"uvwxyz".to_bytes();
|
||||||
|
expected
|
||||||
|
.iter()
|
||||||
|
.zip(dst.iter())
|
||||||
|
.for_each(|(x, y)| assert_eq!(*x, *y));
|
||||||
|
dst.iter().skip(src.len()).for_each(|x| assert_eq!(*x, 0));
|
||||||
|
}
|
||||||
|
}
|
67
libafl_qemu/librasan/asan/tests/hooks_strchrnul.rs
Normal file
67
libafl_qemu/librasan/asan/tests/hooks_strchrnul.rs
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
#[cfg(test)]
|
||||||
|
#[cfg(feature = "hooks")]
|
||||||
|
mod tests {
|
||||||
|
use core::{
|
||||||
|
ffi::{c_char, c_int},
|
||||||
|
ptr::null,
|
||||||
|
};
|
||||||
|
|
||||||
|
use asan::{expect_panic, hooks::strchrnul::strchrnul};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_strchrnul_zero_length() {
|
||||||
|
let data = c"";
|
||||||
|
let ret = unsafe { strchrnul(data.as_ptr() as *const c_char, 0x88) };
|
||||||
|
assert_eq!(ret, data.as_ptr() as *mut c_char);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_strchrnul_null_buffer() {
|
||||||
|
expect_panic();
|
||||||
|
unsafe { strchrnul(null(), 0x88) };
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_strchrnul_find_first() {
|
||||||
|
let data = c"abcdefghij";
|
||||||
|
let c = 'a' as c_int;
|
||||||
|
let ret = unsafe { strchrnul(data.as_ptr() as *const c_char, c) };
|
||||||
|
assert_eq!(ret, data.as_ptr() as *mut c_char);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_strchrnul_find_last() {
|
||||||
|
let data = c"abcdefghij";
|
||||||
|
let c = 'j' as c_int;
|
||||||
|
let ret = unsafe { strchrnul(data.as_ptr() as *const c_char, c) };
|
||||||
|
assert_eq!(ret, unsafe {
|
||||||
|
data.as_ptr().add(data.count_bytes() - 1) as *mut c_char
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_strchrnul_find_mid() {
|
||||||
|
let data = c"abcdefghij";
|
||||||
|
let c = 'e' as c_int;
|
||||||
|
let ret = unsafe { strchrnul(data.as_ptr() as *const c_char, c) };
|
||||||
|
assert_eq!(ret, unsafe { data.as_ptr().add(4) as *mut c_char });
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_strchrnul_find_repeated() {
|
||||||
|
let data = c"ababababab";
|
||||||
|
let c = 'b' as c_int;
|
||||||
|
let ret = unsafe { strchrnul(data.as_ptr() as *const c_char, c) };
|
||||||
|
assert_eq!(ret, unsafe { data.as_ptr().add(1) as *mut c_char });
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_strchrnul_not_found() {
|
||||||
|
let data = c"abcdefghij";
|
||||||
|
let c = 'k' as c_int;
|
||||||
|
let ret = unsafe { strchrnul(data.as_ptr() as *const c_char, c) };
|
||||||
|
assert_eq!(ret, unsafe { data.as_ptr().add(data.count_bytes()) }
|
||||||
|
as *mut c_char);
|
||||||
|
}
|
||||||
|
}
|
81
libafl_qemu/librasan/asan/tests/hooks_strncat.rs
Normal file
81
libafl_qemu/librasan/asan/tests/hooks_strncat.rs
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
#[cfg(test)]
|
||||||
|
#[cfg(feature = "hooks")]
|
||||||
|
mod tests {
|
||||||
|
use core::{
|
||||||
|
ffi::c_char,
|
||||||
|
ptr::{null, null_mut},
|
||||||
|
};
|
||||||
|
|
||||||
|
use asan::{expect_panic, hooks::strncat::strncat};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_strncat_zero_length() {
|
||||||
|
let ret = unsafe { strncat(null_mut(), null_mut(), 0) };
|
||||||
|
assert_eq!(ret, null_mut());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_strncat_null_s() {
|
||||||
|
expect_panic();
|
||||||
|
let data = [0u8; 10];
|
||||||
|
unsafe { strncat(null_mut(), data.as_ptr() as *const c_char, data.len()) };
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_strncat_null_s2() {
|
||||||
|
expect_panic();
|
||||||
|
let data = [0u8; 10];
|
||||||
|
unsafe { strncat(data.as_ptr() as *mut c_char, null(), 10) };
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_strncat_zero_length_both() {
|
||||||
|
let data = [0u8; 10];
|
||||||
|
let ret = unsafe {
|
||||||
|
strncat(
|
||||||
|
data.as_ptr() as *mut c_char,
|
||||||
|
data.as_ptr() as *const c_char,
|
||||||
|
data.len(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
assert_eq!(ret, data.as_ptr() as *mut c_char);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_strncat_appends() {
|
||||||
|
let mut vec = "abcde\0zzzzzzzzzzzzzzz".as_bytes().to_vec();
|
||||||
|
let s = vec.as_mut_slice();
|
||||||
|
let ct = c"fghij";
|
||||||
|
let ret = unsafe {
|
||||||
|
strncat(
|
||||||
|
s.as_ptr() as *mut c_char,
|
||||||
|
ct.as_ptr() as *const c_char,
|
||||||
|
ct.count_bytes(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
assert_eq!(ret, s.as_ptr() as *mut c_char);
|
||||||
|
let expected = c"abcdefghij";
|
||||||
|
expected
|
||||||
|
.to_bytes()
|
||||||
|
.iter()
|
||||||
|
.zip(s.iter())
|
||||||
|
.for_each(|(x, y)| assert_eq!(*x, *y));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_strncat_appends_partial() {
|
||||||
|
let mut vec = "abcde\0zzzzzzzzzzzzzzz".as_bytes().to_vec();
|
||||||
|
let s = vec.as_mut_slice();
|
||||||
|
let ct = c"fghij";
|
||||||
|
let ret = unsafe { strncat(s.as_ptr() as *mut c_char, ct.as_ptr() as *const c_char, 3) };
|
||||||
|
assert_eq!(ret, s.as_ptr() as *mut c_char);
|
||||||
|
let expected = c"abcdefgh";
|
||||||
|
expected
|
||||||
|
.to_bytes()
|
||||||
|
.iter()
|
||||||
|
.zip(s.iter())
|
||||||
|
.for_each(|(x, y)| assert_eq!(*x, *y));
|
||||||
|
}
|
||||||
|
}
|
67
libafl_qemu/librasan/asan/tests/hooks_wcschr.rs
Normal file
67
libafl_qemu/librasan/asan/tests/hooks_wcschr.rs
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
#[cfg(test)]
|
||||||
|
#[cfg(feature = "hooks")]
|
||||||
|
mod tests {
|
||||||
|
use core::{
|
||||||
|
ffi::c_int,
|
||||||
|
ptr::{null, null_mut},
|
||||||
|
};
|
||||||
|
|
||||||
|
use asan::{expect_panic, hooks::wcschr::wcschr, wchar_t};
|
||||||
|
use widestring::widecstr;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wcschr_zero_length() {
|
||||||
|
let data = widecstr!("");
|
||||||
|
let ret = unsafe { wcschr(data.as_ptr() as *const wchar_t, 0x88) };
|
||||||
|
assert_eq!(ret, null_mut());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wcschr_null_buffer() {
|
||||||
|
expect_panic();
|
||||||
|
unsafe { wcschr(null(), 0x88) };
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wcschr_find_first() {
|
||||||
|
let data = widecstr!("abcdefghij");
|
||||||
|
let c = 'a' as c_int;
|
||||||
|
let ret = unsafe { wcschr(data.as_ptr() as *const wchar_t, c) };
|
||||||
|
assert_eq!(ret, data.as_ptr() as *mut wchar_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wcschr_find_last() {
|
||||||
|
let data = widecstr!("abcdefghij");
|
||||||
|
let c = 'j' as c_int;
|
||||||
|
let ret = unsafe { wcschr(data.as_ptr() as *const wchar_t, c) };
|
||||||
|
assert_eq!(ret, unsafe {
|
||||||
|
data.as_ptr().add(data.len() - 1) as *mut wchar_t
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wcschr_find_mid() {
|
||||||
|
let data = widecstr!("abcdefghij");
|
||||||
|
let c = 'e' as c_int;
|
||||||
|
let ret = unsafe { wcschr(data.as_ptr() as *const wchar_t, c) };
|
||||||
|
assert_eq!(ret, unsafe { data.as_ptr().add(4) as *mut wchar_t });
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wcschr_find_repeated() {
|
||||||
|
let data = widecstr!("ababababab");
|
||||||
|
let c = 'b' as c_int;
|
||||||
|
let ret = unsafe { wcschr(data.as_ptr() as *const wchar_t, c) };
|
||||||
|
assert_eq!(ret, unsafe { data.as_ptr().add(1) as *mut wchar_t });
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wcschr_not_found() {
|
||||||
|
let data = widecstr!("abcdefghij");
|
||||||
|
let c = 'k' as c_int;
|
||||||
|
let ret = unsafe { wcschr(data.as_ptr() as *const wchar_t, c) };
|
||||||
|
assert_eq!(ret, null_mut());
|
||||||
|
}
|
||||||
|
}
|
183
libafl_qemu/librasan/asan/tests/hooks_wcsncmp.rs
Normal file
183
libafl_qemu/librasan/asan/tests/hooks_wcsncmp.rs
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
#[cfg(test)]
|
||||||
|
#[cfg(feature = "hooks")]
|
||||||
|
mod tests {
|
||||||
|
use core::ptr::null;
|
||||||
|
|
||||||
|
use asan::{expect_panic, hooks::wcsncmp::wcsncmp, wchar_t};
|
||||||
|
use widestring::widecstr;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wcsncmp_zero_length() {
|
||||||
|
expect_panic();
|
||||||
|
let ret = unsafe { wcsncmp(null(), null(), 0) };
|
||||||
|
assert_eq!(ret, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wcsncmp_null_s1() {
|
||||||
|
expect_panic();
|
||||||
|
let data = [0u32; 10];
|
||||||
|
unsafe { wcsncmp(null(), data.as_ptr() as *const wchar_t, data.len()) };
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wcsncmp_null_s2() {
|
||||||
|
expect_panic();
|
||||||
|
let data = [0u32; 10];
|
||||||
|
unsafe { wcsncmp(data.as_ptr() as *const wchar_t, null(), data.len()) };
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wcsncmp_eq() {
|
||||||
|
let data = [1u32; 10];
|
||||||
|
let ret = unsafe {
|
||||||
|
wcsncmp(
|
||||||
|
data.as_ptr() as *const wchar_t,
|
||||||
|
data.as_ptr() as *const wchar_t,
|
||||||
|
data.len(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
assert_eq!(ret, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wcsncmp_zero_length_both() {
|
||||||
|
let data = [0u32; 10];
|
||||||
|
let ret = unsafe {
|
||||||
|
wcsncmp(
|
||||||
|
data.as_ptr() as *const wchar_t,
|
||||||
|
data.as_ptr() as *const wchar_t,
|
||||||
|
data.len(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
assert_eq!(ret, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wcsncmp_zero_length_s1() {
|
||||||
|
let data1 = [0u32; 10];
|
||||||
|
let data2 = [1u32; 10];
|
||||||
|
let ret = unsafe {
|
||||||
|
wcsncmp(
|
||||||
|
data1.as_ptr() as *const wchar_t,
|
||||||
|
data2.as_ptr() as *const wchar_t,
|
||||||
|
data1.len(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
assert!(ret < 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wcsncmp_zero_length_s2() {
|
||||||
|
let data1 = [1u32; 10];
|
||||||
|
let data2 = [0u32; 10];
|
||||||
|
let ret = unsafe {
|
||||||
|
wcsncmp(
|
||||||
|
data1.as_ptr() as *const wchar_t,
|
||||||
|
data2.as_ptr() as *const wchar_t,
|
||||||
|
data1.len(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
assert!(ret > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wcsncmp_eq_string() {
|
||||||
|
let data1 = widecstr!("abcdefghij");
|
||||||
|
let data2 = widecstr!("abcdefghij");
|
||||||
|
let ret = unsafe {
|
||||||
|
wcsncmp(
|
||||||
|
data1.as_ptr() as *const wchar_t,
|
||||||
|
data2.as_ptr() as *const wchar_t,
|
||||||
|
data1.len(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
assert_eq!(ret, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wcsncmp_s1_shorter() {
|
||||||
|
let data1 = widecstr!("abcdefghi");
|
||||||
|
let data2 = widecstr!("abcdefghij");
|
||||||
|
let ret = unsafe {
|
||||||
|
wcsncmp(
|
||||||
|
data1.as_ptr() as *const wchar_t,
|
||||||
|
data2.as_ptr() as *const wchar_t,
|
||||||
|
data2.len(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
assert!(ret < 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wcsncmp_s1_longer() {
|
||||||
|
let data1 = widecstr!("abcdefghij");
|
||||||
|
let data2 = widecstr!("abcdefghi");
|
||||||
|
let ret = unsafe {
|
||||||
|
wcsncmp(
|
||||||
|
data1.as_ptr() as *const wchar_t,
|
||||||
|
data2.as_ptr() as *const wchar_t,
|
||||||
|
data1.len(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
assert!(ret > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wcsncmp_s1_less_than() {
|
||||||
|
let data1 = widecstr!("abcdefghii");
|
||||||
|
let data2 = widecstr!("abcdefghij");
|
||||||
|
let ret = unsafe {
|
||||||
|
wcsncmp(
|
||||||
|
data1.as_ptr() as *const wchar_t,
|
||||||
|
data2.as_ptr() as *const wchar_t,
|
||||||
|
data1.len(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
assert!(ret < 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wcsncmp_s1_greater_than() {
|
||||||
|
let data1 = widecstr!("abcdefghik");
|
||||||
|
let data2 = widecstr!("abcdefghij");
|
||||||
|
let ret = unsafe {
|
||||||
|
wcsncmp(
|
||||||
|
data1.as_ptr() as *const wchar_t,
|
||||||
|
data2.as_ptr() as *const wchar_t,
|
||||||
|
data1.len(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
assert!(ret > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wcsncmp_case_not_ignored() {
|
||||||
|
let data1 = widecstr!("abcdefghijklmnopqrstuvwxyz");
|
||||||
|
let data2 = widecstr!("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
|
||||||
|
let ret = unsafe {
|
||||||
|
wcsncmp(
|
||||||
|
data1.as_ptr() as *const wchar_t,
|
||||||
|
data2.as_ptr() as *const wchar_t,
|
||||||
|
data1.len(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
assert!(ret > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wcsncmp_differ_after_length() {
|
||||||
|
let data1 = widecstr!("abcdefghijXYZ");
|
||||||
|
let data2 = widecstr!("abcdefghijUVW");
|
||||||
|
let ret = unsafe {
|
||||||
|
wcsncmp(
|
||||||
|
data1.as_ptr() as *const wchar_t,
|
||||||
|
data2.as_ptr() as *const wchar_t,
|
||||||
|
data1.len() - 3,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
assert_eq!(ret, 0);
|
||||||
|
}
|
||||||
|
}
|
42
libafl_qemu/librasan/asan/tests/hooks_wcsnlen.rs
Normal file
42
libafl_qemu/librasan/asan/tests/hooks_wcsnlen.rs
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#[cfg(test)]
|
||||||
|
#[cfg(feature = "hooks")]
|
||||||
|
mod tests {
|
||||||
|
use core::ptr::null;
|
||||||
|
|
||||||
|
use asan::{expect_panic, hooks::wcsnlen::wcsnlen, wchar_t};
|
||||||
|
use widestring::widecstr;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wcsnlen_zero_length() {
|
||||||
|
let ret = unsafe { wcsnlen(null() as *const wchar_t, 0) };
|
||||||
|
assert_eq!(ret, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wcsnlen_cs_null() {
|
||||||
|
expect_panic();
|
||||||
|
unsafe { wcsnlen(null() as *const wchar_t, 10) };
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wcsnlen_cs_empty() {
|
||||||
|
let data = widecstr!("");
|
||||||
|
let ret = unsafe { wcsnlen(data.as_ptr() as *const wchar_t, 10) };
|
||||||
|
assert_eq!(ret, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wcsnlen_full() {
|
||||||
|
let data = widecstr!("abcdefghij");
|
||||||
|
let ret = unsafe { wcsnlen(data.as_ptr() as *const wchar_t, data.len()) };
|
||||||
|
assert_eq!(ret, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wcsnlen_partial() {
|
||||||
|
let data = widecstr!("abcdefghij");
|
||||||
|
let ret = unsafe { wcsnlen(data.as_ptr() as *const wchar_t, 5) };
|
||||||
|
assert_eq!(ret, 5);
|
||||||
|
}
|
||||||
|
}
|
69
libafl_qemu/librasan/asan/tests/hooks_wcsrchr.rs
Normal file
69
libafl_qemu/librasan/asan/tests/hooks_wcsrchr.rs
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#[cfg(test)]
|
||||||
|
#[cfg(feature = "hooks")]
|
||||||
|
mod tests {
|
||||||
|
use core::{
|
||||||
|
ffi::c_int,
|
||||||
|
ptr::{null, null_mut},
|
||||||
|
};
|
||||||
|
|
||||||
|
use asan::{expect_panic, hooks::wcsrchr::wcsrchr, wchar_t};
|
||||||
|
use widestring::widecstr;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wcsrchr_zero_length() {
|
||||||
|
let data = widecstr!("");
|
||||||
|
let ret = unsafe { wcsrchr(data.as_ptr() as *const wchar_t, 0x88) };
|
||||||
|
assert_eq!(ret, null_mut());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wcsrchr_null_buffer() {
|
||||||
|
expect_panic();
|
||||||
|
unsafe { wcsrchr(null(), 0x88) };
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wcsrchr_find_first() {
|
||||||
|
let data = widecstr!("abcdefghij");
|
||||||
|
let c = 'a' as c_int;
|
||||||
|
let ret = unsafe { wcsrchr(data.as_ptr() as *const wchar_t, c) };
|
||||||
|
assert_eq!(ret, data.as_ptr() as *mut wchar_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wcsrchr_find_last() {
|
||||||
|
let data = widecstr!("abcdefghij");
|
||||||
|
let c = 'j' as c_int;
|
||||||
|
let ret = unsafe { wcsrchr(data.as_ptr() as *const wchar_t, c) };
|
||||||
|
assert_eq!(ret, unsafe {
|
||||||
|
data.as_ptr().add(data.len() - 1) as *mut wchar_t
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wcsrchr_find_mid() {
|
||||||
|
let data = widecstr!("abcdefghij");
|
||||||
|
let c = 'e' as c_int;
|
||||||
|
let ret = unsafe { wcsrchr(data.as_ptr() as *const wchar_t, c) };
|
||||||
|
assert_eq!(ret, unsafe { data.as_ptr().add(4) as *mut wchar_t });
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wcsrchr_find_repeated() {
|
||||||
|
let data = widecstr!("ababababab");
|
||||||
|
let c = 'b' as c_int;
|
||||||
|
let ret = unsafe { wcsrchr(data.as_ptr() as *const wchar_t, c) };
|
||||||
|
assert_eq!(ret, unsafe {
|
||||||
|
data.as_ptr().add(data.len() - 1) as *mut wchar_t
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wcsrchr_not_found() {
|
||||||
|
let data = widecstr!("abcdefghij");
|
||||||
|
let c = 'k' as c_int;
|
||||||
|
let ret = unsafe { wcsrchr(data.as_ptr() as *const wchar_t, c) };
|
||||||
|
assert_eq!(ret, null_mut());
|
||||||
|
}
|
||||||
|
}
|
63
libafl_qemu/librasan/asan/tests/hooks_wmemchr.rs
Normal file
63
libafl_qemu/librasan/asan/tests/hooks_wmemchr.rs
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#[cfg(test)]
|
||||||
|
#[cfg(feature = "hooks")]
|
||||||
|
mod tests {
|
||||||
|
use core::ptr::null_mut;
|
||||||
|
|
||||||
|
use asan::{expect_panic, hooks::wmemchr::wmemchr, wchar_t};
|
||||||
|
use widestring::widecstr;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wmemchr_zero_length() {
|
||||||
|
let ret = unsafe { wmemchr(null_mut(), 0, 0) };
|
||||||
|
assert_eq!(ret, null_mut());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wmemchr_null_buffer() {
|
||||||
|
expect_panic();
|
||||||
|
unsafe { wmemchr(null_mut(), 0, 10) };
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wmemchr_find_first() {
|
||||||
|
let data = widecstr!("abcdefghij");
|
||||||
|
let c = 'a' as wchar_t;
|
||||||
|
let ret = unsafe { wmemchr(data.as_ptr() as *const wchar_t, c, data.len()) };
|
||||||
|
assert_eq!(ret, data.as_ptr() as *mut wchar_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wmemchr_find_last() {
|
||||||
|
let data = widecstr!("abcdefghij");
|
||||||
|
let c = 'j' as wchar_t;
|
||||||
|
let ret = unsafe { wmemchr(data.as_ptr() as *const wchar_t, c, data.len()) };
|
||||||
|
assert_eq!(ret, unsafe {
|
||||||
|
data.as_ptr().add(data.len() - 1) as *mut wchar_t
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wmemchr_find_mid() {
|
||||||
|
let data = widecstr!("abcdefghij");
|
||||||
|
let c = 'e' as wchar_t;
|
||||||
|
let ret = unsafe { wmemchr(data.as_ptr() as *const wchar_t, c, data.len()) };
|
||||||
|
assert_eq!(ret, unsafe { data.as_ptr().add(4) as *mut wchar_t });
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wmemchr_find_repeated() {
|
||||||
|
let data = widecstr!("ababababab");
|
||||||
|
let c = 'b' as wchar_t;
|
||||||
|
let ret = unsafe { wmemchr(data.as_ptr() as *const wchar_t, c, data.len()) };
|
||||||
|
assert_eq!(ret, unsafe { data.as_ptr().add(1) as *mut wchar_t });
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wmemchr_not_found() {
|
||||||
|
let data = widecstr!("abcdefghij");
|
||||||
|
let c = 'k' as wchar_t;
|
||||||
|
let ret = unsafe { wmemchr(data.as_ptr() as *const wchar_t, c, data.len()) };
|
||||||
|
assert_eq!(ret, null_mut());
|
||||||
|
}
|
||||||
|
}
|
@ -47,7 +47,7 @@ fuzz_target!(|data: Vec<GuestAddr>| {
|
|||||||
start.saturating_sub(test_offset)
|
start.saturating_sub(test_offset)
|
||||||
};
|
};
|
||||||
|
|
||||||
let result = tracking.alloc(start, len);
|
let result = tracking.track(start, len);
|
||||||
if GuestTracking::is_out_of_bounds(start, len) {
|
if GuestTracking::is_out_of_bounds(start, len) {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
result,
|
result,
|
||||||
@ -61,7 +61,7 @@ fuzz_target!(|data: Vec<GuestAddr>| {
|
|||||||
assert_eq!(result, Ok(()));
|
assert_eq!(result, Ok(()));
|
||||||
}
|
}
|
||||||
|
|
||||||
let test_result = tracking.alloc(test_start, test_len);
|
let test_result = tracking.track(test_start, test_len);
|
||||||
if GuestTracking::is_out_of_bounds(test_start, test_len) {
|
if GuestTracking::is_out_of_bounds(test_start, test_len) {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
test_result,
|
test_result,
|
||||||
@ -92,8 +92,8 @@ fuzz_target!(|data: Vec<GuestAddr>| {
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
assert_eq!(test_result, Ok(()));
|
assert_eq!(test_result, Ok(()));
|
||||||
assert_eq!(tracking.dealloc(test_start), Ok(()));
|
assert_eq!(tracking.untrack(test_start), Ok(()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert_eq!(tracking.dealloc(start), Ok(()));
|
assert_eq!(tracking.untrack(start), Ok(()));
|
||||||
});
|
});
|
||||||
|
@ -9,10 +9,11 @@ use asan::{
|
|||||||
backend::{dlmalloc::DlmallocBackend, mimalloc::MimallocBackend},
|
backend::{dlmalloc::DlmallocBackend, mimalloc::MimallocBackend},
|
||||||
frontend::{AllocatorFrontend, default::DefaultFrontend},
|
frontend::{AllocatorFrontend, default::DefaultFrontend},
|
||||||
},
|
},
|
||||||
|
hooks::PatchedHooks,
|
||||||
logger::libc::LibcLogger,
|
logger::libc::LibcLogger,
|
||||||
maps::libc::LibcMapReader,
|
maps::{MapReader, libc::LibcMapReader},
|
||||||
mmap::libc::LibcMmap,
|
mmap::libc::LibcMmap,
|
||||||
patch::{hooks::PatchedHooks, raw::RawPatch},
|
patch::{Patches, raw::RawPatch},
|
||||||
shadow::{
|
shadow::{
|
||||||
Shadow,
|
Shadow,
|
||||||
guest::{DefaultShadowLayout, GuestShadow},
|
guest::{DefaultShadowLayout, GuestShadow},
|
||||||
@ -53,7 +54,12 @@ static FRONTEND: Lazy<Mutex<GasanFrontend>> = Lazy::new(|| {
|
|||||||
GasanFrontend::DEFAULT_QUARANTINE_SIZE,
|
GasanFrontend::DEFAULT_QUARANTINE_SIZE,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
PatchedHooks::init::<GasanSyms, RawPatch, LibcMapReader<GasanSyms>, GasanMmap>().unwrap();
|
let mappings = LibcMapReader::<GasanSyms>::mappings().unwrap();
|
||||||
|
Patches::init(mappings);
|
||||||
|
for hook in PatchedHooks::default() {
|
||||||
|
let target = hook.lookup::<GasanSyms>().unwrap();
|
||||||
|
Patches::apply::<RawPatch, GasanMmap>(target, hook.destination).unwrap();
|
||||||
|
}
|
||||||
Mutex::new(frontend)
|
Mutex::new(frontend)
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -113,8 +119,8 @@ pub unsafe extern "C" fn asan_get_size(addr: *const c_void) -> usize {
|
|||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
/// # Safety
|
/// # Safety
|
||||||
pub unsafe extern "C" fn asan_sym(name: *const c_char) -> GuestAddr {
|
pub unsafe extern "C" fn asan_sym(name: *const c_char) -> *const c_void {
|
||||||
GasanSyms::lookup(name).unwrap()
|
GasanSyms::lookup(name).unwrap() as *const c_void
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
@ -141,7 +147,7 @@ pub unsafe extern "C" fn asan_track(addr: *const c_void, len: usize) {
|
|||||||
FRONTEND
|
FRONTEND
|
||||||
.lock()
|
.lock()
|
||||||
.tracking_mut()
|
.tracking_mut()
|
||||||
.alloc(addr as GuestAddr, len)
|
.track(addr as GuestAddr, len)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,7 +158,7 @@ pub unsafe extern "C" fn asan_untrack(addr: *const c_void) {
|
|||||||
FRONTEND
|
FRONTEND
|
||||||
.lock()
|
.lock()
|
||||||
.tracking_mut()
|
.tracking_mut()
|
||||||
.dealloc(addr as GuestAddr)
|
.untrack(addr as GuestAddr)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,11 +9,12 @@ use asan::{
|
|||||||
backend::{dlmalloc::DlmallocBackend, mimalloc::MimallocBackend},
|
backend::{dlmalloc::DlmallocBackend, mimalloc::MimallocBackend},
|
||||||
frontend::{AllocatorFrontend, default::DefaultFrontend},
|
frontend::{AllocatorFrontend, default::DefaultFrontend},
|
||||||
},
|
},
|
||||||
|
hooks::PatchedHooks,
|
||||||
host::{Host, libc::LibcHost},
|
host::{Host, libc::LibcHost},
|
||||||
logger::libc::LibcLogger,
|
logger::libc::LibcLogger,
|
||||||
maps::libc::LibcMapReader,
|
maps::{MapReader, libc::LibcMapReader},
|
||||||
mmap::libc::LibcMmap,
|
mmap::libc::LibcMmap,
|
||||||
patch::{hooks::PatchedHooks, raw::RawPatch},
|
patch::{Patches, raw::RawPatch},
|
||||||
shadow::{Shadow, host::HostShadow},
|
shadow::{Shadow, host::HostShadow},
|
||||||
symbols::{
|
symbols::{
|
||||||
Symbols,
|
Symbols,
|
||||||
@ -52,7 +53,12 @@ static FRONTEND: Lazy<Mutex<QasanFrontend>> = Lazy::new(|| {
|
|||||||
QasanFrontend::DEFAULT_QUARANTINE_SIZE,
|
QasanFrontend::DEFAULT_QUARANTINE_SIZE,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
PatchedHooks::init::<QasanSyms, RawPatch, LibcMapReader<QasanSyms>, QasanMmap>().unwrap();
|
let mappings = LibcMapReader::<QasanSyms>::mappings().unwrap();
|
||||||
|
Patches::init(mappings);
|
||||||
|
for hook in PatchedHooks::default() {
|
||||||
|
let target = hook.lookup::<QasanSyms>().unwrap();
|
||||||
|
Patches::apply::<RawPatch, QasanMmap>(target, hook.destination).unwrap();
|
||||||
|
}
|
||||||
Mutex::new(frontend)
|
Mutex::new(frontend)
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -112,8 +118,8 @@ pub unsafe extern "C" fn asan_get_size(addr: *const c_void) -> usize {
|
|||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
/// # Safety
|
/// # Safety
|
||||||
pub unsafe extern "C" fn asan_sym(name: *const c_char) -> GuestAddr {
|
pub unsafe extern "C" fn asan_sym(name: *const c_char) -> *const c_void {
|
||||||
QasanSyms::lookup(name).unwrap()
|
QasanSyms::lookup(name).unwrap() as *const c_void
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
@ -140,7 +146,7 @@ pub unsafe extern "C" fn asan_track(addr: *const c_void, len: usize) {
|
|||||||
FRONTEND
|
FRONTEND
|
||||||
.lock()
|
.lock()
|
||||||
.tracking_mut()
|
.tracking_mut()
|
||||||
.alloc(addr as GuestAddr, len)
|
.track(addr as GuestAddr, len)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,7 +157,7 @@ pub unsafe extern "C" fn asan_untrack(addr: *const c_void) {
|
|||||||
FRONTEND
|
FRONTEND
|
||||||
.lock()
|
.lock()
|
||||||
.tracking_mut()
|
.tracking_mut()
|
||||||
.dealloc(addr as GuestAddr)
|
.untrack(addr as GuestAddr)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,8 +103,8 @@ pub unsafe extern "C" fn asan_get_size(addr: *const c_void) -> usize {
|
|||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
/// # Safety
|
/// # Safety
|
||||||
pub unsafe extern "C" fn asan_sym(name: *const c_char) -> GuestAddr {
|
pub unsafe extern "C" fn asan_sym(name: *const c_char) -> *const c_void {
|
||||||
ZasanSyms::lookup(name).unwrap()
|
ZasanSyms::lookup(name).unwrap() as *const c_void
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
@ -131,7 +131,7 @@ pub unsafe extern "C" fn asan_track(addr: *const c_void, len: usize) {
|
|||||||
FRONTEND
|
FRONTEND
|
||||||
.lock()
|
.lock()
|
||||||
.tracking_mut()
|
.tracking_mut()
|
||||||
.alloc(addr as GuestAddr, len)
|
.track(addr as GuestAddr, len)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,7 +142,7 @@ pub unsafe extern "C" fn asan_untrack(addr: *const c_void) {
|
|||||||
FRONTEND
|
FRONTEND
|
||||||
.lock()
|
.lock()
|
||||||
.tracking_mut()
|
.tracking_mut()
|
||||||
.dealloc(addr as GuestAddr)
|
.untrack(addr as GuestAddr)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user