// 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/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 = syscall(__NR_clone, CLONE_NEWPID | SIGCHLD, 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, syscall(__NR_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 = syscall(__NR_clone, CLONE_NEWPID | SIGCHLD, 0, 0, 0);
  CHECK_NE(-1, pid);
  if (pid == 0) {
    // Child process.
    recv_sock.reset();

    const pid_t pid2 = syscall(__NR_clone, CLONE_NEWPID | SIGCHLD, 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, syscall(__NR_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 = syscall(__NR_clone, CLONE_NEWPID | SIGCHLD, 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
