Skip to content

Commit e1164d0

Browse files
authored
Revert "Reland "[scudo] resize stack depot for allocation ring buffer"" (#82088)
Reverts #81028
1 parent e7291ff commit e1164d0

File tree

6 files changed

+69
-219
lines changed

6 files changed

+69
-219
lines changed

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

Lines changed: 24 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
#ifndef SCUDO_COMBINED_H_
1010
#define SCUDO_COMBINED_H_
1111

12-
#include "atomic_helpers.h"
1312
#include "chunk.h"
1413
#include "common.h"
1514
#include "flags.h"
@@ -283,15 +282,15 @@ class Allocator {
283282
return reinterpret_cast<void *>(addHeaderTag(reinterpret_cast<uptr>(Ptr)));
284283
}
285284

286-
NOINLINE u32 collectStackTrace(UNUSED StackDepot *Depot) {
285+
NOINLINE u32 collectStackTrace() {
287286
#ifdef HAVE_ANDROID_UNSAFE_FRAME_POINTER_CHASE
288287
// Discard collectStackTrace() frame and allocator function frame.
289288
constexpr uptr DiscardFrames = 2;
290289
uptr Stack[MaxTraceSize + DiscardFrames];
291290
uptr Size =
292291
android_unsafe_frame_pointer_chase(Stack, MaxTraceSize + DiscardFrames);
293292
Size = Min<uptr>(Size, MaxTraceSize + DiscardFrames);
294-
return Depot->insert(Stack + Min<uptr>(DiscardFrames, Size), Stack + Size);
293+
return Depot.insert(Stack + Min<uptr>(DiscardFrames, Size), Stack + Size);
295294
#else
296295
return 0;
297296
#endif
@@ -688,12 +687,12 @@ class Allocator {
688687
Quarantine.disable();
689688
Primary.disable();
690689
Secondary.disable();
691-
Depot->disable();
690+
Depot.disable();
692691
}
693692

694693
void enable() NO_THREAD_SAFETY_ANALYSIS {
695694
initThreadMaybe();
696-
Depot->enable();
695+
Depot.enable();
697696
Secondary.enable();
698697
Primary.enable();
699698
Quarantine.enable();
@@ -916,14 +915,8 @@ class Allocator {
916915
Primary.Options.clear(OptionBit::AddLargeAllocationSlack);
917916
}
918917

919-
const char *getStackDepotAddress() {
920-
initThreadMaybe();
921-
return reinterpret_cast<char *>(Depot);
922-
}
923-
924-
uptr getStackDepotSize() {
925-
initThreadMaybe();
926-
return StackDepotSize;
918+
const char *getStackDepotAddress() const {
919+
return reinterpret_cast<const char *>(&Depot);
927920
}
928921

929922
const char *getRegionInfoArrayAddress() const {
@@ -952,35 +945,21 @@ class Allocator {
952945
if (!Depot->find(Hash, &RingPos, &Size))
953946
return;
954947
for (unsigned I = 0; I != Size && I != MaxTraceSize; ++I)
955-
Trace[I] = static_cast<uintptr_t>(Depot->at(RingPos + I));
948+
Trace[I] = static_cast<uintptr_t>((*Depot)[RingPos + I]);
956949
}
957950

958951
static void getErrorInfo(struct scudo_error_info *ErrorInfo,
959952
uintptr_t FaultAddr, const char *DepotPtr,
960-
size_t DepotSize, const char *RegionInfoPtr,
961-
const char *RingBufferPtr, size_t RingBufferSize,
962-
const char *Memory, const char *MemoryTags,
963-
uintptr_t MemoryAddr, size_t MemorySize) {
964-
// N.B. we need to support corrupted data in any of the buffers here. We get
965-
// this information from an external process (the crashing process) that
966-
// should not be able to crash the crash dumper (crash_dump on Android).
967-
// See also the get_error_info_fuzzer.
953+
const char *RegionInfoPtr, const char *RingBufferPtr,
954+
size_t RingBufferSize, const char *Memory,
955+
const char *MemoryTags, uintptr_t MemoryAddr,
956+
size_t MemorySize) {
968957
*ErrorInfo = {};
969958
if (!allocatorSupportsMemoryTagging<Config>() ||
970959
MemoryAddr + MemorySize < MemoryAddr)
971960
return;
972961

973-
const StackDepot *Depot = nullptr;
974-
if (DepotPtr) {
975-
// check for corrupted StackDepot. First we need to check whether we can
976-
// read the metadata, then whether the metadata matches the size.
977-
if (DepotSize < sizeof(*Depot))
978-
return;
979-
Depot = reinterpret_cast<const StackDepot *>(DepotPtr);
980-
if (!Depot->isValid(DepotSize))
981-
return;
982-
}
983-
962+
auto *Depot = reinterpret_cast<const StackDepot *>(DepotPtr);
984963
size_t NextErrorReport = 0;
985964

986965
// Check for OOB in the current block and the two surrounding blocks. Beyond
@@ -1046,9 +1025,7 @@ class Allocator {
10461025
uptr GuardedAllocSlotSize = 0;
10471026
#endif // GWP_ASAN_HOOKS
10481027

1049-
StackDepot *Depot = nullptr;
1050-
uptr StackDepotSize = 0;
1051-
MemMapT RawStackDepotMap;
1028+
StackDepot Depot;
10521029

10531030
struct AllocationRingBuffer {
10541031
struct Entry {
@@ -1257,18 +1234,11 @@ class Allocator {
12571234
storeEndMarker(RoundNewPtr, NewSize, BlockEnd);
12581235
}
12591236

1260-
StackDepot *getDepotIfEnabled(const Options &Options) {
1261-
if (!UNLIKELY(Options.get(OptionBit::TrackAllocationStacks)))
1262-
return nullptr;
1263-
return Depot;
1264-
}
1265-
12661237
void storePrimaryAllocationStackMaybe(const Options &Options, void *Ptr) {
1267-
auto *Depot = getDepotIfEnabled(Options);
1268-
if (!Depot)
1238+
if (!UNLIKELY(Options.get(OptionBit::TrackAllocationStacks)))
12691239
return;
12701240
auto *Ptr32 = reinterpret_cast<u32 *>(Ptr);
1271-
Ptr32[MemTagAllocationTraceIndex] = collectStackTrace(Depot);
1241+
Ptr32[MemTagAllocationTraceIndex] = collectStackTrace();
12721242
Ptr32[MemTagAllocationTidIndex] = getThreadID();
12731243
}
12741244

@@ -1298,10 +1268,10 @@ class Allocator {
12981268

12991269
void storeSecondaryAllocationStackMaybe(const Options &Options, void *Ptr,
13001270
uptr Size) {
1301-
auto *Depot = getDepotIfEnabled(Options);
1302-
if (!Depot)
1271+
if (!UNLIKELY(Options.get(OptionBit::TrackAllocationStacks)))
13031272
return;
1304-
u32 Trace = collectStackTrace(Depot);
1273+
1274+
u32 Trace = collectStackTrace();
13051275
u32 Tid = getThreadID();
13061276

13071277
auto *Ptr32 = reinterpret_cast<u32 *>(Ptr);
@@ -1313,14 +1283,14 @@ class Allocator {
13131283

13141284
void storeDeallocationStackMaybe(const Options &Options, void *Ptr,
13151285
u8 PrevTag, uptr Size) {
1316-
auto *Depot = getDepotIfEnabled(Options);
1317-
if (!Depot)
1286+
if (!UNLIKELY(Options.get(OptionBit::TrackAllocationStacks)))
13181287
return;
1288+
13191289
auto *Ptr32 = reinterpret_cast<u32 *>(Ptr);
13201290
u32 AllocationTrace = Ptr32[MemTagAllocationTraceIndex];
13211291
u32 AllocationTid = Ptr32[MemTagAllocationTidIndex];
13221292

1323-
u32 DeallocationTrace = collectStackTrace(Depot);
1293+
u32 DeallocationTrace = collectStackTrace();
13241294
u32 DeallocationTid = getThreadID();
13251295

13261296
storeRingBufferEntry(addFixedTag(untagPointer(Ptr), PrevTag),
@@ -1399,10 +1369,8 @@ class Allocator {
13991369
UntaggedFaultAddr < ChunkAddr ? BUFFER_UNDERFLOW : BUFFER_OVERFLOW;
14001370
R->allocation_address = ChunkAddr;
14011371
R->allocation_size = Header.SizeOrUnusedBytes;
1402-
if (Depot) {
1403-
collectTraceMaybe(Depot, R->allocation_trace,
1404-
Data[MemTagAllocationTraceIndex]);
1405-
}
1372+
collectTraceMaybe(Depot, R->allocation_trace,
1373+
Data[MemTagAllocationTraceIndex]);
14061374
R->allocation_tid = Data[MemTagAllocationTidIndex];
14071375
return NextErrorReport == NumErrorReports;
14081376
};
@@ -1425,7 +1393,7 @@ class Allocator {
14251393
auto *RingBuffer =
14261394
reinterpret_cast<const AllocationRingBuffer *>(RingBufferPtr);
14271395
size_t RingBufferElements = ringBufferElementsFromBytes(RingBufferSize);
1428-
if (!RingBuffer || RingBufferElements == 0 || !Depot)
1396+
if (!RingBuffer || RingBufferElements == 0)
14291397
return;
14301398
uptr Pos = atomic_load_relaxed(&RingBuffer->Pos);
14311399

@@ -1515,43 +1483,6 @@ class Allocator {
15151483
return;
15161484
u32 AllocationRingBufferSize =
15171485
static_cast<u32>(getFlags()->allocation_ring_buffer_size);
1518-
1519-
// We store alloc and free stacks for each entry.
1520-
constexpr u32 kStacksPerRingBufferEntry = 2;
1521-
constexpr u32 kMaxU32Pow2 = ~(UINT32_MAX >> 1);
1522-
static_assert(isPowerOfTwo(kMaxU32Pow2));
1523-
constexpr u32 kFramesPerStack = 8;
1524-
static_assert(isPowerOfTwo(kFramesPerStack));
1525-
1526-
// We need StackDepot to be aligned to 8-bytes so the ring we store after
1527-
// is correctly assigned.
1528-
static_assert(sizeof(StackDepot) % alignof(atomic_u64) == 0);
1529-
1530-
// Make sure the maximum sized StackDepot fits withint a uintptr_t to
1531-
// simplify the overflow checking.
1532-
static_assert(sizeof(StackDepot) + UINT32_MAX * sizeof(atomic_u64) *
1533-
UINT32_MAX * sizeof(atomic_u32) <
1534-
UINTPTR_MAX);
1535-
1536-
if (AllocationRingBufferSize > kMaxU32Pow2 / kStacksPerRingBufferEntry)
1537-
return;
1538-
u32 TabSize = static_cast<u32>(roundUpPowerOfTwo(kStacksPerRingBufferEntry *
1539-
AllocationRingBufferSize));
1540-
if (TabSize > UINT32_MAX / kFramesPerStack)
1541-
return;
1542-
u32 RingSize = static_cast<u32>(TabSize * kFramesPerStack);
1543-
DCHECK(isPowerOfTwo(RingSize));
1544-
1545-
StackDepotSize = sizeof(StackDepot) + sizeof(atomic_u64) * RingSize +
1546-
sizeof(atomic_u32) * TabSize;
1547-
MemMapT DepotMap;
1548-
DepotMap.map(
1549-
/*Addr=*/0U, roundUp(StackDepotSize, getPageSizeCached()),
1550-
"scudo:stack_depot");
1551-
Depot = reinterpret_cast<StackDepot *>(DepotMap.getBase());
1552-
Depot->init(RingSize, TabSize);
1553-
RawStackDepotMap = DepotMap;
1554-
15551486
MemMapT MemMap;
15561487
MemMap.map(
15571488
/*Addr=*/0U,
@@ -1574,10 +1505,6 @@ class Allocator {
15741505
RawRingBufferMap.getCapacity());
15751506
}
15761507
RawRingBuffer = nullptr;
1577-
if (Depot) {
1578-
RawStackDepotMap.unmap(RawStackDepotMap.getBase(),
1579-
RawStackDepotMap.getCapacity());
1580-
}
15811508
}
15821509

15831510
static constexpr size_t ringBufferSizeInBytes(u32 RingBufferElements) {

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

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
#define SCUDO_FUZZ
1010
#include "allocator_config.h"
1111
#include "combined.h"
12-
#include "common.h"
1312

1413
#include <fuzzer/FuzzedDataProvider.h>
1514

@@ -32,6 +31,11 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t *Data, size_t Size) {
3231

3332
std::string StackDepotBytes =
3433
FDP.ConsumeRandomLengthString(FDP.remaining_bytes());
34+
std::vector<char> StackDepot(sizeof(scudo::StackDepot), 0);
35+
for (size_t i = 0; i < StackDepotBytes.length() && i < StackDepot.size();
36+
++i) {
37+
StackDepot[i] = StackDepotBytes[i];
38+
}
3539

3640
std::string RegionInfoBytes =
3741
FDP.ConsumeRandomLengthString(FDP.remaining_bytes());
@@ -44,9 +48,9 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t *Data, size_t Size) {
4448
std::string RingBufferBytes = FDP.ConsumeRemainingBytesAsString();
4549

4650
scudo_error_info ErrorInfo;
47-
AllocatorT::getErrorInfo(&ErrorInfo, FaultAddr, StackDepotBytes.data(),
48-
StackDepotBytes.size(), RegionInfo.data(),
49-
RingBufferBytes.data(), RingBufferBytes.size(),
50-
Memory, MemoryTags, MemoryAddr, MemorySize);
51+
AllocatorT::getErrorInfo(&ErrorInfo, FaultAddr, StackDepot.data(),
52+
RegionInfo.data(), RingBufferBytes.data(),
53+
RingBufferBytes.size(), Memory, MemoryTags,
54+
MemoryAddr, MemorySize);
5155
return 0;
5256
}

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,16 @@
6363
#define SCUDO_CAN_USE_MTE (SCUDO_LINUX || SCUDO_TRUSTY)
6464
#endif
6565

66+
// Use smaller table sizes for fuzzing in order to reduce input size.
67+
// Trusty just has less available memory.
68+
#ifndef SCUDO_SMALL_STACK_DEPOT
69+
#if defined(SCUDO_FUZZ) || SCUDO_TRUSTY
70+
#define SCUDO_SMALL_STACK_DEPOT 1
71+
#else
72+
#define SCUDO_SMALL_STACK_DEPOT 0
73+
#endif
74+
#endif
75+
6676
#ifndef SCUDO_ENABLE_HOOKS
6777
#define SCUDO_ENABLE_HOOKS 0
6878
#endif

0 commit comments

Comments
 (0)