xref: /aosp_15_r20/external/sandboxed-api/sandboxed_api/sandbox2/network_proxy/client.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/client.h"
16 
17 #include <sys/socket.h>
18 #include <syscall.h>
19 #include <unistd.h>
20 
21 #include <cerrno>
22 #include <cstdint>
23 
24 #include "absl/log/log.h"
25 #include "absl/status/status.h"
26 #include "absl/synchronization/mutex.h"
27 #include "sandboxed_api/sandbox2/util/syscall_trap.h"
28 #include "sandboxed_api/util/status_macros.h"
29 
30 namespace sandbox2 {
31 
Connect(int sockfd,const struct sockaddr * addr,socklen_t addrlen)32 absl::Status NetworkProxyClient::Connect(int sockfd,
33                                          const struct sockaddr* addr,
34                                          socklen_t addrlen) {
35   absl::MutexLock lock(&mutex_);
36 
37   // Check if socket is SOCK_STREAM
38   int type;
39   socklen_t type_size = sizeof(int);
40   int result = getsockopt(sockfd, SOL_SOCKET, SO_TYPE, &type, &type_size);
41   if (result == -1) {
42     return absl::FailedPreconditionError("Invalid socket FD");
43   }
44   if (type_size != sizeof(int) || type != SOCK_STREAM) {
45     errno = EINVAL;
46     return absl::InvalidArgumentError(
47         "Invalid socket, only SOCK_STREAM is allowed");
48   }
49 
50   // Send sockaddr struct
51   if (!comms_.SendBytes(reinterpret_cast<const uint8_t*>(addr), addrlen)) {
52     errno = EIO;
53     return absl::InternalError("Sending data to network proxy failed");
54   }
55 
56   SAPI_RETURN_IF_ERROR(ReceiveRemoteResult());
57 
58   // Receive new socket
59   int s;
60   if (!comms_.RecvFD(&s)) {
61     errno = EIO;
62     return absl::InternalError("Receiving data from network proxy failed");
63   }
64   if (dup2(s, sockfd) == -1) {
65     close(s);
66     return absl::InternalError("Processing data from network proxy failed");
67   }
68   return absl::OkStatus();
69 }
70 
ReceiveRemoteResult()71 absl::Status NetworkProxyClient::ReceiveRemoteResult() {
72   int result;
73   if (!comms_.RecvInt32(&result)) {
74     errno = EIO;
75     return absl::InternalError("Receiving data from the network proxy failed");
76   }
77   if (result != 0) {
78     errno = result;
79     return absl::ErrnoToStatus(errno, "Error in network proxy server");
80   }
81   return absl::OkStatus();
82 }
83 
84 NetworkProxyClient* NetworkProxyHandler::network_proxy_client_ = nullptr;
85 
InstallNetworkProxyHandler(NetworkProxyClient * npc)86 absl::Status NetworkProxyHandler::InstallNetworkProxyHandler(
87     NetworkProxyClient* npc) {
88   if (network_proxy_client_ != nullptr) {
89     return absl::AlreadyExistsError(
90         "Network proxy handler is already installed");
91   }
92   network_proxy_client_ = npc;
93   if (!SyscallTrap::Install([](int nr, SyscallTrap::Args args, uintptr_t* rv) {
94         return ProcessSeccompTrap(nr, args, rv);
95       })) {
96     return absl::InternalError("Could not install syscall trap");
97   }
98   return absl::OkStatus();
99 }
100 
ProcessSeccompTrap(int nr,SyscallTrap::Args args,uintptr_t * rv)101 bool NetworkProxyHandler::ProcessSeccompTrap(int nr, SyscallTrap::Args args,
102                                              uintptr_t* rv) {
103   int sockfd;
104   const struct sockaddr* addr;
105   socklen_t addrlen;
106 
107   if (nr == __NR_connect) {
108     sockfd = static_cast<int>(args[0]);
109     addr = reinterpret_cast<const struct sockaddr*>(args[1]);
110     addrlen = static_cast<socklen_t>(args[2]);
111 #if defined(SAPI_PPC64_LE)
112   } else if (nr == __NR_socketcall &&
113              static_cast<int>(args[0]) == SYS_CONNECT) {
114     auto* connect_args = reinterpret_cast<uint64_t*>(args[1]);
115     sockfd = static_cast<int>(connect_args[0]);
116     addr = reinterpret_cast<const struct sockaddr*>(connect_args[1]);
117     addrlen = static_cast<socklen_t>(connect_args[2]);
118 #endif
119   } else {
120     return false;
121   }
122 
123   absl::Status result = network_proxy_client_->Connect(sockfd, addr, addrlen);
124   if (result.ok()) {
125     *rv = 0;
126   } else {
127     *rv = -errno;
128   }
129   return true;
130 }
131 
132 }  // namespace sandbox2
133