1 /*
2 * Copyright (C) 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <binder_rpc_unstable.hpp>
18
19 #include <android/binder_libbinder.h>
20 #include <binder/RpcServer.h>
21 #include <binder/RpcSession.h>
22 #include <binder/unique_fd.h>
23
24 #ifndef __TRUSTY__
25 #include <cutils/sockets.h>
26 #include "vm_sockets.h"
27 #endif // !__TRUSTY__
28
29 using android::OK;
30 using android::RpcServer;
31 using android::RpcSession;
32 using android::sp;
33 using android::status_t;
34 using android::statusToString;
35 using android::binder::unique_fd;
36
37 // Opaque handle for RpcServer.
38 struct ARpcServer {};
39
40 // Opaque handle for RpcSession.
41 struct ARpcSession {};
42
43 template <typename A, typename T>
createObjectHandle(sp<T> & server)44 static A* createObjectHandle(sp<T>& server) {
45 auto ref = server.get();
46 ref->incStrong(ref);
47 return reinterpret_cast<A*>(ref);
48 }
49
50 template <typename T, typename A>
freeObjectHandle(A * handle)51 static void freeObjectHandle(A* handle) {
52 LOG_ALWAYS_FATAL_IF(handle == nullptr, "Handle cannot be null");
53 auto ref = reinterpret_cast<T*>(handle);
54 ref->decStrong(ref);
55 }
56
57 template <typename T, typename A>
handleToStrongPointer(A * handle)58 static sp<T> handleToStrongPointer(A* handle) {
59 LOG_ALWAYS_FATAL_IF(handle == nullptr, "Handle cannot be null");
60 auto ref = reinterpret_cast<T*>(handle);
61 return sp<T>::fromExisting(ref);
62 }
63
toTransportMode(ARpcSession_FileDescriptorTransportMode mode)64 RpcSession::FileDescriptorTransportMode toTransportMode(
65 ARpcSession_FileDescriptorTransportMode mode) {
66 switch (mode) {
67 case ARpcSession_FileDescriptorTransportMode::None:
68 return RpcSession::FileDescriptorTransportMode::NONE;
69 case ARpcSession_FileDescriptorTransportMode::Unix:
70 return RpcSession::FileDescriptorTransportMode::UNIX;
71 case ARpcSession_FileDescriptorTransportMode::Trusty:
72 return RpcSession::FileDescriptorTransportMode::TRUSTY;
73 default:
74 return RpcSession::FileDescriptorTransportMode::NONE;
75 }
76 }
77
78 extern "C" {
79
80 #ifndef __TRUSTY__
ARpcServer_newVsock(AIBinder * service,unsigned int cid,unsigned int port,unsigned int * assignedPort)81 ARpcServer* ARpcServer_newVsock(AIBinder* service, unsigned int cid, unsigned int port,
82 unsigned int* assignedPort) {
83 auto server = RpcServer::make();
84
85 unsigned int bindCid = VMADDR_CID_ANY; // bind to the remote interface
86 if (cid == VMADDR_CID_LOCAL) {
87 bindCid = VMADDR_CID_LOCAL; // bind to the local interface
88 cid = VMADDR_CID_ANY; // no need for a connection filter
89 }
90
91 if (status_t status = server->setupVsockServer(bindCid, port, assignedPort); status != OK) {
92 ALOGE("Failed to set up vsock server with port %u error: %s", port,
93 statusToString(status).c_str());
94 return nullptr;
95 }
96 if (cid != VMADDR_CID_ANY) {
97 server->setConnectionFilter([=](const void* addr, size_t addrlen) {
98 LOG_ALWAYS_FATAL_IF(addrlen < sizeof(sockaddr_vm), "sockaddr is truncated");
99 const sockaddr_vm* vaddr = reinterpret_cast<const sockaddr_vm*>(addr);
100 LOG_ALWAYS_FATAL_IF(vaddr->svm_family != AF_VSOCK, "address is not a vsock");
101 if (cid != vaddr->svm_cid) {
102 ALOGE("Rejected vsock connection from CID %u", vaddr->svm_cid);
103 return false;
104 }
105 return true;
106 });
107 }
108 server->setRootObject(AIBinder_toPlatformBinder(service));
109 return createObjectHandle<ARpcServer>(server);
110 }
111
ARpcServer_newBoundSocket(AIBinder * service,int socketFd)112 ARpcServer* ARpcServer_newBoundSocket(AIBinder* service, int socketFd) {
113 auto server = RpcServer::make();
114 auto fd = unique_fd(socketFd);
115 if (!fd.ok()) {
116 ALOGE("Invalid socket fd %d", socketFd);
117 return nullptr;
118 }
119 if (status_t status = server->setupRawSocketServer(std::move(fd)); status != OK) {
120 ALOGE("Failed to set up RPC server with fd %d error: %s", socketFd,
121 statusToString(status).c_str());
122 return nullptr;
123 }
124 server->setRootObject(AIBinder_toPlatformBinder(service));
125 return createObjectHandle<ARpcServer>(server);
126 }
127
ARpcServer_newUnixDomainBootstrap(AIBinder * service,int bootstrapFd)128 ARpcServer* ARpcServer_newUnixDomainBootstrap(AIBinder* service, int bootstrapFd) {
129 auto server = RpcServer::make();
130 auto fd = unique_fd(bootstrapFd);
131 if (!fd.ok()) {
132 ALOGE("Invalid bootstrap fd %d", bootstrapFd);
133 return nullptr;
134 }
135 if (status_t status = server->setupUnixDomainSocketBootstrapServer(std::move(fd));
136 status != OK) {
137 ALOGE("Failed to set up Unix Domain RPC server with bootstrap fd %d error: %s", bootstrapFd,
138 statusToString(status).c_str());
139 return nullptr;
140 }
141 server->setRootObject(AIBinder_toPlatformBinder(service));
142 return createObjectHandle<ARpcServer>(server);
143 }
144
ARpcServer_newInet(AIBinder * service,const char * address,unsigned int port)145 ARpcServer* ARpcServer_newInet(AIBinder* service, const char* address, unsigned int port) {
146 auto server = RpcServer::make();
147 if (status_t status = server->setupInetServer(address, port, nullptr); status != OK) {
148 ALOGE("Failed to set up inet RPC server with address %s and port %u error: %s", address,
149 port, statusToString(status).c_str());
150 return nullptr;
151 }
152 server->setRootObject(AIBinder_toPlatformBinder(service));
153 return createObjectHandle<ARpcServer>(server);
154 }
155 #endif // __TRUSTY__
156
ARpcServer_setSupportedFileDescriptorTransportModes(ARpcServer * handle,const ARpcSession_FileDescriptorTransportMode modes[],size_t modes_len)157 void ARpcServer_setSupportedFileDescriptorTransportModes(
158 ARpcServer* handle, const ARpcSession_FileDescriptorTransportMode modes[],
159 size_t modes_len) {
160 auto server = handleToStrongPointer<RpcServer>(handle);
161 std::vector<RpcSession::FileDescriptorTransportMode> modevec;
162 for (size_t i = 0; i < modes_len; i++) {
163 modevec.push_back(toTransportMode(modes[i]));
164 }
165 server->setSupportedFileDescriptorTransportModes(modevec);
166 }
167
ARpcServer_setMaxThreads(ARpcServer * handle,size_t threads)168 void ARpcServer_setMaxThreads(ARpcServer* handle, size_t threads) {
169 handleToStrongPointer<RpcServer>(handle)->setMaxThreads(threads);
170 }
171
ARpcServer_start(ARpcServer * handle)172 void ARpcServer_start(ARpcServer* handle) {
173 handleToStrongPointer<RpcServer>(handle)->start();
174 }
175
ARpcServer_join(ARpcServer * handle)176 void ARpcServer_join(ARpcServer* handle) {
177 handleToStrongPointer<RpcServer>(handle)->join();
178 }
179
ARpcServer_shutdown(ARpcServer * handle)180 bool ARpcServer_shutdown(ARpcServer* handle) {
181 return handleToStrongPointer<RpcServer>(handle)->shutdown();
182 }
183
ARpcServer_free(ARpcServer * handle)184 void ARpcServer_free(ARpcServer* handle) {
185 // Ignore the result of ARpcServer_shutdown - either it had been called
186 // earlier, or the RpcServer destructor will panic.
187 (void)ARpcServer_shutdown(handle);
188 freeObjectHandle<RpcServer>(handle);
189 }
190
ARpcSession_new()191 ARpcSession* ARpcSession_new() {
192 auto session = RpcSession::make();
193 return createObjectHandle<ARpcSession>(session);
194 }
195
ARpcSession_free(ARpcSession * handle)196 void ARpcSession_free(ARpcSession* handle) {
197 freeObjectHandle<RpcSession>(handle);
198 }
199
200 #ifndef __TRUSTY__
ARpcSession_setupVsockClient(ARpcSession * handle,unsigned int cid,unsigned int port)201 AIBinder* ARpcSession_setupVsockClient(ARpcSession* handle, unsigned int cid, unsigned int port) {
202 auto session = handleToStrongPointer<RpcSession>(handle);
203 if (status_t status = session->setupVsockClient(cid, port); status != OK) {
204 ALOGE("Failed to set up vsock client with CID %u and port %u error: %s", cid, port,
205 statusToString(status).c_str());
206 return nullptr;
207 }
208 return AIBinder_fromPlatformBinder(session->getRootObject());
209 }
210
ARpcSession_setupUnixDomainClient(ARpcSession * handle,const char * name)211 AIBinder* ARpcSession_setupUnixDomainClient(ARpcSession* handle, const char* name) {
212 std::string pathname(name);
213 pathname = ANDROID_SOCKET_DIR "/" + pathname;
214 auto session = handleToStrongPointer<RpcSession>(handle);
215 if (status_t status = session->setupUnixDomainClient(pathname.c_str()); status != OK) {
216 ALOGE("Failed to set up Unix Domain RPC client with path: %s error: %s", pathname.c_str(),
217 statusToString(status).c_str());
218 return nullptr;
219 }
220 return AIBinder_fromPlatformBinder(session->getRootObject());
221 }
222
ARpcSession_setupUnixDomainBootstrapClient(ARpcSession * handle,int bootstrapFd)223 AIBinder* ARpcSession_setupUnixDomainBootstrapClient(ARpcSession* handle, int bootstrapFd) {
224 auto session = handleToStrongPointer<RpcSession>(handle);
225 auto fd = unique_fd(dup(bootstrapFd));
226 if (!fd.ok()) {
227 ALOGE("Invalid bootstrap fd %d", bootstrapFd);
228 return nullptr;
229 }
230 if (status_t status = session->setupUnixDomainSocketBootstrapClient(std::move(fd));
231 status != OK) {
232 ALOGE("Failed to set up Unix Domain RPC client with bootstrap fd: %d error: %s",
233 bootstrapFd, statusToString(status).c_str());
234 return nullptr;
235 }
236 return AIBinder_fromPlatformBinder(session->getRootObject());
237 }
238
ARpcSession_setupInet(ARpcSession * handle,const char * address,unsigned int port)239 AIBinder* ARpcSession_setupInet(ARpcSession* handle, const char* address, unsigned int port) {
240 auto session = handleToStrongPointer<RpcSession>(handle);
241 if (status_t status = session->setupInetClient(address, port); status != OK) {
242 ALOGE("Failed to set up inet RPC client with address %s and port %u error: %s", address,
243 port, statusToString(status).c_str());
244 return nullptr;
245 }
246 return AIBinder_fromPlatformBinder(session->getRootObject());
247 }
248 #endif // __TRUSTY__
249
ARpcSession_setupPreconnectedClient(ARpcSession * handle,int (* requestFd)(void * param),void * param,void (* paramDeleteFd)(void * param))250 AIBinder* ARpcSession_setupPreconnectedClient(ARpcSession* handle, int (*requestFd)(void* param),
251 void* param, void (*paramDeleteFd)(void* param)) {
252 auto session = handleToStrongPointer<RpcSession>(handle);
253 auto deleter = [=](void* param) {
254 if (paramDeleteFd) {
255 paramDeleteFd(param);
256 }
257 };
258 // TODO: use unique_ptr once setupPreconnectedClient uses std::move_only_function.
259 std::shared_ptr<void> sharedParam(param, deleter);
260 auto request = [=, sharedParam = std::move(sharedParam)] {
261 return unique_fd{requestFd(sharedParam.get())};
262 };
263 if (status_t status = session->setupPreconnectedClient(unique_fd{}, request); status != OK) {
264 ALOGE("Failed to set up preconnected client. error: %s", statusToString(status).c_str());
265 return nullptr;
266 }
267 return AIBinder_fromPlatformBinder(session->getRootObject());
268 }
269
ARpcSession_setFileDescriptorTransportMode(ARpcSession * handle,ARpcSession_FileDescriptorTransportMode mode)270 void ARpcSession_setFileDescriptorTransportMode(ARpcSession* handle,
271 ARpcSession_FileDescriptorTransportMode mode) {
272 auto session = handleToStrongPointer<RpcSession>(handle);
273 session->setFileDescriptorTransportMode(toTransportMode(mode));
274 }
275
ARpcSession_setMaxIncomingThreads(ARpcSession * handle,size_t threads)276 void ARpcSession_setMaxIncomingThreads(ARpcSession* handle, size_t threads) {
277 auto session = handleToStrongPointer<RpcSession>(handle);
278 session->setMaxIncomingThreads(threads);
279 }
280
ARpcSession_setMaxOutgoingConnections(ARpcSession * handle,size_t connections)281 void ARpcSession_setMaxOutgoingConnections(ARpcSession* handle, size_t connections) {
282 auto session = handleToStrongPointer<RpcSession>(handle);
283 session->setMaxOutgoingConnections(connections);
284 }
285 }
286