// 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 <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/exceptionate.h>
#include <object/job_dispatcher.h>
#include <object/process_dispatcher.h>
#include <object/thread_dispatcher.h>

#include "priv.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,
                                              user_out_handle* 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(
      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(fxbug.dev/33015): thread/process/job rights don't always map 1:1.
  zx_rights_t process_rights = task_rights;
  zx_rights_t thread_rights = task_rights;

  Exceptionate::Type type = (options & ZX_EXCEPTION_CHANNEL_DEBUGGER)
                                ? Exceptionate::Type::kDebug
                                : Exceptionate::Type::kStandard;
  Exceptionate* 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())) {
    exceptionate = job->exceptionate(type);
    job_or_process = true;
  } else if (auto process = DownCastDispatcher<ProcessDispatcher>(task.get())) {
    exceptionate = process->exceptionate(type);
    job_or_process = true;
  } else if (auto thread = DownCastDispatcher<ThreadDispatcher>(task.get())) {
    if (type == Exceptionate::Type::kDebug)
      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;

  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 out->make(ktl::move(user_handle),
                   rights & (ZX_RIGHT_TRANSFER | ZX_RIGHT_WAIT | ZX_RIGHT_READ));
}

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

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

  HandleOwner thread_handle;
  status = exception->MakeThreadHandle(&thread_handle);
  if (status != ZX_OK) {
    return status;
  }

  return thread->transfer(ktl::move(thread_handle));
}

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

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

  HandleOwner process_handle;
  status = exception->MakeProcessHandle(&process_handle);
  if (status != ZX_OK) {
    return status;
  }

  return process->transfer(ktl::move(process_handle));
}
