@@ -103,6 +103,13 @@ pub const ASAN_SAVE_REGISTER_NAMES: [&str; ASAN_SAVE_REGISTER_COUNT] = [
103
103
#[ cfg( target_arch = "aarch64" ) ]
104
104
pub const ASAN_SAVE_REGISTER_COUNT : usize = 32 ;
105
105
106
+ #[ cfg( target_arch = "aarch64" ) ]
107
+ const ASAN_EH_FRAME_DWORD_COUNT : usize = 14 ;
108
+ #[ cfg( target_arch = "aarch64" ) ]
109
+ const ASAN_EH_FRAME_FDE_OFFSET : u32 = 20 ;
110
+ #[ cfg( target_arch = "aarch64" ) ]
111
+ const ASAN_EH_FRAME_FDE_ADDRESS_OFFSET : u32 = 28 ;
112
+
106
113
/// The frida address sanitizer runtime, providing address sanitization.
107
114
/// When executing in `ASAN`, each memory access will get checked, using frida stalker under the hood.
108
115
/// The runtime can report memory errors that occurred during execution,
@@ -131,6 +138,9 @@ pub struct AsanRuntime {
131
138
module_map : Option < ModuleMap > ,
132
139
suppressed_addresses : Vec < usize > ,
133
140
shadow_check_func : Option < extern "C" fn ( * const c_void , usize ) -> bool > ,
141
+
142
+ #[ cfg( target_arch = "aarch64" ) ]
143
+ eh_frame : [ u32 ; ASAN_EH_FRAME_DWORD_COUNT ] ,
134
144
}
135
145
136
146
impl Debug for AsanRuntime {
@@ -304,6 +314,9 @@ impl AsanRuntime {
304
314
module_map : None ,
305
315
suppressed_addresses : Vec :: new ( ) ,
306
316
shadow_check_func : None ,
317
+
318
+ #[ cfg( target_arch = "aarch64" ) ]
319
+ eh_frame : [ 0 ; ASAN_EH_FRAME_DWORD_COUNT ] ,
307
320
}
308
321
}
309
322
@@ -1641,18 +1654,33 @@ impl AsanRuntime {
1641
1654
) ;
1642
1655
1643
1656
let blob = ops. finalize ( ) . unwrap ( ) ;
1657
+ let mut map_flags = MapFlags :: MAP_ANON | MapFlags :: MAP_PRIVATE ;
1658
+
1659
+ // apple aarch64 requires MAP_JIT to allocates WX pages
1660
+ #[ cfg( all( target_vendor = "apple" , target_arch = "aarch64" ) ) ]
1661
+ map_flags |= MapFlags :: MAP_JIT ;
1662
+
1644
1663
unsafe {
1645
1664
let mapping = mmap (
1646
1665
std:: ptr:: null_mut ( ) ,
1647
1666
0x1000 ,
1648
1667
ProtFlags :: all ( ) ,
1649
- MapFlags :: MAP_ANON | MapFlags :: MAP_PRIVATE ,
1668
+ map_flags ,
1650
1669
-1 ,
1651
1670
0 ,
1652
1671
)
1653
1672
. unwrap ( ) ;
1673
+
1674
+ // on apple aarch64, WX pages can't be both writable and executable at the same time.
1675
+ // pthread_jit_write_protect_np flips them from executable (1) to writable (0)
1676
+ #[ cfg( all( target_vendor = "apple" , target_arch = "aarch64" ) ) ]
1677
+ libc:: pthread_jit_write_protect_np ( 0 ) ;
1678
+
1654
1679
blob. as_ptr ( )
1655
1680
. copy_to_nonoverlapping ( mapping as * mut u8 , blob. len ( ) ) ;
1681
+
1682
+ #[ cfg( all( target_vendor = "apple" , target_arch = "aarch64" ) ) ]
1683
+ libc:: pthread_jit_write_protect_np ( 1 ) ;
1656
1684
self . shadow_check_func = Some ( std:: mem:: transmute ( mapping as * mut u8 ) ) ;
1657
1685
}
1658
1686
}
@@ -1967,8 +1995,10 @@ impl AsanRuntime {
1967
1995
; stp x0, x1, [ x28]
1968
1996
1969
1997
; adr x25, <report
1970
- ; adr x0, >eh_frame_fde
1971
- ; adr x27, >fde_address
1998
+ ; adr x15, >eh_frame_cie_addr
1999
+ ; ldr x15, [ x15]
2000
+ ; add x0, x15, ASAN_EH_FRAME_FDE_OFFSET // eh_frame_fde
2001
+ ; add x27, x15, ASAN_EH_FRAME_FDE_ADDRESS_OFFSET // fde_address
1972
2002
; ldr w26, [ x27]
1973
2003
; cmp w26, #0x0
1974
2004
; b. ne >skip_register
@@ -2013,29 +2043,25 @@ impl AsanRuntime {
2013
2043
; . qword AsanRuntime :: handle_trap as * mut c_void as i64
2014
2044
; register_frame_func:
2015
2045
; . qword __register_frame as * mut c_void as i64
2016
- ; eh_frame_cie:
2017
- ; . dword 0x14
2018
- ; . dword 0x00
2019
- ; . dword 0x00527a01
2020
- ; . dword 0x011e7c01
2021
- ; . dword 0x001f0c1b
2022
- ; eh_frame_fde:
2023
- ; . dword 0x14
2024
- ; . dword 0x18
2025
- ; fde_address:
2026
- ; . dword 0x0 // <-- address offset goes here
2027
- ; . dword 0x104
2028
- //advance_loc 12
2029
- //def_cfa r29 (x29) at offset 16
2030
- //offset r30 (x30) at cfa-8
2031
- //offset r29 (x29) at cfa-16
2032
- ; . dword 0x1d0c4c00
2033
- ; . dword 0x9d029e10u32 as i32
2034
- ; . dword 0x04
2035
- // empty next FDE:
2036
- ; . dword 0x0
2037
- ; . dword 0x0
2046
+ ; eh_frame_cie_addr:
2047
+ ; . qword addr_of_mut!( self . eh_frame) as i64
2038
2048
) ;
2049
+ self . eh_frame = [
2050
+ 0x14 , 0 , 0x00527a01 , 0x011e7c01 , 0x001f0c1b ,
2051
+ // eh_frame_fde
2052
+ 0x14 , 0x18 ,
2053
+ // fde_address
2054
+ 0 , // <-- address offset goes here
2055
+ 0x104 ,
2056
+ // advance_loc 12
2057
+ // def_cfa r29 (x29) at offset 16
2058
+ // offset r30 (x30) at cfa-8
2059
+ // offset r29 (x29) at cfa-16
2060
+ 0x1d0c4c00 , 0x9d029e10 , 0x4 ,
2061
+ // empty next FDE:
2062
+ 0 , 0
2063
+ ] ;
2064
+
2039
2065
self . blob_report = Some ( ops_report. finalize ( ) . unwrap ( ) . into_boxed_slice ( ) ) ;
2040
2066
2041
2067
self . blob_check_mem_byte = Some ( self . generate_shadow_check_blob ( 0 ) ) ;
0 commit comments