diff options
| -rw-r--r-- | libs/binder/RpcServer.cpp | 4 | ||||
| -rw-r--r-- | libs/binder/RpcSession.cpp | 66 | ||||
| -rw-r--r-- | libs/binder/RpcSocketAddress.h | 8 | ||||
| -rw-r--r-- | libs/binder/include/binder/RpcServer.h | 2 | ||||
| -rw-r--r-- | libs/binder/include/binder/RpcSession.h | 2 | ||||
| -rw-r--r-- | libs/binder/tests/binderRpcTest.cpp | 60 | ||||
| -rw-r--r-- | libs/binder/vm_sockets.h | 54 |
7 files changed, 115 insertions, 81 deletions
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp index e9186f0e22..a6850ff6aa 100644 --- a/libs/binder/RpcServer.cpp +++ b/libs/binder/RpcServer.cpp @@ -49,8 +49,6 @@ bool RpcServer::setupUnixDomainServer(const char* path) { return setupSocketServer(UnixSocketAddress(path)); } -#ifdef __BIONIC__ - bool RpcServer::setupVsockServer(unsigned int port) { // realizing value w/ this type at compile time to avoid ubsan abort constexpr unsigned int kAnyCid = VMADDR_CID_ANY; @@ -58,8 +56,6 @@ bool RpcServer::setupVsockServer(unsigned int port) { return setupSocketServer(VsockSocketAddress(kAnyCid, port)); } -#endif // __BIONIC__ - bool RpcServer::setupInetServer(unsigned int port, unsigned int* assignedPort) { const char* kAddr = "127.0.0.1"; diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp index d9b5c735a3..0471705ede 100644 --- a/libs/binder/RpcSession.cpp +++ b/libs/binder/RpcSession.cpp @@ -61,14 +61,10 @@ bool RpcSession::setupUnixDomainClient(const char* path) { return setupSocketClient(UnixSocketAddress(path)); } -#ifdef __BIONIC__ - bool RpcSession::setupVsockClient(unsigned int cid, unsigned int port) { return setupSocketClient(VsockSocketAddress(cid, port)); } -#endif // __BIONIC__ - bool RpcSession::setupInetClient(const char* addr, unsigned int port) { auto aiStart = InetSocketAddress::getAddrInfo(addr, port); if (aiStart == nullptr) return false; @@ -219,42 +215,52 @@ bool RpcSession::setupSocketClient(const RpcSocketAddress& addr) { // we've already setup one client for (size_t i = 0; i + 1 < numThreadsAvailable; i++) { - // TODO(b/185167543): avoid race w/ accept4 not being called on server - for (size_t tries = 0; tries < 5; tries++) { - if (setupOneSocketClient(addr, mId.value())) break; - usleep(10000); - } + // TODO(b/185167543): shutdown existing connections? + if (!setupOneSocketClient(addr, mId.value())) return false; } return true; } bool RpcSession::setupOneSocketClient(const RpcSocketAddress& addr, int32_t id) { - unique_fd serverFd( - TEMP_FAILURE_RETRY(socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0))); - if (serverFd == -1) { - int savedErrno = errno; - ALOGE("Could not create socket at %s: %s", addr.toString().c_str(), strerror(savedErrno)); - return false; - } + for (size_t tries = 0; tries < 5; tries++) { + if (tries > 0) usleep(10000); + + unique_fd serverFd( + TEMP_FAILURE_RETRY(socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0))); + if (serverFd == -1) { + int savedErrno = errno; + ALOGE("Could not create socket at %s: %s", addr.toString().c_str(), + strerror(savedErrno)); + return false; + } - if (0 != TEMP_FAILURE_RETRY(connect(serverFd.get(), addr.addr(), addr.addrSize()))) { - int savedErrno = errno; - ALOGE("Could not connect socket at %s: %s", addr.toString().c_str(), strerror(savedErrno)); - return false; - } + if (0 != TEMP_FAILURE_RETRY(connect(serverFd.get(), addr.addr(), addr.addrSize()))) { + if (errno == ECONNRESET) { + ALOGW("Connection reset on %s", addr.toString().c_str()); + continue; + } + int savedErrno = errno; + ALOGE("Could not connect socket at %s: %s", addr.toString().c_str(), + strerror(savedErrno)); + return false; + } - if (sizeof(id) != TEMP_FAILURE_RETRY(write(serverFd.get(), &id, sizeof(id)))) { - int savedErrno = errno; - ALOGE("Could not write id to socket at %s: %s", addr.toString().c_str(), - strerror(savedErrno)); - return false; - } + if (sizeof(id) != TEMP_FAILURE_RETRY(write(serverFd.get(), &id, sizeof(id)))) { + int savedErrno = errno; + ALOGE("Could not write id to socket at %s: %s", addr.toString().c_str(), + strerror(savedErrno)); + return false; + } - LOG_RPC_DETAIL("Socket at %s client with fd %d", addr.toString().c_str(), serverFd.get()); + LOG_RPC_DETAIL("Socket at %s client with fd %d", addr.toString().c_str(), serverFd.get()); - addClient(std::move(serverFd)); - return true; + addClient(std::move(serverFd)); + return true; + } + + ALOGE("Ran out of retries to connect to %s", addr.toString().c_str()); + return false; } void RpcSession::addClient(unique_fd fd) { diff --git a/libs/binder/RpcSocketAddress.h b/libs/binder/RpcSocketAddress.h index c6a06cf817..c7ba5d96a7 100644 --- a/libs/binder/RpcSocketAddress.h +++ b/libs/binder/RpcSocketAddress.h @@ -24,9 +24,7 @@ #include <sys/types.h> #include <sys/un.h> -#ifdef __BIONIC__ -#include <linux/vm_sockets.h> -#endif +#include "vm_sockets.h" namespace android { @@ -59,8 +57,6 @@ private: sockaddr_un mAddr; }; -#ifdef __BIONIC__ - class VsockSocketAddress : public RpcSocketAddress { public: VsockSocketAddress(unsigned int cid, unsigned int port) @@ -80,8 +76,6 @@ private: sockaddr_vm mAddr; }; -#endif // __BIONIC__ - class InetSocketAddress : public RpcSocketAddress { public: InetSocketAddress(const sockaddr* sockAddr, size_t size, const char* addr, unsigned int port) diff --git a/libs/binder/include/binder/RpcServer.h b/libs/binder/include/binder/RpcServer.h index 8c9ba00f06..3534d5196e 100644 --- a/libs/binder/include/binder/RpcServer.h +++ b/libs/binder/include/binder/RpcServer.h @@ -57,12 +57,10 @@ public: */ [[nodiscard]] bool setupUnixDomainServer(const char* path); -#ifdef __BIONIC__ /** * Creates an RPC server at the current port. */ [[nodiscard]] bool setupVsockServer(unsigned int port); -#endif // __BIONIC__ /** * Creates an RPC server at the current port using IPv4. diff --git a/libs/binder/include/binder/RpcSession.h b/libs/binder/include/binder/RpcSession.h index f647c95d4b..0b77787e96 100644 --- a/libs/binder/include/binder/RpcSession.h +++ b/libs/binder/include/binder/RpcSession.h @@ -52,12 +52,10 @@ public: */ [[nodiscard]] bool setupUnixDomainClient(const char* path); -#ifdef __BIONIC__ /** * Connects to an RPC server at the CVD & port. */ [[nodiscard]] bool setupVsockClient(unsigned int cvd, unsigned int port); -#endif // __BIONIC__ /** * Connects to an RPC server at the given address and port. diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp index 8d10727c5b..b3ce7447a9 100644 --- a/libs/binder/tests/binderRpcTest.cpp +++ b/libs/binder/tests/binderRpcTest.cpp @@ -34,14 +34,11 @@ #include <iostream> #include <thread> -#ifdef __BIONIC__ -#include <linux/vm_sockets.h> -#endif //__BIONIC__ - #include <sys/prctl.h> #include <unistd.h> -#include "../RpcState.h" // for debugging +#include "../RpcState.h" // for debugging +#include "../vm_sockets.h" // for VMADDR_* namespace android { @@ -291,19 +288,15 @@ struct BinderRpcTestProcessSession { enum class SocketType { UNIX, -#ifdef __BIONIC__ VSOCK, -#endif // __BIONIC__ INET, }; static inline std::string PrintSocketType(const testing::TestParamInfo<SocketType>& info) { switch (info.param) { case SocketType::UNIX: return "unix_domain_socket"; -#ifdef __BIONIC__ case SocketType::VSOCK: return "vm_socket"; -#endif // __BIONIC__ case SocketType::INET: return "inet_socket"; default: @@ -334,59 +327,53 @@ public: server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction(); server->setMaxThreads(numThreads); + unsigned int outPort = 0; + switch (socketType) { case SocketType::UNIX: CHECK(server->setupUnixDomainServer(addr.c_str())) << addr; break; -#ifdef __BIONIC__ case SocketType::VSOCK: CHECK(server->setupVsockServer(vsockPort)); break; -#endif // __BIONIC__ case SocketType::INET: { - unsigned int outPort = 0; CHECK(server->setupInetServer(0, &outPort)); CHECK_NE(0, outPort); - CHECK(android::base::WriteFully(pipe->writeEnd(), &outPort, - sizeof(outPort))); break; } default: LOG_ALWAYS_FATAL("Unknown socket type"); } + CHECK(android::base::WriteFully(pipe->writeEnd(), &outPort, sizeof(outPort))); + configure(server); server->join(); }), }; - unsigned int inetPort = 0; + // always read socket, so that we have waited for the server to start + unsigned int outPort = 0; + CHECK(android::base::ReadFully(ret.host.getPipe()->readEnd(), &outPort, sizeof(outPort))); if (socketType == SocketType::INET) { - CHECK(android::base::ReadFully(ret.host.getPipe()->readEnd(), &inetPort, - sizeof(inetPort))); - CHECK_NE(0, inetPort); + CHECK_NE(0, outPort); } for (size_t i = 0; i < numSessions; i++) { sp<RpcSession> session = RpcSession::make(); - for (size_t tries = 0; tries < 10; tries++) { - usleep(10000); - switch (socketType) { - case SocketType::UNIX: - if (session->setupUnixDomainClient(addr.c_str())) goto success; - break; -#ifdef __BIONIC__ - case SocketType::VSOCK: - if (session->setupVsockClient(VMADDR_CID_LOCAL, vsockPort)) goto success; - break; -#endif // __BIONIC__ - case SocketType::INET: - if (session->setupInetClient("127.0.0.1", inetPort)) goto success; - break; - default: - LOG_ALWAYS_FATAL("Unknown socket type"); - } + switch (socketType) { + case SocketType::UNIX: + if (session->setupUnixDomainClient(addr.c_str())) goto success; + break; + case SocketType::VSOCK: + if (session->setupVsockClient(VMADDR_CID_LOCAL, vsockPort)) goto success; + break; + case SocketType::INET: + if (session->setupInetClient("127.0.0.1", outPort)) goto success; + break; + default: + LOG_ALWAYS_FATAL("Unknown socket type"); } LOG_ALWAYS_FATAL("Could not connect"); success: @@ -934,9 +921,10 @@ TEST_P(BinderRpc, Fds) { INSTANTIATE_TEST_CASE_P(PerSocket, BinderRpc, ::testing::ValuesIn({ SocketType::UNIX, +// TODO(b/185269356): working on host #ifdef __BIONIC__ SocketType::VSOCK, -#endif // __BIONIC__ +#endif SocketType::INET, }), PrintSocketType); diff --git a/libs/binder/vm_sockets.h b/libs/binder/vm_sockets.h new file mode 100644 index 0000000000..7d9732b0fa --- /dev/null +++ b/libs/binder/vm_sockets.h @@ -0,0 +1,54 @@ +/**************************************************************************** + **************************************************************************** + *** + *** This header was automatically generated from a Linux kernel header + *** of the same name, to make information necessary for userspace to + *** call into the kernel available to libc. It contains only constants, + *** structures, and macros generated from the original header, and thus, + *** contains no copyrightable information. + *** + *** Copied and modified from bionic/libc/kernel/uapi/linux/vm_sockets.h + *** + **************************************************************************** + ****************************************************************************/ +#pragma once + +#ifdef __BIONIC__ +#include <linux/vm_sockets.h> +#else + +#ifndef _UAPI_VM_SOCKETS_H +#define _UAPI_VM_SOCKETS_H +#define SO_VM_SOCKETS_BUFFER_SIZE 0 +#define SO_VM_SOCKETS_BUFFER_MIN_SIZE 1 +#define SO_VM_SOCKETS_BUFFER_MAX_SIZE 2 +#define SO_VM_SOCKETS_PEER_HOST_VM_ID 3 +#define SO_VM_SOCKETS_TRUSTED 5 +#define SO_VM_SOCKETS_CONNECT_TIMEOUT 6 +#define SO_VM_SOCKETS_NONBLOCK_TXRX 7 +#define VMADDR_CID_ANY (-1U) +#define VMADDR_PORT_ANY (-1U) +#define VMADDR_CID_HYPERVISOR 0 +#define VMADDR_CID_LOCAL 1 +#define VMADDR_CID_HOST 2 +#define VM_SOCKETS_INVALID_VERSION (-1U) +#define VM_SOCKETS_VERSION_EPOCH(_v) (((_v)&0xFF000000) >> 24) +#define VM_SOCKETS_VERSION_MAJOR(_v) (((_v)&0x00FF0000) >> 16) +#define VM_SOCKETS_VERSION_MINOR(_v) (((_v)&0x0000FFFF)) +struct sockaddr_vm { + sa_family_t svm_family; + // NOLINTNEXTLINE(google-runtime-int) + unsigned short svm_reserved1; + unsigned int svm_port; + unsigned int svm_cid; + // NOLINTNEXTLINE(google-runtime-int) + unsigned char svm_zero[sizeof(struct sockaddr) - sizeof(sa_family_t) - sizeof(unsigned short) - + sizeof(unsigned int) - sizeof(unsigned int)]; +}; +#define IOCTL_VM_SOCKETS_GET_LOCAL_CID _IO(7, 0xb9) +#ifndef AF_VSOCK +#define AF_VSOCK 40 +#endif +#endif + +#endif |