diff options
Diffstat (limited to '')
-rw-r--r-- | build/build-clang/llvmorg-17-init-6897-g415b1cfd57de.patch | 395 |
1 files changed, 395 insertions, 0 deletions
diff --git a/build/build-clang/llvmorg-17-init-6897-g415b1cfd57de.patch b/build/build-clang/llvmorg-17-init-6897-g415b1cfd57de.patch new file mode 100644 index 0000000000..596e32e56e --- /dev/null +++ b/build/build-clang/llvmorg-17-init-6897-g415b1cfd57de.patch @@ -0,0 +1,395 @@ +From 415b1cfd57de62da8af9ad8dc567fc9d918dbaa5 Mon Sep 17 00:00:00 2001 +From: Thurston Dang <thurston@google.com> +Date: Mon, 3 Apr 2023 21:14:40 +0000 +Subject: [PATCH] Add __sanitizer_get_allocated_begin API and implementations + +This function will return the start of the allocation, if given a pointer that lies within an allocation. Otherwise, it returns NULL. + +It will be useful for detecting dynamic TLS allocations in glibc >=2.25, which +uses malloc (see https://github.com/google/sanitizers/issues/1409#issuecomment-1214244142). + +Reviewed By: vitalybuka + +Differential Revision: https://reviews.llvm.org/D147005 +--- + .../include/sanitizer/allocator_interface.h | 4 ++ + compiler-rt/lib/asan/asan_allocator.cpp | 15 +++++ + compiler-rt/lib/dfsan/dfsan_allocator.cpp | 18 ++++++ + compiler-rt/lib/hwasan/hwasan_allocator.cpp | 21 +++++++ + compiler-rt/lib/lsan/lsan_allocator.cpp | 21 +++++++ + compiler-rt/lib/memprof/memprof_allocator.cpp | 16 +++++ + compiler-rt/lib/msan/msan_allocator.cpp | 19 ++++++ + .../sanitizer_allocator_interface.h | 2 + + .../sanitizer_allocator_internal.h | 3 +- + .../sanitizer_common_interface.inc | 1 + + compiler-rt/lib/tsan/rtl/tsan_mman.cpp | 18 ++++++ + .../TestCases/get_allocated_begin.cpp | 58 +++++++++++++++++++ + 12 files changed, 195 insertions(+), 1 deletion(-) + create mode 100644 compiler-rt/test/sanitizer_common/TestCases/get_allocated_begin.cpp + +diff --git a/compiler-rt/include/sanitizer/allocator_interface.h b/compiler-rt/include/sanitizer/allocator_interface.h +index 6226135ef84b3..d846f3f330741 100644 +--- a/compiler-rt/include/sanitizer/allocator_interface.h ++++ b/compiler-rt/include/sanitizer/allocator_interface.h +@@ -26,6 +26,10 @@ extern "C" { + is not yet freed. */ + int __sanitizer_get_ownership(const volatile void *p); + ++ /* If a pointer lies within an allocation, it will return the start address ++ of the allocation. Otherwise, it returns nullptr. */ ++ void *__sanitizer_get_allocated_begin(const void *p); ++ + /* Returns the number of bytes reserved for the pointer p. + Requires (get_ownership(p) == true) or (p == 0). */ + size_t __sanitizer_get_allocated_size(const volatile void *p); +diff --git a/compiler-rt/lib/asan/asan_allocator.cpp b/compiler-rt/lib/asan/asan_allocator.cpp +index 4c52a45b875c7..4b65b44a88f91 100644 +--- a/compiler-rt/lib/asan/asan_allocator.cpp ++++ b/compiler-rt/lib/asan/asan_allocator.cpp +@@ -1164,6 +1164,17 @@ IgnoreObjectResult IgnoreObjectLocked(const void *p) { + // ---------------------- Interface ---------------- {{{1 + using namespace __asan; + ++void *AllocationBegin(const void *p) { ++ AsanChunk *m = __asan::instance.GetAsanChunkByAddr((uptr)p); ++ if (!m) ++ return nullptr; ++ if (atomic_load(&m->chunk_state, memory_order_acquire) != CHUNK_ALLOCATED) ++ return nullptr; ++ if (m->UsedSize() == 0) ++ return nullptr; ++ return (void *)(m->Beg()); ++} ++ + // ASan allocator doesn't reserve extra bytes, so normally we would + // just return "size". We don't want to expose our redzone sizes, etc here. + uptr __sanitizer_get_estimated_allocated_size(uptr size) { +@@ -1187,6 +1198,10 @@ uptr __sanitizer_get_allocated_size(const void *p) { + return allocated_size; + } + ++void *__sanitizer_get_allocated_begin(const void *p) { ++ return AllocationBegin(p); ++} ++ + void __sanitizer_purge_allocator() { + GET_STACK_TRACE_MALLOC; + instance.Purge(&stack); +diff --git a/compiler-rt/lib/dfsan/dfsan_allocator.cpp b/compiler-rt/lib/dfsan/dfsan_allocator.cpp +index 5fb8fef213b9a..cebf9983c9490 100644 +--- a/compiler-rt/lib/dfsan/dfsan_allocator.cpp ++++ b/compiler-rt/lib/dfsan/dfsan_allocator.cpp +@@ -174,6 +174,20 @@ void *DFsanCalloc(uptr nmemb, uptr size) { + return DFsanAllocate(nmemb * size, sizeof(u64), true /*zeroise*/); + } + ++void *AllocationBegin(const void *p) { ++ if (!p) ++ return nullptr; ++ const void *beg = allocator.GetBlockBegin(p); ++ if (!beg) ++ return nullptr; ++ Metadata *b = (Metadata *)allocator.GetMetaData(beg); ++ if (!b) ++ return nullptr; ++ if (b->requested_size == 0) ++ return nullptr; ++ return (void *)beg; ++} ++ + static uptr AllocationSize(const void *p) { + if (!p) + return 0; +@@ -294,4 +308,8 @@ uptr __sanitizer_get_estimated_allocated_size(uptr size) { return size; } + + int __sanitizer_get_ownership(const void *p) { return AllocationSize(p) != 0; } + ++void *__sanitizer_get_allocated_begin(const void *p) { ++ return AllocationBegin(p); ++} ++ + uptr __sanitizer_get_allocated_size(const void *p) { return AllocationSize(p); } +diff --git a/compiler-rt/lib/hwasan/hwasan_allocator.cpp b/compiler-rt/lib/hwasan/hwasan_allocator.cpp +index d096a8faa2c7e..8ccdeb23fa995 100644 +--- a/compiler-rt/lib/hwasan/hwasan_allocator.cpp ++++ b/compiler-rt/lib/hwasan/hwasan_allocator.cpp +@@ -397,6 +397,23 @@ HwasanChunkView FindHeapChunkByAddress(uptr address) { + return HwasanChunkView(reinterpret_cast<uptr>(block), metadata); + } + ++void *AllocationBegin(const void *p) { ++ const void *untagged_ptr = UntagPtr(p); ++ if (!untagged_ptr) ++ return nullptr; ++ ++ const void *beg = allocator.GetBlockBegin(untagged_ptr); ++ if (!beg) ++ return nullptr; ++ ++ Metadata *b = (Metadata *)allocator.GetMetaData(beg); ++ if (b->GetRequestedSize() == 0) ++ return nullptr; ++ ++ tag_t tag = GetTagFromPointer((uptr)p); ++ return (void *)AddTagToPointer((uptr)beg, tag); ++} ++ + static uptr AllocationSize(const void *tagged_ptr) { + const void *untagged_ptr = UntagPtr(tagged_ptr); + if (!untagged_ptr) return 0; +@@ -641,4 +658,8 @@ uptr __sanitizer_get_estimated_allocated_size(uptr size) { return size; } + + int __sanitizer_get_ownership(const void *p) { return AllocationSize(p) != 0; } + ++void *__sanitizer_get_allocated_begin(const void *p) { ++ return AllocationBegin(p); ++} ++ + uptr __sanitizer_get_allocated_size(const void *p) { return AllocationSize(p); } +diff --git a/compiler-rt/lib/lsan/lsan_allocator.cpp b/compiler-rt/lib/lsan/lsan_allocator.cpp +index 37ba363d479dd..d50882657dc33 100644 +--- a/compiler-rt/lib/lsan/lsan_allocator.cpp ++++ b/compiler-rt/lib/lsan/lsan_allocator.cpp +@@ -145,6 +145,22 @@ void GetAllocatorCacheRange(uptr *begin, uptr *end) { + *end = *begin + sizeof(AllocatorCache); + } + ++void *GetMallocBegin(const void *p) { ++ if (!p) ++ return nullptr; ++ const void *beg = allocator.GetBlockBegin(p); ++ if (!beg) ++ return nullptr; ++ ChunkMetadata *m = Metadata(beg); ++ if (!m) ++ return nullptr; ++ if (!m->allocated) ++ return nullptr; ++ if (m->requested_size == 0) ++ return nullptr; ++ return (void *)beg; ++} ++ + uptr GetMallocUsableSize(const void *p) { + if (!p) + return 0; +@@ -363,6 +379,11 @@ uptr __sanitizer_get_estimated_allocated_size(uptr size) { return size; } + SANITIZER_INTERFACE_ATTRIBUTE + int __sanitizer_get_ownership(const void *p) { return Metadata(p) != nullptr; } + ++SANITIZER_INTERFACE_ATTRIBUTE ++void * __sanitizer_get_allocated_begin(const void *p) { ++ return GetMallocBegin(p); ++} ++ + SANITIZER_INTERFACE_ATTRIBUTE + uptr __sanitizer_get_allocated_size(const void *p) { + return GetMallocUsableSize(p); +diff --git a/compiler-rt/lib/memprof/memprof_allocator.cpp b/compiler-rt/lib/memprof/memprof_allocator.cpp +index 51c3a66ebd680..80a87d49dfc6e 100644 +--- a/compiler-rt/lib/memprof/memprof_allocator.cpp ++++ b/compiler-rt/lib/memprof/memprof_allocator.cpp +@@ -681,6 +681,18 @@ int memprof_posix_memalign(void **memptr, uptr alignment, uptr size, + return 0; + } + ++void *memprof_malloc_begin(const void *p) { ++ u64 user_requested_size; ++ MemprofChunk *m = ++ instance.GetMemprofChunkByAddr((uptr)p, user_requested_size); ++ if (!m) ++ return nullptr; ++ if (user_requested_size == 0) ++ return nullptr; ++ ++ return (void *)m->Beg(); ++} ++ + uptr memprof_malloc_usable_size(const void *ptr, uptr pc, uptr bp) { + if (!ptr) + return 0; +@@ -699,6 +711,10 @@ int __sanitizer_get_ownership(const void *p) { + return memprof_malloc_usable_size(p, 0, 0) != 0; + } + ++void *__sanitizer_get_allocated_begin(const void *p) { ++ return memprof_malloc_begin(p); ++} ++ + uptr __sanitizer_get_allocated_size(const void *p) { + return memprof_malloc_usable_size(p, 0, 0); + } +diff --git a/compiler-rt/lib/msan/msan_allocator.cpp b/compiler-rt/lib/msan/msan_allocator.cpp +index 3308ee7053a61..a760a434158a5 100644 +--- a/compiler-rt/lib/msan/msan_allocator.cpp ++++ b/compiler-rt/lib/msan/msan_allocator.cpp +@@ -260,6 +260,21 @@ static void *MsanCalloc(StackTrace *stack, uptr nmemb, uptr size) { + return MsanAllocate(stack, nmemb * size, sizeof(u64), true); + } + ++void *AllocationBegin(const void *p) { ++ if (!p) ++ return nullptr; ++ const void *beg = allocator.GetBlockBegin(p); ++ if (!beg) ++ return nullptr; ++ Metadata *b = (Metadata *)allocator.GetMetaData(beg); ++ if (!b) ++ return nullptr; ++ if (b->requested_size == 0) ++ return nullptr; ++ ++ return (void *)beg; ++} ++ + static uptr AllocationSize(const void *p) { + if (!p) return 0; + const void *beg = allocator.GetBlockBegin(p); +@@ -373,4 +388,8 @@ uptr __sanitizer_get_estimated_allocated_size(uptr size) { return size; } + + int __sanitizer_get_ownership(const void *p) { return AllocationSize(p) != 0; } + ++void *__sanitizer_get_allocated_begin(const void *p) { ++ return AllocationBegin(p); ++} ++ + uptr __sanitizer_get_allocated_size(const void *p) { return AllocationSize(p); } +diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_interface.h b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_interface.h +index c1b27563e2fc7..35c7c97df3299 100644 +--- a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_interface.h ++++ b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_interface.h +@@ -21,6 +21,8 @@ extern "C" { + SANITIZER_INTERFACE_ATTRIBUTE + uptr __sanitizer_get_estimated_allocated_size(uptr size); + SANITIZER_INTERFACE_ATTRIBUTE int __sanitizer_get_ownership(const void *p); ++SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void * ++__sanitizer_get_allocated_begin(const void *p); + SANITIZER_INTERFACE_ATTRIBUTE uptr + __sanitizer_get_allocated_size(const void *p); + SANITIZER_INTERFACE_ATTRIBUTE uptr __sanitizer_get_current_allocated_bytes(); +diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_internal.h b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_internal.h +index 38994736877ac..adbdad5a1ee0c 100644 +--- a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_internal.h ++++ b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_internal.h +@@ -51,7 +51,8 @@ void InternalFree(void *p, InternalAllocatorCache *cache = nullptr); + void InternalAllocatorLock(); + void InternalAllocatorUnlock(); + InternalAllocator *internal_allocator(); +- ++int __sanitizer_get_allocation_bounds(const void *p, void **start, ++ unsigned long long *size); + } // namespace __sanitizer + + #endif // SANITIZER_ALLOCATOR_INTERNAL_H +diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interface.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interface.inc +index 958f071e7b5f7..01be600e33ba3 100644 +--- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interface.inc ++++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interface.inc +@@ -32,6 +32,7 @@ INTERFACE_FUNCTION(__sanitizer_get_module_and_offset_for_pc) + INTERFACE_FUNCTION(__sanitizer_symbolize_global) + INTERFACE_FUNCTION(__sanitizer_symbolize_pc) + // Allocator interface. ++INTERFACE_FUNCTION(__sanitizer_get_allocated_begin) + INTERFACE_FUNCTION(__sanitizer_get_allocated_size) + INTERFACE_FUNCTION(__sanitizer_get_current_allocated_bytes) + INTERFACE_FUNCTION(__sanitizer_get_estimated_allocated_size) +diff --git a/compiler-rt/lib/tsan/rtl/tsan_mman.cpp b/compiler-rt/lib/tsan/rtl/tsan_mman.cpp +index 99fa492265615..9c548dfff91f3 100644 +--- a/compiler-rt/lib/tsan/rtl/tsan_mman.cpp ++++ b/compiler-rt/lib/tsan/rtl/tsan_mman.cpp +@@ -352,6 +352,20 @@ void *user_pvalloc(ThreadState *thr, uptr pc, uptr sz) { + return SetErrnoOnNull(user_alloc_internal(thr, pc, sz, PageSize)); + } + ++void *user_alloc_begin(const void *p) { ++ if (p == nullptr || !IsAppMem((uptr)p)) ++ return nullptr; ++ const void *beg = allocator()->GetBlockBegin(p); ++ if (!beg) ++ return nullptr; ++ ++ MBlock *b = ctx->metamap.GetBlock((uptr)beg); ++ if (!b) ++ return nullptr; // Not a valid pointer. ++ ++ return (void *)beg; ++} ++ + uptr user_alloc_usable_size(const void *p) { + if (p == 0 || !IsAppMem((uptr)p)) + return 0; +@@ -430,6 +444,10 @@ int __sanitizer_get_ownership(const void *p) { + return allocator()->GetBlockBegin(p) != 0; + } + ++void *__sanitizer_get_allocated_begin(const void *p) { ++ return user_alloc_begin(p); ++} ++ + uptr __sanitizer_get_allocated_size(const void *p) { + return user_alloc_usable_size(p); + } +diff --git a/compiler-rt/test/sanitizer_common/TestCases/get_allocated_begin.cpp b/compiler-rt/test/sanitizer_common/TestCases/get_allocated_begin.cpp +new file mode 100644 +index 0000000000000..6892a4a7fb282 +--- /dev/null ++++ b/compiler-rt/test/sanitizer_common/TestCases/get_allocated_begin.cpp +@@ -0,0 +1,58 @@ ++// RUN: %clangxx -O0 -g %s -o %t && %run %t ++ ++// UBSan does not have its own allocator ++// UNSUPPORTED: ubsan ++ ++#include <assert.h> ++#include <sanitizer/allocator_interface.h> ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++ ++// Based on lib/msan/tests/msan_test.cpp::get_allocated_size_and_ownership ++int main(void) { ++ int sizes[] = {10, 100, 1000, 10000, 100000, 1000000}; ++ ++ for (int i = 0; i < sizeof(sizes) / sizeof(int); i++) { ++ printf("Testing size %d\n", sizes[i]); ++ ++ char *array = reinterpret_cast<char *>(malloc(sizes[i])); ++ int *int_ptr = new int; ++ printf("array: %p\n", array); ++ printf("int_ptr: %p\n", int_ptr); ++ ++ // Bogus value to unpoison start. Calling __sanitizer_get_allocated_begin ++ // does not unpoison it. ++ void *start = NULL; ++ for (int j = 0; j < sizes[i]; j++) { ++ printf("j: %d\n", j); ++ ++ start = __sanitizer_get_allocated_begin(array + j); ++ printf("Start: %p (expected: %p)\n", start, array); ++ fflush(stdout); ++ assert(array == start); ++ } ++ ++ start = __sanitizer_get_allocated_begin(int_ptr); ++ assert(int_ptr == start); ++ ++ void *wild_addr = reinterpret_cast<void *>(4096 * 160); ++ assert(__sanitizer_get_allocated_begin(wild_addr) == NULL); ++ ++ wild_addr = reinterpret_cast<void *>(0x1); ++ assert(__sanitizer_get_allocated_begin(wild_addr) == NULL); ++ ++ // NULL is a valid argument for GetAllocatedSize but is not owned. ++ assert(__sanitizer_get_allocated_begin(NULL) == NULL); ++ ++ free(array); ++ for (int j = 0; j < sizes[i]; j++) { ++ assert(__sanitizer_get_allocated_begin(array + j) == NULL); ++ } ++ ++ delete int_ptr; ++ assert(__sanitizer_get_allocated_begin(int_ptr) == NULL); ++ } ++ ++ return 0; ++} |