diff options
author | 2021-10-21 16:50:33 +0000 | |
---|---|---|
committer | 2021-10-21 16:50:33 +0000 | |
commit | 5f852b9c9bca236b01f8d59853d29fb6b6ee89b6 (patch) | |
tree | 1f5d043aa131c58b18ebbfa0e79e4dfb408c80a5 | |
parent | bc584178dacac2afb131e8a3b0de994c0643dc6d (diff) | |
parent | 51c44a96895b8c462e24984e510b09aded52297f (diff) |
Merge "libbinder: support server-specific session"
-rw-r--r-- | libs/binder/RpcServer.cpp | 38 | ||||
-rw-r--r-- | libs/binder/RpcSession.cpp | 4 | ||||
-rw-r--r-- | libs/binder/RpcState.cpp | 4 | ||||
-rw-r--r-- | libs/binder/include/binder/RpcServer.h | 8 | ||||
-rw-r--r-- | libs/binder/include/binder/RpcSession.h | 7 | ||||
-rw-r--r-- | libs/binder/tests/IBinderRpcTest.aidl | 3 | ||||
-rw-r--r-- | libs/binder/tests/binderRpcTest.cpp | 66 |
7 files changed, 114 insertions, 16 deletions
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp index 967b8e3801..4edc2029dc 100644 --- a/libs/binder/RpcServer.cpp +++ b/libs/binder/RpcServer.cpp @@ -127,14 +127,23 @@ void RpcServer::setProtocolVersion(uint32_t version) { void RpcServer::setRootObject(const sp<IBinder>& binder) { std::lock_guard<std::mutex> _l(mLock); + mRootObjectFactory = nullptr; mRootObjectWeak = mRootObject = binder; } void RpcServer::setRootObjectWeak(const wp<IBinder>& binder) { std::lock_guard<std::mutex> _l(mLock); mRootObject.clear(); + mRootObjectFactory = nullptr; mRootObjectWeak = binder; } +void RpcServer::setPerSessionRootObject( + std::function<sp<IBinder>(const sockaddr*, socklen_t)>&& makeObject) { + std::lock_guard<std::mutex> _l(mLock); + mRootObject.clear(); + mRootObjectWeak.clear(); + mRootObjectFactory = std::move(makeObject); +} sp<IBinder> RpcServer::getRootObject() { std::lock_guard<std::mutex> _l(mLock); @@ -174,8 +183,14 @@ void RpcServer::join() { status_t status; while ((status = mShutdownTrigger->triggerablePoll(mServer, POLLIN)) == OK) { - unique_fd clientFd(TEMP_FAILURE_RETRY( - accept4(mServer.get(), nullptr, nullptr /*length*/, SOCK_CLOEXEC | SOCK_NONBLOCK))); + sockaddr_storage addr; + socklen_t addrLen = sizeof(addr); + + unique_fd clientFd( + TEMP_FAILURE_RETRY(accept4(mServer.get(), reinterpret_cast<sockaddr*>(&addr), + &addrLen, SOCK_CLOEXEC | SOCK_NONBLOCK))); + + LOG_ALWAYS_FATAL_IF(addrLen > static_cast<socklen_t>(sizeof(addr)), "Truncated address"); if (clientFd < 0) { ALOGE("Could not accept4 socket: %s", strerror(errno)); @@ -187,7 +202,7 @@ void RpcServer::join() { std::lock_guard<std::mutex> _l(mLock); std::thread thread = std::thread(&RpcServer::establishConnection, sp<RpcServer>::fromExisting(this), - std::move(clientFd)); + std::move(clientFd), addr, addrLen); mConnectingThreads[thread.get_id()] = std::move(thread); } } @@ -257,7 +272,8 @@ size_t RpcServer::numUninitializedSessions() { return mConnectingThreads.size(); } -void RpcServer::establishConnection(sp<RpcServer>&& server, base::unique_fd clientFd) { +void RpcServer::establishConnection(sp<RpcServer>&& server, base::unique_fd clientFd, + const sockaddr_storage addr, socklen_t addrLen) { // TODO(b/183988761): cannot trust this simple ID LOG_ALWAYS_FATAL_IF(!server->mAgreedExperimental, "no!"); @@ -383,11 +399,23 @@ void RpcServer::establishConnection(sp<RpcServer>&& server, base::unique_fd clie session = RpcSession::make(); session->setMaxIncomingThreads(server->mMaxThreads); if (!session->setProtocolVersion(protocolVersion)) return; + + // if null, falls back to server root + sp<IBinder> sessionSpecificRoot; + if (server->mRootObjectFactory != nullptr) { + sessionSpecificRoot = + server->mRootObjectFactory(reinterpret_cast<const sockaddr*>(&addr), + addrLen); + if (sessionSpecificRoot == nullptr) { + ALOGE("Warning: server returned null from root object factory"); + } + } + if (!session->setForServer(server, sp<RpcServer::EventListener>::fromExisting( static_cast<RpcServer::EventListener*>( server.get())), - sessionId)) { + sessionId, sessionSpecificRoot)) { ALOGE("Failed to attach server to session"); return; } diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp index 9eef3e8914..137411bc6b 100644 --- a/libs/binder/RpcSession.cpp +++ b/libs/binder/RpcSession.cpp @@ -700,7 +700,8 @@ status_t RpcSession::addOutgoingConnection(std::unique_ptr<RpcTransport> rpcTran } bool RpcSession::setForServer(const wp<RpcServer>& server, const wp<EventListener>& eventListener, - const std::vector<uint8_t>& sessionId) { + const std::vector<uint8_t>& sessionId, + const sp<IBinder>& sessionSpecificRoot) { LOG_ALWAYS_FATAL_IF(mForServer != nullptr); LOG_ALWAYS_FATAL_IF(server == nullptr); LOG_ALWAYS_FATAL_IF(mEventListener != nullptr); @@ -713,6 +714,7 @@ bool RpcSession::setForServer(const wp<RpcServer>& server, const wp<EventListene mId = sessionId; mForServer = server; mEventListener = eventListener; + mSessionSpecificRootObject = sessionSpecificRoot; return true; } diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp index 9ba64f3407..09b3d68626 100644 --- a/libs/binder/RpcState.cpp +++ b/libs/binder/RpcState.cpp @@ -870,7 +870,9 @@ processTransactInternalTailCall: if (server) { switch (transaction->code) { case RPC_SPECIAL_TRANSACT_GET_ROOT: { - replyStatus = reply.writeStrongBinder(server->getRootObject()); + sp<IBinder> root = session->mSessionSpecificRootObject + ?: server->getRootObject(); + replyStatus = reply.writeStrongBinder(root); break; } default: { diff --git a/libs/binder/include/binder/RpcServer.h b/libs/binder/include/binder/RpcServer.h index fb2cf23cd0..04c6b592a8 100644 --- a/libs/binder/include/binder/RpcServer.h +++ b/libs/binder/include/binder/RpcServer.h @@ -130,6 +130,10 @@ public: * Holds a weak reference to the root object. */ void setRootObjectWeak(const wp<IBinder>& binder); + /** + * Allows a root object to be created for each session + */ + void setPerSessionRootObject(std::function<sp<IBinder>(const sockaddr*, socklen_t)>&& object); sp<IBinder> getRootObject(); /** @@ -179,7 +183,8 @@ private: void onSessionAllIncomingThreadsEnded(const sp<RpcSession>& session) override; void onSessionIncomingThreadEnded() override; - static void establishConnection(sp<RpcServer>&& server, base::unique_fd clientFd); + static void establishConnection(sp<RpcServer>&& server, base::unique_fd clientFd, + const sockaddr_storage addr, socklen_t addrLen); status_t setupSocketServer(const RpcSocketAddress& address); const std::unique_ptr<RpcTransportCtx> mCtx; @@ -194,6 +199,7 @@ private: std::map<std::thread::id, std::thread> mConnectingThreads; sp<IBinder> mRootObject; wp<IBinder> mRootObjectWeak; + std::function<sp<IBinder>(const sockaddr*, socklen_t)> mRootObjectFactory; std::map<std::vector<uint8_t>, sp<RpcSession>> mSessions; std::unique_ptr<FdTrigger> mShutdownTrigger; std::condition_variable mShutdownCv; diff --git a/libs/binder/include/binder/RpcSession.h b/libs/binder/include/binder/RpcSession.h index f5505da128..f9b733d509 100644 --- a/libs/binder/include/binder/RpcSession.h +++ b/libs/binder/include/binder/RpcSession.h @@ -256,7 +256,8 @@ private: bool init); [[nodiscard]] bool setForServer(const wp<RpcServer>& server, const wp<RpcSession::EventListener>& eventListener, - const std::vector<uint8_t>& sessionId); + const std::vector<uint8_t>& sessionId, + const sp<IBinder>& sessionSpecificRoot); sp<RpcConnection> assignIncomingConnectionToThisThread( std::unique_ptr<RpcTransport> rpcTransport); [[nodiscard]] bool removeIncomingConnection(const sp<RpcConnection>& connection); @@ -313,6 +314,10 @@ private: sp<WaitForShutdownListener> mShutdownListener; // used for client sessions wp<EventListener> mEventListener; // mForServer if server, mShutdownListener if client + // session-specific root object (if a different root is used for each + // session) + sp<IBinder> mSessionSpecificRootObject; + std::vector<uint8_t> mId; std::unique_ptr<FdTrigger> mShutdownTrigger; diff --git a/libs/binder/tests/IBinderRpcTest.aidl b/libs/binder/tests/IBinderRpcTest.aidl index 9e1078870c..fdd02a4435 100644 --- a/libs/binder/tests/IBinderRpcTest.aidl +++ b/libs/binder/tests/IBinderRpcTest.aidl @@ -18,6 +18,9 @@ interface IBinderRpcTest { oneway void sendString(@utf8InCpp String str); @utf8InCpp String doubleString(@utf8InCpp String str); + // get the port that a client used to connect to this object + int getClientPort(); + // number of known RPC binders to process, RpcState::countBinders by session int[] countBinders(); diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp index f132ff7239..62215bb550 100644 --- a/libs/binder/tests/binderRpcTest.cpp +++ b/libs/binder/tests/binderRpcTest.cpp @@ -174,6 +174,7 @@ public: class MyBinderRpcTest : public BnBinderRpcTest { public: wp<RpcServer> server; + int port = 0; Status sendString(const std::string& str) override { (void)str; @@ -183,6 +184,10 @@ public: *strstr = str + str; return Status::ok(); } + Status getClientPort(int* out) override { + *out = port; + return Status::ok(); + } Status countBinders(std::vector<int32_t>* out) override { sp<RpcServer> spServer = server.promote(); if (spServer == nullptr) { @@ -643,13 +648,39 @@ public: BinderRpcTestProcessSession createRpcTestSocketServerProcess(const Options& options) { BinderRpcTestProcessSession ret{ - .proc = createRpcTestSocketServerProcess(options, - [&](const sp<RpcServer>& server) { - sp<MyBinderRpcTest> service = - new MyBinderRpcTest; - server->setRootObject(service); - service->server = server; - }), + .proc = createRpcTestSocketServerProcess( + options, + [&](const sp<RpcServer>& server) { + server->setPerSessionRootObject([&](const sockaddr* addr, + socklen_t len) { + sp<MyBinderRpcTest> service = sp<MyBinderRpcTest>::make(); + switch (addr->sa_family) { + case AF_UNIX: + // nothing to save + break; + case AF_VSOCK: + CHECK_EQ(len, sizeof(sockaddr_vm)); + service->port = reinterpret_cast<const sockaddr_vm*>(addr) + ->svm_port; + break; + case AF_INET: + CHECK_EQ(len, sizeof(sockaddr_in)); + service->port = reinterpret_cast<const sockaddr_in*>(addr) + ->sin_port; + break; + case AF_INET6: + CHECK_EQ(len, sizeof(sockaddr_in)); + service->port = reinterpret_cast<const sockaddr_in6*>(addr) + ->sin6_port; + break; + default: + LOG_ALWAYS_FATAL("Unrecognized address family %d", + addr->sa_family); + } + service->server = server; + return service; + }); + }), }; ret.rootBinder = ret.proc.sessions.at(0).root; @@ -682,6 +713,27 @@ TEST_P(BinderRpc, MultipleSessions) { } } +TEST_P(BinderRpc, SeparateRootObject) { + SocketType type = std::get<0>(GetParam()); + if (type == SocketType::PRECONNECTED || type == SocketType::UNIX) { + // we can't get port numbers for unix sockets + return; + } + + auto proc = createRpcTestSocketServerProcess({.numSessions = 2}); + + int port1 = 0; + EXPECT_OK(proc.rootIface->getClientPort(&port1)); + + sp<IBinderRpcTest> rootIface2 = interface_cast<IBinderRpcTest>(proc.proc.sessions.at(1).root); + int port2; + EXPECT_OK(rootIface2->getClientPort(&port2)); + + // we should have a different IBinderRpcTest object created for each + // session, because we use setPerSessionRootObject + EXPECT_NE(port1, port2); +} + TEST_P(BinderRpc, TransactionsMustBeMarkedRpc) { auto proc = createRpcTestSocketServerProcess({}); Parcel data; |