Loading libs/binder/Parcel.cpp +6 −9 Original line number Diff line number Diff line Loading @@ -2486,10 +2486,10 @@ void Parcel::ipcSetDataReference(const uint8_t* data, size_t dataSize, const bin 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, 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"); Loading Loading @@ -2518,10 +2518,7 @@ status_t Parcel::rpcSetDataReference(const sp<RpcSession>& session, const uint8_ } 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; Loading libs/binder/RpcServer.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -300,7 +300,7 @@ void RpcServer::establishConnection(sp<RpcServer>&& server, base::unique_fd clie if (status == OK) { iovec iov{&header, sizeof(header)}; status = client->interruptableReadFully(server->mShutdownTrigger.get(), &iov, 1, std::nullopt, /*enableAncillaryFds=*/false); std::nullopt, /*ancillaryFds=*/nullptr); if (status != OK) { ALOGE("Failed to read ID for client connecting to RPC server: %s", statusToString(status).c_str()); Loading @@ -315,7 +315,7 @@ void RpcServer::establishConnection(sp<RpcServer>&& server, base::unique_fd clie sessionId.resize(header.sessionIdSize); iovec iov{sessionId.data(), sessionId.size()}; status = client->interruptableReadFully(server->mShutdownTrigger.get(), &iov, 1, std::nullopt, /*enableAncillaryFds=*/false); std::nullopt, /*ancillaryFds=*/nullptr); if (status != OK) { ALOGE("Failed to read session ID for client connecting to RPC server: %s", statusToString(status).c_str()); Loading libs/binder/RpcState.cpp +54 −42 Original line number Diff line number Diff line Loading @@ -346,11 +346,14 @@ status_t RpcState::rpcSend( return OK; } status_t RpcState::rpcRec(const sp<RpcSession::RpcConnection>& connection, const sp<RpcSession>& session, const char* what, iovec* iovs, int niovs) { if (status_t status = connection->rpcTransport->interruptableReadFully( session->mShutdownTrigger.get(), iovs, niovs, std::nullopt, enableAncillaryFds(session->getFileDescriptorTransportMode())); status_t RpcState::rpcRec( const sp<RpcSession::RpcConnection>& connection, const sp<RpcSession>& session, const char* what, iovec* iovs, int niovs, std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* ancillaryFds) { if (status_t status = connection->rpcTransport->interruptableReadFully(session->mShutdownTrigger.get(), iovs, niovs, std::nullopt, ancillaryFds); status != OK) { LOG_RPC_DETAIL("Failed to read %s (%d iovs) on RpcTransport %p, error: %s", what, niovs, connection->rpcTransport.get(), statusToString(status).c_str()); Loading @@ -370,7 +373,7 @@ status_t RpcState::readNewSessionResponse(const sp<RpcSession::RpcConnection>& c const sp<RpcSession>& session, uint32_t* version) { RpcNewSessionResponse response; iovec iov{&response, sizeof(response)}; if (status_t status = rpcRec(connection, session, "new session response", &iov, 1); if (status_t status = rpcRec(connection, session, "new session response", &iov, 1, nullptr); status != OK) { return status; } Loading @@ -391,7 +394,8 @@ status_t RpcState::readConnectionInit(const sp<RpcSession::RpcConnection>& conne const sp<RpcSession>& session) { RpcOutgoingConnectionInit init; iovec iov{&init, sizeof(init)}; if (status_t status = rpcRec(connection, session, "connection init", &iov, 1); status != OK) if (status_t status = rpcRec(connection, session, "connection init", &iov, 1, nullptr); status != OK) return status; static_assert(sizeof(init.msg) == sizeof(RPC_CONNECTION_INIT_OKAY)); Loading Loading @@ -589,18 +593,26 @@ static void cleanup_reply_data(Parcel* p, const uint8_t* data, size_t dataSize, status_t RpcState::waitForReply(const sp<RpcSession::RpcConnection>& connection, const sp<RpcSession>& session, Parcel* reply) { std::vector<std::variant<base::unique_fd, base::borrowed_fd>> ancillaryFds; RpcWireHeader command; while (true) { iovec iov{&command, sizeof(command)}; if (status_t status = rpcRec(connection, session, "command header (for reply)", &iov, 1); if (status_t status = rpcRec(connection, session, "command header (for reply)", &iov, 1, enableAncillaryFds(session->getFileDescriptorTransportMode()) ? &ancillaryFds : nullptr); status != OK) return status; if (command.command == RPC_COMMAND_REPLY) break; if (status_t status = processCommand(connection, session, command, CommandType::ANY); if (status_t status = processCommand(connection, session, command, CommandType::ANY, std::move(ancillaryFds)); status != OK) return status; // Reset to avoid spurious use-after-move warning from clang-tidy. ancillaryFds = decltype(ancillaryFds)(); } const size_t rpcReplyWireSize = RpcWireReply::wireSize(session->getProtocolVersion().value()); Loading @@ -622,17 +634,10 @@ status_t RpcState::waitForReply(const sp<RpcSession::RpcConnection>& connection, {&rpcReply, rpcReplyWireSize}, {data.data(), data.size()}, }; if (status_t status = rpcRec(connection, session, "reply body", iovs, arraysize(iovs)); if (status_t status = rpcRec(connection, session, "reply body", iovs, arraysize(iovs), nullptr); status != OK) return status; // Check if the reply came with any ancillary data. std::vector<base::unique_fd> pendingFds; if (status_t status = connection->rpcTransport->consumePendingAncillaryData(&pendingFds); status != OK) { return status; } if (rpcReply.status != OK) return rpcReply.status; Span<const uint8_t> parcelSpan = {data.data(), data.size()}; Loading @@ -655,7 +660,7 @@ status_t RpcState::waitForReply(const sp<RpcSession::RpcConnection>& connection, data.release(); return reply->rpcSetDataReference(session, parcelSpan.data, parcelSpan.size, objectTableSpan.data, objectTableSpan.size, std::move(pendingFds), cleanup_reply_data); std::move(ancillaryFds), cleanup_reply_data); } status_t RpcState::sendDecStrongToTarget(const sp<RpcSession::RpcConnection>& connection, Loading Loading @@ -698,13 +703,17 @@ status_t RpcState::getAndExecuteCommand(const sp<RpcSession::RpcConnection>& con const sp<RpcSession>& session, CommandType type) { LOG_RPC_DETAIL("getAndExecuteCommand on RpcTransport %p", connection->rpcTransport.get()); std::vector<std::variant<base::unique_fd, base::borrowed_fd>> ancillaryFds; RpcWireHeader command; iovec iov{&command, sizeof(command)}; if (status_t status = rpcRec(connection, session, "command header (for server)", &iov, 1); if (status_t status = rpcRec(connection, session, "command header (for server)", &iov, 1, enableAncillaryFds(session->getFileDescriptorTransportMode()) ? &ancillaryFds : nullptr); status != OK) return status; return processCommand(connection, session, command, type); return processCommand(connection, session, command, type, std::move(ancillaryFds)); } status_t RpcState::drainCommands(const sp<RpcSession::RpcConnection>& connection, Loading @@ -720,9 +729,10 @@ status_t RpcState::drainCommands(const sp<RpcSession::RpcConnection>& connection return OK; } status_t RpcState::processCommand(const sp<RpcSession::RpcConnection>& connection, const sp<RpcSession>& session, const RpcWireHeader& command, CommandType type) { status_t RpcState::processCommand( const sp<RpcSession::RpcConnection>& connection, const sp<RpcSession>& session, const RpcWireHeader& command, CommandType type, std::vector<std::variant<base::unique_fd, base::borrowed_fd>>&& ancillaryFds) { IPCThreadState* kernelBinderState = IPCThreadState::selfOrNull(); IPCThreadState::SpGuard spGuard{ .address = __builtin_frame_address(0), Loading @@ -741,7 +751,7 @@ status_t RpcState::processCommand(const sp<RpcSession::RpcConnection>& connectio switch (command.command) { case RPC_COMMAND_TRANSACT: if (type != CommandType::ANY) return BAD_TYPE; return processTransact(connection, session, command); return processTransact(connection, session, command, std::move(ancillaryFds)); case RPC_COMMAND_DEC_STRONG: return processDecStrong(connection, session, command); } Loading @@ -755,8 +765,10 @@ status_t RpcState::processCommand(const sp<RpcSession::RpcConnection>& connectio (void)session->shutdownAndWait(false); return DEAD_OBJECT; } status_t RpcState::processTransact(const sp<RpcSession::RpcConnection>& connection, const sp<RpcSession>& session, const RpcWireHeader& command) { status_t RpcState::processTransact( const sp<RpcSession::RpcConnection>& connection, const sp<RpcSession>& session, const RpcWireHeader& command, std::vector<std::variant<base::unique_fd, base::borrowed_fd>>&& ancillaryFds) { LOG_ALWAYS_FATAL_IF(command.command != RPC_COMMAND_TRANSACT, "command: %d", command.command); CommandData transactionData(command.bodySize); Loading @@ -764,10 +776,12 @@ status_t RpcState::processTransact(const sp<RpcSession::RpcConnection>& connecti return NO_MEMORY; } iovec iov{transactionData.data(), transactionData.size()}; if (status_t status = rpcRec(connection, session, "transaction body", &iov, 1); status != OK) if (status_t status = rpcRec(connection, session, "transaction body", &iov, 1, nullptr); status != OK) return status; return processTransactInternal(connection, session, std::move(transactionData)); return processTransactInternal(connection, session, std::move(transactionData), std::move(ancillaryFds)); } static void do_nothing_to_transact_data(Parcel* p, const uint8_t* data, size_t dataSize, Loading @@ -779,9 +793,10 @@ static void do_nothing_to_transact_data(Parcel* p, const uint8_t* data, size_t d (void)objectsCount; } status_t RpcState::processTransactInternal(const sp<RpcSession::RpcConnection>& connection, const sp<RpcSession>& session, CommandData transactionData) { status_t RpcState::processTransactInternal( const sp<RpcSession::RpcConnection>& connection, const sp<RpcSession>& session, CommandData transactionData, std::vector<std::variant<base::unique_fd, base::borrowed_fd>>&& ancillaryFds) { // for 'recursive' calls to this, we have already read and processed the // binder from the transaction data and taken reference counts into account, // so it is cached here. Loading Loading @@ -869,13 +884,6 @@ processTransactInternalTailCall: reply.markForRpc(session); if (replyStatus == OK) { // Check if the transaction came with any ancillary data. std::vector<base::unique_fd> pendingFds; if (status_t status = connection->rpcTransport->consumePendingAncillaryData(&pendingFds); status != OK) { return status; } Span<const uint8_t> parcelSpan = {transaction->data, transactionData.size() - offsetof(RpcWireTransaction, data)}; Loading @@ -901,9 +909,12 @@ processTransactInternalTailCall: // only holds onto it for the duration of this function call. Parcel will be // deleted before the 'transactionData' object. replyStatus = data.rpcSetDataReference(session, parcelSpan.data, parcelSpan.size, replyStatus = data.rpcSetDataReference(session, parcelSpan.data, parcelSpan.size, objectTableSpan.data, objectTableSpan.size, std::move(pendingFds), do_nothing_to_transact_data); std::move(ancillaryFds), do_nothing_to_transact_data); // Reset to avoid spurious use-after-move warning from clang-tidy. ancillaryFds = std::remove_reference<decltype(ancillaryFds)>::type(); if (replyStatus == OK) { if (target) { Loading Loading @@ -1073,7 +1084,8 @@ status_t RpcState::processDecStrong(const sp<RpcSession::RpcConnection>& connect RpcDecStrong body; iovec iov{&body, sizeof(RpcDecStrong)}; if (status_t status = rpcRec(connection, session, "dec ref body", &iov, 1); status != OK) if (status_t status = rpcRec(connection, session, "dec ref body", &iov, 1, nullptr); status != OK) return status; uint64_t addr = RpcWireAddress::toRaw(body.address); Loading libs/binder/RpcState.h +16 −12 Original line number Diff line number Diff line Loading @@ -184,21 +184,25 @@ private: const std::optional<android::base::function_ref<status_t()>>& altPoll, const std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* ancillaryFds = nullptr); [[nodiscard]] status_t rpcRec(const sp<RpcSession::RpcConnection>& connection, const sp<RpcSession>& session, const char* what, iovec* iovs, int niovs); [[nodiscard]] status_t rpcRec( const sp<RpcSession::RpcConnection>& connection, const sp<RpcSession>& session, const char* what, iovec* iovs, int niovs, std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* ancillaryFds = nullptr); [[nodiscard]] status_t waitForReply(const sp<RpcSession::RpcConnection>& connection, const sp<RpcSession>& session, Parcel* reply); [[nodiscard]] status_t processCommand(const sp<RpcSession::RpcConnection>& connection, const sp<RpcSession>& session, const RpcWireHeader& command, CommandType type); [[nodiscard]] status_t processTransact(const sp<RpcSession::RpcConnection>& connection, const sp<RpcSession>& session, const RpcWireHeader& command); [[nodiscard]] status_t processTransactInternal(const sp<RpcSession::RpcConnection>& connection, const sp<RpcSession>& session, CommandData transactionData); [[nodiscard]] status_t processCommand( const sp<RpcSession::RpcConnection>& connection, const sp<RpcSession>& session, const RpcWireHeader& command, CommandType type, std::vector<std::variant<base::unique_fd, base::borrowed_fd>>&& ancillaryFds); [[nodiscard]] status_t processTransact( const sp<RpcSession::RpcConnection>& connection, const sp<RpcSession>& session, const RpcWireHeader& command, std::vector<std::variant<base::unique_fd, base::borrowed_fd>>&& ancillaryFds); [[nodiscard]] status_t processTransactInternal( const sp<RpcSession::RpcConnection>& connection, const sp<RpcSession>& session, CommandData transactionData, std::vector<std::variant<base::unique_fd, base::borrowed_fd>>&& ancillaryFds); [[nodiscard]] status_t processDecStrong(const sp<RpcSession::RpcConnection>& connection, const sp<RpcSession>& session, const RpcWireHeader& command); Loading libs/binder/RpcTransportRaw.cpp +5 −13 Original line number Diff line number Diff line Loading @@ -204,9 +204,9 @@ public: status_t interruptableReadFully( FdTrigger* fdTrigger, iovec* iovs, int niovs, const std::optional<android::base::function_ref<status_t()>>& altPoll, bool enableAncillaryFds) override { std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* ancillaryFds) override { auto recv = [&](iovec* iovs, int niovs) -> ssize_t { if (enableAncillaryFds) { if (ancillaryFds != nullptr) { int fdBuffer[kMaxFdsPerMsg]; alignas(struct cmsghdr) char msgControlBuf[CMSG_SPACE(sizeof(fdBuffer))]; Loading @@ -228,10 +228,12 @@ public: // NOTE: It is tempting to reinterpret_cast, but cmsg(3) explicitly asks // application devs to memcpy the data to ensure memory alignment. size_t dataLen = cmsg->cmsg_len - CMSG_LEN(0); LOG_ALWAYS_FATAL_IF(dataLen > sizeof(fdBuffer)); // sanity check memcpy(fdBuffer, CMSG_DATA(cmsg), dataLen); size_t fdCount = dataLen / sizeof(int); ancillaryFds->reserve(ancillaryFds->size() + fdCount); for (size_t i = 0; i < fdCount; i++) { mFdsPendingRead.emplace_back(fdBuffer[i]); ancillaryFds->emplace_back(base::unique_fd(fdBuffer[i])); } break; } Loading @@ -256,18 +258,8 @@ public: return interruptableReadOrWrite(fdTrigger, iovs, niovs, recv, "recvmsg", POLLIN, altPoll); } status_t consumePendingAncillaryData(std::vector<base::unique_fd>* fds) override { fds->reserve(fds->size() + mFdsPendingRead.size()); for (auto& fd : mFdsPendingRead) { fds->emplace_back(std::move(fd)); } mFdsPendingRead.clear(); return OK; } private: base::unique_fd mSocket; std::vector<base::unique_fd> mFdsPendingRead; }; // RpcTransportCtx with TLS disabled. Loading Loading
libs/binder/Parcel.cpp +6 −9 Original line number Diff line number Diff line Loading @@ -2486,10 +2486,10 @@ void Parcel::ipcSetDataReference(const uint8_t* data, size_t dataSize, const bin 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, 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"); Loading Loading @@ -2518,10 +2518,7 @@ status_t Parcel::rpcSetDataReference(const sp<RpcSession>& session, const uint8_ } 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; Loading
libs/binder/RpcServer.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -300,7 +300,7 @@ void RpcServer::establishConnection(sp<RpcServer>&& server, base::unique_fd clie if (status == OK) { iovec iov{&header, sizeof(header)}; status = client->interruptableReadFully(server->mShutdownTrigger.get(), &iov, 1, std::nullopt, /*enableAncillaryFds=*/false); std::nullopt, /*ancillaryFds=*/nullptr); if (status != OK) { ALOGE("Failed to read ID for client connecting to RPC server: %s", statusToString(status).c_str()); Loading @@ -315,7 +315,7 @@ void RpcServer::establishConnection(sp<RpcServer>&& server, base::unique_fd clie sessionId.resize(header.sessionIdSize); iovec iov{sessionId.data(), sessionId.size()}; status = client->interruptableReadFully(server->mShutdownTrigger.get(), &iov, 1, std::nullopt, /*enableAncillaryFds=*/false); std::nullopt, /*ancillaryFds=*/nullptr); if (status != OK) { ALOGE("Failed to read session ID for client connecting to RPC server: %s", statusToString(status).c_str()); Loading
libs/binder/RpcState.cpp +54 −42 Original line number Diff line number Diff line Loading @@ -346,11 +346,14 @@ status_t RpcState::rpcSend( return OK; } status_t RpcState::rpcRec(const sp<RpcSession::RpcConnection>& connection, const sp<RpcSession>& session, const char* what, iovec* iovs, int niovs) { if (status_t status = connection->rpcTransport->interruptableReadFully( session->mShutdownTrigger.get(), iovs, niovs, std::nullopt, enableAncillaryFds(session->getFileDescriptorTransportMode())); status_t RpcState::rpcRec( const sp<RpcSession::RpcConnection>& connection, const sp<RpcSession>& session, const char* what, iovec* iovs, int niovs, std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* ancillaryFds) { if (status_t status = connection->rpcTransport->interruptableReadFully(session->mShutdownTrigger.get(), iovs, niovs, std::nullopt, ancillaryFds); status != OK) { LOG_RPC_DETAIL("Failed to read %s (%d iovs) on RpcTransport %p, error: %s", what, niovs, connection->rpcTransport.get(), statusToString(status).c_str()); Loading @@ -370,7 +373,7 @@ status_t RpcState::readNewSessionResponse(const sp<RpcSession::RpcConnection>& c const sp<RpcSession>& session, uint32_t* version) { RpcNewSessionResponse response; iovec iov{&response, sizeof(response)}; if (status_t status = rpcRec(connection, session, "new session response", &iov, 1); if (status_t status = rpcRec(connection, session, "new session response", &iov, 1, nullptr); status != OK) { return status; } Loading @@ -391,7 +394,8 @@ status_t RpcState::readConnectionInit(const sp<RpcSession::RpcConnection>& conne const sp<RpcSession>& session) { RpcOutgoingConnectionInit init; iovec iov{&init, sizeof(init)}; if (status_t status = rpcRec(connection, session, "connection init", &iov, 1); status != OK) if (status_t status = rpcRec(connection, session, "connection init", &iov, 1, nullptr); status != OK) return status; static_assert(sizeof(init.msg) == sizeof(RPC_CONNECTION_INIT_OKAY)); Loading Loading @@ -589,18 +593,26 @@ static void cleanup_reply_data(Parcel* p, const uint8_t* data, size_t dataSize, status_t RpcState::waitForReply(const sp<RpcSession::RpcConnection>& connection, const sp<RpcSession>& session, Parcel* reply) { std::vector<std::variant<base::unique_fd, base::borrowed_fd>> ancillaryFds; RpcWireHeader command; while (true) { iovec iov{&command, sizeof(command)}; if (status_t status = rpcRec(connection, session, "command header (for reply)", &iov, 1); if (status_t status = rpcRec(connection, session, "command header (for reply)", &iov, 1, enableAncillaryFds(session->getFileDescriptorTransportMode()) ? &ancillaryFds : nullptr); status != OK) return status; if (command.command == RPC_COMMAND_REPLY) break; if (status_t status = processCommand(connection, session, command, CommandType::ANY); if (status_t status = processCommand(connection, session, command, CommandType::ANY, std::move(ancillaryFds)); status != OK) return status; // Reset to avoid spurious use-after-move warning from clang-tidy. ancillaryFds = decltype(ancillaryFds)(); } const size_t rpcReplyWireSize = RpcWireReply::wireSize(session->getProtocolVersion().value()); Loading @@ -622,17 +634,10 @@ status_t RpcState::waitForReply(const sp<RpcSession::RpcConnection>& connection, {&rpcReply, rpcReplyWireSize}, {data.data(), data.size()}, }; if (status_t status = rpcRec(connection, session, "reply body", iovs, arraysize(iovs)); if (status_t status = rpcRec(connection, session, "reply body", iovs, arraysize(iovs), nullptr); status != OK) return status; // Check if the reply came with any ancillary data. std::vector<base::unique_fd> pendingFds; if (status_t status = connection->rpcTransport->consumePendingAncillaryData(&pendingFds); status != OK) { return status; } if (rpcReply.status != OK) return rpcReply.status; Span<const uint8_t> parcelSpan = {data.data(), data.size()}; Loading @@ -655,7 +660,7 @@ status_t RpcState::waitForReply(const sp<RpcSession::RpcConnection>& connection, data.release(); return reply->rpcSetDataReference(session, parcelSpan.data, parcelSpan.size, objectTableSpan.data, objectTableSpan.size, std::move(pendingFds), cleanup_reply_data); std::move(ancillaryFds), cleanup_reply_data); } status_t RpcState::sendDecStrongToTarget(const sp<RpcSession::RpcConnection>& connection, Loading Loading @@ -698,13 +703,17 @@ status_t RpcState::getAndExecuteCommand(const sp<RpcSession::RpcConnection>& con const sp<RpcSession>& session, CommandType type) { LOG_RPC_DETAIL("getAndExecuteCommand on RpcTransport %p", connection->rpcTransport.get()); std::vector<std::variant<base::unique_fd, base::borrowed_fd>> ancillaryFds; RpcWireHeader command; iovec iov{&command, sizeof(command)}; if (status_t status = rpcRec(connection, session, "command header (for server)", &iov, 1); if (status_t status = rpcRec(connection, session, "command header (for server)", &iov, 1, enableAncillaryFds(session->getFileDescriptorTransportMode()) ? &ancillaryFds : nullptr); status != OK) return status; return processCommand(connection, session, command, type); return processCommand(connection, session, command, type, std::move(ancillaryFds)); } status_t RpcState::drainCommands(const sp<RpcSession::RpcConnection>& connection, Loading @@ -720,9 +729,10 @@ status_t RpcState::drainCommands(const sp<RpcSession::RpcConnection>& connection return OK; } status_t RpcState::processCommand(const sp<RpcSession::RpcConnection>& connection, const sp<RpcSession>& session, const RpcWireHeader& command, CommandType type) { status_t RpcState::processCommand( const sp<RpcSession::RpcConnection>& connection, const sp<RpcSession>& session, const RpcWireHeader& command, CommandType type, std::vector<std::variant<base::unique_fd, base::borrowed_fd>>&& ancillaryFds) { IPCThreadState* kernelBinderState = IPCThreadState::selfOrNull(); IPCThreadState::SpGuard spGuard{ .address = __builtin_frame_address(0), Loading @@ -741,7 +751,7 @@ status_t RpcState::processCommand(const sp<RpcSession::RpcConnection>& connectio switch (command.command) { case RPC_COMMAND_TRANSACT: if (type != CommandType::ANY) return BAD_TYPE; return processTransact(connection, session, command); return processTransact(connection, session, command, std::move(ancillaryFds)); case RPC_COMMAND_DEC_STRONG: return processDecStrong(connection, session, command); } Loading @@ -755,8 +765,10 @@ status_t RpcState::processCommand(const sp<RpcSession::RpcConnection>& connectio (void)session->shutdownAndWait(false); return DEAD_OBJECT; } status_t RpcState::processTransact(const sp<RpcSession::RpcConnection>& connection, const sp<RpcSession>& session, const RpcWireHeader& command) { status_t RpcState::processTransact( const sp<RpcSession::RpcConnection>& connection, const sp<RpcSession>& session, const RpcWireHeader& command, std::vector<std::variant<base::unique_fd, base::borrowed_fd>>&& ancillaryFds) { LOG_ALWAYS_FATAL_IF(command.command != RPC_COMMAND_TRANSACT, "command: %d", command.command); CommandData transactionData(command.bodySize); Loading @@ -764,10 +776,12 @@ status_t RpcState::processTransact(const sp<RpcSession::RpcConnection>& connecti return NO_MEMORY; } iovec iov{transactionData.data(), transactionData.size()}; if (status_t status = rpcRec(connection, session, "transaction body", &iov, 1); status != OK) if (status_t status = rpcRec(connection, session, "transaction body", &iov, 1, nullptr); status != OK) return status; return processTransactInternal(connection, session, std::move(transactionData)); return processTransactInternal(connection, session, std::move(transactionData), std::move(ancillaryFds)); } static void do_nothing_to_transact_data(Parcel* p, const uint8_t* data, size_t dataSize, Loading @@ -779,9 +793,10 @@ static void do_nothing_to_transact_data(Parcel* p, const uint8_t* data, size_t d (void)objectsCount; } status_t RpcState::processTransactInternal(const sp<RpcSession::RpcConnection>& connection, const sp<RpcSession>& session, CommandData transactionData) { status_t RpcState::processTransactInternal( const sp<RpcSession::RpcConnection>& connection, const sp<RpcSession>& session, CommandData transactionData, std::vector<std::variant<base::unique_fd, base::borrowed_fd>>&& ancillaryFds) { // for 'recursive' calls to this, we have already read and processed the // binder from the transaction data and taken reference counts into account, // so it is cached here. Loading Loading @@ -869,13 +884,6 @@ processTransactInternalTailCall: reply.markForRpc(session); if (replyStatus == OK) { // Check if the transaction came with any ancillary data. std::vector<base::unique_fd> pendingFds; if (status_t status = connection->rpcTransport->consumePendingAncillaryData(&pendingFds); status != OK) { return status; } Span<const uint8_t> parcelSpan = {transaction->data, transactionData.size() - offsetof(RpcWireTransaction, data)}; Loading @@ -901,9 +909,12 @@ processTransactInternalTailCall: // only holds onto it for the duration of this function call. Parcel will be // deleted before the 'transactionData' object. replyStatus = data.rpcSetDataReference(session, parcelSpan.data, parcelSpan.size, replyStatus = data.rpcSetDataReference(session, parcelSpan.data, parcelSpan.size, objectTableSpan.data, objectTableSpan.size, std::move(pendingFds), do_nothing_to_transact_data); std::move(ancillaryFds), do_nothing_to_transact_data); // Reset to avoid spurious use-after-move warning from clang-tidy. ancillaryFds = std::remove_reference<decltype(ancillaryFds)>::type(); if (replyStatus == OK) { if (target) { Loading Loading @@ -1073,7 +1084,8 @@ status_t RpcState::processDecStrong(const sp<RpcSession::RpcConnection>& connect RpcDecStrong body; iovec iov{&body, sizeof(RpcDecStrong)}; if (status_t status = rpcRec(connection, session, "dec ref body", &iov, 1); status != OK) if (status_t status = rpcRec(connection, session, "dec ref body", &iov, 1, nullptr); status != OK) return status; uint64_t addr = RpcWireAddress::toRaw(body.address); Loading
libs/binder/RpcState.h +16 −12 Original line number Diff line number Diff line Loading @@ -184,21 +184,25 @@ private: const std::optional<android::base::function_ref<status_t()>>& altPoll, const std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* ancillaryFds = nullptr); [[nodiscard]] status_t rpcRec(const sp<RpcSession::RpcConnection>& connection, const sp<RpcSession>& session, const char* what, iovec* iovs, int niovs); [[nodiscard]] status_t rpcRec( const sp<RpcSession::RpcConnection>& connection, const sp<RpcSession>& session, const char* what, iovec* iovs, int niovs, std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* ancillaryFds = nullptr); [[nodiscard]] status_t waitForReply(const sp<RpcSession::RpcConnection>& connection, const sp<RpcSession>& session, Parcel* reply); [[nodiscard]] status_t processCommand(const sp<RpcSession::RpcConnection>& connection, const sp<RpcSession>& session, const RpcWireHeader& command, CommandType type); [[nodiscard]] status_t processTransact(const sp<RpcSession::RpcConnection>& connection, const sp<RpcSession>& session, const RpcWireHeader& command); [[nodiscard]] status_t processTransactInternal(const sp<RpcSession::RpcConnection>& connection, const sp<RpcSession>& session, CommandData transactionData); [[nodiscard]] status_t processCommand( const sp<RpcSession::RpcConnection>& connection, const sp<RpcSession>& session, const RpcWireHeader& command, CommandType type, std::vector<std::variant<base::unique_fd, base::borrowed_fd>>&& ancillaryFds); [[nodiscard]] status_t processTransact( const sp<RpcSession::RpcConnection>& connection, const sp<RpcSession>& session, const RpcWireHeader& command, std::vector<std::variant<base::unique_fd, base::borrowed_fd>>&& ancillaryFds); [[nodiscard]] status_t processTransactInternal( const sp<RpcSession::RpcConnection>& connection, const sp<RpcSession>& session, CommandData transactionData, std::vector<std::variant<base::unique_fd, base::borrowed_fd>>&& ancillaryFds); [[nodiscard]] status_t processDecStrong(const sp<RpcSession::RpcConnection>& connection, const sp<RpcSession>& session, const RpcWireHeader& command); Loading
libs/binder/RpcTransportRaw.cpp +5 −13 Original line number Diff line number Diff line Loading @@ -204,9 +204,9 @@ public: status_t interruptableReadFully( FdTrigger* fdTrigger, iovec* iovs, int niovs, const std::optional<android::base::function_ref<status_t()>>& altPoll, bool enableAncillaryFds) override { std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* ancillaryFds) override { auto recv = [&](iovec* iovs, int niovs) -> ssize_t { if (enableAncillaryFds) { if (ancillaryFds != nullptr) { int fdBuffer[kMaxFdsPerMsg]; alignas(struct cmsghdr) char msgControlBuf[CMSG_SPACE(sizeof(fdBuffer))]; Loading @@ -228,10 +228,12 @@ public: // NOTE: It is tempting to reinterpret_cast, but cmsg(3) explicitly asks // application devs to memcpy the data to ensure memory alignment. size_t dataLen = cmsg->cmsg_len - CMSG_LEN(0); LOG_ALWAYS_FATAL_IF(dataLen > sizeof(fdBuffer)); // sanity check memcpy(fdBuffer, CMSG_DATA(cmsg), dataLen); size_t fdCount = dataLen / sizeof(int); ancillaryFds->reserve(ancillaryFds->size() + fdCount); for (size_t i = 0; i < fdCount; i++) { mFdsPendingRead.emplace_back(fdBuffer[i]); ancillaryFds->emplace_back(base::unique_fd(fdBuffer[i])); } break; } Loading @@ -256,18 +258,8 @@ public: return interruptableReadOrWrite(fdTrigger, iovs, niovs, recv, "recvmsg", POLLIN, altPoll); } status_t consumePendingAncillaryData(std::vector<base::unique_fd>* fds) override { fds->reserve(fds->size() + mFdsPendingRead.size()); for (auto& fd : mFdsPendingRead) { fds->emplace_back(std::move(fd)); } mFdsPendingRead.clear(); return OK; } private: base::unique_fd mSocket; std::vector<base::unique_fd> mFdsPendingRead; }; // RpcTransportCtx with TLS disabled. Loading