libbinder: Add Trusty IPC support to binderRpcTest
Add a new SocketType::TIPC socket to binderRpcTest
that is used to connect to the test service in Trusty.
This enables binderRpcTest on the connection between
Android and Trusty.
Bug: 230135749
Test: atest binderRpcTest on qemu_trusty_arm64
Change-Id: I10c77bab586e6f6a44117c3b376d591ed5e0b1fb
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 150bde8..cebaf17 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -74,6 +74,9 @@
name: "libbinder_common_defaults",
host_supported: true,
+ // for vndbinder and binderRpcTest
+ vendor_available: true,
+
srcs: [
"Binder.cpp",
"BpBinder.cpp",
@@ -197,6 +200,7 @@
cc_library_headers {
name: "trusty_mock_headers",
+ vendor_available: true,
host_supported: true,
export_include_dirs: [
@@ -295,8 +299,6 @@
version_script: "libbinder.map",
- // for vndbinder
- vendor_available: true,
vndk: {
enabled: true,
},
@@ -459,6 +461,7 @@
cc_library_static {
name: "libbinder_tls_static",
defaults: ["libbinder_tls_defaults"],
+ vendor_available: true,
visibility: [
":__subpackages__",
],
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index bab4e73..7006f87 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -138,6 +138,7 @@
aidl_interface {
name: "binderRpcTestIface",
+ vendor_available: true,
host_supported: true,
unstable: true,
srcs: [
@@ -158,6 +159,7 @@
cc_library_static {
name: "libbinder_tls_test_utils",
+ vendor_available: true,
host_supported: true,
target: {
darwin: {
@@ -211,6 +213,7 @@
defaults: [
"binderRpcTest_common_defaults",
],
+ vendor_available: true,
gtest: false,
auto_gen_config: false,
srcs: [
@@ -221,10 +224,18 @@
cc_defaults {
name: "binderRpcTest_defaults",
+ vendor_available: true,
target: {
android: {
test_suites: ["vts"],
},
+
+ vendor: {
+ shared_libs: [
+ "libbinder_trusty",
+ "libtrusty",
+ ],
+ },
},
defaults: [
"binderRpcTest_common_defaults",
@@ -267,6 +278,7 @@
name: "binderRpcTest_static_defaults",
shared_libs: [
+ "liblog",
"libutils",
// libcrypto_static is not visible to this module
"libcrypto",
@@ -274,7 +286,6 @@
static_libs: [
"libbase",
"libcutils",
- "liblog",
"libssl",
],
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index 36c8d8c..84c93dd 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -28,6 +28,11 @@
#include <sys/prctl.h>
#include <sys/socket.h>
+#ifdef __ANDROID_VENDOR__
+#include <binder/RpcTransportTipcAndroid.h>
+#include <trusty/tipc.h>
+#endif // __ANDROID_VENDOR__
+
#include "binderRpcTestCommon.h"
#include "binderRpcTestFixture.h"
@@ -45,6 +50,10 @@
constexpr bool kEnableSharedLibs = true;
#endif
+#ifdef __ANDROID_VENDOR__
+constexpr char kTrustyIpcDevice[] = "/dev/trusty-ipc-dev0";
+#endif
+
static std::string WaitStatusToString(int wstatus) {
if (WIFEXITED(wstatus)) {
return base::StringPrintf("exit status %d", WEXITSTATUS(wstatus));
@@ -270,6 +279,11 @@
auto ret = std::make_unique<LinuxProcessSession>(
Process([=](android::base::borrowed_fd writeEnd, android::base::borrowed_fd readEnd) {
+ if (socketType == SocketType::TIPC) {
+ // Trusty has a single persistent service
+ return;
+ }
+
auto writeFd = std::to_string(writeEnd.get());
auto readFd = std::to_string(readEnd.get());
execl(servicePath.c_str(), servicePath.c_str(), writeFd.c_str(), readFd.c_str(),
@@ -288,31 +302,47 @@
serverConfig.serverSupportedFileDescriptorTransportModes.push_back(
static_cast<int32_t>(mode));
}
- writeToFd(ret->host.writeEnd(), serverConfig);
+ if (socketType != SocketType::TIPC) {
+ writeToFd(ret->host.writeEnd(), serverConfig);
+ }
std::vector<sp<RpcSession>> sessions;
auto certVerifier = std::make_shared<RpcCertificateVerifierSimple>();
for (size_t i = 0; i < options.numSessions; i++) {
- sessions.emplace_back(RpcSession::make(newFactory(rpcSecurity, certVerifier)));
+ std::unique_ptr<RpcTransportCtxFactory> factory;
+ if (socketType == SocketType::TIPC) {
+#ifdef __ANDROID_VENDOR__
+ factory = RpcTransportCtxFactoryTipcAndroid::make();
+#else
+ LOG_ALWAYS_FATAL("TIPC socket type only supported on vendor");
+#endif
+ } else {
+ factory = newFactory(rpcSecurity, certVerifier);
+ }
+ sessions.emplace_back(RpcSession::make(std::move(factory)));
}
- auto serverInfo = readFromFd<BinderRpcTestServerInfo>(ret->host.readEnd());
- BinderRpcTestClientInfo clientInfo;
- for (const auto& session : sessions) {
- auto& parcelableCert = clientInfo.certs.emplace_back();
- parcelableCert.data = session->getCertificate(RpcCertificateFormat::PEM);
- }
- writeToFd(ret->host.writeEnd(), clientInfo);
+ BinderRpcTestServerInfo serverInfo;
+ if (socketType != SocketType::TIPC) {
+ serverInfo = readFromFd<BinderRpcTestServerInfo>(ret->host.readEnd());
+ BinderRpcTestClientInfo clientInfo;
+ for (const auto& session : sessions) {
+ auto& parcelableCert = clientInfo.certs.emplace_back();
+ parcelableCert.data = session->getCertificate(RpcCertificateFormat::PEM);
+ }
+ writeToFd(ret->host.writeEnd(), clientInfo);
- CHECK_LE(serverInfo.port, std::numeric_limits<unsigned int>::max());
- if (socketType == SocketType::INET) {
- CHECK_NE(0, serverInfo.port);
- }
+ CHECK_LE(serverInfo.port, std::numeric_limits<unsigned int>::max());
+ if (socketType == SocketType::INET) {
+ CHECK_NE(0, serverInfo.port);
+ }
- if (rpcSecurity == RpcSecurity::TLS) {
- const auto& serverCert = serverInfo.cert.data;
- CHECK_EQ(OK,
- certVerifier->addTrustedPeerCertificate(RpcCertificateFormat::PEM, serverCert));
+ if (rpcSecurity == RpcSecurity::TLS) {
+ const auto& serverCert = serverInfo.cert.data;
+ CHECK_EQ(OK,
+ certVerifier->addTrustedPeerCertificate(RpcCertificateFormat::PEM,
+ serverCert));
+ }
}
status_t status;
@@ -343,6 +373,19 @@
case SocketType::INET:
status = session->setupInetClient("127.0.0.1", serverInfo.port);
break;
+ case SocketType::TIPC:
+ status = session->setupPreconnectedClient({}, [=]() {
+#ifdef __ANDROID_VENDOR__
+ auto port = trustyIpcPort(serverVersion);
+ int tipcFd = tipc_connect(kTrustyIpcDevice, port.c_str());
+ return tipcFd >= 0 ? android::base::unique_fd(tipcFd)
+ : android::base::unique_fd();
+#else
+ LOG_ALWAYS_FATAL("Tried to connect to Trusty outside of vendor");
+ return android::base::unique_fd();
+#endif
+ });
+ break;
default:
LOG_ALWAYS_FATAL("Unknown socket type");
}
@@ -684,6 +727,10 @@
}
TEST_P(BinderRpc, DeathRecipientFailsWithoutIncoming) {
+ if (socketType() == SocketType::TIPC) {
+ // This should work, but Trusty takes too long to restart the service
+ GTEST_SKIP() << "Service death test not supported on Trusty";
+ }
class MyDeathRec : public IBinder::DeathRecipient {
public:
void binderDied(const wp<IBinder>& /* who */) override {}
@@ -725,6 +772,11 @@
}
TEST_P(BinderRpc, Die) {
+ if (socketType() == SocketType::TIPC) {
+ // This should work, but Trusty takes too long to restart the service
+ GTEST_SKIP() << "Service death test not supported on Trusty";
+ }
+
for (bool doDeathCleanup : {true, false}) {
auto proc = createRpcTestSocketServerProcess({});
@@ -777,6 +829,10 @@
}
TEST_P(BinderRpc, FileDescriptorTransportRejectNone) {
+ if (socketType() == SocketType::TIPC) {
+ GTEST_SKIP() << "File descriptor tests not supported on Trusty (yet)";
+ }
+
auto proc = createRpcTestSocketServerProcess({
.clientFileDescriptorTransportMode = RpcSession::FileDescriptorTransportMode::NONE,
.serverSupportedFileDescriptorTransportModes =
@@ -793,6 +849,10 @@
}
TEST_P(BinderRpc, FileDescriptorTransportRejectUnix) {
+ if (socketType() == SocketType::TIPC) {
+ GTEST_SKIP() << "File descriptor tests not supported on Trusty (yet)";
+ }
+
auto proc = createRpcTestSocketServerProcess({
.clientFileDescriptorTransportMode = RpcSession::FileDescriptorTransportMode::UNIX,
.serverSupportedFileDescriptorTransportModes =
@@ -809,6 +869,10 @@
}
TEST_P(BinderRpc, FileDescriptorTransportOptionalUnix) {
+ if (socketType() == SocketType::TIPC) {
+ GTEST_SKIP() << "File descriptor tests not supported on Trusty (yet)";
+ }
+
auto proc = createRpcTestSocketServerProcess({
.clientFileDescriptorTransportMode = RpcSession::FileDescriptorTransportMode::NONE,
.serverSupportedFileDescriptorTransportModes =
@@ -822,6 +886,10 @@
}
TEST_P(BinderRpc, ReceiveFile) {
+ if (socketType() == SocketType::TIPC) {
+ GTEST_SKIP() << "File descriptor tests not supported on Trusty (yet)";
+ }
+
auto proc = createRpcTestSocketServerProcess({
.clientFileDescriptorTransportMode = RpcSession::FileDescriptorTransportMode::UNIX,
.serverSupportedFileDescriptorTransportModes =
@@ -842,6 +910,10 @@
}
TEST_P(BinderRpc, SendFiles) {
+ if (socketType() == SocketType::TIPC) {
+ GTEST_SKIP() << "File descriptor tests not supported on Trusty (yet)";
+ }
+
auto proc = createRpcTestSocketServerProcess({
.clientFileDescriptorTransportMode = RpcSession::FileDescriptorTransportMode::UNIX,
.serverSupportedFileDescriptorTransportModes =
@@ -914,6 +986,10 @@
}
TEST_P(BinderRpc, AppendInvalidFd) {
+ if (socketType() == SocketType::TIPC) {
+ GTEST_SKIP() << "File descriptor tests not supported on Trusty (yet)";
+ }
+
auto proc = createRpcTestSocketServerProcess({
.clientFileDescriptorTransportMode = RpcSession::FileDescriptorTransportMode::UNIX,
.serverSupportedFileDescriptorTransportModes =
@@ -940,6 +1016,7 @@
ASSERT_EQ(-1, pRaw.readFileDescriptor());
}
+#ifndef __ANDROID_VENDOR__ // No AIBinder_fromPlatformBinder on vendor
TEST_P(BinderRpc, WorksWithLibbinderNdkPing) {
if constexpr (!kEnableSharedLibs) {
GTEST_SKIP() << "Test disabled because Binder was built as a static library";
@@ -971,6 +1048,7 @@
ASSERT_TRUE(status.isOk()) << status.getDescription();
ASSERT_EQ("aoeuaoeu", out);
}
+#endif // __ANDROID_VENDOR__
ssize_t countFds() {
DIR* dir = opendir("/proc/self/fd/");
@@ -986,6 +1064,9 @@
if (serverSingleThreaded()) {
GTEST_SKIP() << "This test requires multiple threads";
}
+ if (socketType() == SocketType::TIPC) {
+ GTEST_SKIP() << "File descriptor tests not supported on Trusty (yet)";
+ }
ssize_t beforeFds = countFds();
ASSERT_GE(beforeFds, 0);
@@ -1100,6 +1181,21 @@
return ret;
}
+static std::vector<SocketType> testTipcSocketTypes() {
+#ifdef __ANDROID_VENDOR__
+ auto port = trustyIpcPort(RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL);
+ int tipcFd = tipc_connect(kTrustyIpcDevice, port.c_str());
+ if (tipcFd >= 0) {
+ close(tipcFd);
+ return {SocketType::TIPC};
+ }
+#endif // __ANDROID_VENDOR__
+
+ // TIPC is not supported on this device, most likely
+ // because /dev/trusty-ipc-dev0 is missing
+ return {};
+}
+
INSTANTIATE_TEST_CASE_P(PerSocket, BinderRpc,
::testing::Combine(::testing::ValuesIn(testSocketTypes()),
::testing::ValuesIn(RpcSecurityValues()),
@@ -1109,6 +1205,14 @@
::testing::Values(false, true)),
BinderRpc::PrintParamInfo);
+INSTANTIATE_TEST_CASE_P(Trusty, BinderRpc,
+ ::testing::Combine(::testing::ValuesIn(testTipcSocketTypes()),
+ ::testing::Values(RpcSecurity::RAW),
+ ::testing::ValuesIn(testVersions()),
+ ::testing::ValuesIn(testVersions()),
+ ::testing::Values(true), ::testing::Values(true)),
+ BinderRpc::PrintParamInfo);
+
class BinderRpcServerRootObject
: public ::testing::TestWithParam<std::tuple<bool, bool, RpcSecurity>> {};
@@ -1360,7 +1464,10 @@
addr, port);
return base::unique_fd{};
};
- }
+ } break;
+ case SocketType::TIPC: {
+ LOG_ALWAYS_FATAL("RpcTransportTest should not be enabled for TIPC");
+ } break;
}
mFd = rpcServer->releaseServer();
if (!mFd.fd.ok()) return AssertionFailure() << "releaseServer returns invalid fd";
diff --git a/libs/binder/tests/binderRpcTestCommon.h b/libs/binder/tests/binderRpcTestCommon.h
index 262d7e4..a467ee3 100644
--- a/libs/binder/tests/binderRpcTestCommon.h
+++ b/libs/binder/tests/binderRpcTestCommon.h
@@ -90,6 +90,7 @@
UNIX_RAW,
VSOCK,
INET,
+ TIPC,
};
static inline std::string PrintToString(SocketType socketType) {
@@ -106,6 +107,8 @@
return "vm_socket";
case SocketType::INET:
return "inet_socket";
+ case SocketType::TIPC:
+ return "trusty_ipc";
default:
LOG_ALWAYS_FATAL("Unknown socket type");
return "";
diff --git a/libs/binder/tests/binderRpcTestFixture.h b/libs/binder/tests/binderRpcTestFixture.h
index 5a78782..c99d68a 100644
--- a/libs/binder/tests/binderRpcTestFixture.h
+++ b/libs/binder/tests/binderRpcTestFixture.h
@@ -106,6 +106,10 @@
// Whether the test params support sending FDs in parcels.
bool supportsFdTransport() const {
+ if (socketType() == SocketType::TIPC) {
+ // Trusty does not support file descriptors yet
+ return false;
+ }
return clientVersion() >= 1 && serverVersion() >= 1 && rpcSecurity() != RpcSecurity::TLS &&
(socketType() == SocketType::PRECONNECTED || socketType() == SocketType::UNIX ||
socketType() == SocketType::UNIX_BOOTSTRAP ||
diff --git a/libs/binder/tests/binderRpcUniversalTests.cpp b/libs/binder/tests/binderRpcUniversalTests.cpp
index 9cd8a82..2249e5c 100644
--- a/libs/binder/tests/binderRpcUniversalTests.cpp
+++ b/libs/binder/tests/binderRpcUniversalTests.cpp
@@ -113,6 +113,10 @@
}
TEST_P(BinderRpc, AppendSeparateFormats) {
+ if (socketType() == SocketType::TIPC) {
+ GTEST_SKIP() << "Trusty does not support multiple server processes";
+ }
+
auto proc1 = createRpcTestSocketServerProcess({});
auto proc2 = createRpcTestSocketServerProcess({});
@@ -155,7 +159,9 @@
TEST_P(BinderRpc, SendAndGetResultBackBig) {
auto proc = createRpcTestSocketServerProcess({});
- std::string single = std::string(1024, 'a');
+ // Trusty has a limit of 4096 bytes for the entire RPC Binder message
+ size_t singleLen = socketType() == SocketType::TIPC ? 512 : 4096;
+ std::string single = std::string(singleLen, 'a');
std::string doubled;
EXPECT_OK(proc.rootIface->doubleString(single, &doubled));
EXPECT_EQ(single + single, doubled);
@@ -259,6 +265,10 @@
// aren't supported.
TEST_P(BinderRpc, CannotMixBindersBetweenUnrelatedSocketSessions) {
+ if (socketType() == SocketType::TIPC) {
+ GTEST_SKIP() << "Trusty does not support multiple server processes";
+ }
+
auto proc1 = createRpcTestSocketServerProcess({});
auto proc2 = createRpcTestSocketServerProcess({});
@@ -319,12 +329,16 @@
}
TEST_P(BinderRpc, NestedTransactions) {
+ auto fileDescriptorTransportMode = RpcSession::FileDescriptorTransportMode::UNIX;
+ if (socketType() == SocketType::TIPC) {
+ // TIPC does not support file descriptors yet
+ fileDescriptorTransportMode = RpcSession::FileDescriptorTransportMode::NONE;
+ }
auto proc = createRpcTestSocketServerProcess({
// Enable FD support because it uses more stack space and so represents
// something closer to a worst case scenario.
- .clientFileDescriptorTransportMode = RpcSession::FileDescriptorTransportMode::UNIX,
- .serverSupportedFileDescriptorTransportModes =
- {RpcSession::FileDescriptorTransportMode::UNIX},
+ .clientFileDescriptorTransportMode = fileDescriptorTransportMode,
+ .serverSupportedFileDescriptorTransportModes = {fileDescriptorTransportMode},
});
auto nastyNester = sp<MyBinderRpcTestDefault>::make();