Skip to content

Commit 6bbf0c3

Browse files
authored
[sanitizer] Fix prctl interceptor causing PAC authentication failure (#153081)
The root cause of this crash is that prctl(PR_PAC_RESET_KEYS) generates a new PAC key. As a result, paciasp and autiasp use different keys, leading to the crash. The solution is: if prctl's option is PR_PAC_RESET_KEYS, call real_prctl directly. This is implemented in assembly, so there are no PAC instructions involved. Related issue: android/ndk#1848 ``` 0000000000095468 <__interceptor_prctl>: 95468: d503233f paciasp 9546c: d10183ff sub sp, sp, #0x60 95470: a90267fe stp x30, x25, [sp, #0x20] 95474: a9035ff8 stp x24, x23, [sp, #0x30] 95478: a90457f6 stp x22, x21, [sp, #0x40] 9547c: a9054ff4 stp x20, x19, [sp, #0x50] 95480: aa1e03f4 mov x20, x30 95484: aa0403f3 mov x19, x4 95488: aa0303f6 mov x22, x3 9548c: aa0203f7 mov x23, x2 95490: aa0103f5 mov x21, x1 95494: 2a0003f8 mov w24, w0 95498: 940172ec bl 0xf2048 <_ZN6__tsan10cur_threadEv> 9549c: 4f05e540 movi v0.16b, #0xaa 954a0: 52801548 mov w8, #0xaa // =170 954a4: aa1403fe mov x30, x20 954a8: 39007fe8 strb w8, [sp, #0x1f] 954ac: aa0003f4 mov x20, x0 954b0: 910043e0 add x0, sp, #0x10 954b4: aa1403e1 mov x1, x20 954b8: bc01b3e0 stur s0, [sp, #0x1b] 954bc: d50320ff xpaclri 954c0: aa1e03e3 mov x3, x30 954c4: 97ffb461 bl 0x82648 <_ZN6__tsan17ScopedInterceptorC2EPNS_11ThreadStateEPKcm> 954c8: 97ff75ea bl 0x72c70 <_ZN11__sanitizer10StackTrace12GetCurrentPcEv> 954cc: 394c2688 ldrb w8, [x20, #0x309] 954d0: 7100051f cmp w8, #0x1 954d4: 540000c1 b.ne 0x954ec <__interceptor_prctl+0x84> 954d8: b9400a88 ldr w8, [x20, #0x8] 954dc: 35000088 cbnz w8, 0x954ec <__interceptor_prctl+0x84> 954e0: 394c2288 ldrb w8, [x20, #0x308] 954e4: 7100051f cmp w8, #0x1 954e8: 54000501 b.ne 0x95588 <__interceptor_prctl+0x120> 954ec: f0001128 adrp x8, 0x2bc000 <_ZN6__tsanL23interceptor_placeholderE+0xcac0> 954f0: 2a1803e0 mov w0, w24 954f4: aa1503e1 mov x1, x21 954f8: f9452508 ldr x8, [x8, #0xa48] 954fc: aa1703e2 mov x2, x23 95500: aa1603e3 mov x3, x22 95504: aa1303e4 mov x4, x19 95508: d63f0100 blr x8 9550c: f9400bf3 ldr x19, [sp, #0x10] 95510: 394c2668 ldrb w8, [x19, #0x309] 95514: 7100051f cmp w8, #0x1 95518: 540002a1 b.ne 0x9556c <__interceptor_prctl+0x104> 9551c: 39406be8 ldrb w8, [sp, #0x1a] 95520: 7100051f cmp w8, #0x1 95524: 54000d60 b.eq 0x956d0 <__interceptor_prctl+0x268> 95528: 394067e8 ldrb w8, [sp, #0x19] 9552c: 7100051f cmp w8, #0x1 95530: 54000de0 b.eq 0x956ec <__interceptor_prctl+0x284> 95534: b9400a68 ldr w8, [x19, #0x8] 95538: 350001a8 cbnz w8, 0x9556c <__interceptor_prctl+0x104> 9553c: b9403268 ldr w8, [x19, #0x30] 95540: 35000e48 cbnz w8, 0x95708 <__interceptor_prctl+0x2a0> 95544: f9400e68 ldr x8, [x19, #0x18] 95548: 91002109 add x9, x8, #0x8 9554c: f27c1d3f tst x9, #0xff0 95550: 54000ec0 b.eq 0x95728 <__interceptor_prctl+0x2c0> 95554: 5280004a mov w10, #0x2 // =2 95558: f900010a str x10, [x8] 9555c: f9000e69 str x9, [x19, #0x18] 95560: f9400a68 ldr x8, [x19, #0x10] 95564: d1002108 sub x8, x8, #0x8 95568: f9000a68 str x8, [x19, #0x10] 9556c: a9454ff4 ldp x20, x19, [sp, #0x50] 95570: a94457f6 ldp x22, x21, [sp, #0x40] 95574: a9435ff8 ldp x24, x23, [sp, #0x30] 95578: a94267fe ldp x30, x25, [sp, #0x20] 9557c: 910183ff add sp, sp, #0x60 95580: d50323bf autiasp 95584: d65f03c0 ret ... ```
1 parent b5f6ce6 commit 6bbf0c3

File tree

1 file changed

+29
-3
lines changed

1 file changed

+29
-3
lines changed

compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1285,8 +1285,34 @@ INTERCEPTOR(int, puts, char *s) {
12851285
#endif
12861286

12871287
#if SANITIZER_INTERCEPT_PRCTL
1288-
INTERCEPTOR(int, prctl, int option, unsigned long arg2, unsigned long arg3,
1289-
unsigned long arg4, unsigned long arg5) {
1288+
1289+
# if defined(__aarch64__)
1290+
// https://llvm.org/docs/PointerAuth.html
1291+
// AArch64 is currently the only architecture with full PAC support.
1292+
// Avoid adding PAC instructions to prevent crashes caused by
1293+
// prctl(PR_PAC_RESET_KEYS, ...). Since PR_PAC_RESET_KEYS resets the
1294+
// authentication key, using the old key afterward will lead to a crash.
1295+
1296+
# if defined(__ARM_FEATURE_BTI_DEFAULT)
1297+
# define BRANCH_PROTECTION_ATTRIBUTE \
1298+
__attribute__((target("branch-protection=bti")))
1299+
# else
1300+
# define BRANCH_PROTECTION_ATTRIBUTE \
1301+
__attribute__((target("branch-protection=none")))
1302+
# endif
1303+
1304+
# define PRCTL_INTERCEPTOR(ret_type, func, ...) \
1305+
DEFINE_REAL(ret_type, func, __VA_ARGS__) \
1306+
DECLARE_WRAPPER(ret_type, func, __VA_ARGS__) \
1307+
extern "C" INTERCEPTOR_ATTRIBUTE BRANCH_PROTECTION_ATTRIBUTE ret_type \
1308+
WRAP(func)(__VA_ARGS__)
1309+
1310+
# else
1311+
# define PRCTL_INTERCEPTOR INTERCEPTOR
1312+
# endif
1313+
1314+
PRCTL_INTERCEPTOR(int, prctl, int option, unsigned long arg2,
1315+
unsigned long arg3, unsigned long arg4, unsigned long arg5) {
12901316
void *ctx;
12911317
COMMON_INTERCEPTOR_ENTER(ctx, prctl, option, arg2, arg3, arg4, arg5);
12921318
static const int PR_SET_NAME = 15;
@@ -1326,7 +1352,7 @@ INTERCEPTOR(int, prctl, int option, unsigned long arg2, unsigned long arg3,
13261352
}
13271353
return res;
13281354
}
1329-
#define INIT_PRCTL COMMON_INTERCEPT_FUNCTION(prctl)
1355+
# define INIT_PRCTL COMMON_INTERCEPT_FUNCTION(prctl)
13301356
#else
13311357
#define INIT_PRCTL
13321358
#endif // SANITIZER_INTERCEPT_PRCTL

0 commit comments

Comments
 (0)