// 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 <fcntl.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);
}
