summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Collingbourne <peter@pcc.me.uk>2021-05-13 04:32:32 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2021-05-13 04:32:32 +0000
commit2f8cba43f784797d5446ef795d5d3e18806b59ce (patch)
treebff7475e69a9de7c3af688dfc7ad83e884ded09e
parent27d8bc33965f6bf2de534319deab67dc07671501 (diff)
parente00e922984eac3c5bab3dd70054a27b1bdc7afd2 (diff)
downloadscudo-2f8cba43f784797d5446ef795d5d3e18806b59ce.tar.gz
scudo: Require fault address to be in bounds for UAF. am: 185fd5671e am: 6158d89413 am: e00e922984
Original change: https://android-review.googlesource.com/c/platform/external/scudo/+/1705267 Change-Id: Ib37b3eaaaa5f297138d2cc107fd5f798dbccacd1
-rw-r--r--standalone/combined.h31
1 files changed, 22 insertions, 9 deletions
diff --git a/standalone/combined.h b/standalone/combined.h
index 529c042633f..70aeaa8ab7a 100644
--- a/standalone/combined.h
+++ b/standalone/combined.h
@@ -1333,22 +1333,35 @@ private:
--I) {
auto *Entry = &RingBuffer->Entries[I % AllocationRingBuffer::NumEntries];
uptr EntryPtr = atomic_load_relaxed(&Entry->Ptr);
- uptr UntaggedEntryPtr = untagPointer(EntryPtr);
- uptr EntrySize = atomic_load_relaxed(&Entry->AllocationSize);
- if (!EntryPtr || FaultAddr < EntryPtr - getPageSizeCached() ||
- FaultAddr >= EntryPtr + EntrySize + getPageSizeCached())
+ if (!EntryPtr)
continue;
+ uptr UntaggedEntryPtr = untagPointer(EntryPtr);
+ uptr EntrySize = atomic_load_relaxed(&Entry->AllocationSize);
u32 AllocationTrace = atomic_load_relaxed(&Entry->AllocationTrace);
u32 AllocationTid = atomic_load_relaxed(&Entry->AllocationTid);
u32 DeallocationTrace = atomic_load_relaxed(&Entry->DeallocationTrace);
u32 DeallocationTid = atomic_load_relaxed(&Entry->DeallocationTid);
- // For UAF the ring buffer will contain two entries, one for the
- // allocation and another for the deallocation. Don't report buffer
- // overflow/underflow using the allocation entry if we have already
- // collected a report from the deallocation entry.
- if (!DeallocationTrace) {
+ if (DeallocationTid) {
+ // For UAF we only consider in-bounds fault addresses because
+ // out-of-bounds UAF is rare and attempting to detect it is very likely
+ // to result in false positives.
+ if (FaultAddr < EntryPtr || FaultAddr >= EntryPtr + EntrySize)
+ continue;
+ } else {
+ // Ring buffer OOB is only possible with secondary allocations. In this
+ // case we are guaranteed a guard region of at least a page on either
+ // side of the allocation (guard page on the right, guard page + tagged
+ // region on the left), so ignore any faults outside of that range.
+ if (FaultAddr < EntryPtr - getPageSizeCached() ||
+ FaultAddr >= EntryPtr + EntrySize + getPageSizeCached())
+ continue;
+
+ // For UAF the ring buffer will contain two entries, one for the
+ // allocation and another for the deallocation. Don't report buffer
+ // overflow/underflow using the allocation entry if we have already
+ // collected a report from the deallocation entry.
bool Found = false;
for (uptr J = 0; J != NextErrorReport; ++J) {
if (ErrorInfo->reports[J].allocation_address == UntaggedEntryPtr) {