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:
omergreen 2022-12-04 19:55:45 +02:00 committed by GitHub
parent 2a2e70a636
commit c879a0a8d3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -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 self.eh_frame = [
; .dword 0x011e7c01 0x14, 0, 0x00527a01, 0x011e7c01, 0x001f0c1b,
; .dword 0x001f0c1b // eh_frame_fde
; eh_frame_fde: 0x14, 0x18,
; .dword 0x14 // fde_address
; .dword 0x18 0, // <-- address offset goes here
; fde_address: 0x104,
; .dword 0x0 // <-- address offset goes here
; .dword 0x104
// advance_loc 12 // advance_loc 12
// def_cfa r29 (x29) at offset 16 // def_cfa r29 (x29) at offset 16
// offset r30 (x30) at cfa-8 // offset r30 (x30) at cfa-8
// offset r29 (x29) at cfa-16 // offset r29 (x29) at cfa-16
; .dword 0x1d0c4c00 0x1d0c4c00, 0x9d029e10, 0x4,
; .dword 0x9d029e10u32 as i32
; .dword 0x04
// empty next FDE: // empty next FDE:
; .dword 0x0 0, 0
; .dword 0x0 ];
);
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));