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