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

Commit 3d89a46d authored by Peter Collingbourne's avatar Peter Collingbourne Committed by Automerger Merge Worker
Browse files

Merge "Read fault address on arm64 using proposed kernel API." am: cd63cae6

Change-Id: I87988443ee8e910345038880ede59937bd87ada0
parents cba24679 cd63cae6
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -295,6 +295,13 @@ static void ReadCrashInfo(unique_fd& fd, siginfo_t* siginfo,
    case 3:
      process_info->abort_msg_address = crash_info->data.s.abort_msg_address;
      *siginfo = crash_info->data.s.siginfo;
      if (signal_has_si_addr(siginfo)) {
        // Make a copy of the ucontext field because otherwise it is not aligned enough (due to
        // being in a packed struct) and clang complains about that.
        ucontext_t ucontext = crash_info->data.s.ucontext;
        process_info->has_fault_address = true;
        process_info->fault_address = get_fault_address(siginfo, &ucontext);
      }
      regs->reset(unwindstack::Regs::CreateFromUcontext(unwindstack::Regs::CurrentArch(),
                                                        &crash_info->data.s.ucontext));
      break;
+26 −0
Original line number Diff line number Diff line
@@ -305,6 +305,32 @@ TEST_F(CrasherTest, smoke) {
  ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0xdead)");
}

TEST_F(CrasherTest, tagged_fault_addr) {
#if !defined(__aarch64__)
  GTEST_SKIP() << "Requires aarch64";
#endif
  int intercept_result;
  unique_fd output_fd;
  StartProcess([]() {
    *reinterpret_cast<volatile char*>(0x100000000000dead) = '1';
  });

  StartIntercept(&output_fd);
  FinishCrasher();
  AssertDeath(SIGSEGV);
  FinishIntercept(&intercept_result);

  ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";

  std::string result;
  ConsumeFd(std::move(output_fd), &result);

  // The address can either be tagged (new kernels) or untagged (old kernels).
  ASSERT_MATCH(
      result,
      R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr (0x100000000000dead|0xdead))");
}

TEST_F(CrasherTest, LD_PRELOAD) {
  int intercept_result;
  unique_fd output_fd;
+7 −4
Original line number Diff line number Diff line
@@ -167,7 +167,7 @@ static bool get_main_thread_name(char* buf, size_t len) {
 * mutex is being held, so we don't want to use any libc functions that
 * could allocate memory or hold a lock.
 */
static void log_signal_summary(const siginfo_t* info) {
static void log_signal_summary(const siginfo_t* info, const ucontext_t* ucontext) {
  char thread_name[MAX_TASK_NAME_LEN + 1];  // one more for termination
  if (prctl(PR_GET_NAME, reinterpret_cast<unsigned long>(thread_name), 0, 0, 0) != 0) {
    strcpy(thread_name, "<name unknown>");
@@ -186,7 +186,8 @@ static void log_signal_summary(const siginfo_t* info) {
  // Many signals don't have an address or sender.
  char addr_desc[32] = "";  // ", fault addr 0x1234"
  if (signal_has_si_addr(info)) {
    async_safe_format_buffer(addr_desc, sizeof(addr_desc), ", fault addr %p", info->si_addr);
    async_safe_format_buffer(addr_desc, sizeof(addr_desc), ", fault addr %p",
                             reinterpret_cast<void*>(get_fault_address(info, ucontext)));
  }
  pid_t self_pid = __getpid();
  char sender_desc[32] = {};  // " from pid 1234, uid 666"
@@ -476,6 +477,8 @@ static void debuggerd_signal_handler(int signal_number, siginfo_t* info, void* c
  // making a syscall and checking errno.
  ErrnoRestorer restorer;

  auto *ucontext = static_cast<ucontext_t*>(context);

  // It's possible somebody cleared the SA_SIGINFO flag, which would mean
  // our "info" arg holds an undefined value.
  if (!have_siginfo(signal_number)) {
@@ -522,7 +525,7 @@ static void debuggerd_signal_handler(int signal_number, siginfo_t* info, void* c
    // This check might be racy if another thread sets NO_NEW_PRIVS, but this should be unlikely,
    // you can only set NO_NEW_PRIVS to 1, and the effect should be at worst a single missing
    // ANR trace.
    debuggerd_fallback_handler(info, static_cast<ucontext_t*>(context), process_info.abort_msg);
    debuggerd_fallback_handler(info, ucontext, process_info.abort_msg);
    resend_signal(info);
    return;
  }
@@ -534,7 +537,7 @@ static void debuggerd_signal_handler(int signal_number, siginfo_t* info, void* c
    return;
  }

  log_signal_summary(info);
  log_signal_summary(info, ucontext);

  debugger_thread_info thread_info = {
      .crashing_tid = __gettid(),
+3 −0
Original line number Diff line number Diff line
@@ -41,4 +41,7 @@ struct ProcessInfo {
  uintptr_t fdsan_table_address = 0;
  uintptr_t gwp_asan_state = 0;
  uintptr_t gwp_asan_metadata = 0;

  bool has_fault_address = false;
  uintptr_t fault_address = 0;
};
+2 −0
Original line number Diff line number Diff line
@@ -93,4 +93,6 @@ void get_signal_sender(char* buf, size_t n, const siginfo_t*);
const char* get_signame(const siginfo_t*);
const char* get_sigcode(const siginfo_t*);

uintptr_t get_fault_address(const siginfo_t* siginfo, const ucontext_t* ucontext);

#endif // _DEBUGGERD_UTILITY_H
Loading