diff options
author | 2021-08-05 16:37:17 -0700 | |
---|---|---|
committer | 2021-08-06 12:09:40 -0700 | |
commit | b675ffe41b574bd7a13ebbc8682cf147508b5c21 (patch) | |
tree | 563138d017c6ccd0b587876c2c8bc66133b6bce1 | |
parent | 8c950421dbe8d9c2cea5e293b925b01d6f8c52da (diff) |
binder: RPC uses non-blocking sockets.
With TLS, even though poll() may have returned for an FD,
there may not be a complete packet available, so I/O operations
within libssl may block and not interruptible by the shutdown
trigger.
Hence, always use non-blocking sockets.
Test: binderRpcTest
Bug: 195683291
Change-Id: I372e8c3bf010c672b1c4b9f7cb5b789ca20c9480
-rw-r--r-- | libs/binder/RpcServer.cpp | 6 | ||||
-rw-r--r-- | libs/binder/RpcSession.cpp | 9 | ||||
-rw-r--r-- | libs/binder/RpcTransportRaw.cpp | 2 | ||||
-rw-r--r-- | libs/binder/Utils.cpp | 16 | ||||
-rw-r--r-- | libs/binder/Utils.h | 5 |
5 files changed, 31 insertions, 7 deletions
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp index 66483edffb..a0c508be03 100644 --- a/libs/binder/RpcServer.cpp +++ b/libs/binder/RpcServer.cpp @@ -168,7 +168,7 @@ void RpcServer::join() { status_t status; while ((status = mShutdownTrigger->triggerablePoll(mServer, POLLIN)) == OK) { unique_fd clientFd(TEMP_FAILURE_RETRY( - accept4(mServer.get(), nullptr, nullptr /*length*/, SOCK_CLOEXEC))); + accept4(mServer.get(), nullptr, nullptr /*length*/, SOCK_CLOEXEC | SOCK_NONBLOCK))); if (clientFd < 0) { ALOGE("Could not accept4 socket: %s", strerror(errno)); @@ -388,8 +388,8 @@ status_t RpcServer::setupSocketServer(const RpcSocketAddress& addr) { LOG_RPC_DETAIL("Setting up socket server %s", addr.toString().c_str()); LOG_ALWAYS_FATAL_IF(hasServer(), "Each RpcServer can only have one server."); - unique_fd serverFd( - TEMP_FAILURE_RETRY(socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0))); + unique_fd serverFd(TEMP_FAILURE_RETRY( + socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0))); if (serverFd == -1) { int savedErrno = errno; ALOGE("Could not create socket: %s", strerror(savedErrno)); diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp index c756f2e8fb..73061b8948 100644 --- a/libs/binder/RpcSession.cpp +++ b/libs/binder/RpcSession.cpp @@ -39,6 +39,7 @@ #include "RpcSocketAddress.h" #include "RpcState.h" #include "RpcWireFormat.h" +#include "Utils.h" #ifdef __GLIBC__ extern "C" pid_t gettid(); @@ -134,6 +135,10 @@ status_t RpcSession::setupPreconnectedClient(unique_fd fd, std::function<unique_ fd = request(); if (!fd.ok()) return BAD_VALUE; } + if (auto res = setNonBlocking(fd); !res.ok()) { + ALOGE("setupPreconnectedClient: %s", res.error().message().c_str()); + return res.error().code() == 0 ? UNKNOWN_ERROR : -res.error().code(); + } return initAndAddConnection(std::move(fd), sessionId, incoming); }); } @@ -470,8 +475,8 @@ status_t RpcSession::setupOneSocketConnection(const RpcSocketAddress& addr, 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))); + unique_fd serverFd(TEMP_FAILURE_RETRY( + socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0))); if (serverFd == -1) { int savedErrno = errno; ALOGE("Could not create socket at %s: %s", addr.toString().c_str(), diff --git a/libs/binder/RpcTransportRaw.cpp b/libs/binder/RpcTransportRaw.cpp index 995c54234f..46170f7f7a 100644 --- a/libs/binder/RpcTransportRaw.cpp +++ b/libs/binder/RpcTransportRaw.cpp @@ -50,7 +50,7 @@ public: return ret; } Result<size_t> peek(void *buf, size_t size) override { - ssize_t ret = TEMP_FAILURE_RETRY(::recv(mSocket.get(), buf, size, MSG_PEEK | MSG_DONTWAIT)); + ssize_t ret = TEMP_FAILURE_RETRY(::recv(mSocket.get(), buf, size, MSG_PEEK)); if (ret < 0) { return ErrnoError() << "recv(MSG_PEEK)"; } diff --git a/libs/binder/Utils.cpp b/libs/binder/Utils.cpp index 90a4502ec5..d2a5be1102 100644 --- a/libs/binder/Utils.cpp +++ b/libs/binder/Utils.cpp @@ -18,10 +18,24 @@ #include <string.h> +using android::base::ErrnoError; +using android::base::Result; + namespace android { void zeroMemory(uint8_t* data, size_t size) { memset(data, 0, size); } -} // namespace android +Result<void> setNonBlocking(android::base::borrowed_fd fd) { + int flags = TEMP_FAILURE_RETRY(fcntl(fd.get(), F_GETFL)); + if (flags == -1) { + return ErrnoError() << "Could not get flags for fd"; + } + if (int ret = TEMP_FAILURE_RETRY(fcntl(fd.get(), F_SETFL, flags | O_NONBLOCK)); ret == -1) { + return ErrnoError() << "Could not set non-blocking flag for fd"; + } + return {}; +} + +} // namespace android diff --git a/libs/binder/Utils.h b/libs/binder/Utils.h index f94b158404..1e383da095 100644 --- a/libs/binder/Utils.h +++ b/libs/binder/Utils.h @@ -17,9 +17,14 @@ #include <cstdint> #include <stddef.h> +#include <android-base/result.h> +#include <android-base/unique_fd.h> + namespace android { // avoid optimizations void zeroMemory(uint8_t* data, size_t size); +android::base::Result<void> setNonBlocking(android::base::borrowed_fd fd); + } // namespace android |