// 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 <errno.h>
#include <getopt.h>
#include <libgen.h>
#include <mach/mach.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>

#include <string>
#include <vector>

#include "base/apple/mach_logging.h"
#include "base/apple/scoped_mach_port.h"
#include "tools/tool_support.h"
#include "util/mach/bootstrap.h"
#include "util/mach/exception_ports.h"
#include "util/mach/mach_extensions.h"
#include "util/mach/symbolic_constants_mach.h"
#include "util/mach/task_for_pid.h"
#include "util/posix/drop_privileges.h"
#include "util/stdlib/string_number_conversion.h"

namespace crashpad {
namespace {

//! \brief Manages a pool of Mach send rights, deallocating all send rights upon
//!     destruction.
//!
//! This class effectively implements what a vector of
//! base::apple::ScopedMachSendRight objects would be.
//!
//! The various “show” operations performed by this program display Mach ports
//! by their names as they are known in this task. For this to be useful, rights
//! to the same ports must have consistent names across successive calls. This
//! cannot be guaranteed if the rights are deallocated as soon as they are used,
//! because if that deallocation causes the task to lose its last right to a
//! port, subsequently regaining a right to the same port would cause it to be
//! known by a new name in this task.
//!
//! Instead of immediately deallocating send rights that are used for display,
//! they can be added to this pool. The pool collects send rights, ensuring that
//! they remain alive in this task, and that subsequent calls that obtain the
//! same rights cause them to be known by the same name. All rights are
//! deallocated upon destruction.
class MachSendRightPool {
 public:
  MachSendRightPool()
      : send_rights_() {
  }

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

  ~MachSendRightPool() {
    for (mach_port_t send_right : send_rights_) {
      kern_return_t kr = mach_port_deallocate(mach_task_self(), send_right);
      MACH_LOG_IF(ERROR, kr != KERN_SUCCESS, kr) << "mach_port_deallocate";
    }
  }

  //! \brief Adds a send right to the pool.
  //!
  //! \param[in] send_right The send right to be added. The pool object takes
  //!     its own reference to the send right, which remains valid until the
  //!     pool object is destroyed. The caller remains responsible for its
  //!     reference to the send right.
  //!
  //! It is possible and in fact likely that one pool will wind up owning the
  //! same send right multiple times. This is acceptable, because send rights
  //! are reference-counted.
  void AddSendRight(mach_port_t send_right) {
    kern_return_t kr = mach_port_mod_refs(mach_task_self(),
                                          send_right,
                                          MACH_PORT_RIGHT_SEND,
                                          1);
    MACH_CHECK(kr == KERN_SUCCESS, kr) << "mach_port_mod_refs";

    send_rights_.push_back(send_right);
  }

 private:
  std::vector<mach_port_t> send_rights_;
};

struct ExceptionHandlerDescription {
  ExceptionPorts::TargetType target_type;
  exception_mask_t mask;
  exception_behavior_t behavior;
  thread_state_flavor_t flavor;
  std::string handler;
};

constexpr char kHandlerNull[] = "NULL";
constexpr char kHandlerBootstrapColon[] = "bootstrap:";

// Populates |description| based on a textual representation in
// |handler_string_ro|, returning true on success and false on failure (parse
// error). The --help string describes the format of |handler_string_ro|.
// Briefly, it is a comma-separated string that allows the members of
// |description| to be specified as "field=value". Values for "target" can be
// "host", "task", or "thread"; values for "handler" are of the form
// "bootstrap:service_name" where service_name will be looked up with the
// bootstrap server; and values for the other fields are interpreted by
// SymbolicConstantsMach.
bool ParseHandlerString(const char* handler_string_ro,
                        ExceptionHandlerDescription* description) {
  static constexpr char kTargetEquals[] = "target=";
  static constexpr char kMaskEquals[] = "mask=";
  static constexpr char kBehaviorEquals[] = "behavior=";
  static constexpr char kFlavorEquals[] = "flavor=";
  static constexpr char kHandlerEquals[] = "handler=";

  std::string handler_string(handler_string_ro);
  char* handler_string_c = &handler_string[0];

  char* token;
  while ((token = strsep(&handler_string_c, ",")) != nullptr) {
    if (strncmp(token, kTargetEquals, strlen(kTargetEquals)) == 0) {
      const char* value = token + strlen(kTargetEquals);
      if (strcmp(value, "host") == 0) {
        description->target_type = ExceptionPorts::kTargetTypeHost;
      } else if (strcmp(value, "task") == 0) {
        description->target_type = ExceptionPorts::kTargetTypeTask;
      } else if (strcmp(value, "thread") == 0) {
        description->target_type = ExceptionPorts::kTargetTypeThread;
      } else {
        return false;
      }
    } else if (strncmp(token, kMaskEquals, strlen(kMaskEquals)) == 0) {
      const char* value = token + strlen(kMaskEquals);
      if (!StringToExceptionMask(
              value,
              kAllowFullName | kAllowShortName | kAllowNumber | kAllowOr,
              &description->mask)) {
        return false;
      }
    } else if (strncmp(token, kBehaviorEquals, strlen(kBehaviorEquals)) == 0) {
      const char* value = token + strlen(kBehaviorEquals);
      if (!StringToExceptionBehavior(
              value,
              kAllowFullName | kAllowShortName | kAllowNumber,
              &description->behavior)) {
        return false;
      }
    } else if (strncmp(token, kFlavorEquals, strlen(kFlavorEquals)) == 0) {
      const char* value = token + strlen(kFlavorEquals);
      if (!StringToThreadStateFlavor(
              value,
              kAllowFullName | kAllowShortName | kAllowNumber,
              &description->flavor)) {
        return false;
      }
    } else if (strncmp(token, kHandlerEquals, strlen(kHandlerEquals)) == 0) {
      const char* value = token + strlen(kHandlerEquals);
      if (strcmp(value, kHandlerNull) != 0 &&
          strncmp(value,
                  kHandlerBootstrapColon,
                  strlen(kHandlerBootstrapColon)) != 0) {
        return false;
      }
      description->handler = std::string(value);
    } else {
      return false;
    }
  }

  return true;
}

// ShowExceptionPorts() shows handlers as numeric mach_port_t values, which are
// opaque and meaningless on their own. ShowBootstrapService() can be used to
// look up a service with the bootstrap server by name and show its mach_port_t
// value, which can then be associated with handlers shown by
// ShowExceptionPorts(). Any send rights obtained by this function are added to
// |mach_send_right_pool|.
void ShowBootstrapService(const std::string& service_name,
                          MachSendRightPool* mach_send_right_pool) {
  base::apple::ScopedMachSendRight service_port(BootstrapLookUp(service_name));
  if (service_port == kMachPortNull) {
    return;
  }

  mach_send_right_pool->AddSendRight(service_port.get());

  printf("service %s %#x\n", service_name.c_str(), service_port.get());
}

// Prints information about all exception ports known for |exception_ports|. If
// |numeric| is true, all information is printed in numeric form, otherwise, it
// will be converted to symbolic constants where possible by
// SymbolicConstantsMach. If |is_new| is true, information will be presented as
// “new exception ports”, indicating that they show the state of the exception
// ports after SetExceptionPort() has been called. Any send rights obtained by
// this function are added to |mach_send_right_pool|.
void ShowExceptionPorts(const ExceptionPorts& exception_ports,
                        bool numeric,
                        bool is_new,
                        MachSendRightPool* mach_send_right_pool) {
  const char* target_name = exception_ports.TargetTypeName();

  ExceptionPorts::ExceptionHandlerVector handlers;
  if (!exception_ports.GetExceptionPorts(ExcMaskValid(), &handlers)) {
    return;
  }

  const char* age_name = is_new ? "new " : "";

  if (handlers.empty()) {
    printf("no %s%s exception ports\n", age_name, target_name);
  }

  for (size_t port_index = 0; port_index < handlers.size(); ++port_index) {
    mach_send_right_pool->AddSendRight(handlers[port_index].port);

    if (numeric) {
      printf(
          "%s%s exception port %zu, mask %#x, port %#x, "
          "behavior %#x, flavor %u\n",
          age_name,
          target_name,
          port_index,
          handlers[port_index].mask,
          handlers[port_index].port,
          handlers[port_index].behavior,
          handlers[port_index].flavor);
    } else {
      std::string mask_string = ExceptionMaskToString(
          handlers[port_index].mask, kUseShortName | kUnknownIsEmpty | kUseOr);
      if (mask_string.empty()) {
        mask_string.assign("?");
      }

      std::string behavior_string = ExceptionBehaviorToString(
          handlers[port_index].behavior, kUseShortName | kUnknownIsEmpty);
      if (behavior_string.empty()) {
        behavior_string.assign("?");
      }

      std::string flavor_string = ThreadStateFlavorToString(
          handlers[port_index].flavor, kUseShortName | kUnknownIsEmpty);
      if (flavor_string.empty()) {
        flavor_string.assign("?");
      }

      printf(
          "%s%s exception port %zu, mask %#x (%s), port %#x, "
          "behavior %#x (%s), flavor %u (%s)\n",
          age_name,
          target_name,
          port_index,
          handlers[port_index].mask,
          mask_string.c_str(),
          handlers[port_index].port,
          handlers[port_index].behavior,
          behavior_string.c_str(),
          handlers[port_index].flavor,
          flavor_string.c_str());
    }
  }
}

// Sets the exception port for |target_port|, a send right to a thread, task, or
// host port, to |description|, which identifies what type of port |target_port|
// is and describes an exception port to be set. Returns true on success.
//
// This function may be called more than once if setting different handlers is
// desired.
bool SetExceptionPort(const ExceptionHandlerDescription* description,
                      mach_port_t target_port) {
  base::apple::ScopedMachSendRight service_port;
  if (description->handler.compare(
          0, strlen(kHandlerBootstrapColon), kHandlerBootstrapColon) == 0) {
    const char* service_name =
        description->handler.c_str() + strlen(kHandlerBootstrapColon);
    service_port = BootstrapLookUp(service_name);
    if (service_port == kMachPortNull) {
      return false;
    }

    // The service port doesn’t need to be added to a MachSendRightPool because
    // it’s not used for display at all. ScopedMachSendRight is sufficient.
  } else if (description->handler != kHandlerNull) {
    return false;
  }

  ExceptionPorts exception_ports(description->target_type, target_port);
  if (!exception_ports.SetExceptionPort(description->mask,
                                        service_port.get(),
                                        description->behavior,
                                        description->flavor)) {
    return false;
  }

  return true;
}

void Usage(const std::string& me) {
  // clang-format off
  fprintf(stderr,
"Usage: %s [OPTION]... [COMMAND [ARG]...]\n"
"View and change Mach exception ports, and run COMMAND if supplied.\n"
"\n"
"  -s, --set-handler=DESCRIPTION  set an exception port to DESCRIPTION, see below\n"
"      --show-bootstrap=SERVICE   look up and display a service registered with\n"
"                                 the bootstrap server\n"
"  -p, --pid=PID                  operate on PID instead of the current task\n"
"  -h, --show-host                display original host exception ports\n"
"  -t, --show-task                display original task exception ports\n"
"      --show-thread              display original thread exception ports\n"
"  -H, --show-new-host            display modified host exception ports\n"
"  -T, --show-new-task            display modified task exception ports\n"
"      --show-new-thread          display modified thread exception ports\n"
"  -n, --numeric                  display values numerically, not symbolically\n"
"      --help                     display this help and exit\n"
"      --version                  output version information and exit\n"
"\n"
"Any operations on host exception ports require superuser permissions.\n"
"\n"
"DESCRIPTION is formatted as a comma-separated sequence of tokens, where each\n"
"token consists of a key and value separated by an equals sign. Available keys:\n"
"  target    which target's exception ports to set: host, task, or thread\n"
"  mask      the mask of exception types to handle: CRASH, ALL, or others\n"
"  behavior  the specific exception handler routine to call: DEFAULT, STATE,\n"
"            or STATE_IDENTITY, possibly with MACH_EXCEPTION_CODES.\n"
"  flavor    the thread state flavor passed to the handler: architecture-specific\n"
"  handler   the exception handler: NULL or bootstrap:SERVICE, indicating that\n"
"            the handler should be looked up with the bootstrap server\n"
"The default DESCRIPTION is\n"
"  target=task,mask=CRASH,behavior=DEFAULT|MACH,flavor=NONE,handler=NULL\n",
          me.c_str());
  // clang-format on
  ToolSupport::UsageTail(me);
}

int ExceptionPortToolMain(int argc, char* argv[]) {
  const std::string me(basename(argv[0]));

  enum ExitCode {
    kExitSuccess = EXIT_SUCCESS,

    // To differentiate this tool’s errors from errors in the programs it execs,
    // use a high exit code for ordinary failures instead of EXIT_FAILURE. This
    // is the same rationale for using the distinct exit codes for exec
    // failures.
    kExitFailure = 125,

    // Like env, use exit code 126 if the program was found but could not be
    // invoked, and 127 if it could not be found.
    // http://pubs.opengroup.org/onlinepubs/9699919799/utilities/env.html
    kExitExecFailure = 126,
    kExitExecENOENT = 127,
  };

  enum OptionFlags {
    // “Short” (single-character) options.
    kOptionSetPort = 's',
    kOptionPid = 'p',
    kOptionShowHost = 'h',
    kOptionShowTask = 't',
    kOptionShowNewHost = 'H',
    kOptionShowNewTask = 'T',
    kOptionNumeric = 'n',

    // Long options without short equivalents.
    kOptionLastChar = 255,
    kOptionShowBootstrap,
    kOptionShowThread,
    kOptionShowNewThread,

    // Standard options.
    kOptionHelp = -2,
    kOptionVersion = -3,
  };

  struct {
    std::vector<const char*> show_bootstrap;
    std::vector<ExceptionHandlerDescription> set_handler;
    pid_t pid;
    task_t alternate_task;
    bool show_host;
    bool show_task;
    bool show_thread;
    bool show_new_host;
    bool show_new_task;
    bool show_new_thread;
    bool numeric;
  } options = {};

  static constexpr option long_options[] = {
      {"set-handler", required_argument, nullptr, kOptionSetPort},
      {"show-bootstrap", required_argument, nullptr, kOptionShowBootstrap},
      {"pid", required_argument, nullptr, kOptionPid},
      {"show-host", no_argument, nullptr, kOptionShowHost},
      {"show-task", no_argument, nullptr, kOptionShowTask},
      {"show-thread", no_argument, nullptr, kOptionShowThread},
      {"show-new-host", no_argument, nullptr, kOptionShowNewHost},
      {"show-new-task", no_argument, nullptr, kOptionShowNewTask},
      {"show-new-thread", no_argument, nullptr, kOptionShowNewThread},
      {"numeric", no_argument, nullptr, kOptionNumeric},
      {"help", no_argument, nullptr, kOptionHelp},
      {"version", no_argument, nullptr, kOptionVersion},
      {nullptr, 0, nullptr, 0},
  };

  int opt;
  while ((opt = getopt_long(argc, argv, "+s:p:htHTn", long_options, nullptr)) !=
         -1) {
    switch (opt) {
      case kOptionSetPort: {
        options.set_handler.push_back({});
        ExceptionHandlerDescription* description = &options.set_handler.back();
        description->target_type = ExceptionPorts::kTargetTypeTask;
        description->mask = EXC_MASK_CRASH;
        description->behavior = EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES;
        description->flavor = THREAD_STATE_NONE;
        description->handler = "NULL";
        if (!ParseHandlerString(optarg, description)) {
          fprintf(stderr,
                  "%s: invalid exception handler: %s\n",
                  me.c_str(),
                  optarg);
          return kExitFailure;
        }
        break;
      }
      case kOptionShowBootstrap:
        options.show_bootstrap.push_back(optarg);
        break;
      case kOptionPid:
        if (!StringToNumber(optarg, &options.pid)) {
          fprintf(stderr, "%s: invalid pid: %s\n", me.c_str(), optarg);
          return kExitFailure;
        }
        break;
      case kOptionShowHost:
        options.show_host = true;
        break;
      case kOptionShowTask:
        options.show_task = true;
        break;
      case kOptionShowThread:
        options.show_thread = true;
        break;
      case kOptionShowNewHost:
        options.show_new_host = true;
        break;
      case kOptionShowNewTask:
        options.show_new_task = true;
        break;
      case kOptionShowNewThread:
        options.show_new_thread = true;
        break;
      case kOptionNumeric:
        options.numeric = true;
        break;
      case kOptionHelp:
        Usage(me);
        return kExitSuccess;
      case kOptionVersion:
        ToolSupport::Version(me);
        return kExitSuccess;
      default:
        ToolSupport::UsageHint(me, nullptr);
        return kExitFailure;
    }
  }
  argc -= optind;
  argv += optind;

  if (options.show_bootstrap.empty() && !options.show_host &&
      !options.show_task && !options.show_thread &&
      options.set_handler.empty() && argc == 0) {
    ToolSupport::UsageHint(me, "nothing to do");
    return kExitFailure;
  }

  base::apple::ScopedMachSendRight alternate_task_owner;
  if (options.pid) {
    if (argc) {
      ToolSupport::UsageHint(me, "cannot combine -p with COMMAND");
      return kExitFailure;
    }

    options.alternate_task = TaskForPID(options.pid);
    if (options.alternate_task == TASK_NULL) {
      return kExitFailure;
    }
    alternate_task_owner.reset(options.alternate_task);
  }

  // This tool may have been installed as a setuid binary so that TaskForPID()
  // could succeed. Drop any privileges now that they’re no longer necessary.
  DropPrivileges();

  MachSendRightPool mach_send_right_pool;

  // Show bootstrap services requested.
  for (const char* service : options.show_bootstrap) {
    ShowBootstrapService(service, &mach_send_right_pool);
  }

  // Show the original exception ports.
  if (options.show_host) {
    ShowExceptionPorts(
        ExceptionPorts(ExceptionPorts::kTargetTypeHost, HOST_NULL),
        options.numeric,
        false,
        &mach_send_right_pool);
  }
  if (options.show_task) {
    ShowExceptionPorts(
        ExceptionPorts(ExceptionPorts::kTargetTypeTask, options.alternate_task),
        options.numeric,
        false,
        &mach_send_right_pool);
  }
  if (options.show_thread) {
    ShowExceptionPorts(
        ExceptionPorts(ExceptionPorts::kTargetTypeThread, THREAD_NULL),
        options.numeric,
        false,
        &mach_send_right_pool);
  }

  if (!options.set_handler.empty()) {
    // Set new exception handlers.
    for (ExceptionHandlerDescription description : options.set_handler) {
      if (!SetExceptionPort(
              &description,
              description.target_type == ExceptionPorts::kTargetTypeTask
                  ? options.alternate_task
                  : TASK_NULL)) {
        return kExitFailure;
      }
    }

    // Show changed exception ports.
    if (options.show_new_host) {
      ShowExceptionPorts(
          ExceptionPorts(ExceptionPorts::kTargetTypeHost, HOST_NULL),
          options.numeric,
          true,
          &mach_send_right_pool);
    }
    if (options.show_new_task) {
      ShowExceptionPorts(
          ExceptionPorts(ExceptionPorts::kTargetTypeTask,
                         options.alternate_task),
          options.numeric,
          true,
          &mach_send_right_pool);
    }
    if (options.show_new_thread) {
      ShowExceptionPorts(
          ExceptionPorts(ExceptionPorts::kTargetTypeThread, THREAD_NULL),
          options.numeric,
          true,
          &mach_send_right_pool);
    }
  }

  if (argc) {
    // Using the remaining arguments, start a new program with the new set of
    // exception ports in effect.
    execvp(argv[0], argv);
    PLOG(ERROR) << "execvp " << argv[0];
    return errno == ENOENT ? kExitExecENOENT : kExitExecFailure;
  }

  return kExitSuccess;
}

}  // namespace
}  // namespace crashpad

int main(int argc, char* argv[]) {
  return crashpad::ExceptionPortToolMain(argc, argv);
}
