The ARM64 stack walker was doing an illegal down cast from base-class (StackFrame) to derived-class (StackFrameARM64).
Inline frames are always of the base-class type (StackFrame). Treating them as derived-class and accessing members is causing buffer overflows. Change-Id: Ib41b74256e6162e7d2b14ca3905dfaf5591b9c86 Reviewed-on: https://chromium-review.googlesource.com/c/breakpad/breakpad/+/4847317 Reviewed-by: Joshua Peraza <jperaza@chromium.org>
This commit is contained in:
parent
e35d1d09ae
commit
f49c2f1a20
1 changed files with 20 additions and 9 deletions
|
@ -267,15 +267,25 @@ void StackwalkerARM64::CorrectRegLRByFramePointer(
|
||||||
last_frame->context.iregs[MD_CONTEXT_ARM64_REG_SP])
|
last_frame->context.iregs[MD_CONTEXT_ARM64_REG_SP])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
StackFrameARM64* last_last_frame =
|
// Searching for a real callee frame. Skipping inline frames since they
|
||||||
static_cast<StackFrameARM64*>(*(frames.end() - 2));
|
// don't contain context (and cannot be downcasted to StackFrameARM64).
|
||||||
uint64_t last_last_fp =
|
size_t last_frame_callee_id = frames.size() - 2;
|
||||||
last_last_frame->context.iregs[MD_CONTEXT_ARM64_REG_FP];
|
while (last_frame_callee_id >= 0 && frames[last_frame_callee_id]->trust ==
|
||||||
|
StackFrame::FRAME_TRUST_INLINE) {
|
||||||
|
last_frame_callee_id--;
|
||||||
|
}
|
||||||
|
if (last_frame_callee_id < 0) return;
|
||||||
|
StackFrameARM64* last_frame_callee =
|
||||||
|
static_cast<StackFrameARM64*>(frames[last_frame_callee_id]);
|
||||||
|
|
||||||
|
uint64_t last_frame_callee_fp =
|
||||||
|
last_frame_callee->context.iregs[MD_CONTEXT_ARM64_REG_FP];
|
||||||
|
|
||||||
uint64_t last_fp = 0;
|
uint64_t last_fp = 0;
|
||||||
if (last_last_fp && !memory_->GetMemoryAtAddress(last_last_fp, &last_fp)) {
|
if (last_frame_callee_fp &&
|
||||||
BPLOG(ERROR) << "Unable to read last_fp from last_last_fp: 0x"
|
!memory_->GetMemoryAtAddress(last_frame_callee_fp, &last_fp)) {
|
||||||
<< std::hex << last_last_fp;
|
BPLOG(ERROR) << "Unable to read last_fp from last_last_fp: 0x" << std::hex
|
||||||
|
<< last_frame_callee_fp;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Give up if STACK CFI doesn't agree with frame pointer.
|
// Give up if STACK CFI doesn't agree with frame pointer.
|
||||||
|
@ -283,9 +293,10 @@ void StackwalkerARM64::CorrectRegLRByFramePointer(
|
||||||
return;
|
return;
|
||||||
|
|
||||||
uint64_t last_lr = 0;
|
uint64_t last_lr = 0;
|
||||||
if (last_last_fp && !memory_->GetMemoryAtAddress(last_last_fp + 8, &last_lr)) {
|
if (last_frame_callee_fp &&
|
||||||
|
!memory_->GetMemoryAtAddress(last_frame_callee_fp + 8, &last_lr)) {
|
||||||
BPLOG(ERROR) << "Unable to read last_lr from (last_last_fp + 8): 0x"
|
BPLOG(ERROR) << "Unable to read last_lr from (last_last_fp + 8): 0x"
|
||||||
<< std::hex << (last_last_fp + 8);
|
<< std::hex << (last_frame_callee_fp + 8);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
last_lr = PtrauthStrip(last_lr);
|
last_lr = PtrauthStrip(last_lr);
|
||||||
|
|
Loading…
Reference in a new issue