xref: /aosp_15_r20/external/sandboxed-api/sandboxed_api/sandbox2/sandbox2_test.cc (revision ec63e07ab9515d95e79c211197c445ef84cefa6a)
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