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
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
index 0820cd1..fedc1d9 100644
--- a/libs/binder/RpcServer.cpp
+++ b/libs/binder/RpcServer.cpp
@@ -70,11 +70,8 @@
     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 @@
     mRootObjectFactory = std::move(makeObject);
 }
 
+void RpcServer::setConnectionFilter(std::function<bool(const void*, size_t)>&& filter) {
+    RpcMutexLockGuard _l(mLock);
+    LOG_ALWAYS_FATAL_IF(mShutdownTrigger != nullptr, "Already joined");
+    mConnectionFilter = std::move(filter);
+}
+
 sp<IBinder> RpcServer::getRootObject() {
     RpcMutexLockGuard _l(mLock);
     bool hasWeak = mRootObjectWeak.unsafe_get();
@@ -242,13 +245,19 @@
         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<sockaddr*>(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);