diff options
-rw-r--r-- | libs/binder/RpcServer.cpp | 19 | ||||
-rw-r--r-- | libs/binder/include/binder/RpcServer.h | 7 | ||||
-rw-r--r-- | libs/binder/tests/BinderRpcTestServerConfig.aidl | 1 | ||||
-rw-r--r-- | libs/binder/tests/binderRpcTest.cpp | 32 | ||||
-rw-r--r-- | libs/binder/tests/binderRpcTestService.cpp | 4 |
5 files changed, 39 insertions, 24 deletions
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp index d9e926a9d5..b8742af1f9 100644 --- a/libs/binder/RpcServer.cpp +++ b/libs/binder/RpcServer.cpp @@ -71,8 +71,23 @@ status_t RpcServer::setupUnixDomainServer(const char* path) { return setupSocketServer(UnixSocketAddress(path)); } -status_t RpcServer::setupVsockServer(unsigned int bindCid, unsigned int port) { - return setupSocketServer(VsockSocketAddress(bindCid, port)); +status_t RpcServer::setupVsockServer(unsigned bindCid, unsigned port, unsigned* assignedPort) { + auto status = setupSocketServer(VsockSocketAddress(bindCid, port)); + if (status != OK) return status; + + if (assignedPort == nullptr) return OK; + sockaddr_vm addr; + socklen_t len = sizeof(addr); + if (0 != getsockname(mServer.fd.get(), reinterpret_cast<sockaddr*>(&addr), &len)) { + status = -errno; + ALOGE("setupVsockServer: Failed to getsockname: %s", strerror(-status)); + return status; + } + + LOG_ALWAYS_FATAL_IF(len != sizeof(addr), "Wrong socket type: len %zu vs len %zu", + static_cast<size_t>(len), sizeof(addr)); + *assignedPort = addr.svm_port; + return OK; } status_t RpcServer::setupInetServer(const char* address, unsigned int port, diff --git a/libs/binder/include/binder/RpcServer.h b/libs/binder/include/binder/RpcServer.h index abea0fb40c..c241d31623 100644 --- a/libs/binder/include/binder/RpcServer.h +++ b/libs/binder/include/binder/RpcServer.h @@ -85,9 +85,12 @@ public: /** * Creates an RPC server binding to the given CID at the given port. + * + * Set |port| to VMADDR_PORT_ANY to pick an ephemeral port. In this case, |assignedPort| + * will be set to the picked port number, if it is not null. */ - [[nodiscard]] LIBBINDER_EXPORTED status_t setupVsockServer(unsigned int bindCid, - unsigned int port); + [[nodiscard]] LIBBINDER_EXPORTED status_t setupVsockServer(unsigned bindCid, unsigned port, + unsigned* assignedPort = nullptr); /** * Creates an RPC server at the current port using IPv4. diff --git a/libs/binder/tests/BinderRpcTestServerConfig.aidl b/libs/binder/tests/BinderRpcTestServerConfig.aidl index b2e0ef21c7..96550bca6b 100644 --- a/libs/binder/tests/BinderRpcTestServerConfig.aidl +++ b/libs/binder/tests/BinderRpcTestServerConfig.aidl @@ -20,7 +20,6 @@ parcelable BinderRpcTestServerConfig { int socketType; int rpcSecurity; int serverVersion; - int vsockPort; int socketFd; // Inherited from the parent process. @utf8InCpp String addr; } diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp index 19882ea1a9..9b1b64ae8c 100644 --- a/libs/binder/tests/binderRpcTest.cpp +++ b/libs/binder/tests/binderRpcTest.cpp @@ -141,11 +141,6 @@ static std::string allocateSocketAddress() { return ret; }; -static unsigned int allocateVsockPort() { - static unsigned int vsockPort = 34567; - return vsockPort++; -} - static unique_fd initUnixSocket(std::string addr) { auto socket_addr = UnixSocketAddress(addr.c_str()); unique_fd fd(TEMP_FAILURE_RETRY(socket(socket_addr.addr()->sa_family, SOCK_STREAM, AF_UNIX))); @@ -300,7 +295,6 @@ std::unique_ptr<ProcessSession> BinderRpc::createRpcTestSocketServerProcessEtc( serverConfig.socketType = static_cast<int32_t>(socketType); serverConfig.rpcSecurity = static_cast<int32_t>(rpcSecurity); serverConfig.serverVersion = serverVersion; - serverConfig.vsockPort = allocateVsockPort(); serverConfig.addr = addr; serverConfig.socketFd = socketFd.get(); for (auto mode : options.serverSupportedFileDescriptorTransportModes) { @@ -379,7 +373,7 @@ std::unique_ptr<ProcessSession> BinderRpc::createRpcTestSocketServerProcessEtc( unique_fd(dup(bootstrapClientFd.get()))); break; case SocketType::VSOCK: - status = session->setupVsockClient(VMADDR_CID_LOCAL, serverConfig.vsockPort); + status = session->setupVsockClient(VMADDR_CID_LOCAL, serverInfo.port); break; case SocketType::INET: status = session->setupInetClient("127.0.0.1", serverInfo.port); @@ -1152,8 +1146,6 @@ INSTANTIATE_TEST_SUITE_P(Trusty, BinderRpc, ::testing::ValuesIn(getTrustyBinderR #else // BINDER_RPC_TO_TRUSTY_TEST bool testSupportVsockLoopback() { // We don't need to enable TLS to know if vsock is supported. - unsigned int vsockPort = allocateVsockPort(); - unique_fd serverFd( TEMP_FAILURE_RETRY(socket(AF_VSOCK, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0))); @@ -1165,16 +1157,21 @@ bool testSupportVsockLoopback() { sockaddr_vm serverAddr{ .svm_family = AF_VSOCK, - .svm_port = vsockPort, + .svm_port = VMADDR_PORT_ANY, .svm_cid = VMADDR_CID_ANY, }; int ret = TEMP_FAILURE_RETRY( bind(serverFd.get(), reinterpret_cast<sockaddr*>(&serverAddr), sizeof(serverAddr))); - LOG_ALWAYS_FATAL_IF(0 != ret, "Could not bind socket to port %u: %s", vsockPort, + LOG_ALWAYS_FATAL_IF(0 != ret, "Could not bind socket to port VMADDR_PORT_ANY: %s", strerror(errno)); + socklen_t len = sizeof(serverAddr); + ret = getsockname(serverFd.get(), reinterpret_cast<sockaddr*>(&serverAddr), &len); + LOG_ALWAYS_FATAL_IF(0 != ret, "Failed to getsockname: %s", strerror(errno)); + LOG_ALWAYS_FATAL_IF(len < sizeof(serverAddr), "getsockname didn't read the full addr struct"); + ret = TEMP_FAILURE_RETRY(listen(serverFd.get(), 1 /*backlog*/)); - LOG_ALWAYS_FATAL_IF(0 != ret, "Could not listen socket on port %u: %s", vsockPort, + LOG_ALWAYS_FATAL_IF(0 != ret, "Could not listen socket on port %u: %s", serverAddr.svm_port, strerror(errno)); // Try to connect to the server using the VMADDR_CID_LOCAL cid @@ -1183,13 +1180,13 @@ bool testSupportVsockLoopback() { // and they return ETIMEDOUT after that. unique_fd connectFd( TEMP_FAILURE_RETRY(socket(AF_VSOCK, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0))); - LOG_ALWAYS_FATAL_IF(!connectFd.ok(), "Could not create socket for port %u: %s", vsockPort, - strerror(errno)); + LOG_ALWAYS_FATAL_IF(!connectFd.ok(), "Could not create socket for port %u: %s", + serverAddr.svm_port, strerror(errno)); bool success = false; sockaddr_vm connectAddr{ .svm_family = AF_VSOCK, - .svm_port = vsockPort, + .svm_port = serverAddr.svm_port, .svm_cid = VMADDR_CID_LOCAL, }; ret = TEMP_FAILURE_RETRY(connect(connectFd.get(), reinterpret_cast<sockaddr*>(&connectAddr), @@ -1538,8 +1535,9 @@ public: }; } break; case SocketType::VSOCK: { - auto port = allocateVsockPort(); - auto status = rpcServer->setupVsockServer(VMADDR_CID_LOCAL, port); + unsigned port; + auto status = + rpcServer->setupVsockServer(VMADDR_CID_LOCAL, VMADDR_PORT_ANY, &port); if (status != OK) { return AssertionFailure() << "setupVsockServer: " << statusToString(status); } diff --git a/libs/binder/tests/binderRpcTestService.cpp b/libs/binder/tests/binderRpcTestService.cpp index 28125f169c..aef946481f 100644 --- a/libs/binder/tests/binderRpcTestService.cpp +++ b/libs/binder/tests/binderRpcTestService.cpp @@ -143,8 +143,8 @@ int main(int argc, char* argv[]) { break; case SocketType::VSOCK: LOG_ALWAYS_FATAL_IF(OK != - server->setupVsockServer(VMADDR_CID_LOCAL, - serverConfig.vsockPort), + server->setupVsockServer(VMADDR_CID_LOCAL, VMADDR_PORT_ANY, + &outPort), "Need `sudo modprobe vsock_loopback`?"); break; case SocketType::INET: { |