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