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