• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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-base/logging.h>
20 #include <android-base/unique_fd.h>
21 #include <android/binder_libbinder.h>
22 #include <binder/RpcServer.h>
23 #include <binder/RpcSession.h>
24 #include <cutils/sockets.h>
25 #include <linux/vm_sockets.h>
26 
27 using android::OK;
28 using android::RpcServer;
29 using android::RpcSession;
30 using android::sp;
31 using android::status_t;
32 using android::statusToString;
33 using android::base::unique_fd;
34 
35 // Opaque handle for RpcServer.
36 struct ARpcServer {};
37 
38 // Opaque handle for RpcSession.
39 struct ARpcSession {};
40 
41 template <typename A, typename T>
createObjectHandle(sp<T> & server)42 static A* createObjectHandle(sp<T>& server) {
43     auto ref = server.get();
44     ref->incStrong(ref);
45     return reinterpret_cast<A*>(ref);
46 }
47 
48 template <typename T, typename A>
freeObjectHandle(A * handle)49 static void freeObjectHandle(A* handle) {
50     LOG_ALWAYS_FATAL_IF(handle == nullptr, "Handle cannot be null");
51     auto ref = reinterpret_cast<T*>(handle);
52     ref->decStrong(ref);
53 }
54 
55 template <typename T, typename A>
handleToStrongPointer(A * handle)56 static sp<T> handleToStrongPointer(A* handle) {
57     LOG_ALWAYS_FATAL_IF(handle == nullptr, "Handle cannot be null");
58     auto ref = reinterpret_cast<T*>(handle);
59     return sp<T>::fromExisting(ref);
60 }
61 
toTransportMode(ARpcSession_FileDescriptorTransportMode mode)62 RpcSession::FileDescriptorTransportMode toTransportMode(
63         ARpcSession_FileDescriptorTransportMode mode) {
64     switch (mode) {
65         case ARpcSession_FileDescriptorTransportMode::None:
66             return RpcSession::FileDescriptorTransportMode::NONE;
67         case ARpcSession_FileDescriptorTransportMode::Unix:
68             return RpcSession::FileDescriptorTransportMode::UNIX;
69         case ARpcSession_FileDescriptorTransportMode::Trusty:
70             return RpcSession::FileDescriptorTransportMode::TRUSTY;
71         default:
72             return RpcSession::FileDescriptorTransportMode::NONE;
73     }
74 }
75 
76 extern "C" {
77 
ARpcServer_newVsock(AIBinder * service,unsigned int cid,unsigned int port)78 ARpcServer* ARpcServer_newVsock(AIBinder* service, unsigned int cid, unsigned int port) {
79     auto server = RpcServer::make();
80 
81     unsigned int bindCid = VMADDR_CID_ANY; // bind to the remote interface
82     if (cid == VMADDR_CID_LOCAL) {
83         bindCid = VMADDR_CID_LOCAL; // bind to the local interface
84         cid = VMADDR_CID_ANY;       // no need for a connection filter
85     }
86 
87     if (status_t status = server->setupVsockServer(bindCid, port); status != OK) {
88         LOG(ERROR) << "Failed to set up vsock server with port " << port
89                    << " error: " << statusToString(status).c_str();
90         return nullptr;
91     }
92     if (cid != VMADDR_CID_ANY) {
93         server->setConnectionFilter([=](const void* addr, size_t addrlen) {
94             LOG_ALWAYS_FATAL_IF(addrlen < sizeof(sockaddr_vm), "sockaddr is truncated");
95             const sockaddr_vm* vaddr = reinterpret_cast<const sockaddr_vm*>(addr);
96             LOG_ALWAYS_FATAL_IF(vaddr->svm_family != AF_VSOCK, "address is not a vsock");
97             if (cid != vaddr->svm_cid) {
98                 LOG(ERROR) << "Rejected vsock connection from CID " << vaddr->svm_cid;
99                 return false;
100             }
101             return true;
102         });
103     }
104     server->setRootObject(AIBinder_toPlatformBinder(service));
105     return createObjectHandle<ARpcServer>(server);
106 }
107 
ARpcServer_newInitUnixDomain(AIBinder * service,const char * name)108 ARpcServer* ARpcServer_newInitUnixDomain(AIBinder* service, const char* name) {
109     auto server = RpcServer::make();
110     auto fd = unique_fd(android_get_control_socket(name));
111     if (!fd.ok()) {
112         LOG(ERROR) << "Failed to get fd for the socket:" << name;
113         return nullptr;
114     }
115     // Control socket fds are inherited from init, so they don't have O_CLOEXEC set.
116     // But we don't want any child processes to inherit the socket we are running
117     // the server on, so attempt to set the flag now.
118     if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0) {
119         LOG(WARNING) << "Failed to set CLOEXEC on control socket with name " << name
120                      << " error: " << errno;
121     }
122     if (status_t status = server->setupRawSocketServer(std::move(fd)); status != OK) {
123         LOG(ERROR) << "Failed to set up Unix Domain RPC server with name " << name
124                    << " error: " << statusToString(status).c_str();
125         return nullptr;
126     }
127     server->setRootObject(AIBinder_toPlatformBinder(service));
128     return createObjectHandle<ARpcServer>(server);
129 }
130 
ARpcServer_newUnixDomainBootstrap(AIBinder * service,int bootstrapFd)131 ARpcServer* ARpcServer_newUnixDomainBootstrap(AIBinder* service, int bootstrapFd) {
132     auto server = RpcServer::make();
133     auto fd = unique_fd(bootstrapFd);
134     if (!fd.ok()) {
135         LOG(ERROR) << "Invalid bootstrap fd " << bootstrapFd;
136         return nullptr;
137     }
138     if (status_t status = server->setupUnixDomainSocketBootstrapServer(std::move(fd));
139         status != OK) {
140         LOG(ERROR) << "Failed to set up Unix Domain RPC server with bootstrap fd " << bootstrapFd
141                    << " error: " << statusToString(status).c_str();
142         return nullptr;
143     }
144     server->setRootObject(AIBinder_toPlatformBinder(service));
145     return createObjectHandle<ARpcServer>(server);
146 }
147 
ARpcServer_newInet(AIBinder * service,const char * address,unsigned int port)148 ARpcServer* ARpcServer_newInet(AIBinder* service, const char* address, unsigned int port) {
149     auto server = RpcServer::make();
150     if (status_t status = server->setupInetServer(address, port, nullptr); status != OK) {
151         LOG(ERROR) << "Failed to set up inet RPC server with address " << address << " and port "
152                    << port << " error: " << statusToString(status).c_str();
153         return nullptr;
154     }
155     server->setRootObject(AIBinder_toPlatformBinder(service));
156     return createObjectHandle<ARpcServer>(server);
157 }
158 
ARpcServer_setSupportedFileDescriptorTransportModes(ARpcServer * handle,const ARpcSession_FileDescriptorTransportMode modes[],size_t modes_len)159 void ARpcServer_setSupportedFileDescriptorTransportModes(
160         ARpcServer* handle, const ARpcSession_FileDescriptorTransportMode modes[],
161         size_t modes_len) {
162     auto server = handleToStrongPointer<RpcServer>(handle);
163     std::vector<RpcSession::FileDescriptorTransportMode> modevec;
164     for (size_t i = 0; i < modes_len; i++) {
165         modevec.push_back(toTransportMode(modes[i]));
166     }
167     server->setSupportedFileDescriptorTransportModes(modevec);
168 }
169 
ARpcServer_start(ARpcServer * handle)170 void ARpcServer_start(ARpcServer* handle) {
171     handleToStrongPointer<RpcServer>(handle)->start();
172 }
173 
ARpcServer_join(ARpcServer * handle)174 void ARpcServer_join(ARpcServer* handle) {
175     handleToStrongPointer<RpcServer>(handle)->join();
176 }
177 
ARpcServer_shutdown(ARpcServer * handle)178 bool ARpcServer_shutdown(ARpcServer* handle) {
179     return handleToStrongPointer<RpcServer>(handle)->shutdown();
180 }
181 
ARpcServer_free(ARpcServer * handle)182 void ARpcServer_free(ARpcServer* handle) {
183     // Ignore the result of ARpcServer_shutdown - either it had been called
184     // earlier, or the RpcServer destructor will panic.
185     (void)ARpcServer_shutdown(handle);
186     freeObjectHandle<RpcServer>(handle);
187 }
188 
ARpcSession_new()189 ARpcSession* ARpcSession_new() {
190     auto session = RpcSession::make();
191     return createObjectHandle<ARpcSession>(session);
192 }
193 
ARpcSession_free(ARpcSession * handle)194 void ARpcSession_free(ARpcSession* handle) {
195     freeObjectHandle<RpcSession>(handle);
196 }
197 
ARpcSession_setupVsockClient(ARpcSession * handle,unsigned int cid,unsigned int port)198 AIBinder* ARpcSession_setupVsockClient(ARpcSession* handle, unsigned int cid, unsigned int port) {
199     auto session = handleToStrongPointer<RpcSession>(handle);
200     if (status_t status = session->setupVsockClient(cid, port); status != OK) {
201         LOG(ERROR) << "Failed to set up vsock client with CID " << cid << " and port " << port
202                    << " error: " << statusToString(status).c_str();
203         return nullptr;
204     }
205     return AIBinder_fromPlatformBinder(session->getRootObject());
206 }
207 
ARpcSession_setupUnixDomainClient(ARpcSession * handle,const char * name)208 AIBinder* ARpcSession_setupUnixDomainClient(ARpcSession* handle, const char* name) {
209     std::string pathname(name);
210     pathname = ANDROID_SOCKET_DIR "/" + pathname;
211     auto session = handleToStrongPointer<RpcSession>(handle);
212     if (status_t status = session->setupUnixDomainClient(pathname.c_str()); status != OK) {
213         LOG(ERROR) << "Failed to set up Unix Domain RPC client with path: " << pathname
214                    << " error: " << statusToString(status).c_str();
215         return nullptr;
216     }
217     return AIBinder_fromPlatformBinder(session->getRootObject());
218 }
219 
ARpcSession_setupUnixDomainBootstrapClient(ARpcSession * handle,int bootstrapFd)220 AIBinder* ARpcSession_setupUnixDomainBootstrapClient(ARpcSession* handle, int bootstrapFd) {
221     auto session = handleToStrongPointer<RpcSession>(handle);
222     auto fd = unique_fd(dup(bootstrapFd));
223     if (!fd.ok()) {
224         LOG(ERROR) << "Invalid bootstrap fd " << bootstrapFd;
225         return nullptr;
226     }
227     if (status_t status = session->setupUnixDomainSocketBootstrapClient(std::move(fd));
228         status != OK) {
229         LOG(ERROR) << "Failed to set up Unix Domain RPC client with bootstrap fd: " << bootstrapFd
230                    << " error: " << statusToString(status).c_str();
231         return nullptr;
232     }
233     return AIBinder_fromPlatformBinder(session->getRootObject());
234 }
235 
ARpcSession_setupInet(ARpcSession * handle,const char * address,unsigned int port)236 AIBinder* ARpcSession_setupInet(ARpcSession* handle, const char* address, unsigned int port) {
237     auto session = handleToStrongPointer<RpcSession>(handle);
238     if (status_t status = session->setupInetClient(address, port); status != OK) {
239         LOG(ERROR) << "Failed to set up inet RPC client with address " << address << " and port "
240                    << port << " error: " << statusToString(status).c_str();
241         return nullptr;
242     }
243     return AIBinder_fromPlatformBinder(session->getRootObject());
244 }
245 
ARpcSession_setupPreconnectedClient(ARpcSession * handle,int (* requestFd)(void * param),void * param)246 AIBinder* ARpcSession_setupPreconnectedClient(ARpcSession* handle, int (*requestFd)(void* param),
247                                               void* param) {
248     auto session = handleToStrongPointer<RpcSession>(handle);
249     auto request = [=] { return unique_fd{requestFd(param)}; };
250     if (status_t status = session->setupPreconnectedClient(unique_fd{}, request); status != OK) {
251         LOG(ERROR) << "Failed to set up vsock client. error: " << statusToString(status).c_str();
252         return nullptr;
253     }
254     return AIBinder_fromPlatformBinder(session->getRootObject());
255 }
256 
ARpcSession_setFileDescriptorTransportMode(ARpcSession * handle,ARpcSession_FileDescriptorTransportMode mode)257 void ARpcSession_setFileDescriptorTransportMode(ARpcSession* handle,
258                                                 ARpcSession_FileDescriptorTransportMode mode) {
259     auto session = handleToStrongPointer<RpcSession>(handle);
260     session->setFileDescriptorTransportMode(toTransportMode(mode));
261 }
262 
ARpcSession_setMaxIncomingThreads(ARpcSession * handle,size_t threads)263 void ARpcSession_setMaxIncomingThreads(ARpcSession* handle, size_t threads) {
264     auto session = handleToStrongPointer<RpcSession>(handle);
265     session->setMaxIncomingThreads(threads);
266 }
267 
ARpcSession_setMaxOutgoingConnections(ARpcSession * handle,size_t connections)268 void ARpcSession_setMaxOutgoingConnections(ARpcSession* handle, size_t connections) {
269     auto session = handleToStrongPointer<RpcSession>(handle);
270     session->setMaxOutgoingConnections(connections);
271 }
272 }
273