From d2397007a164e00a34fdc240bf3d12f01b9d9bff Mon Sep 17 00:00:00 2001 From: Owen Anderson Date: Wed, 25 Sep 2024 08:32:24 +0000 Subject: [PATCH] arm64: Fix a range overrun in ProcessRange * Make the recursion logic in much more explicit * Resolves a rare assertion failure in Protect() Change-Id: I9d93293836251e158ea226792852a63f6d91f3ab Reviewed-on: https://review.haiku-os.org/c/haiku/+/8366 Tested-by: Commit checker robot Reviewed-by: waddlesplash --- .../arch/arm64/VMSAv8TranslationMap.cpp | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/system/kernel/arch/arm64/VMSAv8TranslationMap.cpp b/src/system/kernel/arch/arm64/VMSAv8TranslationMap.cpp index 61f89e7d09..f9d04c3224 100644 --- a/src/system/kernel/arch/arm64/VMSAv8TranslationMap.cpp +++ b/src/system/kernel/arch/arm64/VMSAv8TranslationMap.cpp @@ -435,12 +435,11 @@ VMSAv8TranslationMap::ProcessRange(phys_addr_t ptPa, int level, addr_t va, size_ uint64_t entryMask = entrySize - 1; uint64_t alignedDownVa = va & ~entryMask; - uint64_t alignedUpEnd = (va + size + (entrySize - 1)) & ~entryMask; + uint64_t end = va + size - 1; if (level == 3) ASSERT(alignedDownVa == va); - for (uint64_t effectiveVa = alignedDownVa; effectiveVa < alignedUpEnd; - effectiveVa += entrySize) { + for (uint64_t effectiveVa = alignedDownVa; effectiveVa < end; effectiveVa += entrySize) { int index = ((effectiveVa & vaMask) >> shift) & tableMask; uint64_t* ptePtr = TableFromPa(ptPa) + index; @@ -454,11 +453,26 @@ VMSAv8TranslationMap::ProcessRange(phys_addr_t ptPa, int level, addr_t va, size_ if (subTable == 0) continue; - uint64_t subVa = std::max(effectiveVa, va); - size_t subSize = std::min(size_t(entrySize - (subVa & entryMask)), size); - ProcessRange(subTable, level + 1, subVa, subSize, reservation, updatePte); - - size -= subSize; + if (effectiveVa < va) { + // The range begins inside the slot. + if (effectiveVa + entrySize - 1 > end) { + // The range ends within the slot. + ProcessRange(subTable, level + 1, va, size, reservation, updatePte); + } else { + // The range extends past the end of the slot. + ProcessRange(subTable, level + 1, va, effectiveVa + entrySize - va, reservation, updatePte); + } + } else { + // The range beginning is aligned to the slot. + if (effectiveVa + entrySize - 1 > end) { + // The range ends within the slot. + ProcessRange(subTable, level + 1, effectiveVa, end - effectiveVa + 1, + reservation, updatePte); + } else { + // The range extends past the end of the slot. + ProcessRange(subTable, level + 1, effectiveVa, entrySize, reservation, updatePte); + } + } } } }