aboutsummaryrefslogtreecommitdiff
path: root/src/processor/stackwalker_arm64.cc
diff options
context:
space:
mode:
authorJoshua Peraza <jperaza@chromium.org>2019-07-22 13:26:19 -0700
committerJoshua Peraza <jperaza@chromium.org>2019-07-23 20:02:05 +0000
commitcfad51e9547399a6df3c09a1bee3cb599999b51c (patch)
treed2de9d123372a9729b5d2f0a907042481ec19a65 /src/processor/stackwalker_arm64.cc
parentImproving the support for Fuchsia in Breakpad Processor. (diff)
downloadbreakpad-cfad51e9547399a6df3c09a1bee3cb599999b51c.tar.xz
arm64: strip PACs from link register values
Pointer authentication codes are used to validate pointers against accidental or malicious modification by storing a hash of the address and a secret value in the pointer's unused, upper bits. The exact bits used may vary by implementation and depend on the size of the virtual address space of the target system, and whether other tagged pointer features are in use. Apple has implemented PACs in the Apple A12. https://developer.apple.com/documentation/security/preparing_your_app_to_work_with_pointer_authentication The documented method of stripping PACs from a pointer is to call ptrauth_strip(), which ultimately emits an `xpaci` instruction, but this option isn't available to the Breakpad processor not running on the device. Instead, this patch selects likely address bits from link register values by examining the address range of loaded modules. Change-Id: I054bd1a03605719937fc85dcc8d8b9fe927f44be Reviewed-on: https://chromium-review.googlesource.com/c/breakpad/breakpad/+/1713650 Reviewed-by: Mark Mentovai <mark@chromium.org>
Diffstat (limited to 'src/processor/stackwalker_arm64.cc')
-rw-r--r--src/processor/stackwalker_arm64.cc27
1 files changed, 26 insertions, 1 deletions
diff --git a/src/processor/stackwalker_arm64.cc b/src/processor/stackwalker_arm64.cc
index f9660112..47e245ed 100644
--- a/src/processor/stackwalker_arm64.cc
+++ b/src/processor/stackwalker_arm64.cc
@@ -54,8 +54,29 @@ StackwalkerARM64::StackwalkerARM64(const SystemInfo* system_info,
StackFrameSymbolizer* resolver_helper)
: Stackwalker(system_info, memory, modules, resolver_helper),
context_(context),
- context_frame_validity_(StackFrameARM64::CONTEXT_VALID_ALL) { }
+ context_frame_validity_(StackFrameARM64::CONTEXT_VALID_ALL),
+ address_range_mask_(0xffffffffffffffff) {
+ if (modules && modules->module_count() > 0) {
+ // ARM64 supports storing pointer authentication codes in the upper bits of
+ // a pointer. Make a best guess at the range of valid addresses based on the
+ // range of loaded modules.
+ const CodeModule *high_module =
+ modules->GetModuleAtSequence(modules->module_count() - 1);
+ uint64_t mask = high_module->base_address() + high_module->size();
+ mask |= mask >> 1;
+ mask |= mask >> 2;
+ mask |= mask >> 4;
+ mask |= mask >> 8;
+ mask |= mask >> 16;
+ mask |= mask >> 32;
+ address_range_mask_ = mask;
+ }
+}
+uint64_t StackwalkerARM64::PtrauthStrip(uint64_t ptr) {
+ uint64_t stripped = ptr & address_range_mask_;
+ return modules_ && modules_->GetModuleForAddress(stripped) ? stripped : ptr;
+}
StackFrame* StackwalkerARM64::GetContextFrame() {
if (!context_) {
@@ -71,6 +92,8 @@ StackFrame* StackwalkerARM64::GetContextFrame() {
frame->context_validity = context_frame_validity_;
frame->trust = StackFrame::FRAME_TRUST_CONTEXT;
frame->instruction = frame->context.iregs[MD_CONTEXT_ARM64_REG_PC];
+ frame->context.iregs[MD_CONTEXT_ARM64_REG_LR] =
+ PtrauthStrip(frame->context.iregs[MD_CONTEXT_ARM64_REG_LR]);
return frame;
}
@@ -202,6 +225,8 @@ StackFrameARM64* StackwalkerARM64::GetCallerByFramePointer(
return NULL;
}
+ caller_lr = PtrauthStrip(caller_lr);
+
uint64_t caller_sp = last_fp ? last_fp + 16 :
last_frame->context.iregs[MD_CONTEXT_ARM64_REG_SP];