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