15c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Copyright 2014 The Chromium Authors. All rights reserved.
25c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Use of this source code is governed by a BSD-style license that can be
35c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// found in the LICENSE file.
45c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
55c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include <sched.h>
65c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include <stdio.h>
75c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include <string.h>
85c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include <sys/socket.h>
95c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include <sys/syscall.h>
105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include <sys/wait.h>
115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include <unistd.h>
125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include <vector>
145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/files/scoped_file.h"
165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/logging.h"
175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/memory/scoped_vector.h"
185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/posix/eintr_wrapper.h"
195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/posix/unix_domain_socket_linux.h"
205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/process/process_handle.h"
215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "sandbox/linux/tests/unit_tests.h"
225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Additional tests for base's UnixDomainSocket to make sure it behaves
245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// correctly in the presence of sandboxing functionality (e.g., receiving
255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// PIDs across namespaces).
265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liunamespace sandbox {
285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liunamespace {
305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst char kHello[] = "hello";
325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// If the calling process isn't root, then try using unshare(CLONE_NEWUSER)
345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// to fake it.
355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid FakeRoot() {
365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // If we're already root, then allow test to proceed.
375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (geteuid() == 0)
385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return;
395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Otherwise hope the kernel supports unprivileged namespaces.
415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (unshare(CLONE_NEWUSER) == 0)
425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return;
435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  printf("Permission to use CLONE_NEWPID missing; skipping test.\n");
455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  UnitTests::IgnoreThisTest();
465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid WaitForExit(pid_t pid) {
495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  int status;
505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK_EQ(pid, HANDLE_EINTR(waitpid(pid, &status, 0)));
515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK(WIFEXITED(status));
525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK_EQ(0, WEXITSTATUS(status));
535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubase::ProcessId GetParentProcessId(base::ProcessId pid) {
565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // base::GetParentProcessId() is defined as taking a ProcessHandle instead of
575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // a ProcessId, even though it's a POSIX-only function and IDs and Handles
585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // are both simply pid_t on POSIX... :/
595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  base::ProcessHandle handle;
605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK(base::OpenProcessHandle(pid, &handle));
615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  base::ProcessId ret = base::GetParentProcessId(pid);
625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  base::CloseProcessHandle(handle);
635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return ret;
645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// SendHello sends a "hello" to socket fd, and then blocks until the recipient
675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// acknowledges it by calling RecvHello.
685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid SendHello(int fd) {
695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  int pipe_fds[2];
705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK_EQ(0, pipe(pipe_fds));
715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  base::ScopedFD read_pipe(pipe_fds[0]);
725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  base::ScopedFD write_pipe(pipe_fds[1]);
735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  std::vector<int> send_fds;
755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  send_fds.push_back(write_pipe.get());
765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK(UnixDomainSocket::SendMsg(fd, kHello, sizeof(kHello), send_fds));
775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  write_pipe.reset();
795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Block until receiver closes their end of the pipe.
815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  char ch;
825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK_EQ(0, HANDLE_EINTR(read(read_pipe.get(), &ch, 1)));
835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// RecvHello receives and acknowledges a "hello" on socket fd, and returns the
865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// process ID of the sender in sender_pid.  Optionally, write_pipe can be used
875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// to return a file descriptor, and the acknowledgement will be delayed until
885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// the descriptor is closed.
895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// (Implementation details: SendHello allocates a new pipe, sends us the writing
905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// end alongside the "hello" message, and then blocks until we close the writing
915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// end of the pipe.)
925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid RecvHello(int fd,
935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu               base::ProcessId* sender_pid,
945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu               base::ScopedFD* write_pipe = NULL) {
955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Extra receiving buffer space to make sure we really received only
965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // sizeof(kHello) bytes and it wasn't just truncated to fit the buffer.
975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  char buf[sizeof(kHello) + 1];
985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ScopedVector<base::ScopedFD> message_fds;
995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ssize_t n = UnixDomainSocket::RecvMsgWithPid(
1005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      fd, buf, sizeof(buf), &message_fds, sender_pid);
1015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK_EQ(sizeof(kHello), static_cast<size_t>(n));
1025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK_EQ(0, memcmp(buf, kHello, sizeof(kHello)));
1035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK_EQ(1U, message_fds.size());
1045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (write_pipe)
1055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    write_pipe->swap(*message_fds[0]);
1065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
1075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Check that receiving PIDs works across a fork().
1095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSANDBOX_TEST(UnixDomainSocketTest, Fork) {
1105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  int fds[2];
1115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK_EQ(0, socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds));
1125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  base::ScopedFD recv_sock(fds[0]);
1135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  base::ScopedFD send_sock(fds[1]);
1145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK(UnixDomainSocket::EnableReceiveProcessId(recv_sock.get()));
1165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const pid_t pid = fork();
1185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK_NE(-1, pid);
1195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (pid == 0) {
1205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // Child process.
1215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    recv_sock.reset();
1225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    SendHello(send_sock.get());
1235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    _exit(0);
1245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
1255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Parent process.
1275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  send_sock.reset();
1285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  base::ProcessId sender_pid;
1305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  RecvHello(recv_sock.get(), &sender_pid);
1315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK_EQ(pid, sender_pid);
1325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  WaitForExit(pid);
1345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
1355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Similar to Fork above, but forking the child into a new pid namespace.
1375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSANDBOX_TEST(UnixDomainSocketTest, Namespace) {
1385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  FakeRoot();
1395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  int fds[2];
1415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK_EQ(0, socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds));
1425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  base::ScopedFD recv_sock(fds[0]);
1435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  base::ScopedFD send_sock(fds[1]);
1445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK(UnixDomainSocket::EnableReceiveProcessId(recv_sock.get()));
1465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const pid_t pid = syscall(__NR_clone, CLONE_NEWPID | SIGCHLD, 0, 0, 0);
1485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK_NE(-1, pid);
1495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (pid == 0) {
1505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // Child process.
1515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    recv_sock.reset();
1525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // Check that we think we're pid 1 in our new namespace.
1545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    CHECK_EQ(1, syscall(__NR_getpid));
1555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    SendHello(send_sock.get());
1575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    _exit(0);
1585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
1595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Parent process.
1615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  send_sock.reset();
1625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  base::ProcessId sender_pid;
1645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  RecvHello(recv_sock.get(), &sender_pid);
1655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK_EQ(pid, sender_pid);
1665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  WaitForExit(pid);
1685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
1695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Again similar to Fork, but now with nested PID namespaces.
1715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSANDBOX_TEST(UnixDomainSocketTest, DoubleNamespace) {
1725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  FakeRoot();
1735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  int fds[2];
1755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK_EQ(0, socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds));
1765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  base::ScopedFD recv_sock(fds[0]);
1775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  base::ScopedFD send_sock(fds[1]);
1785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK(UnixDomainSocket::EnableReceiveProcessId(recv_sock.get()));
1805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const pid_t pid = syscall(__NR_clone, CLONE_NEWPID | SIGCHLD, 0, 0, 0);
1825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK_NE(-1, pid);
1835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (pid == 0) {
1845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // Child process.
1855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    recv_sock.reset();
1865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const pid_t pid2 = syscall(__NR_clone, CLONE_NEWPID | SIGCHLD, 0, 0, 0);
1885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    CHECK_NE(-1, pid2);
1895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (pid2 != 0) {
1915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      // Wait for grandchild to run to completion; see comments below.
1925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      WaitForExit(pid2);
1935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      // Fallthrough once grandchild has sent its hello and exited.
1955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
1965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // Check that we think we're pid 1.
1985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    CHECK_EQ(1, syscall(__NR_getpid));
1995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    SendHello(send_sock.get());
2015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    _exit(0);
2025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
2035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Parent process.
2055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  send_sock.reset();
2065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // We have two messages to receive: first from the grand-child,
2085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // then from the child.
2095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  for (unsigned iteration = 0; iteration < 2; ++iteration) {
2105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    base::ProcessId sender_pid;
2115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    base::ScopedFD pipe_fd;
2125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    RecvHello(recv_sock.get(), &sender_pid, &pipe_fd);
2135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // We need our child and grandchild processes to both be alive for
2155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // GetParentProcessId() to return a valid pid, hence the pipe trickery.
2165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // (On the first iteration, grandchild is blocked reading from the pipe
2175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // until we close it, and child is blocked waiting for grandchild to exit.)
2185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    switch (iteration) {
2195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      case 0:  // Grandchild's message
2205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        // Check that sender_pid refers to our grandchild by checking that pid
2215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        // (our child) is its parent.
2225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        CHECK_EQ(pid, GetParentProcessId(sender_pid));
2235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        break;
2245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      case 1:  // Child's message
2255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        CHECK_EQ(pid, sender_pid);
2265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        break;
2275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      default:
2285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        NOTREACHED();
2295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
2305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
2315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  WaitForExit(pid);
2335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
2345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Tests that GetPeerPid() returns 0 if the peer does not exist in caller's
2365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// namespace.
2375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSANDBOX_TEST(UnixDomainSocketTest, ImpossiblePid) {
2385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  FakeRoot();
2395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  int fds[2];
2415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK_EQ(0, socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds));
2425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  base::ScopedFD send_sock(fds[0]);
2435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  base::ScopedFD recv_sock(fds[1]);
2445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK(UnixDomainSocket::EnableReceiveProcessId(recv_sock.get()));
2465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const pid_t pid = syscall(__NR_clone, CLONE_NEWPID | SIGCHLD, 0, 0, 0);
2485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK_NE(-1, pid);
2495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (pid == 0) {
2505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // Child process.
2515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    send_sock.reset();
2525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    base::ProcessId sender_pid;
2545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    RecvHello(recv_sock.get(), &sender_pid);
2555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    CHECK_EQ(0, sender_pid);
2565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    _exit(0);
2575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
2585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Parent process.
2605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  recv_sock.reset();
2615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  SendHello(send_sock.get());
2625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  WaitForExit(pid);
2635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
2645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}  // namespace
2665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}  // namespace sandbox
268