[hwasan] Do not use short granule tags as poison tags.
authorFlorian Mayer <fmayer@google.com>
Tue, 15 Jun 2021 12:12:02 +0000 (13:12 +0100)
committerFlorian Mayer <fmayer@google.com>
Thu, 17 Jun 2021 10:59:37 +0000 (11:59 +0100)
Short granule tags as poison cause a UaF to read the referenced
memory to retrieve the tag, and means we do not detect the UaF
if the last granule's tag is still around.

This only increases the change of not catching a UaF from
0.39 % (1 / 256) to 0.42 % (1 / (256 - 17)).

Reviewed By: eugenis

Differential Revision: https://reviews.llvm.org/D104304

compiler-rt/lib/hwasan/hwasan_allocator.cpp

index a6fc794..21563be 100644 (file)
@@ -229,7 +229,19 @@ static void HwasanDeallocate(StackTrace *stack, void *tagged_ptr) {
       flags()->tag_in_free && malloc_bisect(stack, 0) &&
       atomic_load_relaxed(&hwasan_allocator_tagging_enabled)) {
     // Always store full 8-bit tags on free to maximize UAF detection.
-    tag_t tag = t ? t->GenerateRandomTag(/*num_bits=*/8) : kFallbackFreeTag;
+    tag_t tag;
+    if (t) {
+      // Make sure we are not using a short granule tag as a poison tag. This
+      // would make us attempt to read the memory on a UaF.
+      // The tag can be zero if tagging is disabled on this thread.
+      do {
+        tag = t->GenerateRandomTag(/*num_bits=*/8);
+      } while (UNLIKELY(tag < kShadowAlignment && tag != 0));
+    } else {
+      static_assert(kFallbackFreeTag >= kShadowAlignment,
+                    "fallback tag must not be a short granule tag.");
+      tag = kFallbackFreeTag;
+    }
     TagMemoryAligned(reinterpret_cast<uptr>(aligned_ptr), TaggedSize(orig_size),
                      tag);
   }