libbinder: allow externally created connections

We want to allow:
- VM B process S has server using RpcServer normally
- VM A process V calls socket() and connect()
- VM A process V passes connected socket to VM A process C
- VM A process C talks to S over socket directly

Where:
- V = virtmanager process
- S = server process (e.g. compOS)
- C = client process (e.g. installd)

This way, within a VM, only one process needs permissions to connect to
services, and using this service, we can control access to VM services.

Bug: 193801719
Test: binderRpcTest
Change-Id: I5af60fd24354bce21d79676231172b6357b0c1a3
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index 386183d..6c56a4d 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -42,6 +42,7 @@
 #include <sys/prctl.h>
 #include <unistd.h>
 
+#include "../RpcSocketAddress.h" // for testing preconnected clients
 #include "../RpcState.h"   // for debugging
 #include "../vm_sockets.h" // for VMADDR_*
 
@@ -408,12 +409,15 @@
 };
 
 enum class SocketType {
+    PRECONNECTED,
     UNIX,
     VSOCK,
     INET,
 };
 static inline std::string PrintToString(SocketType socketType) {
     switch (socketType) {
+        case SocketType::PRECONNECTED:
+            return "preconnected_uds";
         case SocketType::UNIX:
             return "unix_domain_socket";
         case SocketType::VSOCK:
@@ -426,6 +430,20 @@
     }
 }
 
+static base::unique_fd connectToUds(const char* addrStr) {
+    UnixSocketAddress addr(addrStr);
+    base::unique_fd serverFd(
+            TEMP_FAILURE_RETRY(socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0)));
+    int savedErrno = errno;
+    CHECK(serverFd.ok()) << "Could not create socket " << addrStr << ": " << strerror(savedErrno);
+
+    if (0 != TEMP_FAILURE_RETRY(connect(serverFd.get(), addr.addr(), addr.addrSize()))) {
+        int savedErrno = errno;
+        LOG(FATAL) << "Could not connect to socket " << addrStr << ": " << strerror(savedErrno);
+    }
+    return serverFd;
+}
+
 class BinderRpc : public ::testing::TestWithParam<std::tuple<SocketType, RpcSecurity>> {
 public:
     struct Options {
@@ -462,6 +480,8 @@
                     unsigned int outPort = 0;
 
                     switch (socketType) {
+                        case SocketType::PRECONNECTED:
+                            [[fallthrough]];
                         case SocketType::UNIX:
                             CHECK(server->setupUnixDomainServer(addr.c_str())) << addr;
                             break;
@@ -500,6 +520,12 @@
             session->setMaxThreads(options.numIncomingConnections);
 
             switch (socketType) {
+                case SocketType::PRECONNECTED:
+                    if (session->setupPreconnectedClient({}, [=]() {
+                            return connectToUds(addr.c_str());
+                        }))
+                        goto success;
+                    break;
                 case SocketType::UNIX:
                     if (session->setupUnixDomainClient(addr.c_str())) goto success;
                     break;
@@ -1175,7 +1201,7 @@
 }
 
 static std::vector<SocketType> testSocketTypes() {
-    std::vector<SocketType> ret = {SocketType::UNIX, SocketType::INET};
+    std::vector<SocketType> ret = {SocketType::PRECONNECTED, SocketType::UNIX, SocketType::INET};
 
     static bool hasVsockLoopback = testSupportVsockLoopback();