summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Steven Moreland <smoreland@google.com> 2021-05-12 20:13:04 +0000
committer Steven Moreland <smoreland@google.com> 2021-05-13 16:53:38 +0000
commit5802c2b0c76b821c63c989afc8078bd5d2ddf2cb (patch)
tree56dcd25205c04907b8bd7fbba304713998674da5
parentdbe7183d0493cba5f53f9f0248a7576cc35b4100 (diff)
libbinder: RPC explicit connect thread ownership
- thread is detached when it is no longer owned (avoids abort) - RpcServer passes connection thread ownership to RpcSession before it lets go of its lock (otherwise, it's possible to take the lock for both the session and the server, and have a relevant thread which isn't reflected as owned in either of these objects). Currently this only affects the fuzzer, but it will also be important for shutting down these threadpools. Future considerations - this code has a few messy parts, but it will have to be rewritten to avoid the std::thread constructor (which throws exceptions) and also to read a header instead of an ID. Bug: 185167543 Test: binderRpcTest, binder_rpc_fuzzer (which is in-progress) Change-Id: Ide630e36595d09a88e904af2e9ab6886ae4f2118
-rw-r--r--libs/binder/RpcServer.cpp15
-rw-r--r--libs/binder/RpcSession.cpp4
-rw-r--r--libs/binder/include/binder/RpcSession.h5
3 files changed, 20 insertions, 4 deletions
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
index 3a98cadb94..06c3a4206d 100644
--- a/libs/binder/RpcServer.cpp
+++ b/libs/binder/RpcServer.cpp
@@ -22,6 +22,7 @@
#include <thread>
#include <vector>
+#include <android-base/scopeguard.h>
#include <binder/Parcel.h>
#include <binder/RpcServer.h>
#include <log/log.h>
@@ -32,6 +33,7 @@
namespace android {
+using base::ScopeGuard;
using base::unique_fd;
RpcServer::RpcServer() {}
@@ -157,10 +159,11 @@ void RpcServer::establishConnection(sp<RpcServer>&& server, base::unique_fd clie
// TODO(b/183988761): cannot trust this simple ID
LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!");
+ bool idValid = true;
int32_t id;
if (sizeof(id) != read(clientFd.get(), &id, sizeof(id))) {
ALOGE("Could not read ID from fd %d", clientFd.get());
- return;
+ idValid = false;
}
std::thread thisThread;
@@ -172,8 +175,13 @@ void RpcServer::establishConnection(sp<RpcServer>&& server, base::unique_fd clie
LOG_ALWAYS_FATAL_IF(threadId == mConnectingThreads.end(),
"Must establish connection on owned thread");
thisThread = std::move(threadId->second);
+ ScopeGuard detachGuard = [&]() { thisThread.detach(); };
mConnectingThreads.erase(threadId);
+ if (!idValid) {
+ return;
+ }
+
if (id == RPC_SESSION_ID_NEW) {
LOG_ALWAYS_FATAL_IF(mSessionIdCounter >= INT32_MAX, "Out of session IDs");
mSessionIdCounter++;
@@ -190,6 +198,9 @@ void RpcServer::establishConnection(sp<RpcServer>&& server, base::unique_fd clie
}
session = it->second;
}
+
+ detachGuard.Disable();
+ session->preJoin(std::move(thisThread));
}
// avoid strong cycle
@@ -199,7 +210,7 @@ void RpcServer::establishConnection(sp<RpcServer>&& server, base::unique_fd clie
// DO NOT ACCESS MEMBER VARIABLES BELOW
//
- session->join(std::move(thisThread), std::move(clientFd));
+ session->join(std::move(clientFd));
}
bool RpcServer::setupSocketServer(const RpcSocketAddress& addr) {
diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp
index f32aa7a72d..05fa49ec76 100644
--- a/libs/binder/RpcSession.cpp
+++ b/libs/binder/RpcSession.cpp
@@ -131,14 +131,16 @@ status_t RpcSession::readId() {
return OK;
}
-void RpcSession::join(std::thread thread, unique_fd client) {
+void RpcSession::preJoin(std::thread thread) {
LOG_ALWAYS_FATAL_IF(thread.get_id() != std::this_thread::get_id(), "Must own this thread");
{
std::lock_guard<std::mutex> _l(mMutex);
mThreads[thread.get_id()] = std::move(thread);
}
+}
+void RpcSession::join(unique_fd client) {
// must be registered to allow arbitrary client code executing commands to
// be able to do nested calls (we can't only read from it)
sp<RpcConnection> connection = assignServerToThisThread(std::move(client));
diff --git a/libs/binder/include/binder/RpcSession.h b/libs/binder/include/binder/RpcSession.h
index 92ee100dc5..bcc213c8bd 100644
--- a/libs/binder/include/binder/RpcSession.h
+++ b/libs/binder/include/binder/RpcSession.h
@@ -114,7 +114,10 @@ private:
status_t readId();
- void join(std::thread thread, base::unique_fd client);
+ // transfer ownership of thread
+ void preJoin(std::thread thread);
+ // join on thread passed to preJoin
+ void join(base::unique_fd client);
void terminateLocked();
struct RpcConnection : public RefBase {