// 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 <lib/syscalls/forward.h>
#include <platform.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <trace.h>
#include <zircon/errors.h>
#include <zircon/types.h>

#include <object/exception_dispatcher.h>
#include <object/exceptionate.h>
#include <object/job_dispatcher.h>
#include <object/process_dispatcher.h>
#include <object/thread_dispatcher.h>

#define LOCAL_TRACE 0

// zx_status_t zx_task_create_exception_channel
zx_status_t sys_task_create_exception_channel(zx_handle_t handle, uint32_t options,
                                              zx_handle_t* out) {
  LTRACE_ENTRY;

  if (options & ~ZX_EXCEPTION_CHANNEL_DEBUGGER)
    return ZX_ERR_INVALID_ARGS;

  auto up = ProcessDispatcher::GetCurrent();
  zx_status_t status = up->EnforceBasicPolicy(ZX_POL_NEW_CHANNEL);
  if (status != ZX_OK)
    return status;

  // Required rights to receive exceptions:
  //   INSPECT: provides non-trivial task information
  //   DUPLICATE: can create new thread and process handles
  //   TRANSFER: exceptions or their channels can be transferred
  //   MANAGE_THREAD: can keep thread paused during exception
  //   ENUMERATE (job/process): can access child thread (enforced below)
  //
  // In the future we may want to support some smarter behavior here e.g.
  // allowing for exceptions but no task handles if these rights don't exist,
  // but to start with we'll keep it simple until we know we want this.
  fbl::RefPtr<Dispatcher> task;
  zx_rights_t task_rights;
  status = up->handle_table().GetDispatcherWithRights(
      *up, handle,
      ZX_RIGHT_INSPECT | ZX_RIGHT_DUPLICATE | ZX_RIGHT_TRANSFER | ZX_RIGHT_MANAGE_THREAD, &task,
      &task_rights);
  if (status != ZX_OK)
    return status;

  // The task handles provided over this exception channel use the rights on
  // |handle| so we are sure not to grant any additional rights the caller
  // didn't already have.
  //
  // TODO(https://fxbug.dev/42108165): thread/process/job rights don't always map 1:1.
  zx_rights_t process_rights = task_rights;
  zx_rights_t thread_rights = task_rights;

  // Only one of the |exceptionate| and |job_to_create_debug_exceptionate| will be non-null.
  //
  // When creating debugger exception channel on a job, |exceptionate| will be null and
  // |job_to_create_debug_exceptionate| is used instead, because JobDispatcher::DebugExceptionate
  // requires dynamic allocation. For other types, only |exceptionate| will be used.
  Exceptionate* exceptionate = nullptr;
  JobDispatcher* job_to_create_debug_exceptionate = nullptr;

  bool job_or_process = false;

  // Use DownCastDispatcher() on the raw task pointer to avoid moving the
  // RefPtr out, we still need to retain the RefPtr to keep our extracted
  // Exceptionate* alive.
  if (auto job = DownCastDispatcher<JobDispatcher>(task.get())) {
    if (options & ZX_EXCEPTION_CHANNEL_DEBUGGER) {
      job_to_create_debug_exceptionate = job;
    } else {
      exceptionate = job->exceptionate();
    }
    job_or_process = true;
  } else if (auto process = DownCastDispatcher<ProcessDispatcher>(task.get())) {
    if (options & ZX_EXCEPTION_CHANNEL_DEBUGGER) {
      exceptionate = process->debug_exceptionate();
    } else {
      exceptionate = process->exceptionate();
    }
    job_or_process = true;
  } else if (auto thread = DownCastDispatcher<ThreadDispatcher>(task.get())) {
    if (options & ZX_EXCEPTION_CHANNEL_DEBUGGER)
      return ZX_ERR_INVALID_ARGS;

    // We don't provide access up the task chain, so don't send the process
    // handle when we're registering on a thread.
    process_rights = 0;
    exceptionate = thread->exceptionate();
  } else {
    return ZX_ERR_WRONG_TYPE;
  }

  DEBUG_ASSERT(task);

  // For job and process handlers, we require the handle be able to enumerate
  // as proof that the caller is allowed to get to the thread handle.
  if (job_or_process && !(task_rights & ZX_RIGHT_ENUMERATE))
    return ZX_ERR_ACCESS_DENIED;

  KernelHandle<ChannelDispatcher> kernel_handle, user_handle;
  zx_rights_t rights;
  status = ChannelDispatcher::Create(&kernel_handle, &user_handle, &rights);
  if (status != ZX_OK)
    return status;

  if (job_to_create_debug_exceptionate) {
    status = job_to_create_debug_exceptionate->CreateDebugExceptionate(
        ktl::move(kernel_handle), thread_rights, process_rights);
  } else {
    status = exceptionate->SetChannel(ktl::move(kernel_handle), thread_rights, process_rights);
  }
  if (status != ZX_OK)
    return status;

  // Strip unwanted rights from the user endpoint, exception channels are
  // read-only from userspace.
  //
  // We don't need to remove the task channel if this fails. Exception
  // channels are built to handle the userspace peer closing so it will just
  // follow that path if we fail to copy the userspace endpoint out.
  return up->MakeAndAddHandle(ktl::move(user_handle),
                              rights & (ZX_RIGHT_TRANSFER | ZX_RIGHT_WAIT | ZX_RIGHT_READ), out);
}

// zx_status_t zx_exception_get_thread
zx_status_t sys_exception_get_thread(zx_handle_t handle, zx_handle_t* thread) {
  auto up = ProcessDispatcher::GetCurrent();

  fbl::RefPtr<ExceptionDispatcher> exception;
  zx_status_t status = up->handle_table().GetDispatcher(*up, handle, &exception);
  if (status != ZX_OK) {
    return status;
  }

  HandleOwner thread_handle;
  status = exception->MakeThreadHandle(&thread_handle);
  if (status != ZX_OK) {
    return status;
  }
  *thread = up->handle_table().MapHandleToValue(thread_handle);
  up->handle_table().AddHandle(ktl::move(thread_handle));
  return ZX_OK;
}

// zx_status_t zx_exception_get_process
zx_status_t sys_exception_get_process(zx_handle_t handle, zx_handle_t* process) {
  auto up = ProcessDispatcher::GetCurrent();

  fbl::RefPtr<ExceptionDispatcher> exception;
  zx_status_t status = up->handle_table().GetDispatcher(*up, handle, &exception);
  if (status != ZX_OK) {
    return status;
  }

  HandleOwner process_handle;
  status = exception->MakeProcessHandle(&process_handle);
  if (status != ZX_OK) {
    return status;
  }
  *process = up->handle_table().MapHandleToValue(process_handle);
  up->handle_table().AddHandle(ktl::move(process_handle));
  return ZX_OK;
}
