// Copyright 2014 The Crashpad Authors
//
// 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 "client/crashpad_client.h"

#include <Availability.h>
#include <errno.h>
#include <mach/mach.h>
#include <pthread.h>
#include <stdint.h>

#include <memory>
#include <tuple>
#include <utility>

#include "base/apple/mach_logging.h"
#include "base/check_op.h"
#include "base/logging.h"
#include "base/strings/stringprintf.h"
#include "util/mac/mac_util.h"
#include "util/mach/bootstrap.h"
#include "util/mach/child_port_handshake.h"
#include "util/mach/exception_ports.h"
#include "util/mach/mach_extensions.h"
#include "util/mach/mach_message.h"
#include "util/mach/notify_server.h"
#include "util/misc/clock.h"
#include "util/misc/implicit_cast.h"
#include "util/posix/spawn_subprocess.h"

namespace crashpad {

namespace {

std::string FormatArgumentString(const std::string& name,
                                 const std::string& value) {
  return base::StringPrintf("--%s=%s", name.c_str(), value.c_str());
}

std::string FormatArgumentInt(const std::string& name, int value) {
  return base::StringPrintf("--%s=%d", name.c_str(), value);
}

// Set the exception handler for EXC_CRASH, EXC_RESOURCE, and EXC_GUARD.
//
// EXC_CRASH is how most crashes are received. Most other exception types such
// as EXC_BAD_ACCESS are delivered to a host-level exception handler in the
// kernel where they are converted to POSIX signals. See 10.9.5
// xnu-2422.115.4/bsd/uxkern/ux_exception.c catch_mach_exception_raise(). If a
// core-generating signal (triggered through this hardware mechanism or a
// software mechanism such as abort() sending SIGABRT) is unhandled and the
// process exits, or if the process is killed with SIGKILL for code-signing
// reasons, an EXC_CRASH exception will be sent. See 10.9.5
// xnu-2422.115.4/bsd/kern/kern_exit.c proc_prepareexit().
//
// EXC_RESOURCE and EXC_GUARD do not become signals or EXC_CRASH exceptions. The
// host-level exception handler in the kernel does not receive these exception
// types, and even if it did, it would not map them to signals. Instead, the
// first Mach service loaded by the root (process ID 1) launchd with a boolean
// “ExceptionServer” property in its job dictionary (regardless of its value) or
// with any subdictionary property will become the host-level exception handler
// for EXC_CRASH, EXC_RESOURCE, and EXC_GUARD. See 10.9.5
// launchd-842.92.1/src/core.c job_setup_exception_port(). Normally, this job is
// com.apple.ReportCrash.Root, the systemwide Apple Crash Reporter. Since it is
// impossible to receive EXC_RESOURCE and EXC_GUARD exceptions through the
// EXC_CRASH mechanism, an exception handler must be registered for them by name
// if it is to receive these exception types. The default task-level handler for
// these exception types is set by launchd in a similar manner.
//
// EXC_MASK_RESOURCE and EXC_MASK_GUARD are not available on all systems, and
// the kernel will reject attempts to use them if it does not understand them,
// so AND them with ExcMaskValid(). EXC_MASK_CRASH is always supported.
bool SetCrashExceptionPorts(exception_handler_t exception_handler) {
  ExceptionPorts exception_ports(ExceptionPorts::kTargetTypeTask, TASK_NULL);
  return exception_ports.SetExceptionPort(
      (EXC_MASK_CRASH | EXC_MASK_RESOURCE | EXC_MASK_GUARD) & ExcMaskValid(),
      exception_handler,
      EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES,
      MACHINE_THREAD_STATE);
}

class ScopedPthreadAttrDestroy {
 public:
  explicit ScopedPthreadAttrDestroy(pthread_attr_t* pthread_attr)
      : pthread_attr_(pthread_attr) {
  }

  ScopedPthreadAttrDestroy(const ScopedPthreadAttrDestroy&) = delete;
  ScopedPthreadAttrDestroy& operator=(const ScopedPthreadAttrDestroy&) = delete;

  ~ScopedPthreadAttrDestroy() {
    errno = pthread_attr_destroy(pthread_attr_);
    PLOG_IF(WARNING, errno != 0) << "pthread_attr_destroy";
  }

 private:
  pthread_attr_t* pthread_attr_;
};

//! \brief Starts a Crashpad handler, possibly restarting it if it dies.
class HandlerStarter final : public NotifyServer::DefaultInterface {
 public:
  HandlerStarter(const HandlerStarter&) = delete;
  HandlerStarter& operator=(const HandlerStarter&) = delete;

  ~HandlerStarter() {}

  //! \brief Starts a Crashpad handler initially, as opposed to starting it for
  //!     subsequent restarts.
  //!
  //! All parameters are as in CrashpadClient::StartHandler().
  //!
  //! \return On success, a send right to the Crashpad handler that has been
  //!     started. On failure, `MACH_PORT_NULL` with a message logged.
  static base::apple::ScopedMachSendRight InitialStart(
      const base::FilePath& handler,
      const base::FilePath& database,
      const base::FilePath& metrics_dir,
      const std::string& url,
      const std::map<std::string, std::string>& annotations,
      const std::vector<std::string>& arguments,
      bool restartable) {
    base::apple::ScopedMachReceiveRight receive_right(
        NewMachPort(MACH_PORT_RIGHT_RECEIVE));
    if (!receive_right.is_valid()) {
      return base::apple::ScopedMachSendRight();
    }

    mach_port_t port;
    mach_msg_type_name_t right_type;
    kern_return_t kr = mach_port_extract_right(mach_task_self(),
                                               receive_right.get(),
                                               MACH_MSG_TYPE_MAKE_SEND,
                                               &port,
                                               &right_type);
    if (kr != KERN_SUCCESS) {
      MACH_LOG(ERROR, kr) << "mach_port_extract_right";
      return base::apple::ScopedMachSendRight();
    }
    base::apple::ScopedMachSendRight send_right(port);
    DCHECK_EQ(port, receive_right.get());
    DCHECK_EQ(right_type,
              implicit_cast<mach_msg_type_name_t>(MACH_MSG_TYPE_PORT_SEND));

    std::unique_ptr<HandlerStarter> handler_restarter;
    if (restartable) {
      handler_restarter.reset(new HandlerStarter());
      if (!handler_restarter->notify_port_.is_valid()) {
        // This is an error that NewMachPort() would have logged. Proceed anyway
        // without the ability to restart.
        handler_restarter.reset();
      }
    }

    if (!CommonStart(handler,
                     database,
                     metrics_dir,
                     url,
                     annotations,
                     arguments,
                     std::move(receive_right),
                     handler_restarter.get(),
                     false)) {
      return base::apple::ScopedMachSendRight();
    }

    if (handler_restarter &&
        handler_restarter->StartRestartThread(
            handler, database, metrics_dir, url, annotations, arguments)) {
      // The thread owns the object now.
      std::ignore = handler_restarter.release();
    }

    // If StartRestartThread() failed, proceed without the ability to restart.
    // handler_restarter will be released when this function returns.

    return send_right;
  }

  // NotifyServer::DefaultInterface:

  kern_return_t DoMachNotifyPortDestroyed(notify_port_t notify,
                                          mach_port_t rights,
                                          const mach_msg_trailer_t* trailer,
                                          bool* destroy_request) override {
    // The receive right corresponding to this process’ crash exception port is
    // now owned by this process. Any crashes that occur before the receive
    // right is moved to a new handler process will cause the process to hang in
    // an unkillable state prior to OS X 10.10.

    if (notify != notify_port_) {
      LOG(WARNING) << "notify port mismatch";
      return KERN_FAILURE;
    }

    // If CommonStart() fails, the receive right will die, and this will just
    // be called again for another try.
    CommonStart(handler_,
                database_,
                metrics_dir_,
                url_,
                annotations_,
                arguments_,
                base::apple::ScopedMachReceiveRight(rights),
                this,
                true);

    return KERN_SUCCESS;
  }

 private:
  HandlerStarter()
      : NotifyServer::DefaultInterface(),
        handler_(),
        database_(),
        metrics_dir_(),
        url_(),
        annotations_(),
        arguments_(),
        notify_port_(NewMachPort(MACH_PORT_RIGHT_RECEIVE)),
        last_start_time_(0) {
  }

  //! \brief Starts a Crashpad handler.
  //!
  //! All parameters are as in CrashpadClient::StartHandler(), with these
  //! additions:
  //!
  //! \param[in] receive_right The receive right to move to the Crashpad
  //!     handler. The handler will use this receive right to run its exception
  //!     server.
  //! \param[in] handler_restarter If CrashpadClient::StartHandler() was invoked
  //!     with \a restartable set to `true`, this is the restart state object.
  //!     Otherwise, this is `nullptr`.
  //! \param[in] restart If CrashpadClient::StartHandler() was invoked with \a
  //!     restartable set to `true` and CommonStart() is being called to restart
  //!     a previously-started handler, this is `true`. Otherwise, this is
  //!     `false`.
  //!
  //! \return `true` on success, `false` on failure, with a message logged.
  //!     Failures include failure to start the handler process and failure to
  //!     rendezvous with it via ChildPortHandshake.
  static bool CommonStart(const base::FilePath& handler,
                          const base::FilePath& database,
                          const base::FilePath& metrics_dir,
                          const std::string& url,
                          const std::map<std::string, std::string>& annotations,
                          const std::vector<std::string>& arguments,
                          base::apple::ScopedMachReceiveRight receive_right,
                          HandlerStarter* handler_restarter,
                          bool restart) {
    DCHECK(!restart || handler_restarter);

    if (handler_restarter) {
      // The port-destroyed notification must be requested each time. It uses
      // a send-once right, so once the notification is received, it won’t be
      // sent again unless re-requested.
      mach_port_t previous;
      kern_return_t kr =
          mach_port_request_notification(mach_task_self(),
                                         receive_right.get(),
                                         MACH_NOTIFY_PORT_DESTROYED,
                                         0,
                                         handler_restarter->notify_port_.get(),
                                         MACH_MSG_TYPE_MAKE_SEND_ONCE,
                                         &previous);
      if (kr != KERN_SUCCESS) {
        MACH_LOG(WARNING, kr) << "mach_port_request_notification";

        // This will cause the restart thread to terminate after this restart
        // attempt. There’s no longer any need for it, because no more
        // port-destroyed notifications can be delivered.
        handler_restarter->notify_port_.reset();
      } else {
        base::apple::ScopedMachSendRight previous_owner(previous);
        DCHECK(restart || !previous_owner.is_valid());
      }

      if (restart) {
        // If the handler was ever started before, don’t restart it too quickly.
        constexpr uint64_t kNanosecondsPerSecond = 1E9;
        constexpr uint64_t kMinimumStartInterval = 1 * kNanosecondsPerSecond;

        const uint64_t earliest_next_start_time =
            handler_restarter->last_start_time_ + kMinimumStartInterval;
        const uint64_t now_time = ClockMonotonicNanoseconds();
        if (earliest_next_start_time > now_time) {
          const uint64_t sleep_time = earliest_next_start_time - now_time;
          LOG(INFO) << "restarting handler"
                    << base::StringPrintf(" in %.3fs",
                                          static_cast<double>(sleep_time) /
                                              kNanosecondsPerSecond);
          SleepNanoseconds(earliest_next_start_time - now_time);
        } else {
          LOG(INFO) << "restarting handler";
        }
      }

      handler_restarter->last_start_time_ = ClockMonotonicNanoseconds();
    }

    ChildPortHandshake child_port_handshake;
    base::ScopedFD server_write_fd = child_port_handshake.ServerWriteFD();

    // Use handler as argv[0], followed by arguments directed by this method’s
    // parameters and a --handshake-fd argument. |arguments| are added first so
    // that if it erroneously contains an argument such as --url, the actual
    // |url| argument passed to this method will supersede it. In normal
    // command-line processing, the last parameter wins in the case of a
    // conflict.
    std::vector<std::string> argv(1, handler.value());
    argv.reserve(1 + arguments.size() + 2 + annotations.size() + 1);
    for (const std::string& argument : arguments) {
      argv.push_back(argument);
    }
    if (!database.value().empty()) {
      argv.push_back(FormatArgumentString("database", database.value()));
    }
    if (!metrics_dir.value().empty()) {
      argv.push_back(FormatArgumentString("metrics-dir", metrics_dir.value()));
    }
    if (!url.empty()) {
      argv.push_back(FormatArgumentString("url", url));
    }
    for (const auto& kv : annotations) {
      argv.push_back(
          FormatArgumentString("annotation", kv.first + '=' + kv.second));
    }
    argv.push_back(FormatArgumentInt("handshake-fd", server_write_fd.get()));

    // When restarting, reset the system default crash handler first. Otherwise,
    // the crash exception port in the handler will have been inherited from
    // this parent process, which was probably using the exception server now
    // being restarted. The handler can’t monitor itself for its own crashes via
    // this interface.
    if (!SpawnSubprocess(
            argv,
            nullptr,
            server_write_fd.get(),
            true,
            restart ? CrashpadClient::UseSystemDefaultHandler : nullptr)) {
      return false;
    }

    // Close the write side of the pipe, so that the handler process is the only
    // process that can write to it.
    server_write_fd.reset();

    // Rendezvous with the handler running in the grandchild process.
    if (!child_port_handshake.RunClient(receive_right.get(),
                                        MACH_MSG_TYPE_MOVE_RECEIVE)) {
      return false;
    }

    std::ignore = receive_right.release();
    return true;
  }

  bool StartRestartThread(const base::FilePath& handler,
                          const base::FilePath& database,
                          const base::FilePath& metrics_dir,
                          const std::string& url,
                          const std::map<std::string, std::string>& annotations,
                          const std::vector<std::string>& arguments) {
    handler_ = handler;
    database_ = database;
    metrics_dir_ = metrics_dir;
    url_ = url;
    annotations_ = annotations;
    arguments_ = arguments;

    pthread_attr_t pthread_attr;
    errno = pthread_attr_init(&pthread_attr);
    if (errno != 0) {
      PLOG(WARNING) << "pthread_attr_init";
      return false;
    }
    ScopedPthreadAttrDestroy pthread_attr_owner(&pthread_attr);

    errno = pthread_attr_setdetachstate(&pthread_attr, PTHREAD_CREATE_DETACHED);
    if (errno != 0) {
      PLOG(WARNING) << "pthread_attr_setdetachstate";
      return false;
    }

    pthread_t pthread;
    errno = pthread_create(&pthread, &pthread_attr, RestartThreadMain, this);
    if (errno != 0) {
      PLOG(WARNING) << "pthread_create";
      return false;
    }

    return true;
  }

  static void* RestartThreadMain(void* argument) {
    HandlerStarter* self = reinterpret_cast<HandlerStarter*>(argument);

    NotifyServer notify_server(self);
    mach_msg_return_t mr;
    do {
      mr = MachMessageServer::Run(&notify_server,
                                  self->notify_port_.get(),
                                  0,
                                  MachMessageServer::kPersistent,
                                  MachMessageServer::kReceiveLargeError,
                                  kMachMessageTimeoutWaitIndefinitely);
      MACH_LOG_IF(ERROR, mr != MACH_MSG_SUCCESS, mr)
          << "MachMessageServer::Run";
    } while (self->notify_port_.is_valid() && mr == MACH_MSG_SUCCESS);

    delete self;

    return nullptr;
  }

  base::FilePath handler_;
  base::FilePath database_;
  base::FilePath metrics_dir_;
  std::string url_;
  std::map<std::string, std::string> annotations_;
  std::vector<std::string> arguments_;
  base::apple::ScopedMachReceiveRight notify_port_;
  uint64_t last_start_time_;
};

}  // namespace

CrashpadClient::CrashpadClient() : exception_port_(MACH_PORT_NULL) {
}

CrashpadClient::~CrashpadClient() {
}

bool CrashpadClient::StartHandler(
    const base::FilePath& handler,
    const base::FilePath& database,
    const base::FilePath& metrics_dir,
    const std::string& url,
    const std::map<std::string, std::string>& annotations,
    const std::vector<std::string>& arguments,
    bool restartable,
    bool asynchronous_start,
    const std::vector<base::FilePath>& attachments) {
  // Attachments are not implemented on MacOS yet.
  DCHECK(attachments.empty());

  // The “restartable” behavior can only be selected on OS X 10.10 and later. In
  // previous OS versions, if the initial client were to crash while attempting
  // to restart the handler, it would become an unkillable process.
  base::apple::ScopedMachSendRight exception_port(HandlerStarter::InitialStart(
      handler,
      database,
      metrics_dir,
      url,
      annotations,
      arguments,
      restartable && (__MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_10 ||
                      MacOSVersionNumber() >= 10'10'00)));
  if (!exception_port.is_valid()) {
    return false;
  }

  SetHandlerMachPort(std::move(exception_port));
  return true;
}

bool CrashpadClient::SetHandlerMachService(const std::string& service_name) {
  base::apple::ScopedMachSendRight exception_port(
      BootstrapLookUp(service_name));
  if (!exception_port.is_valid()) {
    return false;
  }

  SetHandlerMachPort(std::move(exception_port));
  return true;
}

bool CrashpadClient::SetHandlerMachPort(
    base::apple::ScopedMachSendRight exception_port) {
  DCHECK(!exception_port_.is_valid());
  DCHECK(exception_port.is_valid());

  if (!SetCrashExceptionPorts(exception_port.get())) {
    return false;
  }

  exception_port_.swap(exception_port);
  return true;
}

base::apple::ScopedMachSendRight CrashpadClient::GetHandlerMachPort() const {
  DCHECK(exception_port_.is_valid());

  // For the purposes of this method, only return a port set by
  // SetHandlerMachPort().
  //
  // It would be possible to use task_get_exception_ports() to look up the
  // EXC_CRASH task exception port, but that’s probably not what users of this
  // interface really want. If CrashpadClient is asked for the handler Mach
  // port, it should only return a port that it knows about by virtue of having
  // set it. It shouldn’t return any EXC_CRASH task exception port in effect if
  // SetHandlerMachPort() was never called, and it shouldn’t return any
  // EXC_CRASH task exception port that might be set by other code after
  // SetHandlerMachPort() is called.
  //
  // The caller is accepting its own new ScopedMachSendRight, so increment the
  // reference count of the underlying right.
  kern_return_t kr = mach_port_mod_refs(
      mach_task_self(), exception_port_.get(), MACH_PORT_RIGHT_SEND, 1);
  if (kr != KERN_SUCCESS) {
    MACH_LOG(ERROR, kr) << "mach_port_mod_refs";
    return base::apple::ScopedMachSendRight(MACH_PORT_NULL);
  }

  return base::apple::ScopedMachSendRight(exception_port_.get());
}

// static
void CrashpadClient::UseSystemDefaultHandler() {
  base::apple::ScopedMachSendRight system_crash_reporter_handler(
      SystemCrashReporterHandler());

  // Proceed even if SystemCrashReporterHandler() failed, setting MACH_PORT_NULL
  // to clear the current exception ports.
  if (!SetCrashExceptionPorts(system_crash_reporter_handler.get())) {
    SetCrashExceptionPorts(MACH_PORT_NULL);
  }
}

}  // namespace crashpad
