summaryrefslogtreecommitdiff
path: root/libs/binder/RpcConnection.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/binder/RpcConnection.cpp')
-rw-r--r--libs/binder/RpcConnection.cpp158
1 files changed, 104 insertions, 54 deletions
diff --git a/libs/binder/RpcConnection.cpp b/libs/binder/RpcConnection.cpp
index 83a1618e9f..dab3246fc5 100644
--- a/libs/binder/RpcConnection.cpp
+++ b/libs/binder/RpcConnection.cpp
@@ -20,6 +20,7 @@
#include <binder/Parcel.h>
#include <binder/Stability.h>
+#include <utils/String8.h>
#include "RpcState.h"
#include "RpcWireFormat.h"
@@ -29,14 +30,20 @@
#include <sys/un.h>
#include <unistd.h>
-#if defined(__GLIBC__)
+#ifdef __GLIBC__
extern "C" pid_t gettid();
#endif
+#ifdef __BIONIC__
+#include <linux/vm_sockets.h>
+#endif
+
namespace android {
using base::unique_fd;
+RpcConnection::SocketAddress::~SocketAddress() {}
+
RpcConnection::RpcConnection() {
LOG_RPC_DETAIL("RpcConnection created %p", this);
@@ -50,65 +57,68 @@ sp<RpcConnection> RpcConnection::make() {
return new RpcConnection;
}
-bool RpcConnection::setupUnixDomainServer(const char* path) {
- LOG_ALWAYS_FATAL_IF(mServer.get() != -1, "Only supports one server now");
-
- unique_fd serverFd(TEMP_FAILURE_RETRY(socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0)));
- if (serverFd == -1) {
- ALOGE("Could not create socket at %s: %s", path, strerror(errno));
- return false;
+class UnixSocketAddress : public RpcConnection::SocketAddress {
+public:
+ explicit UnixSocketAddress(const char* path) : mAddr({.sun_family = AF_UNIX}) {
+ unsigned int pathLen = strlen(path) + 1;
+ LOG_ALWAYS_FATAL_IF(pathLen > sizeof(mAddr.sun_path), "%u %s", pathLen, path);
+ memcpy(mAddr.sun_path, path, pathLen);
}
-
- struct sockaddr_un addr = {
- .sun_family = AF_UNIX,
- };
-
- unsigned int pathLen = strlen(path) + 1;
- LOG_ALWAYS_FATAL_IF(pathLen > sizeof(addr.sun_path), "%u", pathLen);
- memcpy(addr.sun_path, path, pathLen);
-
- if (0 != TEMP_FAILURE_RETRY(bind(serverFd.get(), (struct sockaddr*)&addr, sizeof(addr)))) {
- ALOGE("Could not bind socket at %s: %s", path, strerror(errno));
- return false;
+ virtual ~UnixSocketAddress() {}
+ std::string toString() const override {
+ return String8::format("path '%.*s'", static_cast<int>(sizeof(mAddr.sun_path)),
+ mAddr.sun_path)
+ .c_str();
}
+ const sockaddr* addr() const override { return reinterpret_cast<const sockaddr*>(&mAddr); }
+ size_t addrSize() const override { return sizeof(mAddr); }
- if (0 != TEMP_FAILURE_RETRY(listen(serverFd.get(), 1 /*backlog*/))) {
- ALOGE("Could not listen socket at %s: %s", path, strerror(errno));
- return false;
- }
+private:
+ sockaddr_un mAddr;
+};
- mServer = std::move(serverFd);
- return true;
+bool RpcConnection::setupUnixDomainServer(const char* path) {
+ return addServer(UnixSocketAddress(path));
}
bool RpcConnection::addUnixDomainClient(const char* path) {
- LOG_RPC_DETAIL("Connecting on path: %s", path);
+ return addClient(UnixSocketAddress(path));
+}
- unique_fd serverFd(TEMP_FAILURE_RETRY(socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0)));
- if (serverFd == -1) {
- ALOGE("Could not create socket at %s: %s", path, strerror(errno));
- return false;
+#ifdef __BIONIC__
+
+class VsockSocketAddress : public RpcConnection::SocketAddress {
+public:
+ VsockSocketAddress(unsigned int cid, unsigned int port)
+ : mAddr({
+ .svm_family = AF_VSOCK,
+ .svm_port = port,
+ .svm_cid = cid,
+ }) {}
+ virtual ~VsockSocketAddress() {}
+ std::string toString() const override {
+ return String8::format("cid %du port %du", mAddr.svm_cid, mAddr.svm_port).c_str();
}
+ const sockaddr* addr() const override { return reinterpret_cast<const sockaddr*>(&mAddr); }
+ size_t addrSize() const override { return sizeof(mAddr); }
- struct sockaddr_un addr = {
- .sun_family = AF_UNIX,
- };
+private:
+ sockaddr_vm mAddr;
+};
- unsigned int pathLen = strlen(path) + 1;
- LOG_ALWAYS_FATAL_IF(pathLen > sizeof(addr.sun_path), "%u", pathLen);
- memcpy(addr.sun_path, path, pathLen);
+bool RpcConnection::setupVsockServer(unsigned int port) {
+ // realizing value w/ this type at compile time to avoid ubsan abort
+ constexpr unsigned int kAnyCid = VMADDR_CID_ANY;
- if (0 != TEMP_FAILURE_RETRY(connect(serverFd.get(), (struct sockaddr*)&addr, sizeof(addr)))) {
- ALOGE("Could not connect socket at %s: %s", path, strerror(errno));
- return false;
- }
-
- LOG_RPC_DETAIL("Unix domain client with fd %d", serverFd.get());
+ return addServer(VsockSocketAddress(kAnyCid, port));
+}
- addClient(std::move(serverFd));
- return true;
+bool RpcConnection::addVsockClient(unsigned int cid, unsigned int port) {
+ return addClient(VsockSocketAddress(cid, port));
}
+#endif // __BIONIC__
+
sp<IBinder> RpcConnection::getRootObject() {
ExclusiveSocket socket(this, SocketUse::CLIENT);
return state()->getRootObject(socket.fd(), this);
@@ -130,11 +140,8 @@ status_t RpcConnection::sendDecStrong(const RpcAddress& address) {
void RpcConnection::join() {
// establish a connection
{
- struct sockaddr_un clientSa;
- socklen_t clientSaLen = sizeof(clientSa);
-
- unique_fd clientFd(TEMP_FAILURE_RETRY(
- accept4(mServer.get(), (struct sockaddr*)&clientSa, &clientSaLen, SOCK_CLOEXEC)));
+ unique_fd clientFd(
+ TEMP_FAILURE_RETRY(accept4(mServer.get(), nullptr, 0 /*length*/, SOCK_CLOEXEC)));
if (clientFd < 0) {
// If this log becomes confusing, should save more state from setupUnixDomainServer
// in order to output here.
@@ -144,7 +151,7 @@ void RpcConnection::join() {
LOG_RPC_DETAIL("accept4 on fd %d yields fd %d", mServer.get(), clientFd.get());
- addServer(std::move(clientFd));
+ assignServerToThisThread(std::move(clientFd));
}
// We may not use the connection we just established (two threads might
@@ -170,14 +177,57 @@ wp<RpcServer> RpcConnection::server() {
return mForServer;
}
-void RpcConnection::addClient(base::unique_fd&& fd) {
+bool RpcConnection::addServer(const SocketAddress& addr) {
+ LOG_ALWAYS_FATAL_IF(mServer.get() != -1, "Each RpcConnection can only have one server.");
+
+ unique_fd serverFd(
+ TEMP_FAILURE_RETRY(socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0)));
+ if (serverFd == -1) {
+ ALOGE("Could not create socket: %s", strerror(errno));
+ return false;
+ }
+
+ if (0 != TEMP_FAILURE_RETRY(bind(serverFd.get(), addr.addr(), addr.addrSize()))) {
+ int savedErrno = errno;
+ ALOGE("Could not bind socket at %s: %s", addr.toString().c_str(), strerror(savedErrno));
+ return false;
+ }
+
+ if (0 != TEMP_FAILURE_RETRY(listen(serverFd.get(), 1 /*backlog*/))) {
+ int savedErrno = errno;
+ ALOGE("Could not listen socket at %s: %s", addr.toString().c_str(), strerror(savedErrno));
+ return false;
+ }
+
+ mServer = std::move(serverFd);
+ return true;
+}
+
+bool RpcConnection::addClient(const SocketAddress& addr) {
+ 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;
+ }
+
+ LOG_RPC_DETAIL("Socket at %s client with fd %d", addr.toString().c_str(), serverFd.get());
+
std::lock_guard<std::mutex> _l(mSocketMutex);
sp<ConnectionSocket> connection = new ConnectionSocket();
- connection->fd = std::move(fd);
+ connection->fd = std::move(serverFd);
mClients.push_back(connection);
+ return true;
}
-void RpcConnection::addServer(base::unique_fd&& fd) {
+void RpcConnection::assignServerToThisThread(base::unique_fd&& fd) {
std::lock_guard<std::mutex> _l(mSocketMutex);
sp<ConnectionSocket> connection = new ConnectionSocket();
connection->fd = std::move(fd);