xref: /aosp_15_r20/frameworks/native/libs/binder/trusty/RpcServerTrusty.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker  * Copyright (C) 2022 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker  *
4*38e8c45fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker  *
8*38e8c45fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker  *
10*38e8c45fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker  * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker  */
16*38e8c45fSAndroid Build Coastguard Worker 
17*38e8c45fSAndroid Build Coastguard Worker #define LOG_TAG "RpcServerTrusty"
18*38e8c45fSAndroid Build Coastguard Worker 
19*38e8c45fSAndroid Build Coastguard Worker #include <binder/Parcel.h>
20*38e8c45fSAndroid Build Coastguard Worker #include <binder/RpcServer.h>
21*38e8c45fSAndroid Build Coastguard Worker #include <binder/RpcServerTrusty.h>
22*38e8c45fSAndroid Build Coastguard Worker #include <binder/RpcThreads.h>
23*38e8c45fSAndroid Build Coastguard Worker #include <binder/RpcTransportTipcTrusty.h>
24*38e8c45fSAndroid Build Coastguard Worker #include <log/log.h>
25*38e8c45fSAndroid Build Coastguard Worker 
26*38e8c45fSAndroid Build Coastguard Worker #include "../FdTrigger.h"
27*38e8c45fSAndroid Build Coastguard Worker #include "../RpcState.h"
28*38e8c45fSAndroid Build Coastguard Worker #include "TrustyStatus.h"
29*38e8c45fSAndroid Build Coastguard Worker 
30*38e8c45fSAndroid Build Coastguard Worker using android::binder::unique_fd;
31*38e8c45fSAndroid Build Coastguard Worker 
32*38e8c45fSAndroid Build Coastguard Worker namespace android {
33*38e8c45fSAndroid Build Coastguard Worker 
make(tipc_hset * handleSet,std::string && portName,std::shared_ptr<const PortAcl> && portAcl,size_t msgMaxSize,std::unique_ptr<RpcTransportCtxFactory> rpcTransportCtxFactory)34*38e8c45fSAndroid Build Coastguard Worker sp<RpcServerTrusty> RpcServerTrusty::make(
35*38e8c45fSAndroid Build Coastguard Worker         tipc_hset* handleSet, std::string&& portName, std::shared_ptr<const PortAcl>&& portAcl,
36*38e8c45fSAndroid Build Coastguard Worker         size_t msgMaxSize, std::unique_ptr<RpcTransportCtxFactory> rpcTransportCtxFactory) {
37*38e8c45fSAndroid Build Coastguard Worker     // Default is without TLS.
38*38e8c45fSAndroid Build Coastguard Worker     if (rpcTransportCtxFactory == nullptr)
39*38e8c45fSAndroid Build Coastguard Worker         rpcTransportCtxFactory = RpcTransportCtxFactoryTipcTrusty::make();
40*38e8c45fSAndroid Build Coastguard Worker     auto ctx = rpcTransportCtxFactory->newServerCtx();
41*38e8c45fSAndroid Build Coastguard Worker     if (ctx == nullptr) {
42*38e8c45fSAndroid Build Coastguard Worker         ALOGE("Failed to create RpcServerTrusty: can't create server context");
43*38e8c45fSAndroid Build Coastguard Worker         return nullptr;
44*38e8c45fSAndroid Build Coastguard Worker     }
45*38e8c45fSAndroid Build Coastguard Worker 
46*38e8c45fSAndroid Build Coastguard Worker     auto srv = sp<RpcServerTrusty>::make(std::move(ctx), std::move(portName), std::move(portAcl),
47*38e8c45fSAndroid Build Coastguard Worker                                          msgMaxSize);
48*38e8c45fSAndroid Build Coastguard Worker     if (srv == nullptr) {
49*38e8c45fSAndroid Build Coastguard Worker         ALOGE("Failed to create RpcServerTrusty: can't create server object");
50*38e8c45fSAndroid Build Coastguard Worker         return nullptr;
51*38e8c45fSAndroid Build Coastguard Worker     }
52*38e8c45fSAndroid Build Coastguard Worker 
53*38e8c45fSAndroid Build Coastguard Worker     int rc = tipc_add_service(handleSet, &srv->mTipcPort, 1, 0, &kTipcOps);
54*38e8c45fSAndroid Build Coastguard Worker     if (rc != NO_ERROR) {
55*38e8c45fSAndroid Build Coastguard Worker         ALOGE("Failed to create RpcServerTrusty: can't add service: %d", rc);
56*38e8c45fSAndroid Build Coastguard Worker         return nullptr;
57*38e8c45fSAndroid Build Coastguard Worker     }
58*38e8c45fSAndroid Build Coastguard Worker     return srv;
59*38e8c45fSAndroid Build Coastguard Worker }
60*38e8c45fSAndroid Build Coastguard Worker 
RpcServerTrusty(std::unique_ptr<RpcTransportCtx> ctx,std::string && portName,std::shared_ptr<const PortAcl> && portAcl,size_t msgMaxSize)61*38e8c45fSAndroid Build Coastguard Worker RpcServerTrusty::RpcServerTrusty(std::unique_ptr<RpcTransportCtx> ctx, std::string&& portName,
62*38e8c45fSAndroid Build Coastguard Worker                                  std::shared_ptr<const PortAcl>&& portAcl, size_t msgMaxSize)
63*38e8c45fSAndroid Build Coastguard Worker       : mRpcServer(makeRpcServer(std::move(ctx))),
64*38e8c45fSAndroid Build Coastguard Worker         mPortName(std::move(portName)),
65*38e8c45fSAndroid Build Coastguard Worker         mPortAcl(std::move(portAcl)) {
66*38e8c45fSAndroid Build Coastguard Worker     mTipcPort.name = mPortName.c_str();
67*38e8c45fSAndroid Build Coastguard Worker     mTipcPort.msg_max_size = msgMaxSize;
68*38e8c45fSAndroid Build Coastguard Worker     mTipcPort.msg_queue_len = 6; // Three each way
69*38e8c45fSAndroid Build Coastguard Worker     mTipcPort.priv = this;
70*38e8c45fSAndroid Build Coastguard Worker 
71*38e8c45fSAndroid Build Coastguard Worker     if (mPortAcl) {
72*38e8c45fSAndroid Build Coastguard Worker         // Initialize the array of pointers to uuids.
73*38e8c45fSAndroid Build Coastguard Worker         // The pointers in mUuidPtrs should stay valid across moves of
74*38e8c45fSAndroid Build Coastguard Worker         // RpcServerTrusty (the addresses of a std::vector's elements
75*38e8c45fSAndroid Build Coastguard Worker         // shouldn't change when the vector is moved), but would be invalidated
76*38e8c45fSAndroid Build Coastguard Worker         // by a copy which is why we disable the copy constructor and assignment
77*38e8c45fSAndroid Build Coastguard Worker         // operator for RpcServerTrusty.
78*38e8c45fSAndroid Build Coastguard Worker         auto numUuids = mPortAcl->uuids.size();
79*38e8c45fSAndroid Build Coastguard Worker         mUuidPtrs.resize(numUuids);
80*38e8c45fSAndroid Build Coastguard Worker         for (size_t i = 0; i < numUuids; i++) {
81*38e8c45fSAndroid Build Coastguard Worker             mUuidPtrs[i] = &mPortAcl->uuids[i];
82*38e8c45fSAndroid Build Coastguard Worker         }
83*38e8c45fSAndroid Build Coastguard Worker 
84*38e8c45fSAndroid Build Coastguard Worker         // Copy the contents of portAcl into the tipc_port_acl structure that we
85*38e8c45fSAndroid Build Coastguard Worker         // pass to tipc_add_service
86*38e8c45fSAndroid Build Coastguard Worker         mTipcPortAcl.flags = mPortAcl->flags;
87*38e8c45fSAndroid Build Coastguard Worker         mTipcPortAcl.uuid_num = numUuids;
88*38e8c45fSAndroid Build Coastguard Worker         mTipcPortAcl.uuids = mUuidPtrs.data();
89*38e8c45fSAndroid Build Coastguard Worker         mTipcPortAcl.extra_data = mPortAcl->extraData;
90*38e8c45fSAndroid Build Coastguard Worker 
91*38e8c45fSAndroid Build Coastguard Worker         mTipcPort.acl = &mTipcPortAcl;
92*38e8c45fSAndroid Build Coastguard Worker     } else {
93*38e8c45fSAndroid Build Coastguard Worker         mTipcPort.acl = nullptr;
94*38e8c45fSAndroid Build Coastguard Worker     }
95*38e8c45fSAndroid Build Coastguard Worker }
96*38e8c45fSAndroid Build Coastguard Worker 
handleConnect(const tipc_port * port,handle_t chan,const uuid * peer,void ** ctx_p)97*38e8c45fSAndroid Build Coastguard Worker int RpcServerTrusty::handleConnect(const tipc_port* port, handle_t chan, const uuid* peer,
98*38e8c45fSAndroid Build Coastguard Worker                                    void** ctx_p) {
99*38e8c45fSAndroid Build Coastguard Worker     auto* server = reinterpret_cast<RpcServerTrusty*>(const_cast<void*>(port->priv));
100*38e8c45fSAndroid Build Coastguard Worker     return handleConnectInternal(server->mRpcServer.get(), chan, peer, ctx_p);
101*38e8c45fSAndroid Build Coastguard Worker }
102*38e8c45fSAndroid Build Coastguard Worker 
handleConnectInternal(RpcServer * rpcServer,handle_t chan,const uuid * peer,void ** ctx_p)103*38e8c45fSAndroid Build Coastguard Worker int RpcServerTrusty::handleConnectInternal(RpcServer* rpcServer, handle_t chan, const uuid* peer,
104*38e8c45fSAndroid Build Coastguard Worker                                            void** ctx_p) {
105*38e8c45fSAndroid Build Coastguard Worker     rpcServer->mShutdownTrigger = FdTrigger::make();
106*38e8c45fSAndroid Build Coastguard Worker     rpcServer->mConnectingThreads[rpc_this_thread::get_id()] = RpcMaybeThread();
107*38e8c45fSAndroid Build Coastguard Worker 
108*38e8c45fSAndroid Build Coastguard Worker     int rc = NO_ERROR;
109*38e8c45fSAndroid Build Coastguard Worker     auto joinFn = [&](sp<RpcSession>&& session, RpcSession::PreJoinSetupResult&& result) {
110*38e8c45fSAndroid Build Coastguard Worker         if (result.status != OK) {
111*38e8c45fSAndroid Build Coastguard Worker             rc = statusToTrusty(result.status);
112*38e8c45fSAndroid Build Coastguard Worker             return;
113*38e8c45fSAndroid Build Coastguard Worker         }
114*38e8c45fSAndroid Build Coastguard Worker 
115*38e8c45fSAndroid Build Coastguard Worker         /* Save the session and connection for the other callbacks */
116*38e8c45fSAndroid Build Coastguard Worker         auto* channelContext = new (std::nothrow) ChannelContext;
117*38e8c45fSAndroid Build Coastguard Worker         if (channelContext == nullptr) {
118*38e8c45fSAndroid Build Coastguard Worker             rc = ERR_NO_MEMORY;
119*38e8c45fSAndroid Build Coastguard Worker             return;
120*38e8c45fSAndroid Build Coastguard Worker         }
121*38e8c45fSAndroid Build Coastguard Worker 
122*38e8c45fSAndroid Build Coastguard Worker         channelContext->session = std::move(session);
123*38e8c45fSAndroid Build Coastguard Worker         channelContext->connection = std::move(result.connection);
124*38e8c45fSAndroid Build Coastguard Worker 
125*38e8c45fSAndroid Build Coastguard Worker         *ctx_p = channelContext;
126*38e8c45fSAndroid Build Coastguard Worker     };
127*38e8c45fSAndroid Build Coastguard Worker 
128*38e8c45fSAndroid Build Coastguard Worker     // We need to duplicate the channel handle here because the tipc library
129*38e8c45fSAndroid Build Coastguard Worker     // owns the original handle and closes is automatically on channel cleanup.
130*38e8c45fSAndroid Build Coastguard Worker     // We use dup() because Trusty does not have fcntl().
131*38e8c45fSAndroid Build Coastguard Worker     // NOLINTNEXTLINE(android-cloexec-dup)
132*38e8c45fSAndroid Build Coastguard Worker     handle_t chanDup = dup(chan);
133*38e8c45fSAndroid Build Coastguard Worker     if (chanDup < 0) {
134*38e8c45fSAndroid Build Coastguard Worker         return chanDup;
135*38e8c45fSAndroid Build Coastguard Worker     }
136*38e8c45fSAndroid Build Coastguard Worker     unique_fd clientFd(chanDup);
137*38e8c45fSAndroid Build Coastguard Worker     android::RpcTransportFd transportFd(std::move(clientFd));
138*38e8c45fSAndroid Build Coastguard Worker 
139*38e8c45fSAndroid Build Coastguard Worker     std::array<uint8_t, RpcServer::kRpcAddressSize> addr;
140*38e8c45fSAndroid Build Coastguard Worker     constexpr size_t addrLen = sizeof(*peer);
141*38e8c45fSAndroid Build Coastguard Worker     memcpy(addr.data(), peer, addrLen);
142*38e8c45fSAndroid Build Coastguard Worker     RpcServer::establishConnection(sp<RpcServer>::fromExisting(rpcServer), std::move(transportFd),
143*38e8c45fSAndroid Build Coastguard Worker                                    addr, addrLen, joinFn);
144*38e8c45fSAndroid Build Coastguard Worker 
145*38e8c45fSAndroid Build Coastguard Worker     return rc;
146*38e8c45fSAndroid Build Coastguard Worker }
147*38e8c45fSAndroid Build Coastguard Worker 
handleMessage(const tipc_port *,handle_t,void * ctx)148*38e8c45fSAndroid Build Coastguard Worker int RpcServerTrusty::handleMessage(const tipc_port* /*port*/, handle_t /*chan*/, void* ctx) {
149*38e8c45fSAndroid Build Coastguard Worker     return handleMessageInternal(ctx);
150*38e8c45fSAndroid Build Coastguard Worker }
151*38e8c45fSAndroid Build Coastguard Worker 
handleMessageInternal(void * ctx)152*38e8c45fSAndroid Build Coastguard Worker int RpcServerTrusty::handleMessageInternal(void* ctx) {
153*38e8c45fSAndroid Build Coastguard Worker     auto* channelContext = reinterpret_cast<ChannelContext*>(ctx);
154*38e8c45fSAndroid Build Coastguard Worker     if (channelContext == nullptr) {
155*38e8c45fSAndroid Build Coastguard Worker         LOG_RPC_DETAIL("bad state: message received on uninitialized channel");
156*38e8c45fSAndroid Build Coastguard Worker         return ERR_BAD_STATE;
157*38e8c45fSAndroid Build Coastguard Worker     }
158*38e8c45fSAndroid Build Coastguard Worker 
159*38e8c45fSAndroid Build Coastguard Worker     auto& session = channelContext->session;
160*38e8c45fSAndroid Build Coastguard Worker     auto& connection = channelContext->connection;
161*38e8c45fSAndroid Build Coastguard Worker     status_t status =
162*38e8c45fSAndroid Build Coastguard Worker             session->state()->drainCommands(connection, session, RpcState::CommandType::ANY);
163*38e8c45fSAndroid Build Coastguard Worker     if (status != OK) {
164*38e8c45fSAndroid Build Coastguard Worker         LOG_RPC_DETAIL("Binder connection thread closing w/ status %s",
165*38e8c45fSAndroid Build Coastguard Worker                        statusToString(status).c_str());
166*38e8c45fSAndroid Build Coastguard Worker     }
167*38e8c45fSAndroid Build Coastguard Worker 
168*38e8c45fSAndroid Build Coastguard Worker     return NO_ERROR;
169*38e8c45fSAndroid Build Coastguard Worker }
170*38e8c45fSAndroid Build Coastguard Worker 
handleDisconnect(const tipc_port *,handle_t,void * ctx)171*38e8c45fSAndroid Build Coastguard Worker void RpcServerTrusty::handleDisconnect(const tipc_port* /*port*/, handle_t /*chan*/, void* ctx) {
172*38e8c45fSAndroid Build Coastguard Worker     return handleDisconnectInternal(ctx);
173*38e8c45fSAndroid Build Coastguard Worker }
174*38e8c45fSAndroid Build Coastguard Worker 
handleDisconnectInternal(void * ctx)175*38e8c45fSAndroid Build Coastguard Worker void RpcServerTrusty::handleDisconnectInternal(void* ctx) {
176*38e8c45fSAndroid Build Coastguard Worker     auto* channelContext = reinterpret_cast<ChannelContext*>(ctx);
177*38e8c45fSAndroid Build Coastguard Worker     if (channelContext == nullptr) {
178*38e8c45fSAndroid Build Coastguard Worker         // Connections marked "incoming" (outgoing from the server's side)
179*38e8c45fSAndroid Build Coastguard Worker         // do not have a valid channel context because joinFn does not get
180*38e8c45fSAndroid Build Coastguard Worker         // called for them. We ignore them here.
181*38e8c45fSAndroid Build Coastguard Worker         return;
182*38e8c45fSAndroid Build Coastguard Worker     }
183*38e8c45fSAndroid Build Coastguard Worker 
184*38e8c45fSAndroid Build Coastguard Worker     auto& session = channelContext->session;
185*38e8c45fSAndroid Build Coastguard Worker     (void)session->shutdownAndWait(false);
186*38e8c45fSAndroid Build Coastguard Worker }
187*38e8c45fSAndroid Build Coastguard Worker 
handleChannelCleanup(void * ctx)188*38e8c45fSAndroid Build Coastguard Worker void RpcServerTrusty::handleChannelCleanup(void* ctx) {
189*38e8c45fSAndroid Build Coastguard Worker     auto* channelContext = reinterpret_cast<ChannelContext*>(ctx);
190*38e8c45fSAndroid Build Coastguard Worker     if (channelContext == nullptr) {
191*38e8c45fSAndroid Build Coastguard Worker         return;
192*38e8c45fSAndroid Build Coastguard Worker     }
193*38e8c45fSAndroid Build Coastguard Worker 
194*38e8c45fSAndroid Build Coastguard Worker     auto& session = channelContext->session;
195*38e8c45fSAndroid Build Coastguard Worker     auto& connection = channelContext->connection;
196*38e8c45fSAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL_IF(!session->removeIncomingConnection(connection),
197*38e8c45fSAndroid Build Coastguard Worker                         "bad state: connection object guaranteed to be in list");
198*38e8c45fSAndroid Build Coastguard Worker 
199*38e8c45fSAndroid Build Coastguard Worker     delete channelContext;
200*38e8c45fSAndroid Build Coastguard Worker }
201*38e8c45fSAndroid Build Coastguard Worker 
202*38e8c45fSAndroid Build Coastguard Worker } // namespace android
203