From c7b288492aae99a890e202d2d2807a7dc35ca14b Mon Sep 17 00:00:00 2001 From: Ryan Macnak Date: Wed, 14 Jun 2023 21:50:17 +0000 Subject: [PATCH] [vm] Mark Zone memory as unallocated/allocated/uninitialized for Address and Memory Sanitizer. TEST=ci Change-Id: Ia283d9aefec767e6ccc4f1c88abba73ce1c35e87 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/212022 Reviewed-by: Brian Quinlan Commit-Queue: Ryan Macnak --- runtime/platform/address_sanitizer.h | 5 +++++ runtime/platform/memory_sanitizer.h | 10 ++++++++++ runtime/vm/zone.cc | 16 ++++++++++++++++ runtime/vm/zone.h | 5 +++++ 4 files changed, 36 insertions(+) diff --git a/runtime/platform/address_sanitizer.h b/runtime/platform/address_sanitizer.h index 71b80244f9e..9b6b2b51658 100644 --- a/runtime/platform/address_sanitizer.h +++ b/runtime/platform/address_sanitizer.h @@ -16,11 +16,16 @@ #endif #if defined(USING_ADDRESS_SANITIZER) +extern "C" void __asan_poison_memory_region(void const volatile*, size_t); extern "C" void __asan_unpoison_memory_region(void const volatile*, size_t); #define NO_SANITIZE_ADDRESS __attribute__((no_sanitize("address"))) +#define ASAN_POISON(ptr, len) __asan_poison_memory_region(ptr, len) #define ASAN_UNPOISON(ptr, len) __asan_unpoison_memory_region(ptr, len) #else // defined(USING_ADDRESS_SANITIZER) #define NO_SANITIZE_ADDRESS +#define ASAN_POISON(ptr, len) \ + do { \ + } while (false && (ptr) == nullptr && (len) == 0) #define ASAN_UNPOISON(ptr, len) \ do { \ } while (false && (ptr) == nullptr && (len) == 0) diff --git a/runtime/platform/memory_sanitizer.h b/runtime/platform/memory_sanitizer.h index d2a805d0566..8b7fa53cf88 100644 --- a/runtime/platform/memory_sanitizer.h +++ b/runtime/platform/memory_sanitizer.h @@ -19,9 +19,13 @@ extern "C" void __msan_poison(const volatile void*, size_t); extern "C" void __msan_unpoison(const volatile void*, size_t); extern "C" void __msan_unpoison_param(size_t); +extern "C" void __msan_allocated_memory(const volatile void*, size_t); +extern "C" void __sanitizer_dtor_callback(const volatile void*, size_t); extern "C" void __msan_check_mem_is_initialized(const volatile void*, size_t); #define MSAN_POISON(ptr, len) __msan_poison(ptr, len) #define MSAN_UNPOISON(ptr, len) __msan_unpoison(ptr, len) +#define MSAN_ALLOCATED(ptr, len) __msan_allocated_memory(ptr, len) +#define MSAN_RELEASED(ptr, len) __sanitizer_dtor_callback(ptr, len) #define MSAN_CHECK_INITIALIZED(ptr, len) \ __msan_check_mem_is_initialized(ptr, len) #define NO_SANITIZE_MEMORY __attribute__((no_sanitize("memory"))) @@ -32,6 +36,12 @@ extern "C" void __msan_check_mem_is_initialized(const volatile void*, size_t); #define MSAN_UNPOISON(ptr, len) \ do { \ } while (false && (ptr) == nullptr && (len) == 0) +#define MSAN_ALLOCATED(ptr, len) \ + do { \ + } while (false && (ptr) == nullptr && (len) == 0) +#define MSAN_RELEASED(ptr, len) \ + do { \ + } while (false && (ptr) == nullptr && (len) == 0) #define MSAN_CHECK_INITIALIZED(ptr, len) \ do { \ } while (false && (ptr) == nullptr && (len) == 0) diff --git a/runtime/vm/zone.cc b/runtime/vm/zone.cc index f5dcc271fba..47a42ab5ea8 100644 --- a/runtime/vm/zone.cc +++ b/runtime/vm/zone.cc @@ -4,8 +4,10 @@ #include "vm/zone.h" +#include "platform/address_sanitizer.h" #include "platform/assert.h" #include "platform/leak_sanitizer.h" +#include "platform/memory_sanitizer.h" #include "platform/utils.h" #include "vm/dart_api_state.h" #include "vm/flags.h" @@ -96,10 +98,15 @@ Zone::Segment* Zone::Segment::New(intptr_t size, Zone::Segment* next) { OUT_OF_MEMORY(); } Segment* result = reinterpret_cast(memory->start()); + #ifdef DEBUG // Zap the entire allocated segment (including the header). memset(reinterpret_cast(result), kZapUninitializedByte, size); #endif + ASAN_POISON(reinterpret_cast(result), size); + MSAN_ALLOCATED(reinterpret_cast(result), size); + + ASAN_UNPOISON(reinterpret_cast(result), sizeof(Segment)); result->next_ = next; result->size_ = size; result->memory_ = memory; @@ -120,6 +127,9 @@ void Zone::Segment::DeleteSegmentList(Segment* head) { // Zap the entire current segment (including the header). memset(reinterpret_cast(current), kZapDeletedByte, current->size()); #endif + ASAN_POISON(reinterpret_cast(current), size); + MSAN_RELEASED(reinterpret_cast(current), size); + LSAN_UNREGISTER_ROOT_REGION(current, sizeof(*current)); if (size == kSegmentSize) { @@ -133,6 +143,7 @@ void Zone::Segment::DeleteSegmentList(Segment* head) { } if (memory != nullptr) { total_size_.fetch_sub(size); + ASAN_UNPOISON(reinterpret_cast(current), size); delete memory; } current = next; @@ -150,6 +161,8 @@ Zone::Zone() // Zap the entire initial buffer. memset(&buffer_, kZapUninitializedByte, kInitialChunkSize); #endif + ASAN_POISON(&buffer_, kInitialChunkSize); + MSAN_POISON(&buffer_, kInitialChunkSize); } Zone::~Zone() { @@ -168,6 +181,9 @@ void Zone::Reset() { #ifdef DEBUG memset(&buffer_, kZapDeletedByte, kInitialChunkSize); #endif + ASAN_POISON(&buffer_, kInitialChunkSize); + MSAN_POISON(&buffer_, kInitialChunkSize); + position_ = reinterpret_cast(&buffer_); limit_ = position_ + kInitialChunkSize; size_ = 0; diff --git a/runtime/vm/zone.h b/runtime/vm/zone.h index ba18349cd3c..1c9c20568c3 100644 --- a/runtime/vm/zone.h +++ b/runtime/vm/zone.h @@ -5,6 +5,7 @@ #ifndef RUNTIME_VM_ZONE_H_ #define RUNTIME_VM_ZONE_H_ +#include "platform/address_sanitizer.h" #include "platform/utils.h" #include "vm/allocation.h" #include "vm/handles.h" @@ -277,6 +278,8 @@ inline uword Zone::AllocUnsafe(intptr_t size) { // Check that the result has the proper alignment and return it. ASSERT(Utils::IsAligned(result, kAlignment)); + + ASAN_UNPOISON(reinterpret_cast(result), size); return result; } @@ -312,6 +315,8 @@ inline ElementType* Zone::Realloc(ElementType* old_data, if (new_end <= limit_) { position_ = Utils::RoundUp(new_end, kAlignment); size_ += static_cast(new_len - old_len); + ASAN_UNPOISON(reinterpret_cast(old_data), + new_len * kElementSize); return old_data; } }