• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 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 <syscall.h>
16 
17 #include <cstdlib>
18 #include <memory>
19 #include <string>
20 #include <tuple>
21 #include <utility>
22 #include <vector>
23 
24 #include "gmock/gmock.h"
25 #include "gtest/gtest.h"
26 #include "absl/status/status.h"
27 #include "absl/time/time.h"
28 #include "sandboxed_api/sandbox2/executor.h"
29 #include "sandboxed_api/sandbox2/network_proxy/testing.h"
30 #include "sandboxed_api/sandbox2/policybuilder.h"
31 #include "sandboxed_api/sandbox2/result.h"
32 #include "sandboxed_api/sandbox2/sandbox2.h"
33 #include "sandboxed_api/testing.h"
34 #include "sandboxed_api/util/status_matchers.h"
35 
36 namespace sandbox2 {
37 namespace {
38 
39 using ::sapi::GetTestSourcePath;
40 using ::sapi::StatusIs;
41 using ::testing::Eq;
42 
TEST(NetworkProxyTest,NoDoublePolicy)43 TEST(NetworkProxyTest, NoDoublePolicy) {
44   PolicyBuilder builder;
45   builder.AddNetworkProxyHandlerPolicy().AddNetworkProxyPolicy();
46   EXPECT_THAT(builder.TryBuild(),
47               StatusIs(absl::StatusCode::kFailedPrecondition));
48 }
49 
TEST(NetworkProxyTest,NoDoublePolicyHandler)50 TEST(NetworkProxyTest, NoDoublePolicyHandler) {
51   PolicyBuilder builder;
52   builder.AddNetworkProxyPolicy().AddNetworkProxyHandlerPolicy();
53   EXPECT_THAT(builder.TryBuild(),
54               StatusIs(absl::StatusCode::kFailedPrecondition));
55 }
56 
TEST(NetworkProxyTest,NoNetworkPolicyIpv4)57 TEST(NetworkProxyTest, NoNetworkPolicyIpv4) {
58   PolicyBuilder builder;
59   builder.AllowIPv4("127.0.0.1");
60   EXPECT_THAT(builder.TryBuild(),
61               StatusIs(absl::StatusCode::kFailedPrecondition));
62 }
63 
TEST(NetworkProxyTest,NoNetworkPolicyIpv6)64 TEST(NetworkProxyTest, NoNetworkPolicyIpv6) {
65   PolicyBuilder builder;
66   builder.AllowIPv6("::1");
67   EXPECT_THAT(builder.TryBuild(),
68               StatusIs(absl::StatusCode::kFailedPrecondition));
69 }
70 
TEST(NetworkProxyTest,WrongIPv4)71 TEST(NetworkProxyTest, WrongIPv4) {
72   PolicyBuilder builder;
73   builder.AddNetworkProxyPolicy().AllowIPv4("256.256.256.256");
74   EXPECT_THAT(builder.TryBuild(), StatusIs(absl::StatusCode::kInvalidArgument));
75 }
76 
TEST(NetworkProxyTest,WrongIPv6)77 TEST(NetworkProxyTest, WrongIPv6) {
78   PolicyBuilder builder;
79   builder.AddNetworkProxyPolicy().AllowIPv6("127.0.0.1");
80   EXPECT_THAT(builder.TryBuild(), StatusIs(absl::StatusCode::kInvalidArgument));
81 }
82 
83 using NetworkProxyTest = ::testing::TestWithParam<std::tuple<bool, bool>>;
84 
TEST_P(NetworkProxyTest,ProxyWithHandlerAllowed)85 TEST_P(NetworkProxyTest, ProxyWithHandlerAllowed) {
86   SKIP_SANITIZERS;
87   const auto [ipv6, use_unotify] = GetParam();
88   const std::string path =
89       GetTestSourcePath("sandbox2/testcases/network_proxy");
90   std::vector<std::string> args = {"network_proxy"};
91   if (ipv6) {
92     args.push_back("--ipv6");
93   }
94   auto executor = std::make_unique<Executor>(path, args);
95   executor->limits()->set_walltime_limit(absl::Seconds(3));
96 
97   PolicyBuilder builder;
98   builder.AllowDynamicStartup()
99       .AllowWrite()
100       .AllowRead()
101       .AllowExit()
102       .AllowSyscall(__NR_sendto)
103       .AllowTcMalloc()
104       .AddNetworkProxyHandlerPolicy()
105       .AllowLlvmCoverage()
106       .AddLibrariesForBinary(path);
107 
108   if (use_unotify) {
109     builder.CollectStacktracesOnSignal(false);
110   }
111   if (ipv6) {
112     builder.AllowIPv6("::1");
113   } else {
114     builder.AllowIPv4("127.0.0.1");
115   }
116 
117   SAPI_ASSERT_OK_AND_ASSIGN(auto policy, builder.TryBuild());
118 
119   Sandbox2 s2(std::move(executor), std::move(policy));
120   if (use_unotify) {
121     ASSERT_THAT(s2.EnableUnotifyMonitor(), sapi::IsOk());
122   }
123   ASSERT_TRUE(s2.RunAsync());
124 
125   SAPI_ASSERT_OK_AND_ASSIGN(auto server, NetworkProxyTestServer::Start(ipv6));
126   ASSERT_TRUE(s2.comms()->SendInt32(server->port()));
127 
128   sandbox2::Result result = s2.AwaitResult();
129   ASSERT_THAT(result.final_status(), Eq(Result::OK));
130   EXPECT_THAT(result.reason_code(), Eq(EXIT_SUCCESS));
131 }
132 
TEST_P(NetworkProxyTest,ProxyWithHandlerNotAllowed)133 TEST_P(NetworkProxyTest, ProxyWithHandlerNotAllowed) {
134   SKIP_SANITIZERS;
135   const auto [ipv6, use_unotify] = GetParam();
136   const std::string path =
137       GetTestSourcePath("sandbox2/testcases/network_proxy");
138   std::vector<std::string> args = {"network_proxy"};
139   if (ipv6) {
140     args.push_back("--ipv6");
141   }
142   auto executor = std::make_unique<Executor>(path, args);
143   executor->limits()->set_walltime_limit(absl::Seconds(3));
144 
145   PolicyBuilder builder;
146   builder.AllowDynamicStartup()
147       .AllowWrite()
148       .AllowRead()
149       .AllowExit()
150       .AllowSyscall(__NR_sendto)
151       .AllowTcMalloc()
152       .AddNetworkProxyHandlerPolicy()
153       .AllowLlvmCoverage()
154       .AddLibrariesForBinary(path);
155   if (use_unotify) {
156     builder.CollectStacktracesOnSignal(false);
157   }
158   SAPI_ASSERT_OK_AND_ASSIGN(auto policy, builder.TryBuild());
159 
160   Sandbox2 s2(std::move(executor), std::move(policy));
161   if (use_unotify) {
162     ASSERT_THAT(s2.EnableUnotifyMonitor(), sapi::IsOk());
163   }
164   ASSERT_TRUE(s2.RunAsync());
165 
166   SAPI_ASSERT_OK_AND_ASSIGN(auto server, NetworkProxyTestServer::Start(ipv6));
167   ASSERT_TRUE(s2.comms()->SendInt32(server->port()));
168 
169   sandbox2::Result result = s2.AwaitResult();
170   ASSERT_THAT(result.final_status(), Eq(Result::VIOLATION));
171   EXPECT_THAT(result.reason_code(), Eq(Result::VIOLATION_NETWORK));
172 }
173 
TEST_P(NetworkProxyTest,ProxyWithoutHandlerAllowed)174 TEST_P(NetworkProxyTest, ProxyWithoutHandlerAllowed) {
175   SKIP_SANITIZERS;
176   const auto [ipv6, use_unotify] = GetParam();
177   const std::string path =
178       GetTestSourcePath("sandbox2/testcases/network_proxy");
179   std::vector<std::string> args = {"network_proxy", "--noconnect_with_handler"};
180   if (ipv6) {
181     args.push_back("--ipv6");
182   }
183   auto executor = std::make_unique<Executor>(path, args);
184   executor->limits()->set_walltime_limit(absl::Seconds(3));
185 
186   PolicyBuilder builder;
187   builder.AllowDynamicStartup()
188       .AllowExit()
189       .AllowWrite()
190       .AllowRead()
191       .AllowSyscall(__NR_sendto)
192       .AllowTcMalloc()
193       .AddNetworkProxyHandlerPolicy()
194       .AllowLlvmCoverage()
195       .AddLibrariesForBinary(path);
196   if (use_unotify) {
197     builder.CollectStacktracesOnSignal(false);
198   }
199   if (ipv6) {
200     builder.AllowIPv6("::1");
201   } else {
202     builder.AllowIPv4("127.0.0.1");
203   }
204 
205   SAPI_ASSERT_OK_AND_ASSIGN(auto policy, builder.TryBuild());
206 
207   Sandbox2 s2(std::move(executor), std::move(policy));
208   if (use_unotify) {
209     ASSERT_THAT(s2.EnableUnotifyMonitor(), sapi::IsOk());
210   }
211   ASSERT_TRUE(s2.RunAsync());
212 
213   SAPI_ASSERT_OK_AND_ASSIGN(auto server, NetworkProxyTestServer::Start(ipv6));
214   ASSERT_TRUE(s2.comms()->SendInt32(server->port()));
215 
216   sandbox2::Result result = s2.AwaitResult();
217   ASSERT_THAT(result.final_status(), Eq(Result::OK));
218   EXPECT_THAT(result.reason_code(), Eq(EXIT_SUCCESS));
219 }
220 
TEST(NetworkProxyTest,ProxyNonExistantAddress)221 TEST(NetworkProxyTest, ProxyNonExistantAddress) {
222   // Creates a IPv6 server tries to connect with IPv4
223   SKIP_SANITIZERS;
224   const std::string path =
225       GetTestSourcePath("sandbox2/testcases/network_proxy");
226   std::vector<std::string> args = {"network_proxy", "--noconnect_with_handler"};
227   auto executor = std::make_unique<Executor>(path, args);
228   executor->limits()->set_walltime_limit(absl::Seconds(3));
229 
230   PolicyBuilder builder;
231   builder.AllowDynamicStartup()
232       .AllowExit()
233       .AllowWrite()
234       .AllowRead()
235       .AllowSyscall(__NR_sendto)
236       .AllowTcMalloc()
237       .AddNetworkProxyHandlerPolicy()
238       .AllowLlvmCoverage()
239       .AddLibrariesForBinary(path)
240       .AllowIPv4("127.0.0.1");
241 
242   SAPI_ASSERT_OK_AND_ASSIGN(auto policy, builder.TryBuild());
243 
244   Sandbox2 s2(std::move(executor), std::move(policy));
245   ASSERT_TRUE(s2.RunAsync());
246 
247   SAPI_ASSERT_OK_AND_ASSIGN(auto server,
248                             NetworkProxyTestServer::Start(/*ipv6=*/true));
249   ASSERT_TRUE(s2.comms()->SendInt32(server->port()));
250 
251   sandbox2::Result result = s2.AwaitResult();
252   ASSERT_THAT(result.final_status(), Eq(Result::OK));
253   EXPECT_THAT(result.reason_code(), Eq(3));
254 }
255 
256 INSTANTIATE_TEST_SUITE_P(NetworkProxyTest, NetworkProxyTest,
257                          ::testing::Combine(::testing::Bool(),
258                                             ::testing::Bool()));
259 
260 }  // namespace
261 }  // namespace sandbox2
262