[libunwind][SystemZ] Use process_vm_readv to avoid potential segfaults
Fix potential crashes during unwind when checking for signal frames and the current PC is invalid. The same bug was fixed for aarch64 in https://reviews.llvm.org/D126343. Reviewed by: MaskRay Differential Revision: https://reviews.llvm.org/D129856
This commit is contained in:
parent
a6316d6da5
commit
24ec521cd7
|
@ -2695,8 +2695,14 @@ bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_s390x &) {
|
|||
// own restorer function, though, or user-mode QEMU might write a trampoline
|
||||
// onto the stack.
|
||||
const pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP));
|
||||
const uint16_t inst = _addressSpace.get16(pc);
|
||||
if (inst == 0x0a77 || inst == 0x0aad) {
|
||||
// The PC might contain an invalid address if the unwind info is bad, so
|
||||
// directly accessing it could cause a segfault. Use process_vm_readv to
|
||||
// read the memory safely instead.
|
||||
uint16_t inst;
|
||||
struct iovec local_iov = {&inst, sizeof inst};
|
||||
struct iovec remote_iov = {reinterpret_cast<void *>(pc), sizeof inst};
|
||||
long bytesRead = process_vm_readv(getpid(), &local_iov, 1, &remote_iov, 1, 0);
|
||||
if (bytesRead == sizeof inst && (inst == 0x0a77 || inst == 0x0aad)) {
|
||||
_info = {};
|
||||
_info.start_ip = pc;
|
||||
_info.end_ip = pc + 2;
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
// Ensure that libunwind doesn't crash on invalid info; the Linux aarch64
|
||||
// sigreturn frame check would previously attempt to access invalid memory in
|
||||
// this scenario.
|
||||
// REQUIRES: linux && (target={{aarch64-.+}} || target={{x86_64-.+}})
|
||||
// REQUIRES: linux && (target={{aarch64-.+}} || target={{s390x-.+}} || target={{x86_64-.+}})
|
||||
|
||||
// GCC doesn't support __attribute__((naked)) on AArch64.
|
||||
// UNSUPPORTED: gcc
|
||||
|
@ -36,6 +36,20 @@ __attribute__((naked)) void bad_unwind_info() {
|
|||
".cfi_def_cfa_offset 0\n"
|
||||
".cfi_restore x30\n"
|
||||
"ret\n");
|
||||
#elif defined(__s390x__)
|
||||
__asm__("stmg %r14,%r15,112(%r15)\n"
|
||||
"mvghi 104(%r15),4\n"
|
||||
"# purposely use incorrect offset for %r14\n"
|
||||
".cfi_offset 14, -56\n"
|
||||
".cfi_offset 15, -40\n"
|
||||
"lay %r15,-160(%r15)\n"
|
||||
".cfi_def_cfa_offset 320\n"
|
||||
"brasl %r14,stepper\n"
|
||||
"lmg %r14,%r15,272(%r15)\n"
|
||||
".cfi_restore 15\n"
|
||||
".cfi_restore 14\n"
|
||||
".cfi_def_cfa_offset 160\n"
|
||||
"br %r14\n");
|
||||
#elif defined(__x86_64__)
|
||||
__asm__("pushq %rbx\n"
|
||||
".cfi_def_cfa_offset 16\n"
|
||||
|
@ -48,7 +62,7 @@ __attribute__((naked)) void bad_unwind_info() {
|
|||
".cfi_def_cfa_offset 8\n"
|
||||
"ret\n");
|
||||
#else
|
||||
#error This test is only supported on aarch64 or x86-64
|
||||
#error This test is only supported on aarch64, s390x, or x86-64
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue