diff options
author | Peter Collingbourne <peter@pcc.me.uk> | 2021-05-13 04:32:32 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2021-05-13 04:32:32 +0000 |
commit | 2f8cba43f784797d5446ef795d5d3e18806b59ce (patch) | |
tree | bff7475e69a9de7c3af688dfc7ad83e884ded09e | |
parent | 27d8bc33965f6bf2de534319deab67dc07671501 (diff) | |
parent | e00e922984eac3c5bab3dd70054a27b1bdc7afd2 (diff) | |
download | scudo-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.h | 31 |
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) { |