[llvm-branch-commits] [scudo] Allow to resize allocation ring buffer (PR #82683)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Feb 22 12:34:24 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-compiler-rt-sanitizer
Author: Florian Mayer (fmayer)
<details>
<summary>Changes</summary>
---
Full diff: https://github.com/llvm/llvm-project/pull/82683.diff
4 Files Affected:
- (modified) compiler-rt/lib/scudo/standalone/combined.h (+34-10)
- (modified) compiler-rt/lib/scudo/standalone/include/scudo/interface.h (+2)
- (modified) compiler-rt/lib/scudo/standalone/tests/combined_test.cpp (+27)
- (modified) compiler-rt/lib/scudo/standalone/wrappers_c_bionic.cpp (+4)
``````````diff
diff --git a/compiler-rt/lib/scudo/standalone/combined.h b/compiler-rt/lib/scudo/standalone/combined.h
index 79b5891fd35869..479e49c328e3d7 100644
--- a/compiler-rt/lib/scudo/standalone/combined.h
+++ b/compiler-rt/lib/scudo/standalone/combined.h
@@ -174,9 +174,11 @@ class Allocator {
static_cast<uptr>(getFlags()->quarantine_size_kb << 10),
static_cast<uptr>(getFlags()->thread_local_quarantine_size_kb << 10));
- mapAndInitializeRingBuffer();
+ mapAndInitializeRingBuffer(getFlags()->allocation_ring_buffer_size);
}
+ bool resizeRingBuffer(int Size) { return mapAndInitializeRingBuffer(Size); }
+
// Initialize the embedded GWP-ASan instance. Requires the main allocator to
// be functional, best called from PostInitCallback.
void initGwpAsan() {
@@ -1531,11 +1533,15 @@ class Allocator {
RBEntryStart)[N];
}
- void mapAndInitializeRingBuffer() {
- if (getFlags()->allocation_ring_buffer_size <= 0)
- return;
- u32 AllocationRingBufferSize =
- static_cast<u32>(getFlags()->allocation_ring_buffer_size);
+ bool mapAndInitializeRingBuffer(int RingBufferSize) {
+ if (RingBufferSize < 0 ||
+ static_cast<unsigned int>(RingBufferSize) >= UINT32_MAX)
+ return false;
+ if (RingBufferSize == 0) {
+ swapOutRingBuffer(nullptr);
+ return true;
+ }
+ u32 AllocationRingBufferSize = static_cast<u32>(RingBufferSize);
// We store alloc and free stacks for each entry.
constexpr u32 kStacksPerRingBufferEntry = 2;
@@ -1555,11 +1561,11 @@ class Allocator {
UINTPTR_MAX);
if (AllocationRingBufferSize > kMaxU32Pow2 / kStacksPerRingBufferEntry)
- return;
+ return false;
u32 TabSize = static_cast<u32>(roundUpPowerOfTwo(kStacksPerRingBufferEntry *
AllocationRingBufferSize));
if (TabSize > UINT32_MAX / kFramesPerStack)
- return;
+ return false;
u32 RingSize = static_cast<u32>(TabSize * kFramesPerStack);
DCHECK(isPowerOfTwo(RingSize));
@@ -1585,12 +1591,30 @@ class Allocator {
RB->StackDepotSize = StackDepotSize;
RB->RawStackDepotMap = DepotMap;
- atomic_store(&RingBufferAddress, reinterpret_cast<uptr>(RB),
- memory_order_release);
+ swapOutRingBuffer(RB);
static_assert(sizeof(AllocationRingBuffer) %
alignof(typename AllocationRingBuffer::Entry) ==
0,
"invalid alignment");
+ return true;
+ }
+
+ void swapOutRingBuffer(AllocationRingBuffer *NewRB) {
+ AllocationRingBuffer *PrevRB = reinterpret_cast<AllocationRingBuffer *>(
+ atomic_exchange(&RingBufferAddress, reinterpret_cast<uptr>(NewRB),
+ memory_order_acq_rel));
+ if (PrevRB) {
+ auto RawStackDepotMap = PrevRB->RawStackDepotMap;
+ if (RawStackDepotMap.isAllocated()) {
+ RawStackDepotMap.releaseAndZeroPagesToOS(
+ RawStackDepotMap.getBase(), RawStackDepotMap.getCapacity());
+ }
+ auto RawRingBufferMap = PrevRB->RawRingBufferMap;
+ if (RawRingBufferMap.isAllocated()) {
+ RawRingBufferMap.releaseAndZeroPagesToOS(
+ RawRingBufferMap.getBase(), RawRingBufferMap.getCapacity());
+ }
+ }
}
void unmapRingBuffer() {
diff --git a/compiler-rt/lib/scudo/standalone/include/scudo/interface.h b/compiler-rt/lib/scudo/standalone/include/scudo/interface.h
index a2dedea910cc08..8aca56b7172d9f 100644
--- a/compiler-rt/lib/scudo/standalone/include/scudo/interface.h
+++ b/compiler-rt/lib/scudo/standalone/include/scudo/interface.h
@@ -123,6 +123,8 @@ size_t __scudo_get_region_info_size(void);
const char *__scudo_get_ring_buffer_addr(void);
size_t __scudo_get_ring_buffer_size(void);
+bool __scudo_resize_ring_buffer(int);
+
#ifndef M_DECAY_TIME
#define M_DECAY_TIME -100
#endif
diff --git a/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp b/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp
index 13d627b116809b..7e7a0e59cfe6d0 100644
--- a/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp
+++ b/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp
@@ -915,6 +915,33 @@ SCUDO_TYPED_TEST(ScudoCombinedTest, StackDepot) {
EXPECT_EQ(Depot->at(RingPosPtr + 2), 3u);
}
+SCUDO_TYPED_TEST(ScudoCombinedTest, ResizeRingBuffer) {
+ auto *Allocator = this->Allocator.get();
+ auto Size = static_cast<int>(Allocator->getRingBufferSize());
+ auto DepotSize = Allocator->getStackDepotSize();
+ ASSERT_GT(Size, 0);
+ ASSERT_TRUE(Allocator->resizeRingBuffer(Size + 1024));
+ EXPECT_GT(Allocator->getRingBufferSize(), Size);
+ EXPECT_GT(Allocator->getStackDepotSize(), DepotSize);
+}
+
+SCUDO_TYPED_TEST(ScudoCombinedTest, ResizeRingBufferToZero) {
+ auto *Allocator = this->Allocator.get();
+ const char *PrevRB = Allocator->getRingBufferAddress();
+ auto PrevRBSize = Allocator->getRingBufferSize();
+ ASSERT_TRUE(Allocator->resizeRingBuffer(0));
+ EXPECT_EQ(Allocator->getRingBufferSize(), 0);
+ EXPECT_EQ(Allocator->getStackDepotSize(), 0);
+ EXPECT_EQ(Allocator->getStackDepotAddress(), nullptr);
+ EXPECT_EQ(Allocator->getRingBufferAddress(), nullptr);
+ // Make sure the old buffer is still accessible without a segfault.
+ // We DONTNEED the buffer, so we free the underlying pages, but we keep the
+ // VMA around to prevent races.
+ ASSERT_NE(PrevRB, nullptr);
+ ASSERT_GT(PrevRBSize, 0);
+ const_cast<volatile const char *>(PrevRB)[PrevRBSize - 1];
+}
+
#if SCUDO_CAN_USE_PRIMARY64
#if SCUDO_TRUSTY
diff --git a/compiler-rt/lib/scudo/standalone/wrappers_c_bionic.cpp b/compiler-rt/lib/scudo/standalone/wrappers_c_bionic.cpp
index e9d8c1e8d3db2f..004c9b9ef36cf6 100644
--- a/compiler-rt/lib/scudo/standalone/wrappers_c_bionic.cpp
+++ b/compiler-rt/lib/scudo/standalone/wrappers_c_bionic.cpp
@@ -72,4 +72,8 @@ INTERFACE size_t __scudo_get_ring_buffer_size() {
return Allocator.getRingBufferSize();
}
+INTERFACE bool __scudo_resize_ring_buffer(int new_size) {
+ return Allocator.resizeRingBuffer(new_size);
+}
+
#endif // SCUDO_ANDROID && _BIONIC
``````````
</details>
https://github.com/llvm/llvm-project/pull/82683
More information about the llvm-branch-commits
mailing list