diff options
author | Ulrich Weigand <ulrich.weigand@de.ibm.com> | 2022-07-18 17:54:48 +0300 |
---|---|---|
committer | Ulrich Weigand <ulrich.weigand@de.ibm.com> | 2022-07-18 17:54:48 +0300 |
commit | 24ec521cd7bb51447f4ab03460d91c57378d49f7 (patch) | |
tree | 7a9a6765aefd1a042b174e4c73a178c3f139a3ef /libunwind/src/UnwindCursor.hpp | |
parent | a6316d6da5938328840d4161e4dc7c671808c20f (diff) |
[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
Diffstat (limited to 'libunwind/src/UnwindCursor.hpp')
-rw-r--r-- | libunwind/src/UnwindCursor.hpp | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/libunwind/src/UnwindCursor.hpp b/libunwind/src/UnwindCursor.hpp index e363f9e59c9a..b8bd9bc59010 100644 --- a/libunwind/src/UnwindCursor.hpp +++ b/libunwind/src/UnwindCursor.hpp @@ -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; |