Merge "Fixed gpuservice_unittest mem leaks"
diff --git a/cmds/dumpstate/Android.bp b/cmds/dumpstate/Android.bp
index a2491e5..a60972b 100644
--- a/cmds/dumpstate/Android.bp
+++ b/cmds/dumpstate/Android.bp
@@ -101,6 +101,7 @@
"libhidlbase",
"liblog",
"libutils",
+ "libvintf",
"libbinderdebug",
"packagemanager_aidl-cpp",
],
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 0dab0e4..f0b2b28 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -88,6 +88,7 @@
#include <private/android_logger.h>
#include <serviceutils/PriorityDumper.h>
#include <utils/StrongPointer.h>
+#include <vintf/VintfObject.h>
#include "DumpstateInternal.h"
#include "DumpstateService.h"
#include "dumpstate.h"
@@ -1396,6 +1397,23 @@
}
}
+// Dump all of the files that make up the vendor interface.
+// See the files listed in dumpFileList() for the latest list of files.
+static void DumpVintf() {
+ const auto vintfFiles = android::vintf::details::dumpFileList();
+ for (const auto vintfFile : vintfFiles) {
+ struct stat st;
+ if (stat(vintfFile.c_str(), &st) == 0) {
+ if (S_ISDIR(st.st_mode)) {
+ ds.AddDir(vintfFile, true /* recursive */);
+ } else {
+ ds.EnqueueAddZipEntryAndCleanupIfNeeded(ZIP_ROOT_DIR + vintfFile,
+ vintfFile);
+ }
+ }
+ }
+}
+
static void DumpExternalFragmentationInfo() {
struct stat st;
if (stat("/proc/buddyinfo", &st) != 0) {
@@ -1621,6 +1639,8 @@
do_dmesg();
}
+ DumpVintf();
+
RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(for_each_pid, do_showmap, "SMAPS OF ALL PROCESSES");
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
index c67b70a..528341e 100644
--- a/libs/binder/RpcServer.cpp
+++ b/libs/binder/RpcServer.cpp
@@ -135,7 +135,7 @@
mRootObjectWeak = binder;
}
void RpcServer::setPerSessionRootObject(
- std::function<sp<IBinder>(const sockaddr*, socklen_t)>&& makeObject) {
+ std::function<sp<IBinder>(const void*, size_t)>&& makeObject) {
std::lock_guard<std::mutex> _l(mLock);
mRootObject.clear();
mRootObjectWeak.clear();
@@ -178,14 +178,16 @@
status_t status;
while ((status = mShutdownTrigger->triggerablePoll(mServer, POLLIN)) == OK) {
- sockaddr_storage addr;
- socklen_t addrLen = sizeof(addr);
+ std::array<uint8_t, kRpcAddressSize> addr;
+ static_assert(addr.size() >= sizeof(sockaddr_storage), "kRpcAddressSize is too small");
+ socklen_t addrLen = addr.size();
unique_fd clientFd(
- TEMP_FAILURE_RETRY(accept4(mServer.get(), reinterpret_cast<sockaddr*>(&addr),
+ TEMP_FAILURE_RETRY(accept4(mServer.get(), reinterpret_cast<sockaddr*>(addr.data()),
&addrLen, SOCK_CLOEXEC | SOCK_NONBLOCK)));
- LOG_ALWAYS_FATAL_IF(addrLen > static_cast<socklen_t>(sizeof(addr)), "Truncated address");
+ LOG_ALWAYS_FATAL_IF(addrLen > static_cast<socklen_t>(sizeof(sockaddr_storage)),
+ "Truncated address");
if (clientFd < 0) {
ALOGE("Could not accept4 socket: %s", strerror(errno));
@@ -268,7 +270,7 @@
}
void RpcServer::establishConnection(sp<RpcServer>&& server, base::unique_fd clientFd,
- const sockaddr_storage addr, socklen_t addrLen) {
+ std::array<uint8_t, kRpcAddressSize> addr, size_t addrLen) {
// mShutdownTrigger can only be cleared once connection threads have joined.
// It must be set before this thread is started
LOG_ALWAYS_FATAL_IF(server->mShutdownTrigger == nullptr);
@@ -390,16 +392,14 @@
}
} while (server->mSessions.end() != server->mSessions.find(sessionId));
- session = RpcSession::make();
+ session = sp<RpcSession>::make(nullptr);
session->setMaxIncomingThreads(server->mMaxThreads);
if (!session->setProtocolVersion(protocolVersion)) return;
// if null, falls back to server root
sp<IBinder> sessionSpecificRoot;
if (server->mRootObjectFactory != nullptr) {
- sessionSpecificRoot =
- server->mRootObjectFactory(reinterpret_cast<const sockaddr*>(&addr),
- addrLen);
+ sessionSpecificRoot = server->mRootObjectFactory(addr.data(), addrLen);
if (sessionSpecificRoot == nullptr) {
ALOGE("Warning: server returned null from root object factory");
}
diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp
index 5c35dd0..8edc78f 100644
--- a/libs/binder/RpcSession.cpp
+++ b/libs/binder/RpcSession.cpp
@@ -715,6 +715,7 @@
LOG_ALWAYS_FATAL_IF(mEventListener != nullptr);
LOG_ALWAYS_FATAL_IF(eventListener == nullptr);
LOG_ALWAYS_FATAL_IF(mShutdownTrigger != nullptr);
+ LOG_ALWAYS_FATAL_IF(mCtx != nullptr);
mShutdownTrigger = FdTrigger::make();
if (mShutdownTrigger == nullptr) return false;
diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp
index 7ec8e07..f5de5b1 100644
--- a/libs/binder/RpcState.cpp
+++ b/libs/binder/RpcState.cpp
@@ -563,7 +563,7 @@
static void cleanup_reply_data(Parcel* p, const uint8_t* data, size_t dataSize,
const binder_size_t* objects, size_t objectsCount) {
(void)p;
- delete[] const_cast<uint8_t*>(data - offsetof(RpcWireReply, data));
+ delete[] const_cast<uint8_t*>(data);
(void)dataSize;
LOG_ALWAYS_FATAL_IF(objects != nullptr);
LOG_ALWAYS_FATAL_IF(objectsCount != 0, "%zu objects remaining", objectsCount);
@@ -585,25 +585,30 @@
return status;
}
- CommandData data(command.bodySize);
- if (!data.valid()) return NO_MEMORY;
-
- iovec iov{data.data(), command.bodySize};
- if (status_t status = rpcRec(connection, session, "reply body", &iov, 1); status != OK)
- return status;
-
if (command.bodySize < sizeof(RpcWireReply)) {
ALOGE("Expecting %zu but got %" PRId32 " bytes for RpcWireReply. Terminating!",
sizeof(RpcWireReply), command.bodySize);
(void)session->shutdownAndWait(false);
return BAD_VALUE;
}
- RpcWireReply* rpcReply = reinterpret_cast<RpcWireReply*>(data.data());
- if (rpcReply->status != OK) return rpcReply->status;
+ RpcWireReply rpcReply;
+ CommandData data(command.bodySize - sizeof(RpcWireReply));
+ if (!data.valid()) return NO_MEMORY;
+
+ iovec iovs[]{
+ {&rpcReply, sizeof(RpcWireReply)},
+ {data.data(), data.size()},
+ };
+ if (status_t status = rpcRec(connection, session, "reply body", iovs, arraysize(iovs));
+ status != OK)
+ return status;
+ if (rpcReply.status != OK) return rpcReply.status;
+
+ uint8_t* parcelData = data.data();
+ size_t parcelDataSize = data.size();
data.release();
- reply->rpcSetDataReference(session, rpcReply->data,
- command.bodySize - offsetof(RpcWireReply, data), cleanup_reply_data);
+ reply->rpcSetDataReference(session, parcelData, parcelDataSize, cleanup_reply_data);
return OK;
}
@@ -959,23 +964,19 @@
const sp<RpcSession>& session, const RpcWireHeader& command) {
LOG_ALWAYS_FATAL_IF(command.command != RPC_COMMAND_DEC_STRONG, "command: %d", command.command);
- CommandData commandData(command.bodySize);
- if (!commandData.valid()) {
- return NO_MEMORY;
- }
- iovec iov{commandData.data(), commandData.size()};
- if (status_t status = rpcRec(connection, session, "dec ref body", &iov, 1); status != OK)
- return status;
-
if (command.bodySize != sizeof(RpcDecStrong)) {
ALOGE("Expecting %zu but got %" PRId32 " bytes for RpcDecStrong. Terminating!",
sizeof(RpcDecStrong), command.bodySize);
(void)session->shutdownAndWait(false);
return BAD_VALUE;
}
- RpcDecStrong* body = reinterpret_cast<RpcDecStrong*>(commandData.data());
- uint64_t addr = RpcWireAddress::toRaw(body->address);
+ RpcDecStrong body;
+ iovec iov{&body, sizeof(RpcDecStrong)};
+ if (status_t status = rpcRec(connection, session, "dec ref body", &iov, 1); status != OK)
+ return status;
+
+ uint64_t addr = RpcWireAddress::toRaw(body.address);
std::unique_lock<std::mutex> _l(mNodeMutex);
auto it = mNodeForAddress.find(addr);
if (it == mNodeForAddress.end()) {
@@ -993,19 +994,19 @@
return BAD_VALUE;
}
- if (it->second.timesSent < body->amount) {
+ if (it->second.timesSent < body.amount) {
ALOGE("Record of sending binder %zu times, but requested decStrong for %" PRIu64 " of %u",
- it->second.timesSent, addr, body->amount);
+ it->second.timesSent, addr, body.amount);
return OK;
}
LOG_ALWAYS_FATAL_IF(it->second.sentRef == nullptr, "Inconsistent state, lost ref for %" PRIu64,
addr);
- LOG_RPC_DETAIL("Processing dec strong of %" PRIu64 " by %u from %zu", addr, body->amount,
+ LOG_RPC_DETAIL("Processing dec strong of %" PRIu64 " by %u from %zu", addr, body.amount,
it->second.timesSent);
- it->second.timesSent -= body->amount;
+ it->second.timesSent -= body.amount;
sp<IBinder> tempHold = tryEraseNode(it);
_l.unlock();
tempHold = nullptr; // destructor may make binder calls on this session
diff --git a/libs/binder/RpcWireFormat.h b/libs/binder/RpcWireFormat.h
index 171550e..d9b5ca0 100644
--- a/libs/binder/RpcWireFormat.h
+++ b/libs/binder/RpcWireFormat.h
@@ -139,7 +139,6 @@
struct RpcWireReply {
int32_t status; // transact return
- uint8_t data[];
};
static_assert(sizeof(RpcWireReply) == 4);
diff --git a/libs/binder/Status.cpp b/libs/binder/Status.cpp
index 83b97d0..dba6587 100644
--- a/libs/binder/Status.cpp
+++ b/libs/binder/Status.cpp
@@ -139,6 +139,9 @@
mMessage = String8(message.value_or(String16()));
// Skip over the remote stack trace data
+ const size_t remote_start = parcel.dataPosition();
+ // Get available size before reading more
+ const size_t remote_avail = parcel.dataAvail();
int32_t remote_stack_trace_header_size;
status = parcel.readInt32(&remote_stack_trace_header_size);
if (status != OK) {
@@ -146,13 +149,16 @@
return status;
}
if (remote_stack_trace_header_size < 0 ||
- static_cast<size_t>(remote_stack_trace_header_size) > parcel.dataAvail()) {
+ static_cast<size_t>(remote_stack_trace_header_size) > remote_avail) {
android_errorWriteLog(0x534e4554, "132650049");
setFromStatusT(UNKNOWN_ERROR);
return UNKNOWN_ERROR;
}
- parcel.setDataPosition(parcel.dataPosition() + remote_stack_trace_header_size);
+
+ if (remote_stack_trace_header_size != 0) {
+ parcel.setDataPosition(remote_start + remote_stack_trace_header_size);
+ }
if (mException == EX_SERVICE_SPECIFIC) {
status = parcel.readInt32(&mErrorCode);
diff --git a/libs/binder/include/binder/RpcServer.h b/libs/binder/include/binder/RpcServer.h
index 6b31812..dba8dd6 100644
--- a/libs/binder/include/binder/RpcServer.h
+++ b/libs/binder/include/binder/RpcServer.h
@@ -125,9 +125,17 @@
*/
void setRootObjectWeak(const wp<IBinder>& binder);
/**
- * Allows a root object to be created for each session
+ * Allows a root object to be created for each session.
+ *
+ * Takes one argument: a callable that is invoked once per new session.
+ * The callable takes two arguments: a type-erased pointer to an OS- and
+ * transport-specific address structure, e.g., sockaddr_vm for vsock, and
+ * an integer representing the size in bytes of that structure. The
+ * callable should validate the size, then cast the type-erased pointer
+ * to a pointer to the actual type of the address, e.g., const void* to
+ * const sockaddr_vm*.
*/
- void setPerSessionRootObject(std::function<sp<IBinder>(const sockaddr*, socklen_t)>&& object);
+ void setPerSessionRootObject(std::function<sp<IBinder>(const void*, size_t)>&& object);
sp<IBinder> getRootObject();
/**
@@ -177,8 +185,9 @@
void onSessionAllIncomingThreadsEnded(const sp<RpcSession>& session) override;
void onSessionIncomingThreadEnded() override;
+ static constexpr size_t kRpcAddressSize = 128;
static void establishConnection(sp<RpcServer>&& server, base::unique_fd clientFd,
- const sockaddr_storage addr, socklen_t addrLen);
+ std::array<uint8_t, kRpcAddressSize> addr, size_t addrLen);
[[nodiscard]] status_t setupSocketServer(const RpcSocketAddress& address);
const std::unique_ptr<RpcTransportCtx> mCtx;
@@ -192,7 +201,7 @@
std::map<std::thread::id, std::thread> mConnectingThreads;
sp<IBinder> mRootObject;
wp<IBinder> mRootObjectWeak;
- std::function<sp<IBinder>(const sockaddr*, socklen_t)> mRootObjectFactory;
+ std::function<sp<IBinder>(const void*, size_t)> mRootObjectFactory;
std::map<std::vector<uint8_t>, sp<RpcSession>> mSessions;
std::unique_ptr<FdTrigger> mShutdownTrigger;
std::condition_variable mShutdownCv;
diff --git a/libs/binder/libbinder_rpc_unstable.cpp b/libs/binder/libbinder_rpc_unstable.cpp
index bf2b25b..a3d42b7 100644
--- a/libs/binder/libbinder_rpc_unstable.cpp
+++ b/libs/binder/libbinder_rpc_unstable.cpp
@@ -38,10 +38,10 @@
<< " error: " << statusToString(status).c_str();
return false;
}
- server->setPerSessionRootObject([=](const sockaddr* addr, socklen_t addrlen) {
- LOG_ALWAYS_FATAL_IF(addr->sa_family != AF_VSOCK, "address is not a vsock");
+ server->setPerSessionRootObject([=](const void* addr, size_t addrlen) {
LOG_ALWAYS_FATAL_IF(addrlen < sizeof(sockaddr_vm), "sockaddr is truncated");
const sockaddr_vm* vaddr = reinterpret_cast<const sockaddr_vm*>(addr);
+ LOG_ALWAYS_FATAL_IF(vaddr->svm_family != AF_VSOCK, "address is not a vsock");
return AIBinder_toPlatformBinder(factory(vaddr->svm_cid, factoryContext));
});
diff --git a/libs/binder/tests/binderAllocationLimits.cpp b/libs/binder/tests/binderAllocationLimits.cpp
index dd1a8c3..60b3c94 100644
--- a/libs/binder/tests/binderAllocationLimits.cpp
+++ b/libs/binder/tests/binderAllocationLimits.cpp
@@ -203,13 +203,15 @@
auto remoteBinder = session->getRootObject();
size_t mallocs = 0, totalBytes = 0;
- const auto on_malloc = OnMalloc([&](size_t bytes) {
- mallocs++;
- totalBytes += bytes;
- });
- CHECK_EQ(OK, remoteBinder->pingBinder());
- EXPECT_EQ(mallocs, 3);
- EXPECT_EQ(totalBytes, 60);
+ {
+ const auto on_malloc = OnMalloc([&](size_t bytes) {
+ mallocs++;
+ totalBytes += bytes;
+ });
+ CHECK_EQ(OK, remoteBinder->pingBinder());
+ }
+ EXPECT_EQ(mallocs, 1);
+ EXPECT_EQ(totalBytes, 40);
}
int main(int argc, char** argv) {
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index 4161a7a..0247e42 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -650,8 +650,11 @@
.proc = createRpcTestSocketServerProcess(
options,
[&](const sp<RpcServer>& server) {
- server->setPerSessionRootObject([&](const sockaddr* addr,
- socklen_t len) {
+ server->setPerSessionRootObject([&](const void* addrPtr, size_t len) {
+ // UNIX sockets with abstract addresses return
+ // sizeof(sa_family_t)==2 in addrlen
+ CHECK_GE(len, sizeof(sa_family_t));
+ const sockaddr* addr = reinterpret_cast<const sockaddr*>(addrPtr);
sp<MyBinderRpcTest> service = sp<MyBinderRpcTest>::make();
switch (addr->sa_family) {
case AF_UNIX: