[compiler-rt] 43aa6e6 - [hwasan] Fixing false invalid-free with disabled tagging (#67169)

via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 22 13:35:39 PDT 2023


Author: Vitaly Buka
Date: 2023-09-22T13:35:35-07:00
New Revision: 43aa6e6bf3d5ca1dde3e839f4c6ebd0e524055a1

URL: https://github.com/llvm/llvm-project/commit/43aa6e6bf3d5ca1dde3e839f4c6ebd0e524055a1
DIFF: https://github.com/llvm/llvm-project/commit/43aa6e6bf3d5ca1dde3e839f4c6ebd0e524055a1.diff

LOG: [hwasan] Fixing false invalid-free with disabled tagging (#67169)

This problem was accidentally discovered by the internal symbolizer, but
it's relevant for external one as well, see the test.

If we just disable tagging, there may still be tagged allocations that
have already been freed. After disabling tagging, these tagged
allocations can be released to the user as-is, which would later break
the "invalid-free" check.

We cannot just disable the "invalid-free" check with disabled tagging,
because if we re-enable tagging, the issue still applies to allocations
created when it was disabled.

The fix is to continue tagging with zero even if tagging is disabled.

This makes the "disabled" mode less efficient, but this is not the
primary use case.

Added: 
    compiler-rt/test/hwasan/TestCases/enable-disable.c

Modified: 
    compiler-rt/lib/hwasan/hwasan_allocator.cpp

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/hwasan/hwasan_allocator.cpp b/compiler-rt/lib/hwasan/hwasan_allocator.cpp
index c99d730e059faab..d21ba024a20e12a 100644
--- a/compiler-rt/lib/hwasan/hwasan_allocator.cpp
+++ b/compiler-rt/lib/hwasan/hwasan_allocator.cpp
@@ -234,28 +234,23 @@ static void *HwasanAllocate(StackTrace *stack, uptr orig_size, uptr alignment,
   }
 
   void *user_ptr = allocated;
-  // Tagging can only be skipped when both tag_in_malloc and tag_in_free are
-  // false. When tag_in_malloc = false and tag_in_free = true malloc needs to
-  // retag to 0.
   if (InTaggableRegion(reinterpret_cast<uptr>(user_ptr)) &&
-      (flags()->tag_in_malloc || flags()->tag_in_free) &&
-      atomic_load_relaxed(&hwasan_allocator_tagging_enabled)) {
-    if (flags()->tag_in_malloc && malloc_bisect(stack, orig_size)) {
-      tag_t tag = t ? t->GenerateRandomTag() : kFallbackAllocTag;
-      uptr tag_size = orig_size ? orig_size : 1;
-      uptr full_granule_size = RoundDownTo(tag_size, kShadowAlignment);
-      user_ptr =
-          (void *)TagMemoryAligned((uptr)user_ptr, full_granule_size, tag);
-      if (full_granule_size != tag_size) {
-        u8 *short_granule =
-            reinterpret_cast<u8 *>(allocated) + full_granule_size;
-        TagMemoryAligned((uptr)short_granule, kShadowAlignment,
-                         tag_size % kShadowAlignment);
-        short_granule[kShadowAlignment - 1] = tag;
-      }
-    } else {
-      user_ptr = (void *)TagMemoryAligned((uptr)user_ptr, size, 0);
+      atomic_load_relaxed(&hwasan_allocator_tagging_enabled) &&
+      flags()->tag_in_malloc && malloc_bisect(stack, orig_size)) {
+    tag_t tag = t ? t->GenerateRandomTag() : kFallbackAllocTag;
+    uptr tag_size = orig_size ? orig_size : 1;
+    uptr full_granule_size = RoundDownTo(tag_size, kShadowAlignment);
+    user_ptr = (void *)TagMemoryAligned((uptr)user_ptr, full_granule_size, tag);
+    if (full_granule_size != tag_size) {
+      u8 *short_granule = reinterpret_cast<u8 *>(allocated) + full_granule_size;
+      TagMemoryAligned((uptr)short_granule, kShadowAlignment,
+                       tag_size % kShadowAlignment);
+      short_granule[kShadowAlignment - 1] = tag;
     }
+  } else {
+    // Tagging can not be completely skipped. If it's disabled, we need to tag
+    // with zeros.
+    user_ptr = (void *)TagMemoryAligned((uptr)user_ptr, size, 0);
   }
 
   Metadata *meta =

diff  --git a/compiler-rt/test/hwasan/TestCases/enable-disable.c b/compiler-rt/test/hwasan/TestCases/enable-disable.c
new file mode 100644
index 000000000000000..290ce07656a6084
--- /dev/null
+++ b/compiler-rt/test/hwasan/TestCases/enable-disable.c
@@ -0,0 +1,42 @@
+// Test that disabling/enabling tagging does not trigger false reports on
+// allocations happened in a 
diff erent state.
+
+// RUN: %clang_hwasan -O1 %s -o %t && %run %t 2>&1
+
+#include <assert.h>
+#include <sanitizer/hwasan_interface.h>
+#include <stdlib.h>
+
+enum {
+  COUNT = 5,
+  SZ = 10,
+};
+void *x[COUNT];
+
+int main() {
+  __hwasan_enable_allocator_tagging();
+  for (unsigned i = 0; i < COUNT; ++i) {
+    x[i] = malloc(SZ);
+    assert(__hwasan_test_shadow(x[i], SZ) == -1);
+  }
+  for (unsigned i = 0; i < COUNT; ++i)
+    free(x[i]);
+
+  __hwasan_disable_allocator_tagging();
+  for (unsigned i = 0; i < COUNT; ++i) {
+    x[i] = malloc(SZ);
+    assert(__hwasan_tag_pointer(x[i], 0) == x[i]);
+    assert(__hwasan_test_shadow(x[i], SZ) == -1);
+  }
+  for (unsigned i = 0; i < COUNT; ++i)
+    free(x[i]);
+
+  __hwasan_enable_allocator_tagging();
+  for (unsigned i = 0; i < COUNT; ++i) {
+    x[i] = malloc(SZ);
+    assert(__hwasan_test_shadow(x[i], SZ) == -1);
+  }
+  for (unsigned i = 0; i < COUNT; ++i)
+    free(x[i]);
+  return 0;
+}


        


More information about the llvm-commits mailing list