1 /* 2 * Copyright (C) 2022 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 #pragma once 18 19 #include <binder/ARpcServerTrusty.h> 20 #include <binder/IBinder.h> 21 #include <binder/RpcServer.h> 22 #include <binder/RpcSession.h> 23 #include <binder/RpcTransport.h> 24 #include <binder/unique_fd.h> 25 #include <utils/Errors.h> 26 #include <utils/RefBase.h> 27 28 #include <map> 29 #include <vector> 30 31 #include <lib/tipc/tipc_srv.h> 32 33 namespace android { 34 35 /** 36 * This is the Trusty-specific RPC server code. 37 */ 38 class RpcServerTrusty final : public virtual RefBase { 39 public: 40 // C++ equivalent to tipc_port_acl that uses safe data structures instead of 41 // raw pointers, except for |extraData| which doesn't have a good 42 // equivalent. 43 struct PortAcl { 44 uint32_t flags; 45 std::vector<uuid> uuids; 46 const void* extraData; 47 }; 48 49 /** 50 * Creates an RPC server listening on the given port and adds it to the 51 * Trusty handle set at |handleSet|. 52 * 53 * The caller is responsible for calling tipc_run_event_loop() to start 54 * the TIPC event loop after creating one or more services here. 55 */ 56 static sp<RpcServerTrusty> make( 57 tipc_hset* handleSet, std::string&& portName, std::shared_ptr<const PortAcl>&& portAcl, 58 size_t msgMaxSize, 59 std::unique_ptr<RpcTransportCtxFactory> rpcTransportCtxFactory = nullptr); 60 setProtocolVersion(uint32_t version)61 [[nodiscard]] bool setProtocolVersion(uint32_t version) { 62 return mRpcServer->setProtocolVersion(version); 63 } setSupportedFileDescriptorTransportModes(const std::vector<RpcSession::FileDescriptorTransportMode> & modes)64 void setSupportedFileDescriptorTransportModes( 65 const std::vector<RpcSession::FileDescriptorTransportMode>& modes) { 66 mRpcServer->setSupportedFileDescriptorTransportModes(modes); 67 } setRootObject(const sp<IBinder> & binder)68 void setRootObject(const sp<IBinder>& binder) { mRpcServer->setRootObject(binder); } setRootObjectWeak(const wp<IBinder> & binder)69 void setRootObjectWeak(const wp<IBinder>& binder) { mRpcServer->setRootObjectWeak(binder); } setPerSessionRootObject(std::function<sp<IBinder> (wp<RpcSession> session,const void *,size_t)> && object)70 void setPerSessionRootObject( 71 std::function<sp<IBinder>(wp<RpcSession> session, const void*, size_t)>&& object) { 72 mRpcServer->setPerSessionRootObject(std::move(object)); 73 } getRootObject()74 sp<IBinder> getRootObject() { return mRpcServer->getRootObject(); } 75 76 /** 77 * For debugging! 78 */ listSessions()79 std::vector<sp<RpcSession>> listSessions() { return mRpcServer->listSessions(); } 80 81 private: 82 // Both this class and RpcServer have multiple non-copyable fields, 83 // including mPortAcl below which can't be copied because mUuidPtrs 84 // holds pointers into it 85 RpcServerTrusty(const RpcServerTrusty&) = delete; 86 void operator=(const RpcServerTrusty&) = delete; 87 88 friend sp<RpcServerTrusty>; 89 explicit RpcServerTrusty(std::unique_ptr<RpcTransportCtx> ctx, std::string&& portName, 90 std::shared_ptr<const PortAcl>&& portAcl, size_t msgMaxSize); 91 92 // Internal helper that creates the RpcServer. 93 // This is used both from here and Rust. makeRpcServer(std::unique_ptr<RpcTransportCtx> ctx)94 static sp<RpcServer> makeRpcServer(std::unique_ptr<RpcTransportCtx> ctx) { 95 auto rpcServer = sp<RpcServer>::make(std::move(ctx)); 96 97 // TODO(b/266741352): follow-up to prevent needing this in the future 98 // Trusty needs to be set to the latest stable version that is in prebuilts there. 99 LOG_ALWAYS_FATAL_IF(!rpcServer->setProtocolVersion(0)); 100 101 return rpcServer; 102 } 103 104 friend struct ::ARpcServerTrusty; 105 friend ::ARpcServerTrusty* ::ARpcServerTrusty_newPerSession(::AIBinder* (*)(const void*, size_t, 106 char*), 107 char*, void (*)(char*)); 108 friend void ::ARpcServerTrusty_delete(::ARpcServerTrusty*); 109 friend int ::ARpcServerTrusty_handleConnect(::ARpcServerTrusty*, handle_t, const uuid*, void**); 110 friend int ::ARpcServerTrusty_handleMessage(void*); 111 friend void ::ARpcServerTrusty_handleDisconnect(void*); 112 friend void ::ARpcServerTrusty_handleChannelCleanup(void*); 113 114 // The Rpc-specific context maintained for every open TIPC channel. 115 struct ChannelContext { 116 sp<RpcSession> session; 117 sp<RpcSession::RpcConnection> connection; 118 }; 119 120 static int handleConnect(const tipc_port* port, handle_t chan, const uuid* peer, void** ctx_p); 121 static int handleMessage(const tipc_port* port, handle_t chan, void* ctx); 122 static void handleDisconnect(const tipc_port* port, handle_t chan, void* ctx); 123 static void handleChannelCleanup(void* ctx); 124 125 static int handleConnectInternal(RpcServer* rpcServer, handle_t chan, const uuid* peer, 126 void** ctx_p); 127 static int handleMessageInternal(void* ctx); 128 static void handleDisconnectInternal(void* ctx); 129 130 static constexpr tipc_srv_ops kTipcOps = { 131 .on_connect = &handleConnect, 132 .on_message = &handleMessage, 133 .on_disconnect = &handleDisconnect, 134 .on_channel_cleanup = &handleChannelCleanup, 135 }; 136 137 sp<RpcServer> mRpcServer; 138 std::string mPortName; 139 std::shared_ptr<const PortAcl> mPortAcl; 140 std::vector<const uuid*> mUuidPtrs; 141 tipc_port_acl mTipcPortAcl; 142 tipc_port mTipcPort; 143 }; 144 145 } // namespace android 146