// Copyright 2016 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT

#include <arch.h>
#include <assert.h>
#include <inttypes.h>
#include <lib/fit/defer.h>
#include <stdio.h>
#include <trace.h>
#include <zircon/errors.h>
#include <zircon/syscalls/object.h>
#include <zircon/types.h>

#include <arch/exception.h>
#include <kernel/restricted.h>
#include <ktl/array.h>
#include <ktl/move.h>
#include <object/exception_dispatcher.h>
#include <object/job_dispatcher.h>
#include <object/process_dispatcher.h>
#include <object/thread_dispatcher.h>

#include <ktl/enforce.h>

#define LOCAL_TRACE 0

namespace {
const char* excp_type_to_string(uint type) {
  switch (type) {
    case ZX_EXCP_FATAL_PAGE_FAULT:
      return "fatal page fault";
    case ZX_EXCP_UNDEFINED_INSTRUCTION:
      return "undefined instruction";
    case ZX_EXCP_GENERAL:
      return "general fault";
    case ZX_EXCP_SW_BREAKPOINT:
      return "software breakpoint";
    case ZX_EXCP_HW_BREAKPOINT:
      return "hardware breakpoint";
    case ZX_EXCP_UNALIGNED_ACCESS:
      return "alignment fault";
    case ZX_EXCP_POLICY_ERROR:
      return "policy error";
    case ZX_EXCP_PROCESS_STARTING:
      return "process starting";
    case ZX_EXCP_THREAD_STARTING:
      return "thread starting";
    case ZX_EXCP_THREAD_EXITING:
      return "thread exiting";
    default:
      return "unknown fault";
  }
}

bool HasRestrictedInThreadHandler() {
  RestrictedState* rs = Thread::Current::restricted_state();
  return rs != nullptr && rs->in_restricted() && rs->in_thread_exceptions_enabled();
}
}  // namespace

// This isn't an "iterator" in the pure c++ sense. We don't need all that
// complexity. I just couldn't think of a better term.
//
// Exception handlers are tried in the following order:
// - debugger
// - thread
// - process
// - debugger (in dealing with a second-chance exception)
// - job (first owning job, then its parent job, and so on up to root job)
class ExceptionHandlerIterator final {
 public:
  explicit ExceptionHandlerIterator(ThreadDispatcher* thread,
                                    fbl::RefPtr<ExceptionDispatcher> exception)
      : thread_(thread), exception_(ktl::move(exception)) {}

  // Sends the exception to the next registered handler, starting with
  // ZX_EXCEPTION_CHANNEL_TYPE_DEBUGGER (the process debug channel) on the first
  // call.
  //
  // Returns true with and fills |result| if the exception was sent to a
  // handler, or returns false if there are no more to try. Do not call this
  // function again after it returns false.
  bool Next(zx_status_t* result) {
    bool sent = false;

    while (true) {
      // This state may change during the handling of the debugger exception
      // channel. Accordingly, we check its value before the next round of
      // handling to be sure of the proper sequencing.
      bool second_chance = exception_->IsSecondChance();

      switch (next_method_) {
        case ExceptionDeliveryMethod::kFirstChanceDebugChannel:
          *result =
              thread_->HandleException(thread_->process()->debug_exceptionate(), exception_, &sent);
          if (HasRestrictedInThreadHandler()) {
            next_method_ = ExceptionDeliveryMethod::kRestrictedModeVectoredException;
          } else {
            next_method_ = ExceptionDeliveryMethod::kThreadChannel;
          }
          break;
        case ExceptionDeliveryMethod::kSecondChanceDebugChannel:
          *result =
              thread_->HandleException(thread_->process()->debug_exceptionate(), exception_, &sent);
          next_method_ = ExceptionDeliveryMethod::kJobChannel;
          next_job_ = thread_->process()->job();
          break;
        case ExceptionDeliveryMethod::kRestrictedModeVectoredException: {
          RestrictedState* rs = Thread::Current::restricted_state();
          DEBUG_ASSERT(rs != nullptr);
          RedirectRestrictedExceptionToNormalMode(rs);

          // Write the exception report into the side-car.
          auto* exception = rs->state_ptr_as<zx_restricted_exception_t>();
          DEBUG_ASSERT(exception != nullptr);
          exception_->FillReport(&exception->exception);

          // Handle the exception on behalf of restricted mode.
          //
          // Note this implies that restricted exceptions can never propagate
          // further and as such are ineligible for subsequent handlers.
          *result = ZX_OK;
          return true;
        }
        case ExceptionDeliveryMethod::kThreadChannel:
          *result = thread_->HandleException(thread_->exceptionate(), exception_, &sent);
          next_method_ = ExceptionDeliveryMethod::kProcessChannel;
          break;
        case ExceptionDeliveryMethod::kProcessChannel:
          *result = thread_->HandleException(thread_->process()->exceptionate(), exception_, &sent);

          if (second_chance) {
            next_method_ = ExceptionDeliveryMethod::kSecondChanceDebugChannel;
          } else {
            next_method_ = ExceptionDeliveryMethod::kJobChannel;
            next_job_ = thread_->process()->job();
          }
          break;
        case ExceptionDeliveryMethod::kJobChannel:
          if (next_job_ == nullptr) {
            // Reached the root job and there was no handler.
            return false;
          }
          *result = thread_->HandleException(next_job_->exceptionate(), exception_, &sent);
          next_job_ = next_job_->parent();
          break;
      }

      // Return to the caller once a handler was activated.
      if (sent) {
        return true;
      }
    }
    __UNREACHABLE;
  }

 private:
  enum class ExceptionDeliveryMethod {
    kFirstChanceDebugChannel,
    kRestrictedModeVectoredException,
    kThreadChannel,
    kProcessChannel,
    kSecondChanceDebugChannel,
    kJobChannel,
  };

  ThreadDispatcher* thread_;
  fbl::RefPtr<ExceptionDispatcher> exception_;
  ExceptionDeliveryMethod next_method_ = ExceptionDeliveryMethod::kFirstChanceDebugChannel;
  fbl::RefPtr<JobDispatcher> next_job_;

  DISALLOW_COPY_ASSIGN_AND_MOVE(ExceptionHandlerIterator);
};

// Subroutine of dispatch_user_exception to simplify the code.
// One useful thing this does is guarantee ExceptionHandlerIterator is properly
// destructed.
//
// |*out_processed| is set to a boolean indicating if at least one
// handler processed the exception.
//
// Returns:
//   ZX_OK if the thread has been resumed.
//   ZX_ERR_NEXT if we ran out of handlers before the thread resumed.
//   ZX_ERR_INTERNAL_INTR_KILLED if the thread was killed.
//   ZX_ERR_NO_MEMORY on allocation failure (TODO(https://fxbug.dev/42108776): remove this case)
static zx_status_t exception_handler_worker(uint exception_type,
                                            const arch_exception_context_t* context,
                                            ThreadDispatcher* thread, bool* out_processed) {
  DEBUG_ASSERT(context != nullptr);

  *out_processed = false;

  zx_exception_report_t report = ExceptionDispatcher::BuildArchReport(exception_type, *context);

  fbl::RefPtr<ExceptionDispatcher> exception =
      ExceptionDispatcher::Create(fbl::RefPtr(thread), exception_type, &report, context);
  if (!exception) {
    // No memory to create the exception, we just have to drop it which
    // will kill the process.
    printf("KERN: failed to allocate memory for %s exception in user thread %lu.%lu\n",
           excp_type_to_string(exception_type), thread->process()->get_koid(), thread->get_koid());
    return ZX_ERR_NO_MEMORY;
  }

  // Most of the time we'll be holding the last reference to the exception
  // when this function exits, but if the task is killed we return HS_KILLED
  // without waiting for the handler which means someone may still have a
  // handle to the exception.
  //
  // For simplicity and to catch any unhandled status cases below, just clean
  // out the exception before returning no matter what.
  auto exception_cleaner = fit::defer([&exception]() { exception->Clear(); });

  ExceptionHandlerIterator iter(thread, exception);
  zx_status_t status = ZX_ERR_NEXT;
  while (iter.Next(&status)) {
    LTRACEF("handler returned %d\n", status);

    // ZX_ERR_NEXT means the handler wants to pass it up to the next in the
    // chain, keep looping but mark that at least one handler saw the exception.
    if (status == ZX_ERR_NEXT) {
      *out_processed = true;
      continue;
    }

    // ZX_ERR_STOP means the handler wants to kill the thread.
    if (status == ZX_ERR_STOP) {
      *out_processed = true;
      DEBUG_ASSERT(thread == ThreadDispatcher::GetCurrent());
      ThreadDispatcher::KillCurrent();
      return ZX_ERR_INTERNAL_INTR_KILLED;
    }

    // Anything other than ZX_ERR_NEXT means we're done.
    return status;
  }

  if (status != ZX_ERR_NEXT) {
    // If the iterator returned false, but status got changed from ZX_ERR_NEXT, then this means it
    // attempted to send to a handler, but the sending process failed. We still have no way to
    // handle the exception but we can at least make noise in the debuglog.
    printf(
        "KERN: Failed to deliver %s exception to exception handler in user thread %lu.%lu with "
        "status: %d\n",
        excp_type_to_string(exception_type), thread->process()->get_koid(), thread->get_koid(),
        status);
  }

  // If we got here we ran out of handlers and nobody resumed the thread.
  return ZX_ERR_NEXT;
}

// Dispatches an exception to the appropriate handler. Called by arch code
// when it cannot handle an exception.
//
// If we return ZX_OK, the caller is expected to resume the thread "as if"
// nothing happened, the handler is expected to have modified state such that
// resumption is possible.
//
// If we return ZX_ERR_BAD_STATE, the current thread is not a user thread
// (i.e., not associated with a ThreadDispatcher).
//
// Otherwise, we cause the current thread to exit and do not return at all.
//
// TODO(dje): Support unwinding from this exception and introducing a different
// exception?
zx_status_t dispatch_user_exception(uint exception_type,
                                    const arch_exception_context_t* arch_context) {
  LTRACEF("type %u, context %p\n", exception_type, arch_context);

  ThreadDispatcher* thread = ThreadDispatcher::GetCurrent();
  if (unlikely(!thread)) {
    // The current thread is not a user thread; bail.
    return ZX_ERR_BAD_STATE;
  }

  // From now until the exception is resolved the thread is in an exception.
  ThreadDispatcher::AutoBlocked by(ThreadDispatcher::Blocked::EXCEPTION);

  constexpr auto get_name = [](auto* task) -> ktl::array<char, ZX_MAX_NAME_LEN> {
    char name[ZX_MAX_NAME_LEN];
    [[maybe_unused]] zx_status_t status = task->get_name(name);
    // get_name cannot fail for a process or for a thread. We are processing an exception on the
    // current thread, so its state should remain RUNNING until we've decided to kill the thread
    // below.
    DEBUG_ASSERT(status == ZX_OK);
    return ktl::to_array(name);
  };

  auto dump_context = [&](const auto& pname) {
    printf("KERN: %s in user thread '%s' (%lu) in process '%s'\n",
           excp_type_to_string(exception_type), get_name(thread).data(), thread->get_koid(),
           pname.data());
    arch_dump_exception_context(arch_context);
  };

  bool processed = false;
  zx_status_t status = ZX_ERR_INTERNAL;
  {
    // We're about to handle the exception.  Use a |ScopedThreadExceptionContext| to make the
    // thread's user register state available to debuggers and exception handlers while the thread
    // is "in exception".
    ScopedThreadExceptionContext context(arch_context);
    status = exception_handler_worker(exception_type, arch_context, thread, &processed);
  }

  if (status == ZX_OK) {
    return ZX_OK;
  }

  // If the thread wasn't resumed or explicitly killed, kill the whole process.
  // If the process is critical to the root job, any fatal exception merits
  // logging all the details available whether the handler decided to kill the
  // process, or no handler processed it at all.
  ProcessDispatcher* process = thread->process();
  if (status == ZX_ERR_INTERNAL_INTR_KILLED) {
    // An exception handler has decided the process should be terminated.
    if (process->CriticalToRootJob()) {
      // Terminating a critical process will likely reboot the system so dump some extra diagnostics
      // to assist in debugging.
      printf("KERN: fatal exception in process critical to root job!\n");
      dump_context(get_name(process));
    }
  } else {
    auto pname = get_name(process);

    if (!processed) {
      // The exception was not handled. Normally, at least crashsvc would handle the exception and
      // make a smarter decision about what to do with it, but in case it didn't, dump some info to
      // the kernel logs.
      printf("KERN: exception_handler_worker returned %d\n", status);
      dump_context(pname);
    }

    printf("KERN: terminating process '%s' (%lu)\n", pname.data(), process->get_koid());
    process->Kill(ZX_TASK_RETCODE_EXCEPTION_KILL);
  }

  // Either the current thread or its whole process was killed, we can now stop
  // it from running.
  ThreadDispatcher::ExitCurrent();
  panic("fell out of thread exit somehow!\n");
  __UNREACHABLE;
}

void dump_common_exception_context(const arch_exception_context_t* context) {
  // Print the common fields in arch_exception_context.
  //
  // In case of a page fault exception, the error code is typecast from zx_status_t to uint32_t when
  // populating user_synth_code. So also log the value typecast to zx_status_t to make debugging
  // easier.
  printf("synth_code %u (%d), synth_data %u\n", context->user_synth_code,
         static_cast<zx_status_t>(context->user_synth_code), context->user_synth_data);
}
