• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "sandboxed_api/sandbox2/forkserver.h"
16 
17 #include <fcntl.h>
18 #include <sys/socket.h>
19 #include <sys/wait.h>
20 #include <unistd.h>
21 
22 #include <string>
23 
24 #include "gtest/gtest.h"
25 #include "absl/log/check.h"
26 #include "absl/log/log.h"
27 #include "absl/strings/str_cat.h"
28 #include "sandboxed_api/sandbox2/forkserver.pb.h"
29 #include "sandboxed_api/sandbox2/global_forkclient.h"
30 #include "sandboxed_api/sandbox2/ipc.h"
31 #include "sandboxed_api/testing.h"
32 
33 namespace sandbox2 {
34 
35 using ::sapi::GetTestSourcePath;
36 
37 class IpcPeer {
38  public:
IpcPeer(IPC * ipc)39   explicit IpcPeer(IPC* ipc) : ipc_(ipc) {}
40 
SetUpServerSideComms(int fd)41   void SetUpServerSideComms(int fd) { ipc_->SetUpServerSideComms(fd); }
42 
43  private:
44   IPC* ipc_;
45 };
46 
GetMinimalTestcaseFd()47 int GetMinimalTestcaseFd() {
48   const std::string path = GetTestSourcePath("sandbox2/testcases/minimal");
49   return open(path.c_str(), O_RDONLY);
50 }
51 
TestSingleRequest(Mode mode,int exec_fd)52 pid_t TestSingleRequest(Mode mode, int exec_fd) {
53   ForkRequest fork_req;
54   IPC ipc;
55   int sv[2];
56   // Setup IPC
57   PCHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != -1);
58   IpcPeer{&ipc}.SetUpServerSideComms(sv[1]);
59   // Setup fork_req
60   fork_req.set_mode(mode);
61   fork_req.add_args("/binary");
62   fork_req.add_envs("FOO=1");
63 
64   SandboxeeProcess process =
65       GlobalForkClient::SendRequest(fork_req, exec_fd, sv[0]);
66   if (process.main_pid != -1) {
67     VLOG(1) << "TestSingleRequest: Waiting for pid=" << process.main_pid;
68     waitpid(process.main_pid, nullptr, 0);
69   }
70 
71   close(sv[0]);
72   return process.main_pid;
73 }
74 
TEST(ForkserverTest,SimpleFork)75 TEST(ForkserverTest, SimpleFork) {
76   // Make sure that the regular fork request works.
77   ASSERT_NE(TestSingleRequest(FORKSERVER_FORK, -1), -1);
78 }
79 
TEST(ForkserverTest,SimpleForkNoZombie)80 TEST(ForkserverTest, SimpleForkNoZombie) {
81   // Make sure that we don't create zombies.
82   pid_t child = TestSingleRequest(FORKSERVER_FORK, -1);
83   ASSERT_NE(child, -1);
84   std::string proc = absl::StrCat("/proc/", child, "/cmdline");
85 
86   // Give the kernel some time to clean up.
87   // Poll every 10ms up to 500 times (5s)
88   bool process_reaped = false;
89   for (int i = 0; i < 500; i++) {
90     if (access(proc.c_str(), F_OK) == -1) {
91       process_reaped = true;
92       break;
93     }
94     usleep(10 * 1000);  // 10 ms
95   }
96   EXPECT_TRUE(process_reaped);
97 }
98 
TEST(ForkserverTest,ForkExecveWorks)99 TEST(ForkserverTest, ForkExecveWorks) {
100   // Run a test binary through the FORK_EXECVE request.
101   int exec_fd = GetMinimalTestcaseFd();
102   PCHECK(exec_fd != -1) << "Could not open test binary";
103   ASSERT_NE(TestSingleRequest(FORKSERVER_FORK_EXECVE, exec_fd), -1);
104 }
105 
TEST(ForkserverTest,ForkExecveSandboxWithoutPolicy)106 TEST(ForkserverTest, ForkExecveSandboxWithoutPolicy) {
107   // Run a test binary through the FORKSERVER_FORK_EXECVE_SANDBOX request.
108   int exec_fd = GetMinimalTestcaseFd();
109   PCHECK(exec_fd != -1) << "Could not open test binary";
110 }
111 
112 }  // namespace sandbox2
113