xref: /aosp_15_r20/external/sandboxed-api/sandboxed_api/sandbox2/testcases/network_proxy.cc (revision ec63e07ab9515d95e79c211197c445ef84cefa6a)
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 // A binary doing various malloc calls to check that the malloc policy works as
16 // expected.
17 // This file is an example of a network sandboxed binary inside a network
18 // namespace. It can't connect with the server directly, but the executor can
19 // establish a connection and pass the connected socket to the sandboxee.
20 
21 #include <arpa/inet.h>
22 #include <netinet/in.h>
23 #include <sys/socket.h>
24 #include <sys/types.h>
25 #include <unistd.h>
26 
27 #include <cerrno>
28 #include <cstdint>
29 #include <cstring>
30 #include <variant>
31 
32 #include "absl/base/log_severity.h"
33 #include "absl/flags/flag.h"
34 #include "absl/flags/parse.h"
35 #include "absl/log/check.h"
36 #include "absl/log/globals.h"
37 #include "absl/log/initialize.h"
38 #include "absl/log/log.h"
39 #include "absl/status/status.h"
40 #include "absl/status/statusor.h"
41 #include "absl/strings/str_format.h"
42 #include "absl/strings/string_view.h"
43 #include "sandboxed_api/sandbox2/client.h"
44 #include "sandboxed_api/sandbox2/comms.h"
45 #include "sandboxed_api/sandbox2/network_proxy/client.h"
46 #include "sandboxed_api/util/fileops.h"
47 #include "sandboxed_api/util/status_macros.h"
48 
49 ABSL_FLAG(bool, connect_with_handler, true, "Connect using automatic mode.");
50 ABSL_FLAG(bool, ipv6, false, "Use IPv6.");
51 
52 namespace {
53 
54 using ::sapi::file_util::fileops::FDCloser;
55 
56 struct IPAddr {
GetSize__anonb87c6c420111::IPAddr57   size_t GetSize() const {
58     return addr.index() == 0 ? sizeof(sockaddr_in) : sizeof(sockaddr_in6);
59   }
GetPtr__anonb87c6c420111::IPAddr60   const sockaddr* GetPtr() const {
61     return addr.index() == 0
62                ? reinterpret_cast<const sockaddr*>(&std::get<0>(addr))
63                : reinterpret_cast<const sockaddr*>(&std::get<1>(addr));
64   }
65   std::variant<sockaddr_in, sockaddr_in6> addr;
66 };
67 
68 static sandbox2::NetworkProxyClient* g_proxy_client;
69 
ReadFromFd(int fd,uint8_t * buf,size_t size)70 ssize_t ReadFromFd(int fd, uint8_t* buf, size_t size) {
71   ssize_t received = 0;
72   while (received < size) {
73     ssize_t read_status =
74         TEMP_FAILURE_RETRY(read(fd, &buf[received], size - received));
75     if (read_status == 0) {
76       break;
77     }
78     if (read_status < 0) {
79       return -1;
80     }
81     received += read_status;
82   }
83   return received;
84 }
85 
CommunicationTest(int sock)86 absl::Status CommunicationTest(int sock) {
87   char received[1025] = {0};
88 
89   if (ReadFromFd(sock, reinterpret_cast<uint8_t*>(received),
90                  sizeof(received) - 1) <= 0) {
91     return absl::InternalError("Data receiving error");
92   }
93   absl::PrintF("Sandboxee received data from the server:\n\n%s\n", received);
94   if (strcmp(received, "Hello World\n")) {
95     return absl::InternalError("Data receiving error");
96   }
97   return absl::OkStatus();
98 }
99 
CreateAddress(int port)100 IPAddr CreateAddress(int port) {
101   static struct sockaddr_in saddr4 {};
102   static struct sockaddr_in6 saddr6 {};
103   saddr4.sin_family = AF_INET;
104   saddr6.sin6_family = AF_INET6;
105   saddr4.sin_port = saddr6.sin6_port = htons(port);
106   PCHECK(inet_pton(AF_INET6, "::1", &saddr6.sin6_addr) == 1);
107   PCHECK(inet_pton(AF_INET, "127.0.0.1", &saddr4.sin_addr) == 1);
108   return absl::GetFlag(FLAGS_ipv6) ? IPAddr{.addr = saddr6}
109                                    : IPAddr{.addr = saddr4};
110 }
111 
ConnectWithoutHandler(int s,IPAddr saddr)112 absl::Status ConnectWithoutHandler(int s, IPAddr saddr) {
113   return g_proxy_client->Connect(s, saddr.GetPtr(), saddr.GetSize());
114 }
115 
ConnectWithHandler(int s,IPAddr saddr)116 absl::Status ConnectWithHandler(int s, IPAddr saddr) {
117   int err = connect(s, saddr.GetPtr(), saddr.GetSize());
118   if (err != 0) {
119     return absl::InternalError("connect() failed");
120   }
121 
122   return absl::OkStatus();
123 }
124 
ConnectToServer(int port)125 absl::StatusOr<FDCloser> ConnectToServer(int port) {
126   IPAddr addr = CreateAddress(port);
127 
128   FDCloser s(
129       socket(absl::GetFlag(FLAGS_ipv6) ? AF_INET6 : AF_INET, SOCK_STREAM, 0));
130   if (s.get() < 0) {
131     return absl::ErrnoToStatus(errno, "socket()");
132   }
133 
134   if (absl::GetFlag(FLAGS_connect_with_handler)) {
135     SAPI_RETURN_IF_ERROR(ConnectWithHandler(s.get(), addr));
136   } else {
137     SAPI_RETURN_IF_ERROR(ConnectWithoutHandler(s.get(), addr));
138   }
139 
140   LOG(INFO) << "Connected to the server";
141   return s;
142 }
143 
144 }  // namespace
145 
main(int argc,char * argv[])146 int main(int argc, char* argv[]) {
147   absl::SetStderrThreshold(absl::LogSeverityAtLeast::kInfo);
148   absl::ParseCommandLine(argc, argv);
149   absl::InitializeLog();
150 
151   // Set-up the sandbox2::Client object, using a file descriptor (1023).
152   sandbox2::Comms comms(sandbox2::Comms::kDefaultConnection);
153   sandbox2::Client sandbox2_client(&comms);
154 
155   if (absl::GetFlag(FLAGS_connect_with_handler)) {
156     if (auto status = sandbox2_client.InstallNetworkProxyHandler();
157         !status.ok()) {
158       LOG(ERROR) << "InstallNetworkProxyHandler() failed: " << status;
159       return 1;
160     }
161   } else {
162     g_proxy_client = sandbox2_client.GetNetworkProxyClient();
163   }
164 
165   // Receive port number of the server
166   int port;
167   if (!comms.RecvInt32(&port)) {
168     LOG(ERROR) << "Failed to receive port number";
169     return 2;
170   }
171 
172   absl::StatusOr<FDCloser> client = ConnectToServer(port);
173   if (!client.ok()) {
174     LOG(ERROR) << client.status();
175     return 3;
176   }
177 
178   if (auto status = CommunicationTest(client->get()); !status.ok()) {
179     LOG(ERROR) << status;
180     return 4;
181   }
182   return 0;
183 }
184