diff options
-rw-r--r-- | libs/binder/RpcServer.cpp | 18 | ||||
-rw-r--r-- | libs/binder/include/binder/RpcServer.h | 19 | ||||
-rw-r--r-- | libs/binder/libbinder_rpc_unstable.cpp | 4 | ||||
-rw-r--r-- | libs/binder/tests/binderRpcTest.cpp | 7 |
4 files changed, 30 insertions, 18 deletions
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp index c67b70abc0..05e0f37abe 100644 --- a/libs/binder/RpcServer.cpp +++ b/libs/binder/RpcServer.cpp @@ -135,7 +135,7 @@ void RpcServer::setRootObjectWeak(const wp<IBinder>& binder) { mRootObjectWeak = binder; } void RpcServer::setPerSessionRootObject( - std::function<sp<IBinder>(const sockaddr*, socklen_t)>&& makeObject) { + std::function<sp<IBinder>(const void*, size_t)>&& makeObject) { std::lock_guard<std::mutex> _l(mLock); mRootObject.clear(); mRootObjectWeak.clear(); @@ -178,14 +178,16 @@ void RpcServer::join() { status_t status; while ((status = mShutdownTrigger->triggerablePoll(mServer, POLLIN)) == OK) { - sockaddr_storage addr; - socklen_t addrLen = sizeof(addr); + std::array<uint8_t, kRpcAddressSize> addr; + static_assert(addr.size() >= sizeof(sockaddr_storage), "kRpcAddressSize is too small"); + socklen_t addrLen = addr.size(); unique_fd clientFd( - TEMP_FAILURE_RETRY(accept4(mServer.get(), reinterpret_cast<sockaddr*>(&addr), + TEMP_FAILURE_RETRY(accept4(mServer.get(), reinterpret_cast<sockaddr*>(addr.data()), &addrLen, SOCK_CLOEXEC | SOCK_NONBLOCK))); - LOG_ALWAYS_FATAL_IF(addrLen > static_cast<socklen_t>(sizeof(addr)), "Truncated address"); + LOG_ALWAYS_FATAL_IF(addrLen > static_cast<socklen_t>(sizeof(sockaddr_storage)), + "Truncated address"); if (clientFd < 0) { ALOGE("Could not accept4 socket: %s", strerror(errno)); @@ -268,7 +270,7 @@ size_t RpcServer::numUninitializedSessions() { } void RpcServer::establishConnection(sp<RpcServer>&& server, base::unique_fd clientFd, - const sockaddr_storage addr, socklen_t addrLen) { + std::array<uint8_t, kRpcAddressSize> addr, size_t addrLen) { // mShutdownTrigger can only be cleared once connection threads have joined. // It must be set before this thread is started LOG_ALWAYS_FATAL_IF(server->mShutdownTrigger == nullptr); @@ -397,9 +399,7 @@ void RpcServer::establishConnection(sp<RpcServer>&& server, base::unique_fd clie // if null, falls back to server root sp<IBinder> sessionSpecificRoot; if (server->mRootObjectFactory != nullptr) { - sessionSpecificRoot = - server->mRootObjectFactory(reinterpret_cast<const sockaddr*>(&addr), - addrLen); + sessionSpecificRoot = server->mRootObjectFactory(addr.data(), addrLen); if (sessionSpecificRoot == nullptr) { ALOGE("Warning: server returned null from root object factory"); } diff --git a/libs/binder/include/binder/RpcServer.h b/libs/binder/include/binder/RpcServer.h index 6b31812d17..dba8dd64e9 100644 --- a/libs/binder/include/binder/RpcServer.h +++ b/libs/binder/include/binder/RpcServer.h @@ -125,9 +125,17 @@ public: */ 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); + * Allows a root object to be created for each session. + * + * Takes one argument: a callable that is invoked once per new session. + * The callable takes two arguments: a type-erased pointer to an OS- and + * transport-specific address structure, e.g., sockaddr_vm for vsock, and + * an integer representing the size in bytes of that structure. The + * callable should validate the size, then cast the type-erased pointer + * to a pointer to the actual type of the address, e.g., const void* to + * const sockaddr_vm*. + */ + void setPerSessionRootObject(std::function<sp<IBinder>(const void*, size_t)>&& object); sp<IBinder> getRootObject(); /** @@ -177,8 +185,9 @@ private: void onSessionAllIncomingThreadsEnded(const sp<RpcSession>& session) override; void onSessionIncomingThreadEnded() override; + static constexpr size_t kRpcAddressSize = 128; static void establishConnection(sp<RpcServer>&& server, base::unique_fd clientFd, - const sockaddr_storage addr, socklen_t addrLen); + std::array<uint8_t, kRpcAddressSize> addr, size_t addrLen); [[nodiscard]] status_t setupSocketServer(const RpcSocketAddress& address); const std::unique_ptr<RpcTransportCtx> mCtx; @@ -192,7 +201,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::function<sp<IBinder>(const void*, size_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/libbinder_rpc_unstable.cpp b/libs/binder/libbinder_rpc_unstable.cpp index bf2b25b265..a3d42b76fe 100644 --- a/libs/binder/libbinder_rpc_unstable.cpp +++ b/libs/binder/libbinder_rpc_unstable.cpp @@ -38,10 +38,10 @@ bool RunRpcServerWithFactory(AIBinder* (*factory)(unsigned int cid, void* contex << " error: " << statusToString(status).c_str(); return false; } - server->setPerSessionRootObject([=](const sockaddr* addr, socklen_t addrlen) { - LOG_ALWAYS_FATAL_IF(addr->sa_family != AF_VSOCK, "address is not a vsock"); + server->setPerSessionRootObject([=](const void* addr, size_t addrlen) { LOG_ALWAYS_FATAL_IF(addrlen < sizeof(sockaddr_vm), "sockaddr is truncated"); const sockaddr_vm* vaddr = reinterpret_cast<const sockaddr_vm*>(addr); + LOG_ALWAYS_FATAL_IF(vaddr->svm_family != AF_VSOCK, "address is not a vsock"); return AIBinder_toPlatformBinder(factory(vaddr->svm_cid, factoryContext)); }); diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp index 4161a7a25b..0247e429c7 100644 --- a/libs/binder/tests/binderRpcTest.cpp +++ b/libs/binder/tests/binderRpcTest.cpp @@ -650,8 +650,11 @@ public: .proc = createRpcTestSocketServerProcess( options, [&](const sp<RpcServer>& server) { - server->setPerSessionRootObject([&](const sockaddr* addr, - socklen_t len) { + server->setPerSessionRootObject([&](const void* addrPtr, size_t len) { + // UNIX sockets with abstract addresses return + // sizeof(sa_family_t)==2 in addrlen + CHECK_GE(len, sizeof(sa_family_t)); + const sockaddr* addr = reinterpret_cast<const sockaddr*>(addrPtr); sp<MyBinderRpcTest> service = sp<MyBinderRpcTest>::make(); switch (addr->sa_family) { case AF_UNIX: |