Skip to content

Commit 0dbd804

Browse files
authored
[scudo] Only init RingBuffer when needed. (#85994)
Only attempt to initialize the ring buffer when tracking is enabled. Updated unit tests, and added a few new unit tests to verify the RingBuffer is not initialized by default. Verified that the two maps associated with the RingBuffer are not created in processes by default.
1 parent af34ac4 commit 0dbd804

File tree

2 files changed

+87
-22
lines changed

2 files changed

+87
-22
lines changed

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

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "local_cache.h"
1919
#include "mem_map.h"
2020
#include "memtag.h"
21+
#include "mutex.h"
2122
#include "options.h"
2223
#include "quarantine.h"
2324
#include "report.h"
@@ -178,17 +179,17 @@ class Allocator {
178179
Quarantine.init(
179180
static_cast<uptr>(getFlags()->quarantine_size_kb << 10),
180181
static_cast<uptr>(getFlags()->thread_local_quarantine_size_kb << 10));
181-
182-
mapAndInitializeRingBuffer();
183182
}
184183

185-
void enableRingBuffer() {
184+
void enableRingBuffer() NO_THREAD_SAFETY_ANALYSIS {
186185
AllocationRingBuffer *RB = getRingBuffer();
187186
if (RB)
188187
RB->Depot->enable();
188+
RingBufferInitLock.unlock();
189189
}
190190

191-
void disableRingBuffer() {
191+
void disableRingBuffer() NO_THREAD_SAFETY_ANALYSIS {
192+
RingBufferInitLock.lock();
192193
AllocationRingBuffer *RB = getRingBuffer();
193194
if (RB)
194195
RB->Depot->disable();
@@ -915,9 +916,11 @@ class Allocator {
915916
DCHECK(!Primary.Options.load().get(OptionBit::TrackAllocationStacks));
916917
return;
917918
}
918-
if (Track)
919+
920+
if (Track) {
921+
initRingBufferMaybe();
919922
Primary.Options.set(OptionBit::TrackAllocationStacks);
920-
else
923+
} else
921924
Primary.Options.clear(OptionBit::TrackAllocationStacks);
922925
}
923926

@@ -1092,6 +1095,9 @@ class Allocator {
10921095
0,
10931096
"invalid alignment");
10941097

1098+
// Lock to initialize the RingBuffer
1099+
HybridMutex RingBufferInitLock;
1100+
10951101
// Pointer to memory mapped area starting with AllocationRingBuffer struct,
10961102
// and immediately followed by Size elements of type Entry.
10971103
atomic_uptr RingBufferAddress = {};
@@ -1546,11 +1552,16 @@ class Allocator {
15461552
RBEntryStart)[N];
15471553
}
15481554

1549-
void mapAndInitializeRingBuffer() {
1550-
if (getFlags()->allocation_ring_buffer_size <= 0)
1555+
void initRingBufferMaybe() {
1556+
ScopedLock L(RingBufferInitLock);
1557+
if (getRingBuffer() != nullptr)
15511558
return;
1552-
u32 AllocationRingBufferSize =
1553-
static_cast<u32>(getFlags()->allocation_ring_buffer_size);
1559+
1560+
int ring_buffer_size = getFlags()->allocation_ring_buffer_size;
1561+
if (ring_buffer_size <= 0)
1562+
return;
1563+
1564+
u32 AllocationRingBufferSize = static_cast<u32>(ring_buffer_size);
15541565

15551566
// We store alloc and free stacks for each entry.
15561567
constexpr u32 kStacksPerRingBufferEntry = 2;

compiler-rt/lib/scudo/standalone/tests/combined_test.cpp

Lines changed: 66 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -867,32 +867,86 @@ SCUDO_TYPED_TEST(ScudoCombinedTest, ReallocateInPlaceStress) {
867867
}
868868
}
869869

870+
SCUDO_TYPED_TEST(ScudoCombinedTest, RingBufferDefaultDisabled) {
871+
// The RingBuffer is not initialized until tracking is enabled for the
872+
// first time.
873+
auto *Allocator = this->Allocator.get();
874+
EXPECT_EQ(0u, Allocator->getRingBufferSize());
875+
EXPECT_EQ(nullptr, Allocator->getRingBufferAddress());
876+
}
877+
878+
SCUDO_TYPED_TEST(ScudoCombinedTest, RingBufferInitOnce) {
879+
auto *Allocator = this->Allocator.get();
880+
Allocator->setTrackAllocationStacks(true);
881+
882+
auto RingBufferSize = Allocator->getRingBufferSize();
883+
ASSERT_GT(RingBufferSize, 0u);
884+
auto *RingBufferAddress = Allocator->getRingBufferAddress();
885+
EXPECT_NE(nullptr, RingBufferAddress);
886+
887+
// Enable tracking again to verify that the initialization only happens once.
888+
Allocator->setTrackAllocationStacks(true);
889+
ASSERT_EQ(RingBufferSize, Allocator->getRingBufferSize());
890+
EXPECT_EQ(RingBufferAddress, Allocator->getRingBufferAddress());
891+
}
892+
870893
SCUDO_TYPED_TEST(ScudoCombinedTest, RingBufferSize) {
871894
auto *Allocator = this->Allocator.get();
872-
auto Size = Allocator->getRingBufferSize();
873-
ASSERT_GT(Size, 0u);
874-
EXPECT_EQ(Allocator->getRingBufferAddress()[Size - 1], '\0');
895+
Allocator->setTrackAllocationStacks(true);
896+
897+
auto RingBufferSize = Allocator->getRingBufferSize();
898+
ASSERT_GT(RingBufferSize, 0u);
899+
EXPECT_EQ(Allocator->getRingBufferAddress()[RingBufferSize - 1], '\0');
875900
}
876901

877902
SCUDO_TYPED_TEST(ScudoCombinedTest, RingBufferAddress) {
878903
auto *Allocator = this->Allocator.get();
879-
auto *Addr = Allocator->getRingBufferAddress();
880-
EXPECT_NE(Addr, nullptr);
881-
EXPECT_EQ(Addr, Allocator->getRingBufferAddress());
904+
Allocator->setTrackAllocationStacks(true);
905+
906+
auto *RingBufferAddress = Allocator->getRingBufferAddress();
907+
EXPECT_NE(RingBufferAddress, nullptr);
908+
EXPECT_EQ(RingBufferAddress, Allocator->getRingBufferAddress());
909+
}
910+
911+
SCUDO_TYPED_TEST(ScudoCombinedTest, StackDepotDefaultDisabled) {
912+
// The StackDepot is not initialized until tracking is enabled for the
913+
// first time.
914+
auto *Allocator = this->Allocator.get();
915+
EXPECT_EQ(0u, Allocator->getStackDepotSize());
916+
EXPECT_EQ(nullptr, Allocator->getStackDepotAddress());
917+
}
918+
919+
SCUDO_TYPED_TEST(ScudoCombinedTest, StackDepotInitOnce) {
920+
auto *Allocator = this->Allocator.get();
921+
Allocator->setTrackAllocationStacks(true);
922+
923+
auto StackDepotSize = Allocator->getStackDepotSize();
924+
EXPECT_GT(StackDepotSize, 0u);
925+
auto *StackDepotAddress = Allocator->getStackDepotAddress();
926+
EXPECT_NE(nullptr, StackDepotAddress);
927+
928+
// Enable tracking again to verify that the initialization only happens once.
929+
Allocator->setTrackAllocationStacks(true);
930+
EXPECT_EQ(StackDepotSize, Allocator->getStackDepotSize());
931+
EXPECT_EQ(StackDepotAddress, Allocator->getStackDepotAddress());
882932
}
883933

884934
SCUDO_TYPED_TEST(ScudoCombinedTest, StackDepotSize) {
885935
auto *Allocator = this->Allocator.get();
886-
auto Size = Allocator->getStackDepotSize();
887-
ASSERT_GT(Size, 0u);
888-
EXPECT_EQ(Allocator->getStackDepotAddress()[Size - 1], '\0');
936+
Allocator->setTrackAllocationStacks(true);
937+
938+
auto StackDepotSize = Allocator->getStackDepotSize();
939+
EXPECT_GT(StackDepotSize, 0u);
940+
EXPECT_EQ(Allocator->getStackDepotAddress()[StackDepotSize - 1], '\0');
889941
}
890942

891943
SCUDO_TYPED_TEST(ScudoCombinedTest, StackDepotAddress) {
892944
auto *Allocator = this->Allocator.get();
893-
auto *Addr = Allocator->getStackDepotAddress();
894-
EXPECT_NE(Addr, nullptr);
895-
EXPECT_EQ(Addr, Allocator->getStackDepotAddress());
945+
Allocator->setTrackAllocationStacks(true);
946+
947+
auto *StackDepotAddress = Allocator->getStackDepotAddress();
948+
EXPECT_NE(StackDepotAddress, nullptr);
949+
EXPECT_EQ(StackDepotAddress, Allocator->getStackDepotAddress());
896950
}
897951

898952
SCUDO_TYPED_TEST(ScudoCombinedTest, StackDepot) {

0 commit comments

Comments
 (0)