libbinder: Stricter protocol and code for receiving FDs
This is a slight change the to wire protocol. Now out-of-band FDs must
be sent along with the command header bytes.
The code changes exploit that by only using the more complex `recvmsg`
call when reading the command header. Additionally, we explicitly pass
around the list of FDs so that there is no risk of accumulating them.
The same (somewhat ugly) vector type is used everywhere now so that
there is only one allocation to capture the FDs and pass them to the
`Parcel` object.
Test: binderRpcTest
Bug: 185909244
Change-Id: I1f55995ca82338ab9716fb2246c954ac8b16cfe5
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 8739105..0354382 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -2486,11 +2486,11 @@
scanForFds();
}
-status_t Parcel::rpcSetDataReference(const sp<RpcSession>& session, const uint8_t* data,
- size_t dataSize, const uint32_t* objectTable,
- size_t objectTableSize,
- std::vector<base::unique_fd> ancillaryFds,
- release_func relFunc) {
+status_t Parcel::rpcSetDataReference(
+ const sp<RpcSession>& session, const uint8_t* data, size_t dataSize,
+ const uint32_t* objectTable, size_t objectTableSize,
+ std::vector<std::variant<base::unique_fd, base::borrowed_fd>>&& ancillaryFds,
+ release_func relFunc) {
// this code uses 'mOwner == nullptr' to understand whether it owns memory
LOG_ALWAYS_FATAL_IF(relFunc == nullptr, "must provide cleanup function");
@@ -2518,10 +2518,7 @@
}
if (!ancillaryFds.empty()) {
rpcFields->mFds = std::make_unique<decltype(rpcFields->mFds)::element_type>();
- rpcFields->mFds->reserve(ancillaryFds.size());
- for (auto& fd : ancillaryFds) {
- rpcFields->mFds->push_back(std::move(fd));
- }
+ *rpcFields->mFds = std::move(ancillaryFds);
}
return OK;