// Copyright 2014 The Chromium 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 <sched.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/syscall.h>
#include <sys/wait.h>
#include <unistd.h>

#include <vector>

#include "base/files/scoped_file.h"
#include "base/logging.h"
#include "base/memory/scoped_vector.h"
#include "base/posix/eintr_wrapper.h"
#include "base/posix/unix_domain_socket_linux.h"
#include "base/process/process_handle.h"
#include "sandbox/linux/services/syscall_wrappers.h"
#include "sandbox/linux/tests/unit_tests.h"

// Additional tests for base's UnixDomainSocket to make sure it behaves
// correctly in the presence of sandboxing functionality (e.g., receiving
// PIDs across namespaces).

namespace sandbox {

namespace {

const char kHello[] = "hello";

// If the calling process isn't root, then try using unshare(CLONE_NEWUSER)
// to fake it.
void FakeRoot() {
  // If we're already root, then allow test to proceed.
  if (geteuid() == 0)
    return;

  // Otherwise hope the kernel supports unprivileged namespaces.
  if (unshare(CLONE_NEWUSER) == 0)
    return;

  printf("Permission to use CLONE_NEWPID missing; skipping test.\n");
  UnitTests::IgnoreThisTest();
}

void WaitForExit(pid_t pid) {
  int status;
  CHECK_EQ(pid, HANDLE_EINTR(waitpid(pid, &status, 0)));
  CHECK(WIFEXITED(status));
  CHECK_EQ(0, WEXITSTATUS(status));
}

base::ProcessId GetParentProcessId(base::ProcessId pid) {
  // base::GetParentProcessId() is defined as taking a ProcessHandle instead of
  // a ProcessId, even though it's a POSIX-only function and IDs and Handles
  // are both simply pid_t on POSIX... :/
  base::ProcessHandle handle;
  CHECK(base::OpenProcessHandle(pid, &handle));
  base::ProcessId ret = base::GetParentProcessId(pid);
  base::CloseProcessHandle(handle);
  return ret;
}

// SendHello sends a "hello" to socket fd, and then blocks until the recipient
// acknowledges it by calling RecvHello.
void SendHello(int fd) {
  int pipe_fds[2];
  CHECK_EQ(0, pipe(pipe_fds));
  base::ScopedFD read_pipe(pipe_fds[0]);
  base::ScopedFD write_pipe(pipe_fds[1]);

  std::vector<int> send_fds;
  send_fds.push_back(write_pipe.get());
  CHECK(UnixDomainSocket::SendMsg(fd, kHello, sizeof(kHello), send_fds));

  write_pipe.reset();

  // Block until receiver closes their end of the pipe.
  char ch;
  CHECK_EQ(0, HANDLE_EINTR(read(read_pipe.get(), &ch, 1)));
}

// RecvHello receives and acknowledges a "hello" on socket fd, and returns the
// process ID of the sender in sender_pid.  Optionally, write_pipe can be used
// to return a file descriptor, and the acknowledgement will be delayed until
// the descriptor is closed.
// (Implementation details: SendHello allocates a new pipe, sends us the writing
// end alongside the "hello" message, and then blocks until we close the writing
// end of the pipe.)
void RecvHello(int fd,
               base::ProcessId* sender_pid,
               base::ScopedFD* write_pipe = NULL) {
  // Extra receiving buffer space to make sure we really received only
  // sizeof(kHello) bytes and it wasn't just truncated to fit the buffer.
  char buf[sizeof(kHello) + 1];
  ScopedVector<base::ScopedFD> message_fds;
  ssize_t n = UnixDomainSocket::RecvMsgWithPid(
      fd, buf, sizeof(buf), &message_fds, sender_pid);
  CHECK_EQ(sizeof(kHello), static_cast<size_t>(n));
  CHECK_EQ(0, memcmp(buf, kHello, sizeof(kHello)));
  CHECK_EQ(1U, message_fds.size());
  if (write_pipe)
    write_pipe->swap(*message_fds[0]);
}

// Check that receiving PIDs works across a fork().
SANDBOX_TEST(UnixDomainSocketTest, Fork) {
  int fds[2];
  CHECK_EQ(0, socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds));
  base::ScopedFD recv_sock(fds[0]);
  base::ScopedFD send_sock(fds[1]);

  CHECK(UnixDomainSocket::EnableReceiveProcessId(recv_sock.get()));

  const pid_t pid = fork();
  CHECK_NE(-1, pid);
  if (pid == 0) {
    // Child process.
    recv_sock.reset();
    SendHello(send_sock.get());
    _exit(0);
  }

  // Parent process.
  send_sock.reset();

  base::ProcessId sender_pid;
  RecvHello(recv_sock.get(), &sender_pid);
  CHECK_EQ(pid, sender_pid);

  WaitForExit(pid);
}

// Similar to Fork above, but forking the child into a new pid namespace.
SANDBOX_TEST(UnixDomainSocketTest, Namespace) {
  FakeRoot();

  int fds[2];
  CHECK_EQ(0, socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds));
  base::ScopedFD recv_sock(fds[0]);
  base::ScopedFD send_sock(fds[1]);

  CHECK(UnixDomainSocket::EnableReceiveProcessId(recv_sock.get()));

  const pid_t pid = sys_clone(CLONE_NEWPID | SIGCHLD, 0, 0, 0, 0);
  CHECK_NE(-1, pid);
  if (pid == 0) {
    // Child process.
    recv_sock.reset();

    // Check that we think we're pid 1 in our new namespace.
    CHECK_EQ(1, sys_getpid());

    SendHello(send_sock.get());
    _exit(0);
  }

  // Parent process.
  send_sock.reset();

  base::ProcessId sender_pid;
  RecvHello(recv_sock.get(), &sender_pid);
  CHECK_EQ(pid, sender_pid);

  WaitForExit(pid);
}

// Again similar to Fork, but now with nested PID namespaces.
SANDBOX_TEST(UnixDomainSocketTest, DoubleNamespace) {
  FakeRoot();

  int fds[2];
  CHECK_EQ(0, socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds));
  base::ScopedFD recv_sock(fds[0]);
  base::ScopedFD send_sock(fds[1]);

  CHECK(UnixDomainSocket::EnableReceiveProcessId(recv_sock.get()));

  const pid_t pid = sys_clone(CLONE_NEWPID | SIGCHLD, 0, 0, 0, 0);
  CHECK_NE(-1, pid);
  if (pid == 0) {
    // Child process.
    recv_sock.reset();

    const pid_t pid2 = sys_clone(CLONE_NEWPID | SIGCHLD, 0, 0, 0, 0);
    CHECK_NE(-1, pid2);

    if (pid2 != 0) {
      // Wait for grandchild to run to completion; see comments below.
      WaitForExit(pid2);

      // Fallthrough once grandchild has sent its hello and exited.
    }

    // Check that we think we're pid 1.
    CHECK_EQ(1, sys_getpid());

    SendHello(send_sock.get());
    _exit(0);
  }

  // Parent process.
  send_sock.reset();

  // We have two messages to receive: first from the grand-child,
  // then from the child.
  for (unsigned iteration = 0; iteration < 2; ++iteration) {
    base::ProcessId sender_pid;
    base::ScopedFD pipe_fd;
    RecvHello(recv_sock.get(), &sender_pid, &pipe_fd);

    // We need our child and grandchild processes to both be alive for
    // GetParentProcessId() to return a valid pid, hence the pipe trickery.
    // (On the first iteration, grandchild is blocked reading from the pipe
    // until we close it, and child is blocked waiting for grandchild to exit.)
    switch (iteration) {
      case 0:  // Grandchild's message
        // Check that sender_pid refers to our grandchild by checking that pid
        // (our child) is its parent.
        CHECK_EQ(pid, GetParentProcessId(sender_pid));
        break;
      case 1:  // Child's message
        CHECK_EQ(pid, sender_pid);
        break;
      default:
        NOTREACHED();
    }
  }

  WaitForExit(pid);
}

// Tests that GetPeerPid() returns 0 if the peer does not exist in caller's
// namespace.
SANDBOX_TEST(UnixDomainSocketTest, ImpossiblePid) {
  FakeRoot();

  int fds[2];
  CHECK_EQ(0, socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds));
  base::ScopedFD send_sock(fds[0]);
  base::ScopedFD recv_sock(fds[1]);

  CHECK(UnixDomainSocket::EnableReceiveProcessId(recv_sock.get()));

  const pid_t pid = sys_clone(CLONE_NEWPID | SIGCHLD, 0, 0, 0, 0);
  CHECK_NE(-1, pid);
  if (pid == 0) {
    // Child process.
    send_sock.reset();

    base::ProcessId sender_pid;
    RecvHello(recv_sock.get(), &sender_pid);
    CHECK_EQ(0, sender_pid);
    _exit(0);
  }

  // Parent process.
  recv_sock.reset();
  SendHello(send_sock.get());
  WaitForExit(pid);
}

}  // namespace

}  // namespace sandbox
