Fix frida ASAN incompatibility with mac m1 (#917)
Add MAP_JIT, and extract the writable portion of generate_instrumentation_blobs into AsanRuntime
This commit is contained in:
parent
2a2e70a636
commit
c879a0a8d3
@ -103,6 +103,13 @@ pub const ASAN_SAVE_REGISTER_NAMES: [&str; ASAN_SAVE_REGISTER_COUNT] = [
|
|||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
pub const ASAN_SAVE_REGISTER_COUNT: usize = 32;
|
pub const ASAN_SAVE_REGISTER_COUNT: usize = 32;
|
||||||
|
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
const ASAN_EH_FRAME_DWORD_COUNT: usize = 14;
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
const ASAN_EH_FRAME_FDE_OFFSET: u32 = 20;
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
const ASAN_EH_FRAME_FDE_ADDRESS_OFFSET: u32 = 28;
|
||||||
|
|
||||||
/// The frida address sanitizer runtime, providing address sanitization.
|
/// The frida address sanitizer runtime, providing address sanitization.
|
||||||
/// When executing in `ASAN`, each memory access will get checked, using frida stalker under the hood.
|
/// When executing in `ASAN`, each memory access will get checked, using frida stalker under the hood.
|
||||||
/// The runtime can report memory errors that occurred during execution,
|
/// The runtime can report memory errors that occurred during execution,
|
||||||
@ -131,6 +138,9 @@ pub struct AsanRuntime {
|
|||||||
module_map: Option<ModuleMap>,
|
module_map: Option<ModuleMap>,
|
||||||
suppressed_addresses: Vec<usize>,
|
suppressed_addresses: Vec<usize>,
|
||||||
shadow_check_func: Option<extern "C" fn(*const c_void, usize) -> bool>,
|
shadow_check_func: Option<extern "C" fn(*const c_void, usize) -> bool>,
|
||||||
|
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
eh_frame: [u32; ASAN_EH_FRAME_DWORD_COUNT],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for AsanRuntime {
|
impl Debug for AsanRuntime {
|
||||||
@ -304,6 +314,9 @@ impl AsanRuntime {
|
|||||||
module_map: None,
|
module_map: None,
|
||||||
suppressed_addresses: Vec::new(),
|
suppressed_addresses: Vec::new(),
|
||||||
shadow_check_func: None,
|
shadow_check_func: None,
|
||||||
|
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
eh_frame: [0; ASAN_EH_FRAME_DWORD_COUNT],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1641,18 +1654,33 @@ impl AsanRuntime {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let blob = ops.finalize().unwrap();
|
let blob = ops.finalize().unwrap();
|
||||||
|
let mut map_flags = MapFlags::MAP_ANON | MapFlags::MAP_PRIVATE;
|
||||||
|
|
||||||
|
// apple aarch64 requires MAP_JIT to allocates WX pages
|
||||||
|
#[cfg(all(target_vendor = "apple", target_arch = "aarch64"))]
|
||||||
|
map_flags |= MapFlags::MAP_JIT;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let mapping = mmap(
|
let mapping = mmap(
|
||||||
std::ptr::null_mut(),
|
std::ptr::null_mut(),
|
||||||
0x1000,
|
0x1000,
|
||||||
ProtFlags::all(),
|
ProtFlags::all(),
|
||||||
MapFlags::MAP_ANON | MapFlags::MAP_PRIVATE,
|
map_flags,
|
||||||
-1,
|
-1,
|
||||||
0,
|
0,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
// on apple aarch64, WX pages can't be both writable and executable at the same time.
|
||||||
|
// pthread_jit_write_protect_np flips them from executable (1) to writable (0)
|
||||||
|
#[cfg(all(target_vendor = "apple", target_arch = "aarch64"))]
|
||||||
|
libc::pthread_jit_write_protect_np(0);
|
||||||
|
|
||||||
blob.as_ptr()
|
blob.as_ptr()
|
||||||
.copy_to_nonoverlapping(mapping as *mut u8, blob.len());
|
.copy_to_nonoverlapping(mapping as *mut u8, blob.len());
|
||||||
|
|
||||||
|
#[cfg(all(target_vendor = "apple", target_arch = "aarch64"))]
|
||||||
|
libc::pthread_jit_write_protect_np(1);
|
||||||
self.shadow_check_func = Some(std::mem::transmute(mapping as *mut u8));
|
self.shadow_check_func = Some(std::mem::transmute(mapping as *mut u8));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1967,8 +1995,10 @@ impl AsanRuntime {
|
|||||||
; stp x0, x1, [x28]
|
; stp x0, x1, [x28]
|
||||||
|
|
||||||
; adr x25, <report
|
; adr x25, <report
|
||||||
; adr x0, >eh_frame_fde
|
; adr x15, >eh_frame_cie_addr
|
||||||
; adr x27, >fde_address
|
; ldr x15, [x15]
|
||||||
|
; add x0, x15, ASAN_EH_FRAME_FDE_OFFSET // eh_frame_fde
|
||||||
|
; add x27, x15, ASAN_EH_FRAME_FDE_ADDRESS_OFFSET // fde_address
|
||||||
; ldr w26, [x27]
|
; ldr w26, [x27]
|
||||||
; cmp w26, #0x0
|
; cmp w26, #0x0
|
||||||
; b.ne >skip_register
|
; b.ne >skip_register
|
||||||
@ -2013,29 +2043,25 @@ impl AsanRuntime {
|
|||||||
; .qword AsanRuntime::handle_trap as *mut c_void as i64
|
; .qword AsanRuntime::handle_trap as *mut c_void as i64
|
||||||
; register_frame_func:
|
; register_frame_func:
|
||||||
; .qword __register_frame as *mut c_void as i64
|
; .qword __register_frame as *mut c_void as i64
|
||||||
; eh_frame_cie:
|
; eh_frame_cie_addr:
|
||||||
; .dword 0x14
|
; .qword addr_of_mut!(self.eh_frame) as i64
|
||||||
; .dword 0x00
|
|
||||||
; .dword 0x00527a01
|
|
||||||
; .dword 0x011e7c01
|
|
||||||
; .dword 0x001f0c1b
|
|
||||||
; eh_frame_fde:
|
|
||||||
; .dword 0x14
|
|
||||||
; .dword 0x18
|
|
||||||
; fde_address:
|
|
||||||
; .dword 0x0 // <-- address offset goes here
|
|
||||||
; .dword 0x104
|
|
||||||
//advance_loc 12
|
|
||||||
//def_cfa r29 (x29) at offset 16
|
|
||||||
//offset r30 (x30) at cfa-8
|
|
||||||
//offset r29 (x29) at cfa-16
|
|
||||||
; .dword 0x1d0c4c00
|
|
||||||
; .dword 0x9d029e10u32 as i32
|
|
||||||
; .dword 0x04
|
|
||||||
// empty next FDE:
|
|
||||||
; .dword 0x0
|
|
||||||
; .dword 0x0
|
|
||||||
);
|
);
|
||||||
|
self.eh_frame = [
|
||||||
|
0x14, 0, 0x00527a01, 0x011e7c01, 0x001f0c1b,
|
||||||
|
// eh_frame_fde
|
||||||
|
0x14, 0x18,
|
||||||
|
// fde_address
|
||||||
|
0, // <-- address offset goes here
|
||||||
|
0x104,
|
||||||
|
// advance_loc 12
|
||||||
|
// def_cfa r29 (x29) at offset 16
|
||||||
|
// offset r30 (x30) at cfa-8
|
||||||
|
// offset r29 (x29) at cfa-16
|
||||||
|
0x1d0c4c00, 0x9d029e10, 0x4,
|
||||||
|
// empty next FDE:
|
||||||
|
0, 0
|
||||||
|
];
|
||||||
|
|
||||||
self.blob_report = Some(ops_report.finalize().unwrap().into_boxed_slice());
|
self.blob_report = Some(ops_report.finalize().unwrap().into_boxed_slice());
|
||||||
|
|
||||||
self.blob_check_mem_byte = Some(self.generate_shadow_check_blob(0));
|
self.blob_check_mem_byte = Some(self.generate_shadow_check_blob(0));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user