// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <dirent.h>
#include <lib/zx/channel.h>
#include <lib/zx/event.h>
#include <lib/zx/process.h>
#include <lib/zx/suspend_token.h>
#include <lib/zx/thread.h>
#include <lib/zx/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <zircon/process.h>
#include <zircon/processargs.h>
#include <zircon/syscalls.h>
#include <zircon/syscalls/exception.h>
#include <zircon/syscalls/port.h>

#include <test-utils/test-utils.h>
#include <zxtest/zxtest.h>

namespace {

const char* process_bin;

// SYSCALL_zx_channel_call_noretry is an internal system call used in the
// vDSO's implementation of zx_channel_call.  It's not part of the ABI and
// so it's not exported from the vDSO.  It's hard to test the kernel's
// invariants without calling this directly.  So use some chicanery to
// find its address in the vDSO despite it not being public.
//
// The vdso-code.h header file is generated from the vDSO binary.  It gives
// the offsets of the internal functions.  So take a public vDSO function,
// subtract its offset to discover the vDSO base (could do this other ways,
// but this is the simplest), and then add the offset of the internal
// SYSCALL_zx_channel_call_noretry function we want to call.
#include "vdso-code.h"
zx_status_t zx_channel_call_noretry(zx_handle_t handle, uint32_t options, zx_time_t deadline,
                                    const zx_channel_call_args_t* args, uint32_t* actual_bytes,
                                    uint32_t* actual_handles) {
  uintptr_t vdso_base = (uintptr_t)&zx_handle_close - VDSO_SYSCALL_zx_handle_close;
  uintptr_t fnptr = vdso_base + VDSO_SYSCALL_zx_channel_call_noretry;
  return (*(__typeof(zx_channel_call_noretry)*)fnptr)(handle, options, deadline, args, actual_bytes,
                                                      actual_handles);
}

// This runs in a separate process, since the expected outcome of running this
// function is that the process is shot by the kernel.  It is launched by the
// bad_channel_call_contract_violation test.
void bad_channel_call() {
  char msg[8] = {
      0,
  };

  zx_channel_call_args_t args = {
      .wr_bytes = msg,
      .wr_handles = nullptr,
      .rd_bytes = nullptr,
      .rd_handles = nullptr,
      .wr_num_bytes = sizeof(msg),
      .wr_num_handles = 0,
      .rd_num_bytes = 0,
      .rd_num_handles = 0,
  };

  uint32_t act_bytes = UINT32_MAX;
  uint32_t act_handles = UINT32_MAX;

  zx::channel chan{zx_take_startup_handle(PA_HND(PA_USER0, 0))};
  zx::event event{zx_take_startup_handle(PA_HND(PA_USER0, 1))};

  // Send a copy of the thread handle to the parent, so the parent can suspend
  // this thread.
  zx::thread thread;
  zx_status_t status = zx::thread::self()->duplicate(ZX_RIGHT_SAME_RIGHTS, &thread);
  if (status != ZX_OK) {
    event.signal(0, ZX_USER_SIGNAL_0);
    __builtin_trap();
  }
  zx_handle_t handles[] = {thread.release()};
  status = chan.write(0, nullptr, 0, handles, 1);
  if (status != ZX_OK) {
    event.signal(0, ZX_USER_SIGNAL_0);
    __builtin_trap();
  }

  status =
      zx_channel_call_noretry(chan.get(), 0, ZX_TIME_INFINITE, &args, &act_bytes, &act_handles);
  if (status != ZX_ERR_INTERNAL_INTR_RETRY) {
    event.signal(0, ZX_USER_SIGNAL_0);
    __builtin_trap();
  }

  event.signal(0, ZX_USER_SIGNAL_1);

  // Doing another channel call at this point violates the VDSO contract,
  // since we haven't called SYSCALL_zx_channel_call_finish().
  zx_channel_call_noretry(chan.get(), 0, ZX_TIME_INFINITE, &args, &act_bytes, &act_handles);
  event.signal(0, ZX_USER_SIGNAL_0);
  __builtin_trap();
}

// Verify that if an interrupted channel call does not retry and instead a new
// channel call happens, the process dies.
TEST(ChannelFatalTestCase, BadChannelCallContractViolation) {
  zx::channel chan, remote;
  zx::event event, event_copy;
  ASSERT_OK(zx::channel::create(0, &chan, &remote));
  ASSERT_OK(zx::event::create(0, &event));
  ASSERT_OK(event.duplicate(ZX_RIGHT_SAME_RIGHTS, &event_copy));

  const char* args[] = {
      process_bin,
      "child",
  };
  zx_handle_t handles[] = {
      remote.release(),
      event_copy.release(),
  };
  uint32_t handle_ids[] = {
      PA_HND(PA_USER0, 0),
      PA_HND(PA_USER0, 1),
  };
  int environ_count = 0;
  for (char** i = environ; *i; i++) {
    environ_count++;
  }
  zx::process proc(tu_launch_process(zx_job_default(), NULL, 2, args, environ_count, environ,
                                     std::size(handles), handles, handle_ids));

  uint32_t act_bytes = UINT32_MAX;
  uint32_t act_handles = UINT32_MAX;
  zx::thread thread;

  // Get the thread handle from our child
  ASSERT_OK(chan.wait_one(ZX_CHANNEL_READABLE, zx::time::infinite(), nullptr));
  ASSERT_OK(chan.read(0, nullptr, thread.reset_and_get_address(), 0, 1, &act_bytes, &act_handles));
  ASSERT_EQ(act_handles, 1u);

  // Wait for the channel call and pull its message out of the pipe.  This
  // relies on an implementation detail of suspend and channel_call,
  // which is that once the syscall starts, suspend will not be acknowledged
  // until it reaches the wait.  So if we see the message written to the
  // channel, we know the other thread is in the call, and so when we see
  // it has suspended, it will have attempted the wait first.
  EXPECT_OK(chan.wait_one(ZX_CHANNEL_READABLE, zx::time::infinite(), nullptr));
  char msg[8] = {0};
  ASSERT_OK(chan.read(0, msg, nullptr, sizeof(msg), 0, &act_bytes, &act_handles));

  {
    zx::suspend_token suspend_token;
    ASSERT_OK(thread.suspend(&suspend_token));

    // Wait for the thread to suspend
    zx_signals_t observed = 0u;
    ASSERT_OK(thread.wait_one(ZX_THREAD_SUSPENDED, zx::time::infinite(), &observed));

    // Resume the thread
  }

  // Wait for signal 0 or 1, meaning either it's going to try its second call,
  // or something unexpected happened.
  zx_signals_t observed = 0u;
  ASSERT_OK(event.wait_one(ZX_USER_SIGNAL_0 | ZX_USER_SIGNAL_1, zx::time::infinite(), &observed));
  ASSERT_TRUE(observed & ZX_USER_SIGNAL_1);
  ASSERT_FALSE(observed & ZX_USER_SIGNAL_0);

  // Process should have been shot
  ASSERT_OK(proc.wait_one(ZX_PROCESS_TERMINATED, zx::time::infinite(), nullptr));
  // Make sure we don't see the "unexpected thing happened" signal.
  ASSERT_EQ(event.wait_one(ZX_USER_SIGNAL_0, zx::time(), &observed), ZX_ERR_TIMED_OUT);
}

}  // namespace

int main(int argc, char** argv) {
  process_bin = argv[0];
  if (argc > 1 && !strcmp(argv[1], "child")) {
    bad_channel_call();
    return 0;
  }
  return RUN_ALL_TESTS(argc, argv);
}
