Skip to content

Commit 406e77f

Browse files
QEMU Asan backtrace and report (#1628)
* wip * ExtractFirstRefMutType * Asan report with backtrace * Print asan reports and fix backtraces in libafl qemu * print context * enlarge redzone * nopstate * fix * reproducer * clippy * clippy * Fix android * Crash hook
1 parent 02cd260 commit 406e77f

File tree

14 files changed

+852
-141
lines changed

14 files changed

+852
-141
lines changed

libafl/src/executors/inprocess.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -829,8 +829,10 @@ pub mod unix_signal_handler {
829829
Z: HasObjective<Objective = OF, State = E::State>,
830830
{
831831
#[cfg(all(target_os = "android", target_arch = "aarch64"))]
832-
let _context = &mut *(((_context as *mut _ as *mut libc::c_void as usize) + 128)
833-
as *mut libc::c_void as *mut ucontext_t);
832+
let _context = _context.map(|p| {
833+
&mut *(((p as *mut _ as *mut libc::c_void as usize) + 128) as *mut libc::c_void
834+
as *mut ucontext_t)
835+
});
834836

835837
log::error!("Crashed with {signal}");
836838
if data.is_valid() {

libafl/src/state/mod.rs

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,8 @@ use std::{
1313
vec::Vec,
1414
};
1515

16-
#[cfg(test)]
17-
use libafl_bolts::rands::StdRand;
1816
use libafl_bolts::{
19-
rands::Rand,
17+
rands::{Rand, StdRand},
2018
serdeany::{NamedSerdeAnyMap, SerdeAny, SerdeAnyMap},
2119
};
2220
use serde::{de::DeserializeOwned, Deserialize, Serialize};
@@ -881,7 +879,6 @@ impl<I, C, R, SC> HasClientPerfMonitor for StdState<I, C, R, SC> {
881879
}
882880
}
883881

884-
#[cfg(test)]
885882
/// A very simple state without any bells or whistles, for testing.
886883
#[derive(Debug, Serialize, Deserialize, Default)]
887884
pub struct NopState<I> {
@@ -891,7 +888,6 @@ pub struct NopState<I> {
891888
phantom: PhantomData<I>,
892889
}
893890

894-
#[cfg(test)]
895891
impl<I> NopState<I> {
896892
/// Create a new State that does nothing (for tests)
897893
#[must_use]
@@ -905,15 +901,13 @@ impl<I> NopState<I> {
905901
}
906902
}
907903

908-
#[cfg(test)]
909904
impl<I> UsesInput for NopState<I>
910905
where
911906
I: Input,
912907
{
913908
type Input = I;
914909
}
915910

916-
#[cfg(test)]
917911
impl<I> HasExecutions for NopState<I> {
918912
fn executions(&self) -> &usize {
919913
&self.execution
@@ -924,7 +918,6 @@ impl<I> HasExecutions for NopState<I> {
924918
}
925919
}
926920

927-
#[cfg(test)]
928921
impl<I> HasLastReportTime for NopState<I> {
929922
fn last_report_time(&self) -> &Option<Duration> {
930923
unimplemented!();
@@ -935,7 +928,6 @@ impl<I> HasLastReportTime for NopState<I> {
935928
}
936929
}
937930

938-
#[cfg(test)]
939931
impl<I> HasMetadata for NopState<I> {
940932
fn metadata_map(&self) -> &SerdeAnyMap {
941933
&self.metadata
@@ -946,7 +938,6 @@ impl<I> HasMetadata for NopState<I> {
946938
}
947939
}
948940

949-
#[cfg(test)]
950941
impl<I> HasRand for NopState<I> {
951942
type Rand = StdRand;
952943

@@ -959,7 +950,6 @@ impl<I> HasRand for NopState<I> {
959950
}
960951
}
961952

962-
#[cfg(test)]
963953
impl<I> HasClientPerfMonitor for NopState<I> {
964954
fn introspection_monitor(&self) -> &ClientPerfMonitor {
965955
unimplemented!()
@@ -970,7 +960,6 @@ impl<I> HasClientPerfMonitor for NopState<I> {
970960
}
971961
}
972962

973-
#[cfg(test)]
974963
impl<I> State for NopState<I> where I: Input {}
975964

976965
#[cfg(feature = "python")]

libafl_bolts/src/tuples.rs

Lines changed: 150 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,45 @@ pub fn type_eq<T: ?Sized, U: ?Sized>() -> bool {
4949
type_name::<T>() == type_name::<U>()
5050
}
5151

52+
/// Borrow each member of the tuple
53+
pub trait SplitBorrow<'a> {
54+
/// The Resulting [`TupleList`], of an [`SplitBorrow::borrow()`] call
55+
type SplitBorrowResult;
56+
/// The Resulting [`TupleList`], of an [`SplitBorrow::borrow_mut()`] call
57+
type SplitBorrowMutResult;
58+
59+
/// Return a tuple of borrowed references
60+
fn borrow(&'a self) -> Self::SplitBorrowResult;
61+
/// Return a tuple of borrowed mutable references
62+
fn borrow_mut(&'a mut self) -> Self::SplitBorrowMutResult;
63+
}
64+
65+
impl<'a> SplitBorrow<'a> for () {
66+
type SplitBorrowResult = ();
67+
type SplitBorrowMutResult = ();
68+
69+
fn borrow(&'a self) -> Self::SplitBorrowResult {}
70+
71+
fn borrow_mut(&'a mut self) -> Self::SplitBorrowMutResult {}
72+
}
73+
74+
impl<'a, Head, Tail> SplitBorrow<'a> for (Head, Tail)
75+
where
76+
Head: 'a,
77+
Tail: SplitBorrow<'a>,
78+
{
79+
type SplitBorrowResult = (Option<&'a Head>, Tail::SplitBorrowResult);
80+
type SplitBorrowMutResult = (Option<&'a mut Head>, Tail::SplitBorrowMutResult);
81+
82+
fn borrow(&'a self) -> Self::SplitBorrowResult {
83+
(Some(&self.0), self.1.borrow())
84+
}
85+
86+
fn borrow_mut(&'a mut self) -> Self::SplitBorrowMutResult {
87+
(Some(&mut self.0), self.1.borrow_mut())
88+
}
89+
}
90+
5291
/// Gets the length of the element
5392
pub trait HasConstLen {
5493
/// The length as constant `usize`
@@ -172,6 +211,117 @@ where
172211
}
173212
}
174213

214+
/// Returns the first element with the given type (dereference mut version)
215+
pub trait ExtractFirstRefType {
216+
/// Returns the first element with the given type as borrow, or [`Option::None`]
217+
fn take<'a, T: 'static>(self) -> (Option<&'a T>, Self);
218+
}
219+
220+
impl ExtractFirstRefType for () {
221+
fn take<'a, T: 'static>(self) -> (Option<&'a T>, Self) {
222+
(None, ())
223+
}
224+
}
225+
226+
impl<Head, Tail> ExtractFirstRefType for (Option<&Head>, Tail)
227+
where
228+
Head: 'static,
229+
Tail: ExtractFirstRefType,
230+
{
231+
fn take<'a, T: 'static>(mut self) -> (Option<&'a T>, Self) {
232+
if TypeId::of::<T>() == TypeId::of::<Head>() {
233+
let r = self.0.take();
234+
(unsafe { core::mem::transmute(r) }, self)
235+
} else {
236+
let (r, tail) = self.1.take::<T>();
237+
(r, (self.0, tail))
238+
}
239+
}
240+
}
241+
242+
impl<Head, Tail> ExtractFirstRefType for (Option<&mut Head>, Tail)
243+
where
244+
Head: 'static,
245+
Tail: ExtractFirstRefType,
246+
{
247+
fn take<'a, T: 'static>(mut self) -> (Option<&'a T>, Self) {
248+
if TypeId::of::<T>() == TypeId::of::<Head>() {
249+
let r = self.0.take();
250+
(unsafe { core::mem::transmute(r) }, self)
251+
} else {
252+
let (r, tail) = self.1.take::<T>();
253+
(r, (self.0, tail))
254+
}
255+
}
256+
}
257+
258+
/// Returns the first element with the given type (dereference mut version)
259+
pub trait ExtractFirstRefMutType {
260+
/// Returns the first element with the given type as borrow, or [`Option::None`]
261+
fn take<'a, T: 'static>(self) -> (Option<&'a mut T>, Self);
262+
}
263+
264+
impl ExtractFirstRefMutType for () {
265+
fn take<'a, T: 'static>(self) -> (Option<&'a mut T>, Self) {
266+
(None, ())
267+
}
268+
}
269+
270+
impl<Head, Tail> ExtractFirstRefMutType for (Option<&mut Head>, Tail)
271+
where
272+
Head: 'static,
273+
Tail: ExtractFirstRefMutType,
274+
{
275+
fn take<'a, T: 'static>(mut self) -> (Option<&'a mut T>, Self) {
276+
if TypeId::of::<T>() == TypeId::of::<Head>() {
277+
let r = self.0.take();
278+
(unsafe { core::mem::transmute(r) }, self)
279+
} else {
280+
let (r, tail) = self.1.take::<T>();
281+
(r, (self.0, tail))
282+
}
283+
}
284+
}
285+
286+
/// Borrow each member of the tuple
287+
pub trait SplitBorrowExtractFirstType<'a> {
288+
/// The Resulting [`TupleList`], of an [`SplitBorrow::borrow()`] call
289+
type SplitBorrowResult: ExtractFirstRefType;
290+
/// The Resulting [`TupleList`], of an [`SplitBorrow::borrow_mut()`] call
291+
type SplitBorrowMutResult: ExtractFirstRefType + ExtractFirstRefMutType;
292+
293+
/// Return a tuple of borrowed references
294+
fn borrow(&'a self) -> Self::SplitBorrowResult;
295+
/// Return a tuple of borrowed mutable references
296+
fn borrow_mut(&'a mut self) -> Self::SplitBorrowMutResult;
297+
}
298+
299+
impl<'a> SplitBorrowExtractFirstType<'a> for () {
300+
type SplitBorrowResult = ();
301+
type SplitBorrowMutResult = ();
302+
303+
fn borrow(&'a self) -> Self::SplitBorrowResult {}
304+
305+
fn borrow_mut(&'a mut self) -> Self::SplitBorrowMutResult {}
306+
}
307+
308+
impl<'a, Head, Tail> SplitBorrowExtractFirstType<'a> for (Head, Tail)
309+
where
310+
Head: 'static,
311+
Tail: SplitBorrowExtractFirstType<'a>,
312+
{
313+
type SplitBorrowResult = (Option<&'a Head>, Tail::SplitBorrowResult);
314+
type SplitBorrowMutResult = (Option<&'a mut Head>, Tail::SplitBorrowMutResult);
315+
316+
fn borrow(&'a self) -> Self::SplitBorrowResult {
317+
(Some(&self.0), self.1.borrow())
318+
}
319+
320+
fn borrow_mut(&'a mut self) -> Self::SplitBorrowMutResult {
321+
(Some(&mut self.0), self.1.borrow_mut())
322+
}
323+
}
324+
175325
/// Match by type
176326
pub trait MatchType {
177327
/// Match by type and call the passed `f` function with a borrow, if found
@@ -209,45 +359,6 @@ where
209359
}
210360
}
211361

212-
/// Borrow each member of the tuple
213-
pub trait SplitBorrow<'a> {
214-
/// The Resulting [`TupleList`], of an [`SplitBorrow::split_borrow()`] call
215-
type SplitBorrowResult;
216-
/// The Resulting [`TupleList`], of an [`SplitBorrow::split_borrow_mut()`] call
217-
type SplitBorrowMutResult;
218-
219-
/// Return a tuple of borrowed references
220-
fn split_borrow(&'a self) -> Self::SplitBorrowResult;
221-
/// Return a tuple of borrowed mutable references
222-
fn split_borrow_mut(&'a mut self) -> Self::SplitBorrowMutResult;
223-
}
224-
225-
impl<'a> SplitBorrow<'a> for () {
226-
type SplitBorrowResult = ();
227-
type SplitBorrowMutResult = ();
228-
229-
fn split_borrow(&'a self) -> Self::SplitBorrowResult {}
230-
231-
fn split_borrow_mut(&'a mut self) -> Self::SplitBorrowMutResult {}
232-
}
233-
234-
impl<'a, Head, Tail> SplitBorrow<'a> for (Head, Tail)
235-
where
236-
Head: 'a,
237-
Tail: SplitBorrow<'a>,
238-
{
239-
type SplitBorrowResult = (&'a Head, Tail::SplitBorrowResult);
240-
type SplitBorrowMutResult = (&'a mut Head, Tail::SplitBorrowMutResult);
241-
242-
fn split_borrow(&'a self) -> Self::SplitBorrowResult {
243-
(&self.0, self.1.split_borrow())
244-
}
245-
246-
fn split_borrow_mut(&'a mut self) -> Self::SplitBorrowMutResult {
247-
(&mut self.0, self.1.split_borrow_mut())
248-
}
249-
}
250-
251362
/// A named tuple
252363
pub trait NamedTuple: HasConstLen {
253364
/// Gets the name of this tuple

libafl_qemu/Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,12 @@ syscall-numbers = "3.0"
6060
meminterval = "0.4"
6161
thread_local = "1.1.4"
6262
capstone = "0.11.0"
63-
pyo3 = { version = "0.18", optional = true }
6463
rangemap = "1.3"
6564
log = "0.4.20"
65+
addr2line = "0.21"
66+
typed-arena = "2.0"
67+
68+
pyo3 = { version = "0.18", optional = true }
6669

6770
[build-dependencies]
6871
pyo3-build-config = { version = "0.18", optional = true }

libafl_qemu/libafl_qemu_build/src/build.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use which::which;
88

99
const QEMU_URL: &str = "https://github.com/AFLplusplus/qemu-libafl-bridge";
1010
const QEMU_DIRNAME: &str = "qemu-libafl-bridge";
11-
const QEMU_REVISION: &str = "ead06288fd597e72cbf50db1c89386f952592860";
11+
const QEMU_REVISION: &str = "e42124c0c8363184ef286fde43dce1d5c607699b";
1212

1313
fn build_dep_check(tools: &[&str]) {
1414
for tool in tools {

libafl_qemu/libafl_qemu_build/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,8 @@ fn qemu_bindgen_clang_args(
124124
)
125125
} else {
126126
(
127-
"/softmmu/main.c",
128-
format!("qemu-system-{cpu_target}.p/softmmu_main.c.o"),
127+
"/system/main.c",
128+
format!("libqemu-system-{cpu_target}.so.p/system_main.c.o"),
129129
)
130130
};
131131

libafl_qemu/libafl_qemu_sys/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,10 @@ pub fn memop_big_endian(op: MemOp) -> bool {
3636
pub fn make_plugin_meminfo(oi: MemOpIdx, rw: qemu_plugin_mem_rw) -> qemu_plugin_meminfo_t {
3737
oi | (rw.0 << 16)
3838
}
39+
40+
// from include/hw/core/cpu.h
41+
42+
#[cfg(target_os = "linux")]
43+
pub fn cpu_env(cpu: *mut CPUState) -> *mut CPUArchState {
44+
unsafe { cpu.add(1) as *mut CPUArchState }
45+
}

libafl_qemu/libqasan/malloc.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
Copyright (c) 2019-2020, Andrea Fioraldi
2+
Copyright (c) 2019-2023, Andrea Fioraldi
33
44
55
Redistribution and use in source and binary forms, with or without
@@ -53,13 +53,15 @@ struct chunk_begin {
5353
struct chunk_begin *next;
5454
struct chunk_begin *prev;
5555
char redzone[REDZONE_SIZE];
56-
};
56+
57+
} __attribute__((packed));
5758

5859
struct chunk_struct {
5960
struct chunk_begin begin;
6061
char redzone[REDZONE_SIZE];
6162
size_t prev_size_padding;
62-
};
63+
64+
} __attribute__((packed));
6365

6466
#ifdef __GLIBC__
6567

libafl_qemu/src/aarch64.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use capstone::arch::BuildsCapstone;
12
use num_enum::{IntoPrimitive, TryFromPrimitive};
23
#[cfg(feature = "python")]
34
use pyo3::prelude::*;
@@ -62,7 +63,9 @@ impl IntoPy<PyObject> for Regs {
6263

6364
/// Return an ARM64 ArchCapstoneBuilder
6465
pub fn capstone() -> capstone::arch::arm64::ArchCapstoneBuilder {
65-
capstone::Capstone::new().arm64()
66+
capstone::Capstone::new()
67+
.arm64()
68+
.mode(capstone::arch::arm64::ArchMode::Arm)
6669
}
6770

6871
pub type GuestReg = u64;

0 commit comments

Comments
 (0)