/*
 * Copyright 2016, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <arpa/inet.h>
#include <dirent.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/capability.h>
#include <sys/prctl.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/un.h>
#include <syscall.h>
#include <unistd.h>

#include <limits>
#include <map>
#include <memory>
#include <set>
#include <vector>

#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/parseint.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <cutils/sockets.h>
#include <log/log.h>
#include <procinfo/process.h>
#include <selinux/selinux.h>

#include "backtrace.h"
#include "tombstone.h"
#include "utility.h"

#include "debuggerd/handler.h"
#include "debuggerd/protocol.h"
#include "debuggerd/tombstoned.h"
#include "debuggerd/util.h"

using android::base::unique_fd;
using android::base::ReadFileToString;
using android::base::StringPrintf;
using android::base::Trim;

static std::string get_process_name(pid_t pid) {
  std::string result = "<unknown>";
  ReadFileToString(StringPrintf("/proc/%d/cmdline", pid), &result);
  return result;
}

static std::string get_thread_name(pid_t tid) {
  std::string result = "<unknown>";
  ReadFileToString(StringPrintf("/proc/%d/comm", tid), &result);
  return Trim(result);
}

static bool pid_contains_tid(int pid_proc_fd, pid_t tid) {
  struct stat st;
  std::string task_path = StringPrintf("task/%d", tid);
  return fstatat(pid_proc_fd, task_path.c_str(), &st, 0) == 0;
}

// Attach to a thread, and verify that it's still a member of the given process
static bool ptrace_seize_thread(int pid_proc_fd, pid_t tid, std::string* error) {
  if (ptrace(PTRACE_SEIZE, tid, 0, 0) != 0) {
    *error = StringPrintf("failed to attach to thread %d: %s", tid, strerror(errno));
    return false;
  }

  // Make sure that the task we attached to is actually part of the pid we're dumping.
  if (!pid_contains_tid(pid_proc_fd, tid)) {
    if (ptrace(PTRACE_DETACH, tid, 0, 0) != 0) {
      PLOG(FATAL) << "failed to detach from thread " << tid;
    }
    *error = StringPrintf("thread %d is not in process", tid);
    return false;
  }

  // Put the task into ptrace-stop state.
  if (ptrace(PTRACE_INTERRUPT, tid, 0, 0) != 0) {
    PLOG(FATAL) << "failed to interrupt thread " << tid;
  }

  return true;
}

static bool activity_manager_notify(int pid, int signal, const std::string& amfd_data) {
  android::base::unique_fd amfd(socket_local_client("/data/system/ndebugsocket", ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM));
  if (amfd.get() == -1) {
    PLOG(ERROR) << "unable to connect to activity manager";
    return false;
  }

  struct timeval tv = {
    .tv_sec = 1,
    .tv_usec = 0,
  };
  if (setsockopt(amfd.get(), SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) == -1) {
    PLOG(ERROR) << "failed to set send timeout on activity manager socket";
    return false;
  }
  tv.tv_sec = 3;  // 3 seconds on handshake read
  if (setsockopt(amfd.get(), SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) {
    PLOG(ERROR) << "failed to set receive timeout on activity manager socket";
    return false;
  }

  // Activity Manager protocol: binary 32-bit network-byte-order ints for the
  // pid and signal number, followed by the raw text of the dump, culminating
  // in a zero byte that marks end-of-data.
  uint32_t datum = htonl(pid);
  if (!android::base::WriteFully(amfd, &datum, 4)) {
    PLOG(ERROR) << "AM pid write failed";
    return false;
  }
  datum = htonl(signal);
  if (!android::base::WriteFully(amfd, &datum, 4)) {
    PLOG(ERROR) << "AM signal write failed";
    return false;
  }
  if (!android::base::WriteFully(amfd, amfd_data.c_str(), amfd_data.size() + 1)) {
    PLOG(ERROR) << "AM data write failed";
    return false;
  }

  // 3 sec timeout reading the ack; we're fine if the read fails.
  char ack;
  android::base::ReadFully(amfd, &ack, 1);
  return true;
}

static void signal_handler(int) {
  // We can't log easily, because the heap might be corrupt.
  // Just die and let the surrounding log context explain things.
  _exit(1);
}

static void abort_handler(pid_t target, const bool& tombstoned_connected,
                          unique_fd& tombstoned_socket, unique_fd& output_fd,
                          const char* abort_msg) {
  // If we abort before we get an output fd, contact tombstoned to let any
  // potential listeners know that we failed.
  if (!tombstoned_connected) {
    if (!tombstoned_connect(target, &tombstoned_socket, &output_fd)) {
      // We failed to connect, not much we can do.
      LOG(ERROR) << "failed to connected to tombstoned to report failure";
      _exit(1);
    }
  }

  dprintf(output_fd.get(), "crash_dump failed to dump process");
  if (target != 1) {
    dprintf(output_fd.get(), " %d: %s\n", target, abort_msg);
  } else {
    dprintf(output_fd.get(), ": %s\n", abort_msg);
  }

  _exit(1);
}

static void drop_capabilities() {
  __user_cap_header_struct capheader;
  memset(&capheader, 0, sizeof(capheader));
  capheader.version = _LINUX_CAPABILITY_VERSION_3;
  capheader.pid = 0;

  __user_cap_data_struct capdata[2];
  memset(&capdata, 0, sizeof(capdata));

  if (capset(&capheader, &capdata[0]) == -1) {
    PLOG(FATAL) << "failed to drop capabilities";
  }

  if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) != 0) {
    PLOG(FATAL) << "failed to set PR_SET_NO_NEW_PRIVS";
  }
}

int main(int argc, char** argv) {
  pid_t target = getppid();
  bool tombstoned_connected = false;
  unique_fd tombstoned_socket;
  unique_fd output_fd;

  android::base::InitLogging(argv);
  android::base::SetAborter([&](const char* abort_msg) {
    abort_handler(target, tombstoned_connected, tombstoned_socket, output_fd, abort_msg);
  });

  // Don't try to dump ourselves.
  struct sigaction action = {};
  action.sa_handler = signal_handler;
  debuggerd_register_handlers(&action);

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

  pid_t main_tid;
  pid_t pseudothread_tid;

  if (!android::base::ParseInt(argv[1], &main_tid, 1, std::numeric_limits<pid_t>::max())) {
    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[2];
  }

  if (target == 1) {
    LOG(FATAL) << "target died before we could attach (received main tid = " << main_tid << ")";
  }

  android::procinfo::ProcessInfo target_info;
  if (!android::procinfo::GetProcessInfo(main_tid, &target_info)) {
    LOG(FATAL) << "failed to fetch process info for target " << main_tid;
  }

  if (main_tid != target_info.tid || target != target_info.pid) {
    LOG(FATAL) << "target info mismatch, expected pid " << target << ", tid " << main_tid
               << ", received pid " << target_info.pid << ", tid " << target_info.tid;
  }

  // Open /proc/`getppid()` in the original process, and pass it down to the forked child.
  std::string target_proc_path = "/proc/" + std::to_string(target);
  int target_proc_fd = open(target_proc_path.c_str(), O_DIRECTORY | O_RDONLY);
  if (target_proc_fd == -1) {
    PLOG(FATAL) << "failed to open " << target_proc_path;
  }

  // Make sure our parent didn't die.
  if (getppid() != target) {
    PLOG(FATAL) << "parent died";
  }

  // Reparent ourselves to init, so that the signal handler can waitpid on the
  // original process to avoid leaving a zombie for non-fatal dumps.
  pid_t forkpid = fork();
  if (forkpid == -1) {
    PLOG(FATAL) << "fork failed";
  } else if (forkpid != 0) {
    exit(0);
  }

  // Die if we take too long.
  alarm(20);

  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::map<pid_t, std::string> threads;
  {
    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 {
        threads.emplace(sibling_tid, get_thread_name(sibling_tid));
      }
    }
  }

  // Collect the backtrace map, open files, and process/thread names, while we still have caps.
  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);

  std::string process_name = get_process_name(main_tid);
  threads.emplace(main_tid, get_thread_name(main_tid));

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

  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";
  }

  if (tombstoned_connected) {
    if (TEMP_FAILURE_RETRY(dup2(output_fd.get(), STDOUT_FILENO)) == -1) {
      PLOG(ERROR) << "failed to dup2 output fd (" << output_fd.get() << ") to STDOUT_FILENO";
    }
  } else {
    unique_fd devnull(TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR)));
    TEMP_FAILURE_RETRY(dup2(devnull.get(), STDOUT_FILENO));
    output_fd = std::move(devnull);
  }

  LOG(INFO) << "performing dump of process " << target << " (target tid = " << main_tid << ")";

  // At this point, the thread that made the request has been attached and is
  // in ptrace-stopped state. After resumption, the triggering signal that has
  // been queued will be delivered.
  if (ptrace(PTRACE_CONT, main_tid, 0, 0) != 0) {
    PLOG(ERROR) << "PTRACE_CONT(" << main_tid << ") failed";
    exit(1);
  }

  siginfo_t siginfo = {};
  if (!wait_for_signal(main_tid, &siginfo)) {
    printf("failed to wait for signal in tid %d: %s\n", main_tid, strerror(errno));
    exit(1);
  }

  int signo = siginfo.si_signo;
  bool fatal_signal = signo != DEBUGGER_SIGNAL;
  bool backtrace = false;
  uintptr_t abort_address = 0;

  // si_value can represent three things:
  //   0: dump tombstone
  //   1: dump backtrace
  //   everything else: abort message address (implies dump tombstone)
  if (siginfo.si_value.sival_int == 1) {
    backtrace = true;
  } else if (siginfo.si_value.sival_ptr != nullptr) {
    abort_address = reinterpret_cast<uintptr_t>(siginfo.si_value.sival_ptr);
  }

  // TODO: Use seccomp to lock ourselves down.

  std::string amfd_data;
  if (backtrace) {
    dump_backtrace(output_fd.get(), backtrace_map.get(), target, main_tid, process_name, threads, 0);
  } else {
    engrave_tombstone(output_fd.get(), backtrace_map.get(), &open_files, target, main_tid,
                      process_name, threads, abort_address, fatal_signal ? &amfd_data : nullptr);
  }

  // We don't actually need to PTRACE_DETACH, as long as our tracees aren't in
  // group-stop state, which is true as long as no stopping signals are sent.

  bool wait_for_gdb = android::base::GetBoolProperty("debug.debuggerd.wait_for_gdb", false);
  if (!fatal_signal || siginfo.si_code == SI_USER) {
    // Don't wait_for_gdb when the process didn't actually crash.
    wait_for_gdb = false;
  }

  // If the process crashed or we need to send it SIGSTOP for wait_for_gdb,
  // get it in a state where it can receive signals, and then send the relevant
  // signal.
  if (wait_for_gdb || fatal_signal) {
    if (ptrace(PTRACE_INTERRUPT, main_tid, 0, 0) != 0) {
      PLOG(ERROR) << "failed to use PTRACE_INTERRUPT on " << main_tid;
    }

    if (tgkill(target, main_tid, wait_for_gdb ? SIGSTOP : signo) != 0) {
      PLOG(ERROR) << "failed to resend signal " << signo << " to " << main_tid;
    }
  }

  if (wait_for_gdb) {
    // Use ALOGI to line up with output from engrave_tombstone.
    ALOGI(
      "***********************************************************\n"
      "* Process %d has been suspended while crashing.\n"
      "* To attach gdbserver and start gdb, run this on the host:\n"
      "*\n"
      "*     gdbclient.py -p %d\n"
      "*\n"
      "***********************************************************",
      target, main_tid);
  }

  if (fatal_signal) {
    activity_manager_notify(target, signo, amfd_data);
  }

  // Close stdout before we notify tombstoned of completion.
  close(STDOUT_FILENO);
  if (tombstoned_connected && !tombstoned_notify_completion(tombstoned_socket.get())) {
    LOG(ERROR) << "failed to notify tombstoned of completion";
  }

  return 0;
}
