Skip to content

Commit a5bdc4a

Browse files
authored
[scudo] do not store size inside ring buffer (#74541)
1 parent 437b4f1 commit a5bdc4a

File tree

3 files changed

+35
-30
lines changed

3 files changed

+35
-30
lines changed

compiler-rt/lib/scudo/standalone/combined.h

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "flags.h"
1515
#include "flags_parser.h"
1616
#include "local_cache.h"
17+
#include "mem_map.h"
1718
#include "memtag.h"
1819
#include "options.h"
1920
#include "quarantine.h"
@@ -935,8 +936,7 @@ class Allocator {
935936

936937
uptr getRingBufferSize() {
937938
initThreadMaybe();
938-
auto *RingBuffer = getRingBuffer();
939-
return RingBuffer ? ringBufferSizeInBytes(RingBuffer->Size) : 0;
939+
return RingBufferElements ? ringBufferSizeInBytes(RingBufferElements) : 0;
940940
}
941941

942942
static bool setRingBufferSizeForBuffer(char *Buffer, size_t Size) {
@@ -966,8 +966,9 @@ class Allocator {
966966
static void getErrorInfo(struct scudo_error_info *ErrorInfo,
967967
uintptr_t FaultAddr, const char *DepotPtr,
968968
const char *RegionInfoPtr, const char *RingBufferPtr,
969-
const char *Memory, const char *MemoryTags,
970-
uintptr_t MemoryAddr, size_t MemorySize) {
969+
size_t RingBufferSize, const char *Memory,
970+
const char *MemoryTags, uintptr_t MemoryAddr,
971+
size_t MemorySize) {
971972
*ErrorInfo = {};
972973
if (!allocatorSupportsMemoryTagging<Config>() ||
973974
MemoryAddr + MemorySize < MemoryAddr)
@@ -986,7 +987,7 @@ class Allocator {
986987
// Check the ring buffer. For primary allocations this will only find UAF;
987988
// for secondary allocations we can find either UAF or OOB.
988989
getRingBufferErrorInfo(ErrorInfo, NextErrorReport, FaultAddr, Depot,
989-
RingBufferPtr);
990+
RingBufferPtr, RingBufferSize);
990991

991992
// Check for OOB in the 28 blocks surrounding the 3 we checked earlier.
992993
// Beyond that we are likely to hit false positives.
@@ -1051,15 +1052,15 @@ class Allocator {
10511052
atomic_u32 DeallocationTid;
10521053
};
10531054

1054-
MemMapT MemMap;
10551055
atomic_uptr Pos;
1056-
u32 Size;
10571056
// An array of Size (at least one) elements of type Entry is immediately
10581057
// following to this struct.
10591058
};
10601059
// Pointer to memory mapped area starting with AllocationRingBuffer struct,
10611060
// and immediately followed by Size elements of type Entry.
10621061
char *RawRingBuffer = {};
1062+
u32 RingBufferElements = 0;
1063+
MemMapT RawRingBufferMap;
10631064

10641065
// The following might get optimized out by the compiler.
10651066
NOINLINE void performSanityChecks() {
@@ -1267,7 +1268,7 @@ class Allocator {
12671268
u32 DeallocationTid) {
12681269
uptr Pos = atomic_fetch_add(&getRingBuffer()->Pos, 1, memory_order_relaxed);
12691270
typename AllocationRingBuffer::Entry *Entry =
1270-
getRingBufferEntry(RawRingBuffer, Pos % getRingBuffer()->Size);
1271+
getRingBufferEntry(RawRingBuffer, Pos % RingBufferElements);
12711272

12721273
// First invalidate our entry so that we don't attempt to interpret a
12731274
// partially written state in getSecondaryErrorInfo(). The fences below
@@ -1408,17 +1409,19 @@ class Allocator {
14081409
size_t &NextErrorReport,
14091410
uintptr_t FaultAddr,
14101411
const StackDepot *Depot,
1411-
const char *RingBufferPtr) {
1412+
const char *RingBufferPtr,
1413+
size_t RingBufferSize) {
14121414
auto *RingBuffer =
14131415
reinterpret_cast<const AllocationRingBuffer *>(RingBufferPtr);
1414-
if (!RingBuffer || RingBuffer->Size == 0)
1416+
size_t RingBufferElements = ringBufferElementsFromBytes(RingBufferSize);
1417+
if (!RingBuffer || RingBufferElements == 0)
14151418
return;
14161419
uptr Pos = atomic_load_relaxed(&RingBuffer->Pos);
14171420

1418-
for (uptr I = Pos - 1;
1419-
I != Pos - 1 - RingBuffer->Size && NextErrorReport != NumErrorReports;
1421+
for (uptr I = Pos - 1; I != Pos - 1 - RingBufferElements &&
1422+
NextErrorReport != NumErrorReports;
14201423
--I) {
1421-
auto *Entry = getRingBufferEntry(RingBufferPtr, I % RingBuffer->Size);
1424+
auto *Entry = getRingBufferEntry(RingBufferPtr, I % RingBufferElements);
14221425
uptr EntryPtr = atomic_load_relaxed(&Entry->Ptr);
14231426
if (!EntryPtr)
14241427
continue;
@@ -1508,9 +1511,8 @@ class Allocator {
15081511
getPageSizeCached()),
15091512
"scudo:ring_buffer");
15101513
RawRingBuffer = reinterpret_cast<char *>(MemMap.getBase());
1511-
auto *RingBuffer = reinterpret_cast<AllocationRingBuffer *>(RawRingBuffer);
1512-
RingBuffer->MemMap = MemMap;
1513-
RingBuffer->Size = AllocationRingBufferSize;
1514+
RawRingBufferMap = MemMap;
1515+
RingBufferElements = AllocationRingBufferSize;
15141516
static_assert(sizeof(AllocationRingBuffer) %
15151517
alignof(typename AllocationRingBuffer::Entry) ==
15161518
0,
@@ -1520,16 +1522,23 @@ class Allocator {
15201522
void unmapRingBuffer() {
15211523
auto *RingBuffer = getRingBuffer();
15221524
if (RingBuffer != nullptr) {
1523-
MemMapT MemMap = RingBuffer->MemMap;
1524-
MemMap.unmap(MemMap.getBase(), MemMap.getCapacity());
1525+
RawRingBufferMap.unmap(RawRingBufferMap.getBase(),
1526+
RawRingBufferMap.getCapacity());
15251527
}
15261528
RawRingBuffer = nullptr;
15271529
}
15281530

1529-
static constexpr size_t ringBufferSizeInBytes(u32 AllocationRingBufferSize) {
1531+
static constexpr size_t ringBufferSizeInBytes(u32 RingBufferElements) {
15301532
return sizeof(AllocationRingBuffer) +
1531-
AllocationRingBufferSize *
1532-
sizeof(typename AllocationRingBuffer::Entry);
1533+
RingBufferElements * sizeof(typename AllocationRingBuffer::Entry);
1534+
}
1535+
1536+
static constexpr size_t ringBufferElementsFromBytes(size_t Bytes) {
1537+
if (Bytes < sizeof(AllocationRingBuffer)) {
1538+
return 0;
1539+
}
1540+
return (Bytes - sizeof(AllocationRingBuffer)) /
1541+
sizeof(typename AllocationRingBuffer::Entry);
15331542
}
15341543

15351544
inline AllocationRingBuffer *getRingBuffer() {

compiler-rt/lib/scudo/standalone/fuzz/get_error_info_fuzzer.cpp

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,11 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t *Data, size_t Size) {
4646
}
4747

4848
std::string RingBufferBytes = FDP.ConsumeRemainingBytesAsString();
49-
// RingBuffer is too short.
50-
if (!AllocatorT::setRingBufferSizeForBuffer(RingBufferBytes.data(),
51-
RingBufferBytes.size()))
52-
return 0;
5349

5450
scudo_error_info ErrorInfo;
5551
AllocatorT::getErrorInfo(&ErrorInfo, FaultAddr, StackDepot.data(),
56-
RegionInfo.data(), RingBufferBytes.data(), Memory,
57-
MemoryTags, MemoryAddr, MemorySize);
52+
RegionInfo.data(), RingBufferBytes.data(),
53+
RingBufferBytes.size(), Memory, MemoryTags,
54+
MemoryAddr, MemorySize);
5855
return 0;
5956
}

compiler-rt/lib/scudo/standalone/wrappers_c_bionic.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,9 @@ INTERFACE void __scudo_get_error_info(
4444
const char *ring_buffer, size_t ring_buffer_size, const char *memory,
4545
const char *memory_tags, uintptr_t memory_addr, size_t memory_size) {
4646
(void)(stack_depot_size);
47-
(void)(ring_buffer_size);
4847
Allocator.getErrorInfo(error_info, fault_addr, stack_depot, region_info,
49-
ring_buffer, memory, memory_tags, memory_addr,
50-
memory_size);
48+
ring_buffer, ring_buffer_size, memory, memory_tags,
49+
memory_addr, memory_size);
5150
}
5251

5352
INTERFACE const char *__scudo_get_stack_depot_addr() {

0 commit comments

Comments
 (0)