[rpc_binder] Implement RPC binder over init-managed Unix domain socket
This implements an RPC binder over init-managed Unix domain sockets.
The cl adds binder tests and the new API is also used for
vm_payload_service inside Microdroid.
A previous cl aosp/2229557 sets up the binder over anonymous Unix sockets.
Test: atest MicrodroidTests ComposHostTestCases
Bug: 222479468
Change-Id: I0c7c38f4792c4536f5f88eb7e035091505f782f7
diff --git a/libs/binder/tests/BinderRpcTestServerConfig.aidl b/libs/binder/tests/BinderRpcTestServerConfig.aidl
index 4cdeac4..aac4b04 100644
--- a/libs/binder/tests/BinderRpcTestServerConfig.aidl
+++ b/libs/binder/tests/BinderRpcTestServerConfig.aidl
@@ -22,5 +22,6 @@
int serverVersion;
int vsockPort;
int unixBootstrapFd; // Inherited from parent
+ int socketFd;
@utf8InCpp String addr;
}
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index 004dea3..79bd9d4 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -129,6 +129,15 @@
return vsockPort++;
}
+static base::unique_fd initUnixSocket(std::string addr) {
+ auto socket_addr = UnixSocketAddress(addr.c_str());
+ base::unique_fd fd(
+ TEMP_FAILURE_RETRY(socket(socket_addr.addr()->sa_family, SOCK_STREAM, AF_UNIX)));
+ CHECK(fd.ok());
+ CHECK_EQ(0, TEMP_FAILURE_RETRY(bind(fd.get(), socket_addr.addr(), socket_addr.addrSize())));
+ return fd;
+}
+
// Destructors need to be defined, even if pure virtual
ProcessSession::~ProcessSession() {}
@@ -243,13 +252,18 @@
singleThreaded ? "_single_threaded" : "",
noKernel ? "_no_kernel" : "");
- base::unique_fd bootstrapClientFd, bootstrapServerFd;
+ base::unique_fd bootstrapClientFd, bootstrapServerFd, socketFd;
// Do not set O_CLOEXEC, bootstrapServerFd needs to survive fork/exec.
// This is because we cannot pass ParcelFileDescriptor over a pipe.
if (!base::Socketpair(SOCK_STREAM, &bootstrapClientFd, &bootstrapServerFd)) {
int savedErrno = errno;
LOG(FATAL) << "Failed socketpair(): " << strerror(savedErrno);
}
+ auto addr = allocateSocketAddress();
+ // Initializes the socket before the fork/exec.
+ if (socketType == SocketType::UNIX_RAW) {
+ socketFd = initUnixSocket(addr);
+ }
auto ret = std::make_unique<LinuxProcessSession>(
Process([=](android::base::borrowed_fd writeEnd, android::base::borrowed_fd readEnd) {
@@ -265,8 +279,9 @@
serverConfig.rpcSecurity = static_cast<int32_t>(rpcSecurity);
serverConfig.serverVersion = serverVersion;
serverConfig.vsockPort = allocateVsockPort();
- serverConfig.addr = allocateSocketAddress();
+ serverConfig.addr = addr;
serverConfig.unixBootstrapFd = bootstrapServerFd.get();
+ serverConfig.socketFd = socketFd.get();
for (auto mode : options.serverSupportedFileDescriptorTransportModes) {
serverConfig.serverSupportedFileDescriptorTransportModes.push_back(
static_cast<int32_t>(mode));
@@ -312,6 +327,7 @@
return connectTo(UnixSocketAddress(serverConfig.addr.c_str()));
});
break;
+ case SocketType::UNIX_RAW:
case SocketType::UNIX:
status = session->setupUnixDomainClient(serverConfig.addr.c_str());
break;
@@ -1042,7 +1058,8 @@
}
static std::vector<SocketType> testSocketTypes(bool hasPreconnected = true) {
- std::vector<SocketType> ret = {SocketType::UNIX, SocketType::UNIX_BOOTSTRAP, SocketType::INET};
+ std::vector<SocketType> ret = {SocketType::UNIX, SocketType::UNIX_BOOTSTRAP, SocketType::INET,
+ SocketType::UNIX_RAW};
if (hasPreconnected) ret.push_back(SocketType::PRECONNECTED);
@@ -1284,6 +1301,17 @@
mAcceptConnection = &Server::recvmsgServerConnection;
mConnectToServer = [this] { return connectToUnixBootstrap(mBootstrapSocket); };
} break;
+ case SocketType::UNIX_RAW: {
+ auto addr = allocateSocketAddress();
+ auto status = rpcServer->setupRawSocketServer(initUnixSocket(addr));
+ if (status != OK) {
+ return AssertionFailure()
+ << "setupRawSocketServer: " << statusToString(status);
+ }
+ mConnectToServer = [addr] {
+ return connectTo(UnixSocketAddress(addr.c_str()));
+ };
+ } break;
case SocketType::VSOCK: {
auto port = allocateVsockPort();
auto status = rpcServer->setupVsockServer(port);
diff --git a/libs/binder/tests/binderRpcTestCommon.h b/libs/binder/tests/binderRpcTestCommon.h
index dc7d264..654e16c 100644
--- a/libs/binder/tests/binderRpcTestCommon.h
+++ b/libs/binder/tests/binderRpcTestCommon.h
@@ -69,6 +69,7 @@
PRECONNECTED,
UNIX,
UNIX_BOOTSTRAP,
+ UNIX_RAW,
VSOCK,
INET,
};
@@ -81,6 +82,8 @@
return "unix_domain_socket";
case SocketType::UNIX_BOOTSTRAP:
return "unix_domain_socket_bootstrap";
+ case SocketType::UNIX_RAW:
+ return "raw_uds";
case SocketType::VSOCK:
return "vm_socket";
case SocketType::INET:
diff --git a/libs/binder/tests/binderRpcTestFixture.h b/libs/binder/tests/binderRpcTestFixture.h
index 721fbfe..5a78782 100644
--- a/libs/binder/tests/binderRpcTestFixture.h
+++ b/libs/binder/tests/binderRpcTestFixture.h
@@ -108,7 +108,8 @@
bool supportsFdTransport() const {
return clientVersion() >= 1 && serverVersion() >= 1 && rpcSecurity() != RpcSecurity::TLS &&
(socketType() == SocketType::PRECONNECTED || socketType() == SocketType::UNIX ||
- socketType() == SocketType::UNIX_BOOTSTRAP);
+ socketType() == SocketType::UNIX_BOOTSTRAP ||
+ socketType() == SocketType::UNIX_RAW);
}
void SetUp() override {
diff --git a/libs/binder/tests/binderRpcTestService.cpp b/libs/binder/tests/binderRpcTestService.cpp
index a922b21..cc40995 100644
--- a/libs/binder/tests/binderRpcTestService.cpp
+++ b/libs/binder/tests/binderRpcTestService.cpp
@@ -54,6 +54,9 @@
case SocketType::UNIX_BOOTSTRAP:
CHECK_EQ(OK, server->setupUnixDomainSocketBootstrapServer(std::move(unixBootstrapFd)));
break;
+ case SocketType::UNIX_RAW:
+ CHECK_EQ(OK, server->setupRawSocketServer(base::unique_fd(serverConfig.socketFd)));
+ break;
case SocketType::VSOCK:
CHECK_EQ(OK, server->setupVsockServer(serverConfig.vsockPort));
break;
diff --git a/libs/binder/tests/binderRpcUniversalTests.cpp b/libs/binder/tests/binderRpcUniversalTests.cpp
index 1e8d93d..f960442 100644
--- a/libs/binder/tests/binderRpcUniversalTests.cpp
+++ b/libs/binder/tests/binderRpcUniversalTests.cpp
@@ -86,7 +86,7 @@
SocketType type = std::get<0>(GetParam());
if (type == SocketType::PRECONNECTED || type == SocketType::UNIX ||
- type == SocketType::UNIX_BOOTSTRAP) {
+ type == SocketType::UNIX_BOOTSTRAP || type == SocketType::UNIX_RAW) {
// we can't get port numbers for unix sockets
return;
}