[compiler-rt] bae9527 - [hwasan] Add report for wild frees.
Florian Mayer via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 13 01:05:03 PDT 2021
Author: Florian Mayer
Date: 2021-08-13T09:04:48+01:00
New Revision: bae9527c204406cacad42b97f524ae51ffbd8823
URL: https://github.com/llvm/llvm-project/commit/bae9527c204406cacad42b97f524ae51ffbd8823
DIFF: https://github.com/llvm/llvm-project/commit/bae9527c204406cacad42b97f524ae51ffbd8823.diff
LOG: [hwasan] Add report for wild frees.
Reviewed By: eugenis
Differential Revision: https://reviews.llvm.org/D107577
Added:
compiler-rt/test/hwasan/TestCases/wild-free-close.c
compiler-rt/test/hwasan/TestCases/wild-free-realloc.c
compiler-rt/test/hwasan/TestCases/wild-free-shadow.c
compiler-rt/test/hwasan/TestCases/wild-free.c
Modified:
compiler-rt/lib/hwasan/hwasan_allocator.cpp
compiler-rt/lib/hwasan/hwasan_report.cpp
compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h
Removed:
################################################################################
diff --git a/compiler-rt/lib/hwasan/hwasan_allocator.cpp b/compiler-rt/lib/hwasan/hwasan_allocator.cpp
index ef6d4d6c7678..7d8b9f9212a9 100644
--- a/compiler-rt/lib/hwasan/hwasan_allocator.cpp
+++ b/compiler-rt/lib/hwasan/hwasan_allocator.cpp
@@ -201,21 +201,35 @@ static bool PointerAndMemoryTagsMatch(void *tagged_ptr) {
return PossiblyShortTagMatches(mem_tag, tagged_uptr, 1);
}
+static bool CheckInvalidFree(StackTrace *stack, void *untagged_ptr,
+ void *tagged_ptr) {
+ // This function can return true if halt_on_error is false.
+ if (!allocator.PointerIsMine(untagged_ptr) ||
+ !PointerAndMemoryTagsMatch(tagged_ptr)) {
+ ReportInvalidFree(stack, reinterpret_cast<uptr>(tagged_ptr));
+ return true;
+ }
+ return false;
+}
+
static void HwasanDeallocate(StackTrace *stack, void *tagged_ptr) {
CHECK(tagged_ptr);
HWASAN_FREE_HOOK(tagged_ptr);
-
- if (!PointerAndMemoryTagsMatch(tagged_ptr))
- ReportInvalidFree(stack, reinterpret_cast<uptr>(tagged_ptr));
-
void *untagged_ptr = InTaggableRegion(reinterpret_cast<uptr>(tagged_ptr))
? UntagPtr(tagged_ptr)
: tagged_ptr;
+ if (CheckInvalidFree(stack, untagged_ptr, tagged_ptr))
+ return;
+
void *aligned_ptr = reinterpret_cast<void *>(
RoundDownTo(reinterpret_cast<uptr>(untagged_ptr), kShadowAlignment));
tag_t pointer_tag = GetTagFromPointer(reinterpret_cast<uptr>(tagged_ptr));
Metadata *meta =
reinterpret_cast<Metadata *>(allocator.GetMetaData(aligned_ptr));
+ if (!meta) {
+ ReportInvalidFree(stack, reinterpret_cast<uptr>(tagged_ptr));
+ return;
+ }
uptr orig_size = meta->get_requested_size();
u32 free_context_id = StackDepotPut(*stack);
u32 alloc_context_id = meta->alloc_context_id;
@@ -278,13 +292,15 @@ static void HwasanDeallocate(StackTrace *stack, void *tagged_ptr) {
static void *HwasanReallocate(StackTrace *stack, void *tagged_ptr_old,
uptr new_size, uptr alignment) {
- if (!PointerAndMemoryTagsMatch(tagged_ptr_old))
- ReportInvalidFree(stack, reinterpret_cast<uptr>(tagged_ptr_old));
-
+ void *untagged_ptr_old =
+ InTaggableRegion(reinterpret_cast<uptr>(tagged_ptr_old))
+ ? UntagPtr(tagged_ptr_old)
+ : tagged_ptr_old;
+ if (CheckInvalidFree(stack, untagged_ptr_old, tagged_ptr_old))
+ return nullptr;
void *tagged_ptr_new =
HwasanAllocate(stack, new_size, alignment, false /*zeroise*/);
if (tagged_ptr_old && tagged_ptr_new) {
- void *untagged_ptr_old = UntagPtr(tagged_ptr_old);
Metadata *meta =
reinterpret_cast<Metadata *>(allocator.GetMetaData(untagged_ptr_old));
internal_memcpy(
@@ -305,6 +321,8 @@ static void *HwasanCalloc(StackTrace *stack, uptr nmemb, uptr size) {
}
HwasanChunkView FindHeapChunkByAddress(uptr address) {
+ if (!allocator.PointerIsMine(reinterpret_cast<void *>(address)))
+ return HwasanChunkView();
void *block = allocator.GetBlockBegin(reinterpret_cast<void*>(address));
if (!block)
return HwasanChunkView();
diff --git a/compiler-rt/lib/hwasan/hwasan_report.cpp b/compiler-rt/lib/hwasan/hwasan_report.cpp
index e2be7596c8c2..8e7f3bbf26bf 100644
--- a/compiler-rt/lib/hwasan/hwasan_report.cpp
+++ b/compiler-rt/lib/hwasan/hwasan_report.cpp
@@ -372,6 +372,12 @@ void PrintAddressDescription(
int num_descriptions_printed = 0;
uptr untagged_addr = UntagAddr(tagged_addr);
+ if (MemIsShadow(untagged_addr)) {
+ Printf("%s%p is HWAsan shadow memory.\n%s", d.Location(), untagged_addr,
+ d.Default());
+ return;
+ }
+
// Print some very basic information about the address, if it's a heap.
HwasanChunkView chunk = FindHeapChunkByAddress(untagged_addr);
if (uptr beg = chunk.Beg()) {
@@ -559,8 +565,15 @@ void ReportInvalidFree(StackTrace *stack, uptr tagged_addr) {
uptr untagged_addr = UntagAddr(tagged_addr);
tag_t ptr_tag = GetTagFromPointer(tagged_addr);
- tag_t *tag_ptr = reinterpret_cast<tag_t*>(MemToShadow(untagged_addr));
- tag_t mem_tag = *tag_ptr;
+ tag_t *tag_ptr = nullptr;
+ tag_t mem_tag = 0;
+ if (MemIsApp(untagged_addr)) {
+ tag_ptr = reinterpret_cast<tag_t *>(MemToShadow(untagged_addr));
+ if (MemIsShadow(reinterpret_cast<uptr>(tag_ptr)))
+ mem_tag = *tag_ptr;
+ else
+ tag_ptr = nullptr;
+ }
Decorator d;
Printf("%s", d.Error());
uptr pc = GetTopPc(stack);
@@ -574,14 +587,16 @@ void ReportInvalidFree(StackTrace *stack, uptr tagged_addr) {
SanitizerToolName, bug_type, untagged_addr, pc);
}
Printf("%s", d.Access());
- Printf("tags: %02x/%02x (ptr/mem)\n", ptr_tag, mem_tag);
+ if (tag_ptr)
+ Printf("tags: %02x/%02x (ptr/mem)\n", ptr_tag, mem_tag);
Printf("%s", d.Default());
stack->Print();
PrintAddressDescription(tagged_addr, 0, nullptr);
- PrintTagsAroundAddr(tag_ptr);
+ if (tag_ptr)
+ PrintTagsAroundAddr(tag_ptr);
ReportErrorSummary(bug_type, stack);
}
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h
index 316a36385e17..81477aa74112 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h
@@ -282,6 +282,8 @@ class SizeClassAllocator64 {
CHECK(kMetadataSize);
uptr class_id = GetSizeClass(p);
uptr size = ClassIdToSize(class_id);
+ if (!size)
+ return nullptr;
uptr chunk_idx = GetChunkIdx(reinterpret_cast<uptr>(p), size);
uptr region_beg = GetRegionBeginBySizeClass(class_id);
return reinterpret_cast<void *>(GetMetadataEnd(region_beg) -
diff --git a/compiler-rt/test/hwasan/TestCases/wild-free-close.c b/compiler-rt/test/hwasan/TestCases/wild-free-close.c
new file mode 100644
index 000000000000..5c4c0863899e
--- /dev/null
+++ b/compiler-rt/test/hwasan/TestCases/wild-free-close.c
@@ -0,0 +1,21 @@
+// RUN: %clang_hwasan %s -o %t && not %run %t 2>&1 | FileCheck %s
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sanitizer/hwasan_interface.h>
+
+int main() {
+ __hwasan_enable_allocator_tagging();
+ char *p = (char *)malloc(1);
+ fprintf(stderr, "ALLOC %p\n", __hwasan_tag_pointer(p, 0));
+ // CHECK: ALLOC {{[0x]+}}[[ADDR:.*]]
+ free(p - 8);
+ // CHECK: ERROR: HWAddressSanitizer: invalid-free on address {{.*}} at pc {{[0x]+}}[[PC:.*]] on thread T{{[0-9]+}}
+ // CHECK: #0 {{[0x]+}}{{.*}}[[PC]] in free
+ // CHECK: #1 {{.*}} in main {{.*}}wild-free-close.c:[[@LINE-3]]
+ // CHECK: is located 8 bytes to the left of 1-byte region [{{[0x]+}}{{.*}}[[ADDR]]
+ // CHECK-NOT: Segmentation fault
+ // CHECK-NOT: SIGSEGV
+ return 0;
+}
diff --git a/compiler-rt/test/hwasan/TestCases/wild-free-realloc.c b/compiler-rt/test/hwasan/TestCases/wild-free-realloc.c
new file mode 100644
index 000000000000..e87cd8caa703
--- /dev/null
+++ b/compiler-rt/test/hwasan/TestCases/wild-free-realloc.c
@@ -0,0 +1,14 @@
+// RUN: %clang_hwasan %s -o %t && not %run %t 2>&1 | FileCheck %s
+
+#include <stdlib.h>
+
+int main() {
+ char *p = (char *)malloc(1);
+ realloc(p + 0x10000000000, 2);
+ // CHECK: ERROR: HWAddressSanitizer: invalid-free on address {{.*}} at pc {{[0x]+}}[[PC:.*]] on thread T{{[0-9]+}}
+ // CHECK: #0 {{[0x]+}}{{.*}}[[PC]] in realloc
+ // CHECK: #1 {{.*}} in main {{.*}}wild-free-realloc.c:[[@LINE-3]]
+ // CHECK-NOT: Segmentation fault
+ // CHECK-NOT: SIGSEGV
+ return 0;
+}
diff --git a/compiler-rt/test/hwasan/TestCases/wild-free-shadow.c b/compiler-rt/test/hwasan/TestCases/wild-free-shadow.c
new file mode 100644
index 000000000000..c2c512cf94eb
--- /dev/null
+++ b/compiler-rt/test/hwasan/TestCases/wild-free-shadow.c
@@ -0,0 +1,17 @@
+// RUN: %clang_hwasan %s -o %t && not %run %t 2>&1 | FileCheck %s
+
+#include <stdlib.h>
+
+extern void *__hwasan_shadow_memory_dynamic_address;
+
+int main() {
+ char *p = (char *)malloc(1);
+ free(__hwasan_shadow_memory_dynamic_address);
+ // CHECK: ERROR: HWAddressSanitizer: invalid-free on address {{[0x]+}}[[PTR:.*]] at pc {{[0x]+}}[[PC:.*]] on thread T{{[0-9]+}}
+ // CHECK: #0 {{[0x]+}}{{.*}}[[PC]] in free
+ // CHECK: #1 {{.*}} in main {{.*}}wild-free-shadow.c:[[@LINE-3]]
+ // CHECK: {{[0x]+}}{{.*}}[[PTR]] is HWAsan shadow memory.
+ // CHECK-NOT: Segmentation fault
+ // CHECK-NOT: SIGSEGV
+ return 0;
+}
diff --git a/compiler-rt/test/hwasan/TestCases/wild-free.c b/compiler-rt/test/hwasan/TestCases/wild-free.c
new file mode 100644
index 000000000000..7cb98f1a1d8c
--- /dev/null
+++ b/compiler-rt/test/hwasan/TestCases/wild-free.c
@@ -0,0 +1,14 @@
+// RUN: %clang_hwasan %s -o %t && not %run %t 2>&1 | FileCheck %s
+
+#include <stdlib.h>
+
+int main() {
+ char *p = (char *)malloc(1);
+ free(p + 0x10000000000);
+ // CHECK: ERROR: HWAddressSanitizer: invalid-free on address {{.*}} at pc {{[0x]+}}[[PC:.*]] on thread T{{[0-9]+}}
+ // CHECK: #0 {{[0x]+}}{{.*}}[[PC]] in free
+ // CHECK: #1 {{.*}} in main {{.*}}wild-free.c:[[@LINE-3]]
+ // CHECK-NOT: Segmentation fault
+ // CHECK-NOT: SIGSEGV
+ return 0;
+}
More information about the llvm-commits
mailing list