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

Commit 274eb164 authored by Josh Gao's avatar Josh Gao Committed by android-build-merger
Browse files

Merge "debuggerd_handler: set PR_SET_DUMPABLE before running crash_dump." am: af776fd5

am: 877becaf

Change-Id: Icb5c2ade77a25dea268cc311fc7ddb45c10aa76e
parents 2e0997bc 877becaf
Loading
Loading
Loading
Loading
+43 −37
Original line number Diff line number Diff line
@@ -238,11 +238,12 @@ int main(int argc, char** argv) {
  action.sa_handler = signal_handler;
  debuggerd_register_handlers(&action);

  if (argc != 2) {
  if (argc != 3) {
    return 1;
  }

  pid_t main_tid;
  pid_t pseudothread_tid;

  if (target == 1) {
    LOG(FATAL) << "target died before we could attach";
@@ -252,6 +253,10 @@ int main(int argc, char** argv) {
    LOG(FATAL) << "invalid main tid: " << argv[1];
  }

  if (!android::base::ParseInt(argv[2], &pseudothread_tid, 1, std::numeric_limits<pid_t>::max())) {
    LOG(FATAL) << "invalid pseudothread tid: " << argv[1];
  }

  android::procinfo::ProcessInfo target_info;
  if (!android::procinfo::GetProcessInfo(main_tid, &target_info)) {
    LOG(FATAL) << "failed to fetch process info for target " << main_tid;
@@ -284,16 +289,53 @@ int main(int argc, char** argv) {
  check_process(target_proc_fd, target);

  std::string attach_error;

  // Seize the main thread.
  if (!ptrace_seize_thread(target_proc_fd, main_tid, &attach_error)) {
    LOG(FATAL) << attach_error;
  }

  // Seize the siblings.
  std::set<pid_t> attached_siblings;
  {
    std::set<pid_t> siblings;
    if (!android::procinfo::GetProcessTids(target, &siblings)) {
      PLOG(FATAL) << "failed to get process siblings";
    }

    // but not the already attached main thread.
    siblings.erase(main_tid);
    // or the handler pseudothread.
    siblings.erase(pseudothread_tid);

    for (pid_t sibling_tid : siblings) {
      if (!ptrace_seize_thread(target_proc_fd, sibling_tid, &attach_error)) {
        LOG(WARNING) << attach_error;
      } else {
        attached_siblings.insert(sibling_tid);
      }
    }
  }

  // Collect the backtrace map and open files, while the process still has PR_GET_DUMPABLE=1
  std::unique_ptr<BacktraceMap> backtrace_map(BacktraceMap::Create(main_tid));
  if (!backtrace_map) {
    LOG(FATAL) << "failed to create backtrace map";
  }

  // Collect the list of open files.
  OpenFilesList open_files;
  populate_open_files_list(target, &open_files);

  // Drop our capabilities now that we've attached to the threads we care about.
  drop_capabilities();
  check_process(target_proc_fd, target);

  LOG(INFO) << "obtaining output fd from tombstoned";
  tombstoned_connected = tombstoned_connect(target, &tombstoned_socket, &output_fd);

  // Write a '\1' to stdout to tell the crashing process to resume.
  // It also restores the value of PR_SET_DUMPABLE at this point.
  if (TEMP_FAILURE_RETRY(write(STDOUT_FILENO, "\1", 1)) == -1) {
    PLOG(ERROR) << "failed to communicate to target process";
  }
@@ -339,45 +381,9 @@ int main(int argc, char** argv) {
    abort_address = reinterpret_cast<uintptr_t>(siginfo.si_value.sival_ptr);
  }

  // Now that we have the signal that kicked things off, attach all of the
  // sibling threads, and then proceed.
  std::set<pid_t> attached_siblings;
  {
    std::set<pid_t> siblings;
    if (!android::procinfo::GetProcessTids(target, &siblings)) {
      PLOG(FATAL) << "failed to get process siblings";
    }
    siblings.erase(main_tid);

    for (pid_t sibling_tid : siblings) {
      if (!ptrace_seize_thread(target_proc_fd, sibling_tid, &attach_error)) {
        LOG(WARNING) << attach_error;
      } else {
        attached_siblings.insert(sibling_tid);
      }
    }
  }

  std::unique_ptr<BacktraceMap> backtrace_map(BacktraceMap::Create(main_tid));
  if (!backtrace_map) {
    LOG(FATAL) << "failed to create backtrace map";
  }

  // Collect the list of open files.
  OpenFilesList open_files;
  if (!backtrace) {
    populate_open_files_list(target, &open_files);
  }

  // Drop our capabilities now that we've attached to the threads we care about.
  drop_capabilities();

  check_process(target_proc_fd, target);

  // TODO: Use seccomp to lock ourselves down.

  std::string amfd_data;

  if (backtrace) {
    dump_backtrace(output_fd.get(), backtrace_map.get(), target, main_tid, attached_siblings, 0);
  } else {
+16 −3
Original line number Diff line number Diff line
@@ -254,9 +254,11 @@ static int debuggerd_dispatch_pseudothread(void* arg) {

    raise_caps();

    char buf[10];
    snprintf(buf, sizeof(buf), "%d", thread_info->crashing_tid);
    execl(CRASH_DUMP_PATH, CRASH_DUMP_NAME, buf, nullptr);
    char main_tid[10];
    char pseudothread_tid[10];
    snprintf(main_tid, sizeof(main_tid), "%d", thread_info->crashing_tid);
    snprintf(pseudothread_tid, sizeof(pseudothread_tid), "%d", thread_info->pseudothread_tid);
    execl(CRASH_DUMP_PATH, CRASH_DUMP_NAME, main_tid, pseudothread_tid, nullptr);

    fatal_errno("exec failed");
  } else {
@@ -381,6 +383,12 @@ static void debuggerd_signal_handler(int signal_number, siginfo_t* info, void*)
    .info = info
  };

  // Set PR_SET_DUMPABLE to 1, so that crash_dump can ptrace us.
  int orig_dumpable = prctl(PR_GET_DUMPABLE);
  if (prctl(PR_SET_DUMPABLE, 1) != 0) {
    fatal_errno("failed to set dumpable");
  }

  // Essentially pthread_create without CLONE_FILES (see debuggerd_dispatch_pseudothread).
  pid_t child_pid =
    clone(debuggerd_dispatch_pseudothread, pseudothread_stack,
@@ -396,6 +404,11 @@ static void debuggerd_signal_handler(int signal_number, siginfo_t* info, void*)
  // and then wait for it to finish.
  __futex_wait(&thread_info.pseudothread_tid, child_pid, nullptr);

  // Restore PR_SET_DUMPABLE to its original value.
  if (prctl(PR_SET_DUMPABLE, orig_dumpable) != 0) {
    fatal_errno("failed to restore dumpable");
  }

  // Signals can either be fatal or nonfatal.
  // For fatal signals, crash_dump will PTRACE_CONT us with the signal we
  // crashed with, so that processes using waitpid on us will see that we