xref: /aosp_15_r20/external/sandboxed-api/sandboxed_api/sandbox2/network_proxy/server.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/network_proxy/server.h"
16 
17 #include <netinet/in.h>
18 #include <pthread.h>
19 #include <signal.h>
20 #include <sys/socket.h>
21 #include <sys/types.h>
22 
23 #include <atomic>
24 #include <cerrno>
25 #include <cstdint>
26 #include <memory>
27 #include <string>
28 #include <utility>
29 #include <vector>
30 
31 #include "absl/log/log.h"
32 #include "absl/status/status.h"
33 #include "absl/status/statusor.h"
34 #include "sandboxed_api/sandbox2/comms.h"
35 #include "sandboxed_api/sandbox2/network_proxy/filtering.h"
36 #include "sandboxed_api/util/fileops.h"
37 
38 namespace sandbox2 {
39 
40 namespace file_util = ::sapi::file_util;
41 
NetworkProxyServer(int fd,AllowedHosts * allowed_hosts,pthread_t monitor_thread_id)42 NetworkProxyServer::NetworkProxyServer(int fd, AllowedHosts* allowed_hosts,
43                                        pthread_t monitor_thread_id)
44     : violation_occurred_(false),
45       comms_(std::make_unique<Comms>(fd)),
46       fatal_error_(false),
47       monitor_thread_id_(monitor_thread_id),
48       allowed_hosts_(allowed_hosts) {}
49 
ProcessConnectRequest()50 void NetworkProxyServer::ProcessConnectRequest() {
51   std::vector<uint8_t> addr;
52   if (!comms_->RecvBytes(&addr)) {
53     fatal_error_ = true;
54     return;
55   }
56 
57   const struct sockaddr* saddr = reinterpret_cast<const sockaddr*>(addr.data());
58 
59   // Only IPv4 TCP and IPv6 TCP are supported.
60   if (!((addr.size() == sizeof(sockaddr_in) && saddr->sa_family == AF_INET) ||
61         (addr.size() == sizeof(sockaddr_in6) &&
62          saddr->sa_family == AF_INET6))) {
63     SendError(EINVAL);
64     return;
65   }
66 
67   if (!allowed_hosts_->IsHostAllowed(saddr)) {
68     NotifyViolation(saddr);
69     return;
70   }
71 
72   int new_socket = socket(saddr->sa_family, SOCK_STREAM, 0);
73   if (new_socket < 0) {
74     SendError(errno);
75     return;
76   }
77 
78   file_util::fileops::FDCloser new_socket_closer(new_socket);
79 
80   int result = connect(
81       new_socket, reinterpret_cast<const sockaddr*>(addr.data()), addr.size());
82 
83   if (result < 0) {
84     SendError(errno);
85     return;
86   }
87 
88   NotifySuccess();
89   if (!fatal_error_ && !comms_->SendFD(new_socket)) {
90     fatal_error_ = true;
91     return;
92   }
93 }
94 
Run()95 void NetworkProxyServer::Run() {
96   while (!fatal_error_ &&
97          !violation_occurred_.load(std::memory_order_relaxed)) {
98     ProcessConnectRequest();
99   }
100   LOG(INFO)
101       << "Clean shutdown or error occurred, shutting down NetworkProxyServer";
102 }
103 
SendError(int saved_errno)104 void NetworkProxyServer::SendError(int saved_errno) {
105   if (!comms_->SendInt32(saved_errno)) {
106     fatal_error_ = true;
107   }
108 }
109 
NotifySuccess()110 void NetworkProxyServer::NotifySuccess() {
111   if (!comms_->SendInt32(0)) {
112     fatal_error_ = true;
113   }
114 }
115 
NotifyViolation(const struct sockaddr * saddr)116 void NetworkProxyServer::NotifyViolation(const struct sockaddr* saddr) {
117   if (absl::StatusOr<std::string> result = AddrToString(saddr); result.ok()) {
118     violation_msg_ = std::move(result).value();
119   } else {
120     violation_msg_ = std::string(result.status().message());
121   }
122   violation_occurred_.store(true, std::memory_order_release);
123   pthread_kill(monitor_thread_id_, SIGCHLD);
124 }
125 
126 }  // namespace sandbox2
127