// Copyright 2017 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 "handler/linux/exception_handler_server.h"

#include <errno.h>
#include <linux/capability.h>
#include <sys/epoll.h>
#include <sys/eventfd.h>
#include <sys/socket.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>

#include <utility>

#include "base/check_op.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/posix/eintr_wrapper.h"
#include "base/strings/string_number_conversions.h"
#include "build/build_config.h"
#include "util/file/file_io.h"
#include "util/file/filesystem.h"
#include "util/linux/proc_task_reader.h"
#include "util/linux/socket.h"
#include "util/misc/as_underlying_type.h"

namespace crashpad {

namespace {

// Log an error for a socket after an EPOLLERR.
void LogSocketError(int sock) {
  int err;
  socklen_t err_len = sizeof(err);
  if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &err, &err_len) != 0) {
    PLOG(ERROR) << "getsockopt";
  } else {
    errno = err;
    PLOG(ERROR) << "EPOLLERR";
  }
}

enum class PtraceScope {
  kClassic = 0,
  kRestricted,
  kAdminOnly,
  kNoAttach,
  kUnknown
};

PtraceScope GetPtraceScope() {
  const base::FilePath settings_file("/proc/sys/kernel/yama/ptrace_scope");
  if (!IsRegularFile(base::FilePath(settings_file))) {
    return PtraceScope::kClassic;
  }

  std::string contents;
  if (!LoggingReadEntireFile(settings_file, &contents)) {
    return PtraceScope::kUnknown;
  }

  if (contents.back() != '\n') {
    LOG(ERROR) << "format error";
    return PtraceScope::kUnknown;
  }
  contents.pop_back();

  int ptrace_scope;
  if (!base::StringToInt(contents, &ptrace_scope)) {
    LOG(ERROR) << "format error";
    return PtraceScope::kUnknown;
  }

  if (ptrace_scope < static_cast<int>(PtraceScope::kClassic) ||
      ptrace_scope >= static_cast<int>(PtraceScope::kUnknown)) {
    LOG(ERROR) << "invalid ptrace scope";
    return PtraceScope::kUnknown;
  }

  return static_cast<PtraceScope>(ptrace_scope);
}

bool HaveCapSysPtrace() {
  __user_cap_header_struct cap_header;
  cap_header.pid = getpid();
  cap_header.version = _LINUX_CAPABILITY_VERSION_3;

  __user_cap_data_struct cap_data[_LINUX_CAPABILITY_U32S_3];
  if (syscall(SYS_capget, &cap_header, &cap_data) != 0) {
    PLOG(ERROR) << "capget";
    LOG_IF(ERROR, errno == EINVAL) << "cap_header.version " << std::hex
                                   << cap_header.version;
    return false;
  }

  return (cap_data[CAP_TO_INDEX(CAP_SYS_PTRACE)].effective &
          CAP_TO_MASK(CAP_SYS_PTRACE)) != 0;
}

bool SendMessageToClient(
    int client_sock,
    ExceptionHandlerProtocol::ServerToClientMessage::Type type) {
  ExceptionHandlerProtocol::ServerToClientMessage message = {};
  message.type = type;
  if (type ==
      ExceptionHandlerProtocol::ServerToClientMessage::kTypeSetPtracer) {
    message.pid = getpid();
  }
  return LoggingWriteFile(client_sock, &message, sizeof(message));
}

int tgkill(pid_t pid, pid_t tid, int signo) {
  return syscall(SYS_tgkill, pid, tid, signo);
}

void SendSIGCONT(pid_t pid, pid_t tid) {
  if (tid > 0) {
    if (tgkill(pid, tid, ExceptionHandlerProtocol::kDumpDoneSignal) != 0) {
      PLOG(ERROR) << "tgkill";
    }
    return;
  }

  std::vector<pid_t> threads;
  if (!ReadThreadIDs(pid, &threads)) {
    return;
  }
  for (const auto& thread : threads) {
    if (tgkill(pid, thread, ExceptionHandlerProtocol::kDumpDoneSignal) != 0) {
      PLOG(ERROR) << "tgkill";
    }
  }
}

bool SendCredentials(int client_sock) {
  ExceptionHandlerProtocol::ServerToClientMessage message = {};
  message.type =
      ExceptionHandlerProtocol::ServerToClientMessage::kTypeCredentials;
  return UnixCredentialSocket::SendMsg(
             client_sock, &message, sizeof(message)) == 0;
}

class PtraceStrategyDeciderImpl : public PtraceStrategyDecider {
 public:
  PtraceStrategyDeciderImpl() : PtraceStrategyDecider() {}
  ~PtraceStrategyDeciderImpl() = default;

  Strategy ChooseStrategy(int sock,
                          bool multiple_clients,
                          const ucred& client_credentials) override {
    if (client_credentials.pid <= 0) {
      LOG(ERROR) << "invalid credentials";
      return Strategy::kNoPtrace;
    }

    switch (GetPtraceScope()) {
      case PtraceScope::kClassic:
        if (getuid() == client_credentials.uid || HaveCapSysPtrace()) {
          return Strategy::kDirectPtrace;
        }
        return multiple_clients ? Strategy::kNoPtrace : TryForkingBroker(sock);

      case PtraceScope::kRestricted:
        if (multiple_clients) {
          return Strategy::kDirectPtrace;
        }
        if (!SendMessageToClient(sock,
                                 ExceptionHandlerProtocol::
                                     ServerToClientMessage::kTypeSetPtracer)) {
          return Strategy::kError;
        }

        ExceptionHandlerProtocol::Errno status;
        if (!LoggingReadFileExactly(sock, &status, sizeof(status))) {
          return Strategy::kError;
        }

        if (status != 0) {
          errno = status;
          PLOG(ERROR) << "Handler Client SetPtracer";
          return TryForkingBroker(sock);
        }
        return Strategy::kDirectPtrace;

      case PtraceScope::kAdminOnly:
        if (HaveCapSysPtrace()) {
          return Strategy::kDirectPtrace;
        }
        [[fallthrough]];
      case PtraceScope::kNoAttach:
        LOG(WARNING) << "no ptrace";
        return Strategy::kNoPtrace;

      case PtraceScope::kUnknown:
        LOG(WARNING) << "Unknown ptrace scope";
        return Strategy::kError;
    }

    DCHECK(false);
    return Strategy::kError;
  }

 private:
  static Strategy TryForkingBroker(int client_sock) {
    if (!SendMessageToClient(
            client_sock,
            ExceptionHandlerProtocol::ServerToClientMessage::kTypeForkBroker)) {
      return Strategy::kError;
    }

    ExceptionHandlerProtocol::Errno status;
    if (!LoggingReadFileExactly(client_sock, &status, sizeof(status))) {
      return Strategy::kError;
    }

    if (status != 0) {
      errno = status;
      PLOG(ERROR) << "Handler Client ForkBroker";
      return Strategy::kNoPtrace;
    }
    return Strategy::kUseBroker;
  }
};

}  // namespace

ExceptionHandlerServer::ExceptionHandlerServer()
    : clients_(),
      shutdown_event_(),
      strategy_decider_(new PtraceStrategyDeciderImpl()),
      delegate_(nullptr),
      pollfd_(),
      keep_running_(true) {}

ExceptionHandlerServer::~ExceptionHandlerServer() = default;

void ExceptionHandlerServer::SetPtraceStrategyDecider(
    std::unique_ptr<PtraceStrategyDecider> decider) {
  strategy_decider_ = std::move(decider);
}

bool ExceptionHandlerServer::InitializeWithClient(ScopedFileHandle sock,
                                                  bool multiple_clients) {
  INITIALIZATION_STATE_SET_INITIALIZING(initialized_);

  pollfd_.reset(epoll_create1(EPOLL_CLOEXEC));
  if (!pollfd_.is_valid()) {
    PLOG(ERROR) << "epoll_create1";
    return false;
  }

  shutdown_event_ = std::make_unique<Event>();
  shutdown_event_->type = Event::Type::kShutdown;
  shutdown_event_->fd.reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
  if (!shutdown_event_->fd.is_valid()) {
    PLOG(ERROR) << "eventfd";
    return false;
  }

  epoll_event poll_event;
  poll_event.events = EPOLLIN;
  poll_event.data.ptr = shutdown_event_.get();
  if (epoll_ctl(pollfd_.get(),
                EPOLL_CTL_ADD,
                shutdown_event_->fd.get(),
                &poll_event) != 0) {
    PLOG(ERROR) << "epoll_ctl";
    return false;
  }

  if (!InstallClientSocket(std::move(sock),
                           multiple_clients ? Event::Type::kSharedSocketMessage
                                            : Event::Type::kClientMessage)) {
    return false;
  }

  INITIALIZATION_STATE_SET_VALID(initialized_);
  return true;
}

void ExceptionHandlerServer::Run(Delegate* delegate) {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  delegate_ = delegate;

  while (keep_running_ && clients_.size() > 0) {
    epoll_event poll_event;
    int res = HANDLE_EINTR(epoll_wait(pollfd_.get(), &poll_event, 1, -1));
    if (res < 0) {
      PLOG(ERROR) << "epoll_wait";
      return;
    }
    DCHECK_EQ(res, 1);

    Event* eventp = reinterpret_cast<Event*>(poll_event.data.ptr);
    if (eventp->type == Event::Type::kShutdown) {
      if (poll_event.events & EPOLLERR) {
        LogSocketError(eventp->fd.get());
      }
      keep_running_ = false;
    } else {
      HandleEvent(eventp, poll_event.events);
    }
  }
}

void ExceptionHandlerServer::Stop() {
  keep_running_ = false;
  if (shutdown_event_ && shutdown_event_->fd.is_valid()) {
    uint64_t value = 1;
    LoggingWriteFile(shutdown_event_->fd.get(), &value, sizeof(value));
  }
}

void ExceptionHandlerServer::HandleEvent(Event* event, uint32_t event_type) {
  DCHECK_NE(AsUnderlyingType(event->type),
            AsUnderlyingType(Event::Type::kShutdown));

  if (event_type & EPOLLERR) {
    LogSocketError(event->fd.get());
    UninstallClientSocket(event);
    return;
  }

  if (event_type & EPOLLIN) {
    if (!ReceiveClientMessage(event)) {
      UninstallClientSocket(event);
    }
    return;
  }

  if (event_type & EPOLLHUP || event_type & EPOLLRDHUP) {
    UninstallClientSocket(event);
    return;
  }

  LOG(ERROR) << "Unexpected event 0x" << std::hex << event_type;
  return;
}

bool ExceptionHandlerServer::InstallClientSocket(ScopedFileHandle socket,
                                                 Event::Type type) {
  // The handler may not have permission to set SO_PASSCRED on the socket, but
  // it doesn't need to if the client has already set it.
  // https://bugs.chromium.org/p/crashpad/issues/detail?id=252
  int optval;
  socklen_t optlen = sizeof(optval);
  if (getsockopt(socket.get(), SOL_SOCKET, SO_PASSCRED, &optval, &optlen) !=
      0) {
    PLOG(ERROR) << "getsockopt";
    return false;
  }
  if (!optval) {
    optval = 1;
    optlen = sizeof(optval);
    if (setsockopt(socket.get(), SOL_SOCKET, SO_PASSCRED, &optval, optlen) !=
        0) {
      PLOG(ERROR) << "setsockopt";
      return false;
    }
  }

  auto event = std::make_unique<Event>();
  event->type = type;
  event->fd.reset(socket.release());

  Event* eventp = event.get();

  if (!clients_.insert(std::make_pair(event->fd.get(), std::move(event)))
           .second) {
    LOG(ERROR) << "duplicate descriptor";
    return false;
  }

  epoll_event poll_event;
  poll_event.events = EPOLLIN | EPOLLRDHUP;
  poll_event.data.ptr = eventp;

  if (epoll_ctl(pollfd_.get(), EPOLL_CTL_ADD, eventp->fd.get(), &poll_event) !=
      0) {
    PLOG(ERROR) << "epoll_ctl";
    clients_.erase(eventp->fd.get());
    return false;
  }

  return true;
}

bool ExceptionHandlerServer::UninstallClientSocket(Event* event) {
  if (epoll_ctl(pollfd_.get(), EPOLL_CTL_DEL, event->fd.get(), nullptr) != 0) {
    PLOG(ERROR) << "epoll_ctl";
    return false;
  }

  if (clients_.erase(event->fd.get()) != 1) {
    LOG(ERROR) << "event not found";
    return false;
  }

  return true;
}

bool ExceptionHandlerServer::ReceiveClientMessage(Event* event) {
  ExceptionHandlerProtocol::ClientToServerMessage message;
  ucred creds;
  if (!UnixCredentialSocket::RecvMsg(
          event->fd.get(), &message, sizeof(message), &creds)) {
    return false;
  }

  switch (message.type) {
    case ExceptionHandlerProtocol::ClientToServerMessage::kTypeCheckCredentials:
      return SendCredentials(event->fd.get());

    case ExceptionHandlerProtocol::ClientToServerMessage::kTypeCrashDumpRequest:
      return HandleCrashDumpRequest(
          creds,
          message.client_info,
          message.requesting_thread_stack_address,
          event->fd.get(),
          event->type == Event::Type::kSharedSocketMessage);
  }

  DCHECK(false);
  LOG(ERROR) << "Unknown message type";
  return false;
}

bool ExceptionHandlerServer::HandleCrashDumpRequest(
    const ucred& creds,
    const ExceptionHandlerProtocol::ClientInformation& client_info,
    VMAddress requesting_thread_stack_address,
    int client_sock,
    bool multiple_clients) {
  pid_t client_process_id = creds.pid;
  pid_t requesting_thread_id = -1;
  uid_t client_uid = creds.uid;

  switch (
      strategy_decider_->ChooseStrategy(client_sock, multiple_clients, creds)) {
    case PtraceStrategyDecider::Strategy::kError:
      if (multiple_clients) {
        SendSIGCONT(client_process_id, requesting_thread_id);
      }
      return false;

    case PtraceStrategyDecider::Strategy::kNoPtrace:
      if (multiple_clients) {
        SendSIGCONT(client_process_id, requesting_thread_id);
        return true;
      }
      return SendMessageToClient(
          client_sock,
          ExceptionHandlerProtocol::ServerToClientMessage::
              kTypeCrashDumpFailed);

    case PtraceStrategyDecider::Strategy::kDirectPtrace: {
      delegate_->HandleException(client_process_id,
                                 client_uid,
                                 client_info,
                                 requesting_thread_stack_address,
                                 &requesting_thread_id);
      if (multiple_clients) {
        SendSIGCONT(client_process_id, requesting_thread_id);
        return true;
      }
      break;
    }

    case PtraceStrategyDecider::Strategy::kUseBroker:
      DCHECK(!multiple_clients);
      delegate_->HandleExceptionWithBroker(
          client_process_id, client_uid, client_info, client_sock);
      break;
  }

  return SendMessageToClient(
      client_sock,
      ExceptionHandlerProtocol::ServerToClientMessage::kTypeCrashDumpComplete);
}

}  // namespace crashpad
