From a47dfdaf7b7e24cf87d7711fe70d8bc4ab1ddf45 Mon Sep 17 00:00:00 2001 From: David Brazdil Date: Tue, 22 Nov 2022 22:52:19 +0000 Subject: rpc_binder: Specify CID for vsock RpcServer Currently RpcServer only allows to start a server listening for connections from VMHOST_CID_ANY. This is not always desirable as clients may want to listen only for connections from specific CIDs, eg. only the host or only local. This can be partially solved by setting the bind CID of the virtual socket. The server can bind to VMADDR_CID_LOCAL for local interface only. VMADDR_CID_ANY same as its own CID will bind to the remote interface and accept connections from all clients. To this end, add a callback for filtering accepted connections in RpcServer. This may already be possible with per-session root object. However, the root object is selected very late, after initial negotiation with the client. For both performance and safety, add the callback immediately after accept() to reject the connection as early as possible. Bug: 245727626 Test: atest binderRpcTest Change-Id: I5b3e6fd5119c77ef8c5c4fbbfead9892c5de1a07 --- libs/binder/RpcServer.cpp | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'libs/binder/RpcServer.cpp') diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp index 0820cd1d5c..fedc1d9593 100644 --- a/libs/binder/RpcServer.cpp +++ b/libs/binder/RpcServer.cpp @@ -70,11 +70,8 @@ status_t RpcServer::setupUnixDomainServer(const char* path) { return setupSocketServer(UnixSocketAddress(path)); } -status_t RpcServer::setupVsockServer(unsigned int port) { - // realizing value w/ this type at compile time to avoid ubsan abort - constexpr unsigned int kAnyCid = VMADDR_CID_ANY; - - return setupSocketServer(VsockSocketAddress(kAnyCid, port)); +status_t RpcServer::setupVsockServer(unsigned int bindCid, unsigned int port) { + return setupSocketServer(VsockSocketAddress(bindCid, port)); } status_t RpcServer::setupInetServer(const char* address, unsigned int port, @@ -157,6 +154,12 @@ void RpcServer::setPerSessionRootObject( mRootObjectFactory = std::move(makeObject); } +void RpcServer::setConnectionFilter(std::function&& filter) { + RpcMutexLockGuard _l(mLock); + LOG_ALWAYS_FATAL_IF(mShutdownTrigger != nullptr, "Already joined"); + mConnectionFilter = std::move(filter); +} + sp RpcServer::getRootObject() { RpcMutexLockGuard _l(mLock); bool hasWeak = mRootObjectWeak.unsafe_get(); @@ -242,13 +245,19 @@ void RpcServer::join() { if (mAcceptFn(*this, &clientSocket) != OK) { continue; } + + LOG_RPC_DETAIL("accept on fd %d yields fd %d", mServer.fd.get(), clientSocket.fd.get()); + if (getpeername(clientSocket.fd.get(), reinterpret_cast(addr.data()), &addrLen)) { ALOGE("Could not getpeername socket: %s", strerror(errno)); continue; } - LOG_RPC_DETAIL("accept on fd %d yields fd %d", mServer.fd.get(), clientSocket.fd.get()); + if (mConnectionFilter != nullptr && !mConnectionFilter(addr.data(), addrLen)) { + ALOGE("Dropped client connection fd %d", clientSocket.fd.get()); + continue; + } { RpcMutexLockGuard _l(mLock); -- cgit v1.2.3-59-g8ed1b