parent
888079aea5
commit
51db18eea8
@ -20,6 +20,7 @@ members = [
|
||||
"utils/deexit",
|
||||
"utils/libafl_benches",
|
||||
"utils/gramatron/construct_automata",
|
||||
"utils/desyscall",
|
||||
]
|
||||
default-members = [
|
||||
"libafl",
|
||||
|
@ -12,7 +12,6 @@
|
||||
// For `std::simd`
|
||||
#![cfg_attr(nightly, feature(portable_simd))]
|
||||
// For `core::error`
|
||||
#![cfg_attr(nightly, feature(error_in_core))]
|
||||
#![warn(clippy::cargo)]
|
||||
#![allow(ambiguous_glob_reexports)]
|
||||
#![deny(clippy::cargo_common_metadata)]
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* 1.80.0-nightly */
|
||||
/* 1.81.0-nightly */
|
||||
/* automatically generated by rust-bindgen 0.69.4 */
|
||||
|
||||
#[repr(C)]
|
||||
@ -2341,6 +2341,7 @@ pub type DeviceReset = ::std::option::Option<unsafe extern "C" fn(dev: *mut Devi
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct DeviceClass {
|
||||
pub parent_class: ObjectClass,
|
||||
#[doc = " @categories: device categories device belongs to"]
|
||||
pub categories: [::std::os::raw::c_ulong; 1usize],
|
||||
#[doc = " @fw_name: name used to identify device to firmware interfaces"]
|
||||
pub fw_name: *const ::std::os::raw::c_char,
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* 1.80.0-nightly */
|
||||
/* 1.81.0-nightly */
|
||||
/* automatically generated by rust-bindgen 0.69.4 */
|
||||
|
||||
pub const _STDINT_H: u32 = 1;
|
||||
@ -36,7 +36,7 @@ pub const __STDC_IEC_60559_COMPLEX__: u32 = 201404;
|
||||
pub const __STDC_ISO_10646__: u32 = 201706;
|
||||
pub const __GNU_LIBRARY__: u32 = 6;
|
||||
pub const __GLIBC__: u32 = 2;
|
||||
pub const __GLIBC_MINOR__: u32 = 39;
|
||||
pub const __GLIBC_MINOR__: u32 = 38;
|
||||
pub const _SYS_CDEFS_H: u32 = 1;
|
||||
pub const __glibc_c99_flexarr_available: u32 = 1;
|
||||
pub const __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI: u32 = 0;
|
||||
@ -60,7 +60,6 @@ pub const _BITS_TIME64_H: u32 = 1;
|
||||
pub const _BITS_WCHAR_H: u32 = 1;
|
||||
pub const _BITS_STDINT_INTN_H: u32 = 1;
|
||||
pub const _BITS_STDINT_UINTN_H: u32 = 1;
|
||||
pub const _BITS_STDINT_LEAST_H: u32 = 1;
|
||||
pub const INT8_MIN: i32 = -128;
|
||||
pub const INT16_MIN: i32 = -32768;
|
||||
pub const INT32_MIN: i32 = -2147483648;
|
||||
|
@ -2,6 +2,11 @@
|
||||
name = "desyscall"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
description = "DeSyscall: Hooks syscalls for reduces overhead during in-process fuzzing"
|
||||
repository = "https://github.com/AFLplusplus/LibAFL/"
|
||||
license = "MIT OR Apache-2.0"
|
||||
categories = ["development-tools::testing", "emulators", "embedded", "os", "no-std"]
|
||||
keywords = ["fuzzing", "libafl", "ldpreload"]
|
||||
|
||||
[dependencies]
|
||||
meminterval = "0.3"
|
||||
|
@ -3,6 +3,11 @@
|
||||
use std::env;
|
||||
|
||||
fn main() {
|
||||
if cfg!(not(target_os = "linux")) {
|
||||
println!("Not supported!");
|
||||
return;
|
||||
}
|
||||
|
||||
let out_dir = env::var_os("OUT_DIR").unwrap();
|
||||
let out_dir = out_dir.to_string_lossy().to_string();
|
||||
|
||||
|
@ -9,8 +9,11 @@ extern "C" {
|
||||
fn __libafl_raw_read(fd: c_int, buf: Pointer, count: size_t) -> ssize_t;
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
/// Call to functions using syscalls
|
||||
#[allow(clippy::cast_possible_wrap)]
|
||||
#[no_mangle]
|
||||
pub unsafe fn write(fd: c_int, buf: Pointer, count: size_t) -> ssize_t {
|
||||
pub unsafe extern "C" fn write(fd: c_int, buf: Pointer, count: size_t) -> ssize_t {
|
||||
let ctx = Context::get();
|
||||
|
||||
if ctx.enabled && (fd == 1 || fd == 2) {
|
||||
@ -20,11 +23,13 @@ pub unsafe fn write(fd: c_int, buf: Pointer, count: size_t) -> ssize_t {
|
||||
}
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
/// Call to functions using syscalls
|
||||
#[no_mangle]
|
||||
pub unsafe fn read(fd: c_int, buf: Pointer, count: size_t) -> ssize_t {
|
||||
pub unsafe extern "C" fn read(fd: c_int, buf: Pointer, count: size_t) -> ssize_t {
|
||||
let ctx = Context::get();
|
||||
|
||||
if ctx.enabled && fd >= 0 && fd <= 2 {
|
||||
if ctx.enabled && (0..=2).contains(&fd) {
|
||||
0
|
||||
} else {
|
||||
__libafl_raw_read(fd, buf, count)
|
||||
|
@ -1,6 +1,7 @@
|
||||
use std::{mem::MaybeUninit, sync::Once};
|
||||
|
||||
use libc::{c_int, c_void};
|
||||
use meminterval::IntervalTree;
|
||||
use std::{mem::MaybeUninit, sync::Once};
|
||||
|
||||
pub mod file;
|
||||
pub mod mmap;
|
||||
@ -20,7 +21,14 @@ pub struct Context {
|
||||
exit_hook: Option<Box<dyn FnMut(i32)>>,
|
||||
}
|
||||
|
||||
impl Default for Context {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Context {
|
||||
#[must_use]
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
enabled: false,
|
||||
@ -73,13 +81,15 @@ extern "C" {
|
||||
}
|
||||
|
||||
// void _exit(int status);
|
||||
/// # Safety
|
||||
/// Call to function using syscalls
|
||||
#[no_mangle]
|
||||
pub unsafe fn _exit(status: c_int) {
|
||||
pub unsafe extern "C" fn _exit(status: c_int) {
|
||||
let ctx = Context::get();
|
||||
|
||||
if ctx.enabled {
|
||||
if let Some(hook) = &mut ctx.exit_hook {
|
||||
(hook)(status as i32);
|
||||
(hook)(status);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
use std::ptr;
|
||||
|
||||
use libc::{c_int, c_void, off_t, size_t};
|
||||
use meminterval::Interval;
|
||||
use std::ptr;
|
||||
|
||||
use crate::{Context, Mapping, Pointer};
|
||||
|
||||
@ -36,8 +37,11 @@ extern "C" {
|
||||
fn __libafl_raw_madvise(addr: *mut c_void, length: size_t, advice: c_int) -> c_int;
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
/// Call to functions using syscalls
|
||||
#[no_mangle]
|
||||
pub unsafe fn mmap(
|
||||
#[allow(clippy::too_many_lines)]
|
||||
pub unsafe extern "C" fn mmap(
|
||||
addr: Pointer,
|
||||
length: size_t,
|
||||
prot: c_int,
|
||||
@ -66,7 +70,7 @@ pub unsafe fn mmap(
|
||||
continue;
|
||||
}
|
||||
if length <= entry.interval.end as usize - entry.interval.start as usize {
|
||||
candidate = Some((entry.interval.clone(), entry.value.clone()));
|
||||
candidate = Some((*entry.interval, entry.value.clone()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -76,7 +80,7 @@ pub unsafe fn mmap(
|
||||
if length < size {
|
||||
ctx.mappings.delete(cand.0);
|
||||
|
||||
let end = cand.0.start.offset(length as isize);
|
||||
let end = cand.0.start.add(length);
|
||||
ctx.mappings.insert(
|
||||
cand.0.start..end,
|
||||
Mapping {
|
||||
@ -100,7 +104,7 @@ pub unsafe fn mmap(
|
||||
let ret = __libafl_raw_mmap(addr, length, prot, flags, fd, offset) as Pointer;
|
||||
|
||||
if ret != libc::MAP_FAILED as Pointer {
|
||||
let end = ret.offset(length as isize);
|
||||
let end = ret.add(length);
|
||||
ctx.mappings.insert(
|
||||
ret..end,
|
||||
Mapping {
|
||||
@ -119,7 +123,7 @@ pub unsafe fn mmap(
|
||||
return ret;
|
||||
}
|
||||
|
||||
let end = addr.offset(length as isize);
|
||||
let end = addr.add(length);
|
||||
|
||||
let mut prev: Option<(_, _)> = None;
|
||||
let mut fail = false;
|
||||
@ -133,13 +137,11 @@ pub unsafe fn mmap(
|
||||
if entry.interval.start != p.0 {
|
||||
fail = true;
|
||||
}
|
||||
} else {
|
||||
if entry.interval.start > addr {
|
||||
} else if entry.interval.start > addr {
|
||||
fail = true;
|
||||
} else if entry.interval.start < addr {
|
||||
reminder = Some((entry.interval.start, entry.value.clone()));
|
||||
}
|
||||
}
|
||||
if entry.value.prot != prot {
|
||||
fail = true;
|
||||
}
|
||||
@ -148,12 +150,13 @@ pub unsafe fn mmap(
|
||||
already_mapped = true;
|
||||
}
|
||||
|
||||
intervals.push(entry.interval.clone());
|
||||
intervals.push(*entry.interval);
|
||||
|
||||
prev = Some((entry.interval.end, entry.value));
|
||||
}
|
||||
|
||||
let mut reminder_next = None;
|
||||
#[allow(clippy::comparison_chain)]
|
||||
if let Some(p) = prev.take() {
|
||||
if p.0 < end {
|
||||
fail = true;
|
||||
@ -216,8 +219,10 @@ pub unsafe fn mmap(
|
||||
ret
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
/// Call to functions using syscalls
|
||||
#[no_mangle]
|
||||
pub unsafe fn munmap(addr: *mut c_void, length: size_t) -> c_int {
|
||||
pub unsafe extern "C" fn munmap(addr: *mut c_void, length: size_t) -> c_int {
|
||||
let ctx = Context::get();
|
||||
|
||||
if !ctx.enabled {
|
||||
@ -234,7 +239,7 @@ pub unsafe fn munmap(addr: *mut c_void, length: size_t) -> c_int {
|
||||
} else {
|
||||
length
|
||||
};
|
||||
let end = addr.offset(aligned_length as isize);
|
||||
let end = addr.add(aligned_length);
|
||||
|
||||
ctx.disable();
|
||||
|
||||
@ -286,7 +291,7 @@ pub unsafe fn munmap(addr: *mut c_void, length: size_t) -> c_int {
|
||||
new_entries.push((Interval::new(end, entry.interval.end), entry.value.clone()));
|
||||
}
|
||||
|
||||
intervals.push(entry.interval.clone());
|
||||
intervals.push(*entry.interval);
|
||||
}
|
||||
|
||||
for interval in intervals {
|
||||
@ -302,8 +307,10 @@ pub unsafe fn munmap(addr: *mut c_void, length: size_t) -> c_int {
|
||||
0
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
/// Calling to functions using syscalls
|
||||
#[no_mangle]
|
||||
pub unsafe fn mprotect(addr: *mut c_void, length: size_t, prot: c_int) -> c_int {
|
||||
pub unsafe extern "C" fn mprotect(addr: *mut c_void, length: size_t, prot: c_int) -> c_int {
|
||||
let ctx = Context::get();
|
||||
|
||||
if !ctx.enabled {
|
||||
@ -316,7 +323,7 @@ pub unsafe fn mprotect(addr: *mut c_void, length: size_t, prot: c_int) -> c_int
|
||||
} else {
|
||||
length
|
||||
};
|
||||
let end = addr.offset(aligned_length as isize);
|
||||
let end = addr.add(aligned_length);
|
||||
|
||||
ctx.disable();
|
||||
|
||||
@ -324,12 +331,10 @@ pub unsafe fn mprotect(addr: *mut c_void, length: size_t, prot: c_int) -> c_int
|
||||
|
||||
if let Some(mut entry) = query_iter.next() {
|
||||
// cache the repeated mprotects on the same region
|
||||
if entry.interval.start == addr && entry.interval.end == end {
|
||||
if entry.value.prot == prot {
|
||||
if entry.interval.start == addr && entry.interval.end == end && entry.value.prot == prot {
|
||||
ctx.enable();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
let ret = __libafl_raw_mprotect(addr, length, prot);
|
||||
// return on error
|
||||
@ -385,7 +390,7 @@ pub unsafe fn mprotect(addr: *mut c_void, length: size_t, prot: c_int) -> c_int
|
||||
new_entries.push((Interval::new(end, entry.interval.end), entry.value.clone()));
|
||||
}
|
||||
|
||||
intervals.push(entry.interval.clone());
|
||||
intervals.push(*entry.interval);
|
||||
|
||||
if let Some(next) = query_iter.next() {
|
||||
entry = next;
|
||||
@ -427,8 +432,10 @@ pub unsafe fn mprotect(addr: *mut c_void, length: size_t, prot: c_int) -> c_int
|
||||
}
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
/// Call to functions using syscalls
|
||||
#[no_mangle]
|
||||
pub unsafe fn madvise(addr: *mut c_void, length: size_t, advice: c_int) -> c_int {
|
||||
pub unsafe extern "C" fn madvise(addr: *mut c_void, length: size_t, advice: c_int) -> c_int {
|
||||
let ctx = Context::get();
|
||||
|
||||
if ctx.enabled && advice == libc::MADV_DONTNEED {
|
||||
@ -440,8 +447,9 @@ pub unsafe fn madvise(addr: *mut c_void, length: size_t, advice: c_int) -> c_int
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use rusty_fork::rusty_fork_test;
|
||||
|
||||
use super::*;
|
||||
// cargo test -- --nocapture --test-threads=1
|
||||
|
||||
rusty_fork_test! {
|
||||
@ -453,7 +461,7 @@ mod tests {
|
||||
let p = mmap(0x7ffff9f9e000usize as Pointer, 4096, 0x7, 0x22, 0, 0);
|
||||
assert!(p as isize != -1);
|
||||
|
||||
println!("Pre {:?}", p);
|
||||
println!("Pre {p:?}", );
|
||||
Context::get().print_mappings();
|
||||
|
||||
let r = munmap(p, 1);
|
||||
@ -474,10 +482,10 @@ mod tests {
|
||||
let p = mmap(0x7ffff9f9e000usize as Pointer, PAGE_SIZE*4, 0x7, 0x22, 0, 0);
|
||||
assert!(p as isize != -1);
|
||||
|
||||
println!("Pre {:?}", p);
|
||||
println!("Pre {p:?}",);
|
||||
Context::get().print_mappings();
|
||||
|
||||
let r = munmap(p.offset(PAGE_SIZE as isize), PAGE_SIZE*2);
|
||||
let r = munmap(p.add(PAGE_SIZE), PAGE_SIZE*2);
|
||||
assert!(r == 0);
|
||||
|
||||
println!("Post");
|
||||
@ -495,19 +503,19 @@ mod tests {
|
||||
let p = mmap(0x7ffff9f9e000usize as Pointer, PAGE_SIZE*4, 0x7, 0x22, 0, 0);
|
||||
assert!(p as isize != -1);
|
||||
|
||||
println!("Pre {:?}", p);
|
||||
println!("Pre {p:?}");
|
||||
Context::get().print_mappings();
|
||||
|
||||
let r = munmap(p.offset(PAGE_SIZE as isize), PAGE_SIZE*2);
|
||||
let r = munmap(p.add(PAGE_SIZE), PAGE_SIZE*2);
|
||||
assert!(r == 0);
|
||||
|
||||
println!("Post");
|
||||
Context::get().print_mappings();
|
||||
|
||||
let p = mmap(p.offset(PAGE_SIZE as isize), PAGE_SIZE, 0x1, 0x22, 0, 0);
|
||||
let p = mmap(p.add(PAGE_SIZE), PAGE_SIZE, 0x1, 0x22, 0, 0);
|
||||
assert!(p as isize != -1);
|
||||
|
||||
println!("Remap {:?}", p);
|
||||
println!("Remap {p:?}");
|
||||
Context::get().print_mappings();
|
||||
}
|
||||
}
|
||||
@ -522,10 +530,10 @@ mod tests {
|
||||
let p = mmap(0 as Pointer, PAGE_SIZE*4, 0x7, 0x22, 0, 0);
|
||||
assert!(p as isize != -1);
|
||||
|
||||
println!("Pre {:?}", p);
|
||||
println!("Pre {p:?}");
|
||||
Context::get().print_mappings();
|
||||
|
||||
let r = munmap(p.offset(PAGE_SIZE as isize), PAGE_SIZE*2);
|
||||
let r = munmap(p.add(PAGE_SIZE), PAGE_SIZE*2);
|
||||
assert!(r == 0);
|
||||
|
||||
println!("Post");
|
||||
@ -534,7 +542,7 @@ mod tests {
|
||||
let p = mmap(0 as Pointer, PAGE_SIZE, 0x7, 0x22, 0, 0);
|
||||
assert!(p as isize != -1);
|
||||
|
||||
println!("Remap {:?}", p);
|
||||
println!("Remap {p:?}");
|
||||
Context::get().print_mappings();
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user