Index: compiler-rt/lib/asan/asan_suppressions.cpp =================================================================== --- compiler-rt/lib/asan/asan_suppressions.cpp +++ compiler-rt/lib/asan/asan_suppressions.cpp @@ -15,6 +15,7 @@ #include "asan_stack.h" #include "sanitizer_common/sanitizer_placement_new.h" +#include "sanitizer_common/sanitizer_ptrauth.h" #include "sanitizer_common/sanitizer_suppressions.h" #include "sanitizer_common/sanitizer_symbolizer.h" @@ -71,7 +72,7 @@ Symbolizer *symbolizer = Symbolizer::GetOrInit(); Suppression *s; for (uptr i = 0; i < stack->size && stack->trace[i]; i++) { - uptr addr = stack->trace[i]; + uptr addr = STRIP_PC(stack->trace[i]); if (suppression_ctx->HasSuppressionType(kInterceptorViaLibrary)) { // Match "interceptor_via_lib" suppressions. Index: compiler-rt/lib/lsan/lsan_common.cpp =================================================================== --- compiler-rt/lib/lsan/lsan_common.cpp +++ compiler-rt/lib/lsan/lsan_common.cpp @@ -18,6 +18,7 @@ #include "sanitizer_common/sanitizer_flags.h" #include "sanitizer_common/sanitizer_placement_new.h" #include "sanitizer_common/sanitizer_procmaps.h" +#include "sanitizer_common/sanitizer_ptrauth.h" #include "sanitizer_common/sanitizer_report_decorator.h" #include "sanitizer_common/sanitizer_stackdepot.h" #include "sanitizer_common/sanitizer_stacktrace.h" @@ -507,7 +508,7 @@ // If caller_pc is unknown, this chunk may be allocated in a coroutine. Mark // it as reachable, as we can't properly report its allocation stack anyway. if (caller_pc == 0 || (param->skip_linker_allocations && - GetLinker()->containsAddress(caller_pc))) { + GetLinker()->containsAddress(STRIP_PC(caller_pc)))) { m.set_tag(kReachable); param->frontier->push_back(chunk); } @@ -785,7 +786,7 @@ StackTrace stack = StackDepotGet(stack_trace_id); for (uptr i = 0; i < stack.size; i++) { Suppression *s = GetSuppressionForAddr( - StackTrace::GetPreviousInstructionPc(stack.trace[i])); + StackTrace::GetPreviousInstructionPc(STRIP_PC(stack.trace[i]))); if (s) { suppressed_stacks_sorted = false; suppressed_stacks.push_back(stack_trace_id); Index: compiler-rt/lib/sanitizer_common/sanitizer_ptrauth.h =================================================================== --- compiler-rt/lib/sanitizer_common/sanitizer_ptrauth.h +++ compiler-rt/lib/sanitizer_common/sanitizer_ptrauth.h @@ -11,6 +11,25 @@ #if __has_feature(ptrauth_calls) #include +#elif defined(__aarch64__) +inline unsigned long ptrauth_strip(unsigned long __value, + unsigned int __key) { + // On the stack the link register could be protected with Pointer + // Authentication Code when compiled with -mbranch-protection. + // Let's stripping the PAC unconditionally because xpaclri is in + // the NOP space so will do nothing when it is not enabled or not available. + unsigned long ret; + asm volatile( + "mov x30, %1\n\t" + "xpaclri\n\t" + "mov %0, x30\n\t" + : "=r"(ret) + : "r"(__value) + : "x30"); + return ret; +} +#define ptrauth_auth_data(__value, __old_key, __old_data) __value +#define ptrauth_string_discriminator(__string) ((int)0) #else // Copied from #define ptrauth_strip(__value, __key) __value @@ -18,6 +37,6 @@ #define ptrauth_string_discriminator(__string) ((int)0) #endif -#define STRIP_PC(pc) ((uptr)ptrauth_strip(pc, 0)) +#define STRIP_PC(pc) ((uptr)ptrauth_strip((uptr)pc, 0)) #endif // SANITIZER_PTRAUTH_H Index: compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cpp =================================================================== --- compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cpp +++ compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cpp @@ -14,6 +14,7 @@ #include "sanitizer_common.h" #include "sanitizer_hash.h" +#include "sanitizer_ptrauth.h" #include "sanitizer_stackdepotbase.h" namespace __sanitizer { @@ -42,7 +43,8 @@ return false; uptr i = 0; for (; i < size; i++) { - if (stack[i] != args.trace[i]) return false; + if (STRIP_PC(stack[i]) != STRIP_PC(args.trace[i])) + return false; } return true; } @@ -51,7 +53,7 @@ } static u32 hash(const args_type &args) { MurMur2HashBuilder H(args.size * sizeof(uptr)); - for (uptr i = 0; i < args.size; i++) H.add(args.trace[i]); + for (uptr i = 0; i < args.size; i++) H.add(STRIP_PC(args.trace[i])); return H.get(); } static bool is_valid(const args_type &args) { Index: compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cpp =================================================================== --- compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cpp +++ compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cpp @@ -15,6 +15,7 @@ #include "sanitizer_common.h" #include "sanitizer_flags.h" #include "sanitizer_platform.h" +#include "sanitizer_ptrauth.h" namespace __sanitizer { @@ -121,6 +122,18 @@ #elif defined(__riscv) // frame[-1] contains the return address uhwptr pc1 = frame[-1]; +#elif defined(__aarch64__) + uhwptr pc1; + // On the stack the link register could be protected with Pointer + // Authentication Code. Strip the AUTH part unconditionally, xpaclri is in + // the NOP space so will do nothing when it is not enabled or not available. + asm volatile( + "mov x30, %1\n\t" + "xpaclri\n\t" + "mov %0, x30\n\t" + : "=r"(pc1) + : "r"(frame[1]) + : "x30"); #else uhwptr pc1 = frame[1]; #endif @@ -158,7 +171,8 @@ uptr BufferedStackTrace::LocatePcInTrace(uptr pc) { uptr best = 0; for (uptr i = 1; i < size; ++i) { - if (Distance(trace[i], pc) < Distance(trace[best], pc)) best = i; + if (Distance(STRIP_PC(trace[i]), pc) < Distance(STRIP_PC(trace[best]), pc)) + best = i; } return best; } Index: compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cpp =================================================================== --- compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cpp +++ compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cpp @@ -12,6 +12,7 @@ #include "sanitizer_common.h" #include "sanitizer_placement_new.h" +#include "sanitizer_ptrauth.h" #include "sanitizer_stacktrace.h" #include "sanitizer_stacktrace_printer.h" #include "sanitizer_symbolizer.h" @@ -31,7 +32,7 @@ for (uptr i = 0; i < size && trace[i]; i++) { // PCs in stack traces are actually the return addresses, that is, // addresses of the next instructions after the call. - uptr pc = GetPreviousInstructionPc(trace[i]); + uptr pc = GetPreviousInstructionPc(STRIP_PC(trace[i])); SymbolizedStack *frames; if (symbolize) frames = Symbolizer::GetOrInit()->SymbolizePC(pc); Index: compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_report.cpp =================================================================== --- compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_report.cpp +++ compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_report.cpp @@ -15,6 +15,7 @@ #include "sanitizer_file.h" #include "sanitizer_flags.h" #include "sanitizer_procmaps.h" +#include "sanitizer_ptrauth.h" #include "sanitizer_report_decorator.h" #include "sanitizer_stacktrace.h" #include "sanitizer_stacktrace_printer.h" @@ -81,7 +82,7 @@ } // Currently, we include the first stack frame into the report summary. // Maybe sometimes we need to choose another frame (e.g. skip memcpy/etc). - uptr pc = StackTrace::GetPreviousInstructionPc(stack->trace[0]); + uptr pc = StackTrace::GetPreviousInstructionPc(STRIP_PC(stack->trace[0])); SymbolizedStack *frame = Symbolizer::GetOrInit()->SymbolizePC(pc); ReportErrorSummary(error_type, frame->info, alt_tool_name); frame->ClearAll(); Index: compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp =================================================================== --- compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp +++ compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp @@ -15,6 +15,7 @@ #include "sanitizer_common/sanitizer_stackdepot.h" #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_stacktrace.h" +#include "sanitizer_common/sanitizer_ptrauth.h" #include "tsan_platform.h" #include "tsan_rtl.h" #include "tsan_suppressions.h" @@ -119,11 +120,11 @@ SymbolizedStack *top = nullptr; for (uptr si = 0; si < trace.size; si++) { const uptr pc = trace.trace[si]; - uptr pc1 = pc; + uptr pc1 = STRIP_PC(pc); // We obtain the return address, but we're interested in the previous // instruction. if ((pc & kExternalPCBit) == 0) - pc1 = StackTrace::GetPreviousInstructionPc(pc); + pc1 = StackTrace::GetPreviousInstructionPc(STRIP_PC(pc)); SymbolizedStack *ent = SymbolizeCode(pc1); CHECK_NE(ent, 0); SymbolizedStack *last = ent;