Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 30c942cf authored by Christopher Ferris's avatar Christopher Ferris
Browse files

Prevent crashes if a map cannot be created.

Under some conditions, /proc/<pid>/maps might return nothing. If we
try and unwind in this case, we'll crash. Check this case and fail
the unwind.

Add checks that no other functions try and use map_ without
checking for nullptr.

Add logging when an unwind fails so it's clear what happened.

Bug: 21162746
Change-Id: I56ce51dda0cfc9db20475a441f118108196aa07c
parent 000c009b
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -14,6 +14,8 @@
 * limitations under the License.
 */

#define LOG_TAG "DEBUG"

#include <stddef.h>
#include <stdlib.h>
#include <string.h>
@@ -27,6 +29,8 @@
#include <sys/ptrace.h>

#include <backtrace/Backtrace.h>

#include <log/log.h>
#include <UniquePtr.h>

#include "backtrace.h"
@@ -95,6 +99,8 @@ static void dump_thread(
  UniquePtr<Backtrace> backtrace(Backtrace::Create(tid, BACKTRACE_CURRENT_THREAD));
  if (backtrace->Unwind(0)) {
    dump_backtrace_to_log(backtrace.get(), log, "  ");
  } else {
    ALOGE("Unwind failed: tid = %d", tid);
  }

  if (!attached && ptrace(PTRACE_DETACH, tid, 0, 0) != 0) {
+7 −1
Original line number Diff line number Diff line
@@ -448,6 +448,8 @@ static bool dump_sibling_thread_report(
    UniquePtr<Backtrace> backtrace(Backtrace::Create(pid, new_tid, map));
    if (backtrace->Unwind(0)) {
      dump_backtrace_and_stack(backtrace.get(), log);
    } else {
      ALOGE("Unwind of sibling failed: pid = %d, tid = %d", pid, new_tid);
    }

    log->current_tid = log->crashed_tid;
@@ -650,9 +652,13 @@ static bool dump_crash(log_t* log, pid_t pid, pid_t tid, int signal, int si_code
  dump_registers(log, tid);
  if (backtrace->Unwind(0)) {
    dump_backtrace_and_stack(backtrace.get(), log);
  } else {
    ALOGE("Unwind failed: pid = %d, tid = %d", pid, tid);
  }
  dump_memory_and_code(log, tid);
  if (map.get() != nullptr) {
    dump_all_maps(backtrace.get(), map.get(), log, tid);
  }

  if (want_logs) {
    dump_logs(log, pid, 5);
+3 −1
Original line number Diff line number Diff line
@@ -114,8 +114,10 @@ std::string Backtrace::FormatFrameData(const backtrace_frame_data_t* frame) {
}

void Backtrace::FillInMap(uintptr_t pc, backtrace_map_t* map) {
  if (map_ != nullptr) {
    map_->FillIn(pc, map);
  }
}

Backtrace* Backtrace::Create(pid_t pid, pid_t tid, BacktraceMap* map) {
  if (pid == BACKTRACE_CURRENT_PROCESS) {
+5 −0
Original line number Diff line number Diff line
@@ -65,6 +65,11 @@ size_t BacktraceCurrent::Read(uintptr_t addr, uint8_t* buffer, size_t bytes) {
}

bool BacktraceCurrent::Unwind(size_t num_ignore_frames, ucontext_t* ucontext) {
  if (GetMap() == nullptr) {
    // Without a map object, we can't do anything.
    return false;
  }

  if (ucontext) {
    return UnwindFromContext(num_ignore_frames, ucontext);
  }
+5 −0
Original line number Diff line number Diff line
@@ -48,6 +48,11 @@ UnwindPtrace::~UnwindPtrace() {
}

bool UnwindPtrace::Unwind(size_t num_ignore_frames, ucontext_t* ucontext) {
  if (GetMap() == nullptr) {
    // Without a map object, we can't do anything.
    return false;
  }

  if (ucontext) {
    BACK_LOGW("Unwinding from a specified context not supported yet.");
    return false;