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