Loading PREUPLOAD.cfg +1 −0 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ rustfmt = true bpfmt = true clang_format = true alint = false [Builtin Hooks Options] rustfmt = --config-path=rustfmt.toml Loading include/input/InputFlags.h +0 −9 Original line number Diff line number Diff line Loading @@ -53,15 +53,6 @@ public: * connectedDisplaysCursorEnabled flag. */ static bool scaleCursorSpeedWithDisplayDensity(); /** * This is a temporary fix that removes the SKIP_SCREENSHOT flag for the Mouse cursor. This is * only intended to be temporarily used as workaround only when connected displays dev option * is enabled. * * This will make mouse cursor visible on recordings and screenshots of secure windows. */ static bool doNotUseSkipScreenshotFlagForMouseCursor(); }; } // namespace android libs/binder/Parcel.cpp +117 −64 Original line number Diff line number Diff line Loading @@ -348,14 +348,51 @@ status_t Parcel::flattenBinder(const sp<IBinder>& binder) { #endif // BINDER_WITH_KERNEL_IPC } template <class T> status_t Parcel::readPartialRpcObject(T* val) const { static_assert(sizeof(T) == sizeof(int32_t) || sizeof(T) == sizeof(uint64_t)); size_t end; if (__builtin_add_overflow(mDataPos, sizeof(T), &end) || end > mDataSize) { return NOT_ENOUGH_DATA; } memcpy(val, mData + mDataPos, sizeof(T)); mDataPos += sizeof(T); return OK; } status_t Parcel::readRpcObjectType(int32_t* objectType) const { return readPartialRpcObject(objectType); } status_t Parcel::readRpcBinderAddress(uint64_t* addr) const { return readPartialRpcObject(addr); } status_t Parcel::readRpcFdIndex(int32_t* fdIndex) const { return readPartialRpcObject(fdIndex); } constexpr size_t Parcel::getRpcObjectSize(int32_t objectType) { switch (objectType) { case RpcFields::TYPE_BINDER: return sizeof(RpcFields::ObjectType) + sizeof(uint64_t); break; case RpcFields::TYPE_NATIVE_FILE_DESCRIPTOR: return sizeof(RpcFields::ObjectType) + sizeof(int32_t); break; default: LOG_ALWAYS_FATAL("Unknown RpcFields type: %" PRId32, objectType); } } status_t Parcel::unflattenBinder(sp<IBinder>* out) const { if (const auto* rpcFields = maybeRpcFields()) { const size_t objectPos = mDataPos; // see TYPE_BINDER/TYPE_BINDER_NULL int32_t isPresent; if (status_t status = readInt32(&isPresent); status != OK) return status; int32_t isPresent = 0; if (status_t status = readRpcObjectType(&isPresent); status != OK) return status; sp<IBinder> binder; Loading @@ -377,8 +414,8 @@ status_t Parcel::unflattenBinder(sp<IBinder>* out) const LOG_ALWAYS_FATAL_IF(binder == nullptr); } uint64_t addr; if (status_t status = readUint64(&addr); status != OK) return status; uint64_t addr = 0; if (status_t status = readRpcBinderAddress(&addr); status != OK) return status; if (binder == nullptr) { if (rpcFields->mSendState == RpcFields::RpcSendState::RECEIVED) { Loading Loading @@ -731,15 +768,14 @@ status_t Parcel::appendFrom(const Parcel* parcel, size_t offset, size_t len) { newDataPos); mDataPos = newDataPos; int32_t objectType; if (status_t status = readInt32(&objectType); status != OK) { int32_t objectType = 0; if (status_t status = readRpcObjectType(&objectType); status != OK) { return status; } if (objectType == RpcFields::TYPE_BINDER) { uint64_t addr; if (status_t status = readUint64(&addr); status != OK) return status; uint64_t addr = 0; if (status_t status = readRpcBinderAddress(&addr); status != OK) return status; sp<IBinder> binder = rpcFields->mSession->state()->lookupAddress(addr); if (binder == nullptr) { ALOGE("Invalid state could not find address: %" PRIu64 Loading Loading @@ -778,10 +814,10 @@ status_t Parcel::appendFrom(const Parcel* parcel, size_t offset, size_t len) { } // Read FD, duplicate, and add to list. int32_t fdIndex; if (status_t status = readInt32(&fdIndex); status != OK) { return status; } size_t indexDataPos = mDataPos; int32_t fdIndex = -1; if (status_t status = readRpcFdIndex(&fdIndex); status != OK) return status; int oldFd = toRawFd(otherRpcFields->mImpl->mFds.at(fdIndex)); // To match kernel binder behavior, we always dup, even if the // FD was unowned in the source parcel. Loading @@ -791,11 +827,13 @@ status_t Parcel::appendFrom(const Parcel* parcel, size_t offset, size_t len) { statusToString(status).c_str()); } rpcFields->mImpl->mFds.emplace_back(unique_fd(newFd)); // Fixup the index in the data. mDataPos = newDataPos + 4; if (status_t status = writeInt32(rpcFields->mImpl->mFds.size() - 1); status != OK) { return status; if (otherRpcFields->mImpl->mFds.size() > std::numeric_limits<int32_t>::max()) { ALOGE("Too many FDs in Parcel to be able to write an index"); return INVALID_OPERATION; } // Fixup the index in the data. *reinterpret_cast<int32_t*>(mData + indexDataPos) = static_cast<int32_t>(otherRpcFields->mImpl->mFds.size()) - 1; } } } Loading Loading @@ -1986,8 +2024,39 @@ status_t Parcel::validateReadData(size_t upperBound) const { const auto* kernelFields = maybeKernelFields(); if (kernelFields == nullptr) { // Can't validate RPC Parcel reads because the location of binder // objects is unknown. auto* rpcFields = maybeRpcFields(); LOG_ALWAYS_FATAL_IF(rpcFields == nullptr); if (rpcFields->mObjectPositions.empty()) return OK; const size_t savedDataPos = mDataPos; auto scopeGuard = make_scope_guard([&]() { mDataPos = savedDataPos; }); // lower bound of objects that could overlap with or start at/after mDataPos size_t low = mDataPos < getRpcObjectSize(RpcFields::ObjectType::TYPE_BINDER) ? 0 : mDataPos - getRpcObjectSize(RpcFields::ObjectType::TYPE_BINDER) + 1; auto start = std::lower_bound(rpcFields->mObjectPositions.begin(), rpcFields->mObjectPositions.end(), low); if (start == rpcFields->mObjectPositions.end()) return OK; auto end = std::upper_bound(start, rpcFields->mObjectPositions.end(), upperBound - 1); for (auto it = start; it != end; it++) { uint32_t pos = *it; mDataPos = pos; int32_t objectType = 0; if (status_t status = readRpcObjectType(&objectType); status != OK) return status; size_t objSize = getRpcObjectSize(objectType); if ((pos <= savedDataPos && savedDataPos < pos + objSize) || (savedDataPos < pos && upperBound > pos)) { if (!mServiceFuzzing) { ALOGE("Validate read data failed! This would be reading the raw values of an " "object in the parcel (at position %u) that is marked for RPC. objSize: " "%zu, " "savedDataPos: %zu, upperBound: %zu", pos, objSize, savedDataPos, upperBound); } return PERMISSION_DENIED; } } return OK; } Loading Loading @@ -2065,8 +2134,7 @@ status_t Parcel::read(void* outData, size_t len) const if ((mDataPos+pad_size(len)) >= mDataPos && (mDataPos+pad_size(len)) <= mDataSize && len <= pad_size(len)) { const auto* kernelFields = maybeKernelFields(); if (kernelFields != nullptr && kernelFields->mObjectsSize > 0) { if (objectsCount() > 0) { status_t err = validateReadData(mDataPos + pad_size(len)); if(err != NO_ERROR) { // Still increment the data position by the expected length Loading @@ -2093,8 +2161,7 @@ const void* Parcel::readInplace(size_t len) const if ((mDataPos+pad_size(len)) >= mDataPos && (mDataPos+pad_size(len)) <= mDataSize && len <= pad_size(len)) { const auto* kernelFields = maybeKernelFields(); if (kernelFields != nullptr && kernelFields->mObjectsSize > 0) { if (objectsCount() > 0) { status_t err = validateReadData(mDataPos + pad_size(len)); if(err != NO_ERROR) { // Still increment the data position by the expected length Loading Loading @@ -2146,8 +2213,7 @@ status_t Parcel::readAligned(T *pArg) const { static_assert(std::is_trivially_copyable_v<T>); if ((mDataPos+sizeof(T)) <= mDataSize) { const auto* kernelFields = maybeKernelFields(); if (kernelFields != nullptr && kernelFields->mObjectsSize > 0) { if (objectsCount() > 0) { status_t err = validateReadData(mDataPos + sizeof(T)); if(err != NO_ERROR) { // Still increment the data position by the expected length Loading Loading @@ -2551,12 +2617,14 @@ int Parcel::readFileDescriptor() const { return BAD_TYPE; } int32_t objectType = readInt32(); int32_t objectType = 0; if (status_t status = readRpcObjectType(&objectType); status != OK) return status; if (objectType != RpcFields::TYPE_NATIVE_FILE_DESCRIPTOR) { return BAD_TYPE; } int32_t fdIndex = -1; if (status_t status = readRpcFdIndex(&fdIndex); status != OK) return status; int32_t fdIndex = readInt32(); if (rpcFields->mImpl == nullptr || fdIndex < 0 || static_cast<size_t>(fdIndex) >= rpcFields->mImpl->mFds.size()) { ALOGE("RPC Parcel contains invalid file descriptor index. index=%d fd_count=%zu", Loading Loading @@ -3059,12 +3127,11 @@ status_t Parcel::rpcSetDataReference( // acquire and validate all objects bool bindersInObjectPositions = session->getProtocolVersion() >= RPC_WIRE_PROTOCOL_VERSION_RPC_HEADER_INCLUDES_BINDER_POSITIONS; size_t numFds = 0; for (uint32_t pos : rpcFields->mObjectPositions) { mDataPos = pos; int32_t objectType; if (status_t status = readInt32(&objectType); status != OK) { if (status_t status = readRpcObjectType(&objectType); status != OK) { ALOGE("Failed to read object type: %s, pos: %" PRIu32 ". Terminating.", statusToString(status).c_str(), pos); (void)session->shutdownAndWait(false); Loading Loading @@ -3356,27 +3423,16 @@ status_t Parcel::continueWrite(size_t desired) } #endif // BINDER_WITH_KERNEL_IPC } else { const size_t savedDataPos = mDataPos; auto scopeGuard = make_scope_guard([&]() { mDataPos = savedDataPos; }); while (objectsSize > 0) { // Object size varies by type. uint32_t pos = rpcFields->mObjectPositions[objectsSize - 1]; size_t size = sizeof(RpcFields::ObjectType); uint32_t minObjectEnd; if (__builtin_add_overflow(pos, sizeof(RpcFields::ObjectType), &minObjectEnd) || minObjectEnd > mDataSize) { return BAD_VALUE; } const auto type = *reinterpret_cast<const RpcFields::ObjectType*>(mData + pos); switch (type) { case RpcFields::TYPE_BINDER_NULL: break; case RpcFields::TYPE_BINDER: size += sizeof(uint64_t); // address break; case RpcFields::TYPE_NATIVE_FILE_DESCRIPTOR: size += sizeof(int32_t); // fd index break; } mDataPos = pos; int32_t objectType = 0; if (status_t status = readRpcObjectType(&objectType); status != OK) return status; size_t size = getRpcObjectSize(objectType); if (pos + size <= desired) break; objectsSize--; } Loading Loading @@ -3564,12 +3620,13 @@ status_t Parcel::truncateRpcObjects(size_t newObjectsSize) { // this is only called during shutdown, position will be cleared mDataPos = rpcFields->mObjectPositions[i]; int32_t objectType; LOG_ALWAYS_FATAL_IF(OK != readInt32(&objectType), int32_t objectType = 0; LOG_ALWAYS_FATAL_IF(readRpcObjectType(&objectType) != OK, "Inconsistent acquisition state."); if (objectType != RpcFields::TYPE_BINDER) continue; uint64_t addr; LOG_ALWAYS_FATAL_IF(OK != readUint64(&addr), "Inconsistent acquisition state."); uint64_t addr = 0; LOG_ALWAYS_FATAL_IF(readRpcBinderAddress(&addr) != OK, "Inconsistent acquisition state."); if (status_t status = rpcFields->mSession->state()->cancelBinderLeaving(rpcFields->mSession, addr); Loading @@ -3595,21 +3652,17 @@ status_t Parcel::truncateRpcObjects(size_t newObjectsSize) { } return OK; } const size_t savedDataPos = mDataPos; auto scopeGuard = make_scope_guard([&]() { mDataPos = savedDataPos; }); while (rpcFields->mObjectPositions.size() > newObjectsSize) { uint32_t pos = rpcFields->mObjectPositions.back(); uint32_t minObjectEnd; if (__builtin_add_overflow(pos, sizeof(RpcFields::ObjectType), &minObjectEnd) || minObjectEnd > mDataSize) { return BAD_VALUE; } const auto type = *reinterpret_cast<const RpcFields::ObjectType*>(mData + pos); if (type == RpcFields::TYPE_NATIVE_FILE_DESCRIPTOR) { uint32_t objectEnd; if (__builtin_add_overflow(minObjectEnd, sizeof(int32_t), &objectEnd) || objectEnd > mDataSize) { return BAD_VALUE; } const auto fdIndex = *reinterpret_cast<const int32_t*>(mData + minObjectEnd); mDataPos = pos; int32_t objectType = 0; if (status_t status = readRpcObjectType(&objectType); status != OK) return status; if (objectType == RpcFields::TYPE_NATIVE_FILE_DESCRIPTOR) { int32_t fdIndex = -1; if (status_t status = readRpcFdIndex(&fdIndex); status != OK) return status; if (rpcFields->mImpl == nullptr || fdIndex < 0 || static_cast<size_t>(fdIndex) >= rpcFields->mImpl->mFds.size()) { ALOGE("RPC Parcel contains invalid file descriptor index. index=%d fd_count=%zu", Loading libs/binder/RpcState.cpp +6 −2 Original line number Diff line number Diff line Loading @@ -1409,6 +1409,7 @@ status_t RpcState::doDecStrong(const sp<RpcSession>& session, uint64_t addr, uin auto it = mNodeForAddress.find(addr); if (it == mNodeForAddress.end()) { ALOGE("Unknown binder address %" PRIu64 " for dec strong. Terminating!", addr); _l.unlock(); (void)session->shutdownAndWait(false); return BAD_VALUE; } Loading @@ -1424,9 +1425,12 @@ status_t RpcState::doDecStrong(const sp<RpcSession>& session, uint64_t addr, uin } if (it->second.timesSent < amount) { ALOGE("Record of sending binder %zu times, but requested decStrong for %" PRIu64 " of %u", ALOGE("Record of sending binder %zu times, but requested decStrong for %" PRIu64 " of %u. Terminating!", it->second.timesSent, addr, amount); return OK; _l.unlock(); (void)session->shutdownAndWait(false); return BAD_VALUE; } LOG_ALWAYS_FATAL_IF(it->second.sentRef == nullptr, "Inconsistent state, lost ref for %" PRIu64, Loading libs/binder/include/binder/Parcel.h +10 −0 Original line number Diff line number Diff line Loading @@ -708,6 +708,16 @@ private: status_t finishUnflattenBinder(const sp<IBinder>& binder, sp<IBinder>* out) const; status_t flattenBinder(const sp<IBinder>& binder); status_t unflattenBinder(sp<IBinder>* out) const; [[nodiscard]] status_t readRpcObjectType(int32_t* objectType) const; [[nodiscard]] static constexpr size_t getRpcObjectSize(int32_t objectType); [[nodiscard]] status_t readRpcBinderAddress(uint64_t* addr) const; [[nodiscard]] status_t readRpcFdIndex(int32_t* addr) const; // This is similar to readAligned without a call to validateReadData. // validateReadData would cause the read to fail because we are reading // over objects - but it's intentional in this case! // Used only for the readRpc* methods directly above. template <class T> [[nodiscard]] status_t readPartialRpcObject(T* val) const; LIBBINDER_EXPORTED status_t readOutVectorSizeWithCheck(size_t elmSize, int32_t* size) const; Loading Loading
PREUPLOAD.cfg +1 −0 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ rustfmt = true bpfmt = true clang_format = true alint = false [Builtin Hooks Options] rustfmt = --config-path=rustfmt.toml Loading
include/input/InputFlags.h +0 −9 Original line number Diff line number Diff line Loading @@ -53,15 +53,6 @@ public: * connectedDisplaysCursorEnabled flag. */ static bool scaleCursorSpeedWithDisplayDensity(); /** * This is a temporary fix that removes the SKIP_SCREENSHOT flag for the Mouse cursor. This is * only intended to be temporarily used as workaround only when connected displays dev option * is enabled. * * This will make mouse cursor visible on recordings and screenshots of secure windows. */ static bool doNotUseSkipScreenshotFlagForMouseCursor(); }; } // namespace android
libs/binder/Parcel.cpp +117 −64 Original line number Diff line number Diff line Loading @@ -348,14 +348,51 @@ status_t Parcel::flattenBinder(const sp<IBinder>& binder) { #endif // BINDER_WITH_KERNEL_IPC } template <class T> status_t Parcel::readPartialRpcObject(T* val) const { static_assert(sizeof(T) == sizeof(int32_t) || sizeof(T) == sizeof(uint64_t)); size_t end; if (__builtin_add_overflow(mDataPos, sizeof(T), &end) || end > mDataSize) { return NOT_ENOUGH_DATA; } memcpy(val, mData + mDataPos, sizeof(T)); mDataPos += sizeof(T); return OK; } status_t Parcel::readRpcObjectType(int32_t* objectType) const { return readPartialRpcObject(objectType); } status_t Parcel::readRpcBinderAddress(uint64_t* addr) const { return readPartialRpcObject(addr); } status_t Parcel::readRpcFdIndex(int32_t* fdIndex) const { return readPartialRpcObject(fdIndex); } constexpr size_t Parcel::getRpcObjectSize(int32_t objectType) { switch (objectType) { case RpcFields::TYPE_BINDER: return sizeof(RpcFields::ObjectType) + sizeof(uint64_t); break; case RpcFields::TYPE_NATIVE_FILE_DESCRIPTOR: return sizeof(RpcFields::ObjectType) + sizeof(int32_t); break; default: LOG_ALWAYS_FATAL("Unknown RpcFields type: %" PRId32, objectType); } } status_t Parcel::unflattenBinder(sp<IBinder>* out) const { if (const auto* rpcFields = maybeRpcFields()) { const size_t objectPos = mDataPos; // see TYPE_BINDER/TYPE_BINDER_NULL int32_t isPresent; if (status_t status = readInt32(&isPresent); status != OK) return status; int32_t isPresent = 0; if (status_t status = readRpcObjectType(&isPresent); status != OK) return status; sp<IBinder> binder; Loading @@ -377,8 +414,8 @@ status_t Parcel::unflattenBinder(sp<IBinder>* out) const LOG_ALWAYS_FATAL_IF(binder == nullptr); } uint64_t addr; if (status_t status = readUint64(&addr); status != OK) return status; uint64_t addr = 0; if (status_t status = readRpcBinderAddress(&addr); status != OK) return status; if (binder == nullptr) { if (rpcFields->mSendState == RpcFields::RpcSendState::RECEIVED) { Loading Loading @@ -731,15 +768,14 @@ status_t Parcel::appendFrom(const Parcel* parcel, size_t offset, size_t len) { newDataPos); mDataPos = newDataPos; int32_t objectType; if (status_t status = readInt32(&objectType); status != OK) { int32_t objectType = 0; if (status_t status = readRpcObjectType(&objectType); status != OK) { return status; } if (objectType == RpcFields::TYPE_BINDER) { uint64_t addr; if (status_t status = readUint64(&addr); status != OK) return status; uint64_t addr = 0; if (status_t status = readRpcBinderAddress(&addr); status != OK) return status; sp<IBinder> binder = rpcFields->mSession->state()->lookupAddress(addr); if (binder == nullptr) { ALOGE("Invalid state could not find address: %" PRIu64 Loading Loading @@ -778,10 +814,10 @@ status_t Parcel::appendFrom(const Parcel* parcel, size_t offset, size_t len) { } // Read FD, duplicate, and add to list. int32_t fdIndex; if (status_t status = readInt32(&fdIndex); status != OK) { return status; } size_t indexDataPos = mDataPos; int32_t fdIndex = -1; if (status_t status = readRpcFdIndex(&fdIndex); status != OK) return status; int oldFd = toRawFd(otherRpcFields->mImpl->mFds.at(fdIndex)); // To match kernel binder behavior, we always dup, even if the // FD was unowned in the source parcel. Loading @@ -791,11 +827,13 @@ status_t Parcel::appendFrom(const Parcel* parcel, size_t offset, size_t len) { statusToString(status).c_str()); } rpcFields->mImpl->mFds.emplace_back(unique_fd(newFd)); // Fixup the index in the data. mDataPos = newDataPos + 4; if (status_t status = writeInt32(rpcFields->mImpl->mFds.size() - 1); status != OK) { return status; if (otherRpcFields->mImpl->mFds.size() > std::numeric_limits<int32_t>::max()) { ALOGE("Too many FDs in Parcel to be able to write an index"); return INVALID_OPERATION; } // Fixup the index in the data. *reinterpret_cast<int32_t*>(mData + indexDataPos) = static_cast<int32_t>(otherRpcFields->mImpl->mFds.size()) - 1; } } } Loading Loading @@ -1986,8 +2024,39 @@ status_t Parcel::validateReadData(size_t upperBound) const { const auto* kernelFields = maybeKernelFields(); if (kernelFields == nullptr) { // Can't validate RPC Parcel reads because the location of binder // objects is unknown. auto* rpcFields = maybeRpcFields(); LOG_ALWAYS_FATAL_IF(rpcFields == nullptr); if (rpcFields->mObjectPositions.empty()) return OK; const size_t savedDataPos = mDataPos; auto scopeGuard = make_scope_guard([&]() { mDataPos = savedDataPos; }); // lower bound of objects that could overlap with or start at/after mDataPos size_t low = mDataPos < getRpcObjectSize(RpcFields::ObjectType::TYPE_BINDER) ? 0 : mDataPos - getRpcObjectSize(RpcFields::ObjectType::TYPE_BINDER) + 1; auto start = std::lower_bound(rpcFields->mObjectPositions.begin(), rpcFields->mObjectPositions.end(), low); if (start == rpcFields->mObjectPositions.end()) return OK; auto end = std::upper_bound(start, rpcFields->mObjectPositions.end(), upperBound - 1); for (auto it = start; it != end; it++) { uint32_t pos = *it; mDataPos = pos; int32_t objectType = 0; if (status_t status = readRpcObjectType(&objectType); status != OK) return status; size_t objSize = getRpcObjectSize(objectType); if ((pos <= savedDataPos && savedDataPos < pos + objSize) || (savedDataPos < pos && upperBound > pos)) { if (!mServiceFuzzing) { ALOGE("Validate read data failed! This would be reading the raw values of an " "object in the parcel (at position %u) that is marked for RPC. objSize: " "%zu, " "savedDataPos: %zu, upperBound: %zu", pos, objSize, savedDataPos, upperBound); } return PERMISSION_DENIED; } } return OK; } Loading Loading @@ -2065,8 +2134,7 @@ status_t Parcel::read(void* outData, size_t len) const if ((mDataPos+pad_size(len)) >= mDataPos && (mDataPos+pad_size(len)) <= mDataSize && len <= pad_size(len)) { const auto* kernelFields = maybeKernelFields(); if (kernelFields != nullptr && kernelFields->mObjectsSize > 0) { if (objectsCount() > 0) { status_t err = validateReadData(mDataPos + pad_size(len)); if(err != NO_ERROR) { // Still increment the data position by the expected length Loading @@ -2093,8 +2161,7 @@ const void* Parcel::readInplace(size_t len) const if ((mDataPos+pad_size(len)) >= mDataPos && (mDataPos+pad_size(len)) <= mDataSize && len <= pad_size(len)) { const auto* kernelFields = maybeKernelFields(); if (kernelFields != nullptr && kernelFields->mObjectsSize > 0) { if (objectsCount() > 0) { status_t err = validateReadData(mDataPos + pad_size(len)); if(err != NO_ERROR) { // Still increment the data position by the expected length Loading Loading @@ -2146,8 +2213,7 @@ status_t Parcel::readAligned(T *pArg) const { static_assert(std::is_trivially_copyable_v<T>); if ((mDataPos+sizeof(T)) <= mDataSize) { const auto* kernelFields = maybeKernelFields(); if (kernelFields != nullptr && kernelFields->mObjectsSize > 0) { if (objectsCount() > 0) { status_t err = validateReadData(mDataPos + sizeof(T)); if(err != NO_ERROR) { // Still increment the data position by the expected length Loading Loading @@ -2551,12 +2617,14 @@ int Parcel::readFileDescriptor() const { return BAD_TYPE; } int32_t objectType = readInt32(); int32_t objectType = 0; if (status_t status = readRpcObjectType(&objectType); status != OK) return status; if (objectType != RpcFields::TYPE_NATIVE_FILE_DESCRIPTOR) { return BAD_TYPE; } int32_t fdIndex = -1; if (status_t status = readRpcFdIndex(&fdIndex); status != OK) return status; int32_t fdIndex = readInt32(); if (rpcFields->mImpl == nullptr || fdIndex < 0 || static_cast<size_t>(fdIndex) >= rpcFields->mImpl->mFds.size()) { ALOGE("RPC Parcel contains invalid file descriptor index. index=%d fd_count=%zu", Loading Loading @@ -3059,12 +3127,11 @@ status_t Parcel::rpcSetDataReference( // acquire and validate all objects bool bindersInObjectPositions = session->getProtocolVersion() >= RPC_WIRE_PROTOCOL_VERSION_RPC_HEADER_INCLUDES_BINDER_POSITIONS; size_t numFds = 0; for (uint32_t pos : rpcFields->mObjectPositions) { mDataPos = pos; int32_t objectType; if (status_t status = readInt32(&objectType); status != OK) { if (status_t status = readRpcObjectType(&objectType); status != OK) { ALOGE("Failed to read object type: %s, pos: %" PRIu32 ". Terminating.", statusToString(status).c_str(), pos); (void)session->shutdownAndWait(false); Loading Loading @@ -3356,27 +3423,16 @@ status_t Parcel::continueWrite(size_t desired) } #endif // BINDER_WITH_KERNEL_IPC } else { const size_t savedDataPos = mDataPos; auto scopeGuard = make_scope_guard([&]() { mDataPos = savedDataPos; }); while (objectsSize > 0) { // Object size varies by type. uint32_t pos = rpcFields->mObjectPositions[objectsSize - 1]; size_t size = sizeof(RpcFields::ObjectType); uint32_t minObjectEnd; if (__builtin_add_overflow(pos, sizeof(RpcFields::ObjectType), &minObjectEnd) || minObjectEnd > mDataSize) { return BAD_VALUE; } const auto type = *reinterpret_cast<const RpcFields::ObjectType*>(mData + pos); switch (type) { case RpcFields::TYPE_BINDER_NULL: break; case RpcFields::TYPE_BINDER: size += sizeof(uint64_t); // address break; case RpcFields::TYPE_NATIVE_FILE_DESCRIPTOR: size += sizeof(int32_t); // fd index break; } mDataPos = pos; int32_t objectType = 0; if (status_t status = readRpcObjectType(&objectType); status != OK) return status; size_t size = getRpcObjectSize(objectType); if (pos + size <= desired) break; objectsSize--; } Loading Loading @@ -3564,12 +3620,13 @@ status_t Parcel::truncateRpcObjects(size_t newObjectsSize) { // this is only called during shutdown, position will be cleared mDataPos = rpcFields->mObjectPositions[i]; int32_t objectType; LOG_ALWAYS_FATAL_IF(OK != readInt32(&objectType), int32_t objectType = 0; LOG_ALWAYS_FATAL_IF(readRpcObjectType(&objectType) != OK, "Inconsistent acquisition state."); if (objectType != RpcFields::TYPE_BINDER) continue; uint64_t addr; LOG_ALWAYS_FATAL_IF(OK != readUint64(&addr), "Inconsistent acquisition state."); uint64_t addr = 0; LOG_ALWAYS_FATAL_IF(readRpcBinderAddress(&addr) != OK, "Inconsistent acquisition state."); if (status_t status = rpcFields->mSession->state()->cancelBinderLeaving(rpcFields->mSession, addr); Loading @@ -3595,21 +3652,17 @@ status_t Parcel::truncateRpcObjects(size_t newObjectsSize) { } return OK; } const size_t savedDataPos = mDataPos; auto scopeGuard = make_scope_guard([&]() { mDataPos = savedDataPos; }); while (rpcFields->mObjectPositions.size() > newObjectsSize) { uint32_t pos = rpcFields->mObjectPositions.back(); uint32_t minObjectEnd; if (__builtin_add_overflow(pos, sizeof(RpcFields::ObjectType), &minObjectEnd) || minObjectEnd > mDataSize) { return BAD_VALUE; } const auto type = *reinterpret_cast<const RpcFields::ObjectType*>(mData + pos); if (type == RpcFields::TYPE_NATIVE_FILE_DESCRIPTOR) { uint32_t objectEnd; if (__builtin_add_overflow(minObjectEnd, sizeof(int32_t), &objectEnd) || objectEnd > mDataSize) { return BAD_VALUE; } const auto fdIndex = *reinterpret_cast<const int32_t*>(mData + minObjectEnd); mDataPos = pos; int32_t objectType = 0; if (status_t status = readRpcObjectType(&objectType); status != OK) return status; if (objectType == RpcFields::TYPE_NATIVE_FILE_DESCRIPTOR) { int32_t fdIndex = -1; if (status_t status = readRpcFdIndex(&fdIndex); status != OK) return status; if (rpcFields->mImpl == nullptr || fdIndex < 0 || static_cast<size_t>(fdIndex) >= rpcFields->mImpl->mFds.size()) { ALOGE("RPC Parcel contains invalid file descriptor index. index=%d fd_count=%zu", Loading
libs/binder/RpcState.cpp +6 −2 Original line number Diff line number Diff line Loading @@ -1409,6 +1409,7 @@ status_t RpcState::doDecStrong(const sp<RpcSession>& session, uint64_t addr, uin auto it = mNodeForAddress.find(addr); if (it == mNodeForAddress.end()) { ALOGE("Unknown binder address %" PRIu64 " for dec strong. Terminating!", addr); _l.unlock(); (void)session->shutdownAndWait(false); return BAD_VALUE; } Loading @@ -1424,9 +1425,12 @@ status_t RpcState::doDecStrong(const sp<RpcSession>& session, uint64_t addr, uin } if (it->second.timesSent < amount) { ALOGE("Record of sending binder %zu times, but requested decStrong for %" PRIu64 " of %u", ALOGE("Record of sending binder %zu times, but requested decStrong for %" PRIu64 " of %u. Terminating!", it->second.timesSent, addr, amount); return OK; _l.unlock(); (void)session->shutdownAndWait(false); return BAD_VALUE; } LOG_ALWAYS_FATAL_IF(it->second.sentRef == nullptr, "Inconsistent state, lost ref for %" PRIu64, Loading
libs/binder/include/binder/Parcel.h +10 −0 Original line number Diff line number Diff line Loading @@ -708,6 +708,16 @@ private: status_t finishUnflattenBinder(const sp<IBinder>& binder, sp<IBinder>* out) const; status_t flattenBinder(const sp<IBinder>& binder); status_t unflattenBinder(sp<IBinder>* out) const; [[nodiscard]] status_t readRpcObjectType(int32_t* objectType) const; [[nodiscard]] static constexpr size_t getRpcObjectSize(int32_t objectType); [[nodiscard]] status_t readRpcBinderAddress(uint64_t* addr) const; [[nodiscard]] status_t readRpcFdIndex(int32_t* addr) const; // This is similar to readAligned without a call to validateReadData. // validateReadData would cause the read to fail because we are reading // over objects - but it's intentional in this case! // Used only for the readRpc* methods directly above. template <class T> [[nodiscard]] status_t readPartialRpcObject(T* val) const; LIBBINDER_EXPORTED status_t readOutVectorSizeWithCheck(size_t elmSize, int32_t* size) const; Loading