• 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/sandbox2.h"
16 
17 #include <fcntl.h>
18 #include <syscall.h>
19 #include <unistd.h>
20 
21 #include <csignal>
22 #include <memory>
23 #include <string>
24 #include <utility>
25 #include <vector>
26 
27 #include "gmock/gmock.h"
28 #include "gtest/gtest.h"
29 #include "absl/status/status.h"
30 #include "absl/strings/str_cat.h"
31 #include "absl/strings/string_view.h"
32 #include "absl/synchronization/notification.h"
33 #include "absl/time/clock.h"
34 #include "absl/time/time.h"
35 #include "sandboxed_api/config.h"
36 #include "sandboxed_api/sandbox2/executor.h"
37 #include "sandboxed_api/sandbox2/fork_client.h"
38 #include "sandboxed_api/sandbox2/policy.h"
39 #include "sandboxed_api/sandbox2/policybuilder.h"
40 #include "sandboxed_api/sandbox2/result.h"
41 #include "sandboxed_api/testing.h"
42 #include "sandboxed_api/util/status_matchers.h"
43 #include "sandboxed_api/util/thread.h"
44 
45 namespace sandbox2 {
46 namespace {
47 
48 using ::sapi::CreateDefaultPermissiveTestPolicy;
49 using ::sapi::GetTestSourcePath;
50 using ::sapi::IsOk;
51 using ::testing::Eq;
52 using ::testing::IsEmpty;
53 using ::testing::IsFalse;
54 using ::testing::IsTrue;
55 using ::testing::Lt;
56 using ::testing::Ne;
57 
58 class Sandbox2Test : public ::testing::TestWithParam<bool> {
59  public:
CreateDefaultTestPolicy(absl::string_view path)60   PolicyBuilder CreateDefaultTestPolicy(absl::string_view path) {
61     PolicyBuilder builder = CreateDefaultPermissiveTestPolicy(path);
62     if (GetParam()) {
63       builder.CollectStacktracesOnSignal(false);
64     }
65     return builder;
66   }
SetUpSandbox(Sandbox2 * sandbox)67   absl::Status SetUpSandbox(Sandbox2* sandbox) {
68     return GetParam() ? sandbox->EnableUnotifyMonitor() : absl::OkStatus();
69   }
70 };
71 
72 // Test that aborting inside a sandbox with all userspace core dumping
73 // disabled reports the signal.
TEST_P(Sandbox2Test,AbortWithoutCoreDumpReturnsSignaled)74 TEST_P(Sandbox2Test, AbortWithoutCoreDumpReturnsSignaled) {
75   const std::string path = GetTestSourcePath("sandbox2/testcases/abort");
76   std::vector<std::string> args = {
77       path,
78   };
79   auto executor = std::make_unique<Executor>(path, args);
80 
81   SAPI_ASSERT_OK_AND_ASSIGN(
82       auto policy,
83       CreateDefaultTestPolicy(path)
84           .TryBuild());
85   Sandbox2 sandbox(std::move(executor), std::move(policy));
86   ASSERT_THAT(SetUpSandbox(&sandbox), IsOk());
87   auto result = sandbox.Run();
88 
89   ASSERT_THAT(result.final_status(), Eq(Result::SIGNALED));
90   EXPECT_THAT(result.reason_code(), Eq(SIGABRT));
91 }
92 
93 // Test that with TSYNC we are able to sandbox when multithreaded.
TEST_P(Sandbox2Test,TsyncNoMemoryChecks)94 TEST_P(Sandbox2Test, TsyncNoMemoryChecks) {
95   const std::string path = GetTestSourcePath("sandbox2/testcases/tsync");
96 
97   auto executor =
98       std::make_unique<Executor>(path, std::vector<std::string>{path});
99   executor->set_enable_sandbox_before_exec(false);
100 
101   SAPI_ASSERT_OK_AND_ASSIGN(auto policy,
102                             CreateDefaultTestPolicy(path).TryBuild());
103   Sandbox2 sandbox(std::move(executor), std::move(policy));
104   ASSERT_THAT(SetUpSandbox(&sandbox), IsOk());
105   auto result = sandbox.Run();
106 
107   // With TSYNC, SandboxMeHere should be able to sandbox when multithreaded.
108   ASSERT_EQ(result.final_status(), Result::OK);
109   ASSERT_EQ(result.reason_code(), 0);
110 }
111 
112 // Tests whether Executor(fd, std::vector<std::string>{path}, envp) constructor
113 // works as expected.
TEST(ExecutorTest,ExecutorFdConstructor)114 TEST(ExecutorTest, ExecutorFdConstructor) {
115   const std::string path = GetTestSourcePath("sandbox2/testcases/minimal");
116   int fd = open(path.c_str(), O_RDONLY);
117   ASSERT_NE(fd, -1);
118 
119   std::vector<std::string> args = {absl::StrCat("FD:", fd)};
120   auto executor = std::make_unique<Executor>(fd, args);
121 
122   SAPI_ASSERT_OK_AND_ASSIGN(auto policy,
123                             CreateDefaultPermissiveTestPolicy(path).TryBuild());
124   Sandbox2 sandbox(std::move(executor), std::move(policy));
125   auto result = sandbox.Run();
126 
127   EXPECT_THAT(sandbox.IsTerminated(), IsTrue());
128   ASSERT_EQ(result.final_status(), Result::OK);
129 }
130 
131 // Tests that we return the correct state when the sandboxee was killed by an
132 // external signal. Also make sure that we do not have the stack trace.
TEST_P(Sandbox2Test,SandboxeeExternalKill)133 TEST_P(Sandbox2Test, SandboxeeExternalKill) {
134   const std::string path = GetTestSourcePath("sandbox2/testcases/sleep");
135 
136   std::vector<std::string> args = {path};
137   auto executor = std::make_unique<Executor>(path, args);
138 
139   SAPI_ASSERT_OK_AND_ASSIGN(auto policy,
140                             CreateDefaultTestPolicy(path).TryBuild());
141   Sandbox2 sandbox(std::move(executor), std::move(policy));
142   ASSERT_THAT(SetUpSandbox(&sandbox), IsOk());
143   ASSERT_TRUE(sandbox.RunAsync());
144   EXPECT_THAT(sandbox.IsTerminated(), IsFalse());
145   absl::SleepFor(absl::Seconds(1));
146   sandbox.Kill();
147   auto result = sandbox.AwaitResult();
148   EXPECT_THAT(sandbox.IsTerminated(), IsTrue());
149   EXPECT_EQ(result.final_status(), Result::EXTERNAL_KILL);
150   EXPECT_THAT(result.stack_trace(), IsEmpty());
151 }
152 
TEST_P(Sandbox2Test,SandboxeeKillDontAwait)153 TEST_P(Sandbox2Test, SandboxeeKillDontAwait) {
154   const std::string path = GetTestSourcePath("sandbox2/testcases/sleep");
155 
156   std::vector<std::string> args = {path};
157   auto executor = std::make_unique<Executor>(path, args);
158 
159   SAPI_ASSERT_OK_AND_ASSIGN(auto policy,
160                             CreateDefaultTestPolicy(path).TryBuild());
161   absl::Time kill_time;
162   {
163     Sandbox2 sandbox(std::move(executor), std::move(policy));
164     ASSERT_THAT(SetUpSandbox(&sandbox), IsOk());
165     ASSERT_TRUE(sandbox.RunAsync());
166     EXPECT_THAT(sandbox.IsTerminated(), IsFalse());
167     absl::SleepFor(absl::Seconds(1));
168     sandbox.Kill();
169     kill_time = absl::Now();
170   }
171   absl::Duration elapsed = absl::Now() - kill_time;
172   EXPECT_THAT(elapsed, Lt(absl::Milliseconds(200)));
173 }
174 
175 // Tests that we do not collect stack traces if it was disabled (signaled).
TEST_P(Sandbox2Test,SandboxeeTimeoutDisabledStacktraces)176 TEST_P(Sandbox2Test, SandboxeeTimeoutDisabledStacktraces) {
177   const std::string path = GetTestSourcePath("sandbox2/testcases/sleep");
178 
179   std::vector<std::string> args = {path};
180   auto executor = std::make_unique<Executor>(path, args);
181 
182   SAPI_ASSERT_OK_AND_ASSIGN(auto policy, CreateDefaultTestPolicy(path)
183                                              .CollectStacktracesOnTimeout(false)
184                                              .TryBuild());
185   Sandbox2 sandbox(std::move(executor), std::move(policy));
186   ASSERT_THAT(SetUpSandbox(&sandbox), IsOk());
187   absl::Time start_time = absl::Now();
188   ASSERT_TRUE(sandbox.RunAsync());
189   sandbox.set_walltime_limit(absl::Seconds(1));
190   auto result = sandbox.AwaitResult();
191   EXPECT_EQ(result.final_status(), Result::TIMEOUT);
192   auto elapsed = absl::Now() - start_time;
193   EXPECT_THAT(elapsed, Lt(absl::Seconds(2)));
194   EXPECT_THAT(result.stack_trace(), IsEmpty());
195 }
196 
197 // Tests that we do not collect stack traces if it was disabled (violation).
TEST(Sandbox2Test,SandboxeeViolationDisabledStacktraces)198 TEST(Sandbox2Test, SandboxeeViolationDisabledStacktraces) {
199   const std::string path = GetTestSourcePath("sandbox2/testcases/sleep");
200 
201   std::vector<std::string> args = {path};
202   auto executor = std::make_unique<Executor>(path, args);
203 
204   SAPI_ASSERT_OK_AND_ASSIGN(
205       auto policy, PolicyBuilder()
206                        // Don't allow anything - Make sure that we'll crash.
207                        .CollectStacktracesOnViolation(false)
208                        .TryBuild());
209   Sandbox2 sandbox(std::move(executor), std::move(policy));
210   ASSERT_TRUE(sandbox.RunAsync());
211   auto result = sandbox.AwaitResult();
212   EXPECT_EQ(result.final_status(), Result::VIOLATION);
213   EXPECT_THAT(result.stack_trace(), IsEmpty());
214 }
215 
TEST_P(Sandbox2Test,SandboxeeNotKilledWhenStartingThreadFinishes)216 TEST_P(Sandbox2Test, SandboxeeNotKilledWhenStartingThreadFinishes) {
217   const std::string path = GetTestSourcePath("sandbox2/testcases/minimal");
218   std::vector<std::string> args = {path};
219   auto executor = std::make_unique<Executor>(path, args);
220 
221   SAPI_ASSERT_OK_AND_ASSIGN(auto policy,
222                             CreateDefaultTestPolicy(path).TryBuild());
223   Sandbox2 sandbox(std::move(executor), std::move(policy));
224   ASSERT_THAT(SetUpSandbox(&sandbox), IsOk());
225   sapi::Thread sandbox_start_thread([&sandbox]() { sandbox.RunAsync(); });
226   sandbox_start_thread.Join();
227   Result result = sandbox.AwaitResult();
228   EXPECT_EQ(result.final_status(), Result::OK);
229 }
230 
TEST_P(Sandbox2Test,CustomForkserverWorks)231 TEST_P(Sandbox2Test, CustomForkserverWorks) {
232   const std::string path = GetTestSourcePath("sandbox2/testcases/custom_fork");
233   std::vector<std::string> args = {path};
234   auto fork_executor = std::make_unique<Executor>(path, args);
235   std::unique_ptr<ForkClient> fork_client = fork_executor->StartForkServer();
236   ASSERT_THAT(fork_client.get(), Ne(nullptr));
237 
238   SAPI_ASSERT_OK_AND_ASSIGN(auto policy,
239                             CreateDefaultTestPolicy(path).TryBuild());
240 
241   Sandbox2 sandbox(std::make_unique<Executor>(fork_client.get()),
242                    std::move(policy));
243   ASSERT_THAT(SetUpSandbox(&sandbox), IsOk());
244   Result result = sandbox.Run();
245   EXPECT_EQ(result.final_status(), Result::OK);
246 }
247 
TEST(StarvationTest,MonitorIsNotStarvedByTheSandboxee)248 TEST(StarvationTest, MonitorIsNotStarvedByTheSandboxee) {
249   const std::string path = GetTestSourcePath("sandbox2/testcases/starve");
250 
251   std::vector<std::string> args = {path};
252   auto executor = std::make_unique<Executor>(path, args);
253   executor->limits()->set_walltime_limit(absl::Seconds(5));
254 
255   SAPI_ASSERT_OK_AND_ASSIGN(auto policy,
256                             CreateDefaultPermissiveTestPolicy(path).TryBuild());
257   Sandbox2 sandbox(std::move(executor), std::move(policy));
258 
259   auto start = absl::Now();
260   ASSERT_THAT(sandbox.RunAsync(), IsTrue());
261   auto result = sandbox.AwaitResult();
262   EXPECT_THAT(result.final_status(), Eq(Result::TIMEOUT));
263 
264   auto elapsed = absl::Now() - start;
265   EXPECT_THAT(elapsed, Lt(absl::Seconds(10)));
266 }
267 
268 INSTANTIATE_TEST_SUITE_P(Sandbox2, Sandbox2Test, ::testing::Values(false, true),
__anon5bded7f90302(const ::testing::TestParamInfo<bool>& info) 269                          [](const ::testing::TestParamInfo<bool>& info) {
270                            return info.param ? "UnotifyMonitor"
271                                              : "PtraceMonitor";
272                          });
273 
274 }  // namespace
275 }  // namespace sandbox2
276