[compiler-rt] 5a5bf05 - [HWASAN] Support short granules in __hwasan_test_shadow
Vitaly Buka via llvm-commits
llvm-commits at lists.llvm.org
Fri Apr 28 18:34:39 PDT 2023
Author: Vitaly Buka
Date: 2023-04-28T18:34:34-07:00
New Revision: 5a5bf053d8847852e578bec769ac01d0f9242e06
URL: https://github.com/llvm/llvm-project/commit/5a5bf053d8847852e578bec769ac01d0f9242e06
DIFF: https://github.com/llvm/llvm-project/commit/5a5bf053d8847852e578bec769ac01d0f9242e06.diff
LOG: [HWASAN] Support short granules in __hwasan_test_shadow
Reviewed By: thurston
Differential Revision: https://reviews.llvm.org/D149430
Added:
compiler-rt/test/hwasan/TestCases/test_shadow.c
Modified:
compiler-rt/lib/hwasan/hwasan.cpp
compiler-rt/lib/hwasan/hwasan_checks.h
Removed:
################################################################################
diff --git a/compiler-rt/lib/hwasan/hwasan.cpp b/compiler-rt/lib/hwasan/hwasan.cpp
index 097136fe5480c..26aae9b4869b9 100644
--- a/compiler-rt/lib/hwasan/hwasan.cpp
+++ b/compiler-rt/lib/hwasan/hwasan.cpp
@@ -445,16 +445,32 @@ void __hwasan_print_shadow(const void *p, uptr sz) {
sptr __hwasan_test_shadow(const void *p, uptr sz) {
if (sz == 0)
return -1;
- tag_t ptr_tag = GetTagFromPointer((uptr)p);
- uptr ptr_raw = UntagAddr(reinterpret_cast<uptr>(p));
+ uptr ptr = reinterpret_cast<uptr>(p);
+ tag_t ptr_tag = GetTagFromPointer(ptr);
+ uptr ptr_raw = UntagAddr(ptr);
uptr shadow_first = MemToShadow(ptr_raw);
- uptr shadow_last = MemToShadow(ptr_raw + sz - 1);
- for (uptr s = shadow_first; s <= shadow_last; ++s)
- if (*(tag_t *)s != ptr_tag) {
- sptr offset = ShadowToMem(s) - ptr_raw;
+ uptr shadow_last = MemToShadow(ptr_raw + sz);
+ for (uptr s = shadow_first; s < shadow_last; ++s) {
+ if (UNLIKELY(*(tag_t *)s != ptr_tag)) {
+ uptr short_size =
+ ShortTagSize(*(tag_t *)s, AddTagToPointer(ShadowToMem(s), ptr_tag));
+ sptr offset = ShadowToMem(s) - ptr_raw + short_size;
return offset < 0 ? 0 : offset;
}
- return -1;
+ }
+
+ uptr end = ptr + sz;
+ uptr tail_sz = end & (kShadowAlignment - 1);
+ if (!tail_sz)
+ return -1;
+
+ uptr short_size =
+ ShortTagSize(*(tag_t *)shadow_last, end & ~(kShadowAlignment - 1));
+ if (LIKELY(tail_sz <= short_size))
+ return -1;
+
+ sptr offset = sz - tail_sz + short_size;
+ return offset < 0 ? 0 : offset;
}
u16 __sanitizer_unaligned_load16(const uu16 *p) {
diff --git a/compiler-rt/lib/hwasan/hwasan_checks.h b/compiler-rt/lib/hwasan/hwasan_checks.h
index 4ffd5246cbd21..0911af30dcb8f 100644
--- a/compiler-rt/lib/hwasan/hwasan_checks.h
+++ b/compiler-rt/lib/hwasan/hwasan_checks.h
@@ -125,8 +125,22 @@ __attribute__((always_inline)) static void SigTrap(uptr p, uptr size) {
// __builtin_unreachable();
}
+__attribute__((always_inline, nodebug)) static inline uptr ShortTagSize(
+ tag_t mem_tag, uptr ptr) {
+ DCHECK(IsAligned(ptr, kShadowAlignment));
+ tag_t ptr_tag = GetTagFromPointer(ptr);
+ if (ptr_tag == mem_tag)
+ return kShadowAlignment;
+ if (!mem_tag || mem_tag >= kShadowAlignment)
+ return 0;
+ if (*(u8 *)(ptr | (kShadowAlignment - 1)) != ptr_tag)
+ return 0;
+ return mem_tag;
+}
+
__attribute__((always_inline, nodebug)) static inline bool
PossiblyShortTagMatches(tag_t mem_tag, uptr ptr, uptr sz) {
+ DCHECK(IsAligned(ptr, kShadowAlignment));
tag_t ptr_tag = GetTagFromPointer(ptr);
if (ptr_tag == mem_tag)
return true;
diff --git a/compiler-rt/test/hwasan/TestCases/test_shadow.c b/compiler-rt/test/hwasan/TestCases/test_shadow.c
new file mode 100644
index 0000000000000..693ba255a030e
--- /dev/null
+++ b/compiler-rt/test/hwasan/TestCases/test_shadow.c
@@ -0,0 +1,41 @@
+// RUN: %clang_hwasan %s -o %t && %run %t
+
+#include <assert.h>
+#include <sanitizer/hwasan_interface.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int main() {
+ __hwasan_enable_allocator_tagging();
+ for (int sz = 0; sz < 64; ++sz) {
+ fprintf(stderr, "sz: %d\n", sz);
+ char *x = (char *)malloc(sz);
+ do {
+ // Empty range is always OK.
+ for (int b = -16; b < sz + 32; ++b)
+ assert(__hwasan_test_shadow(x + b, 0) == -1);
+
+ int real_sz = sz ? sz : 1;
+ // Unlucky case when we cant distinguish between tag and short granule size.
+ if (__hwasan_tag_pointer(x, real_sz % 16) == x)
+ break;
+
+ // Underflow - the first byte is bad.
+ for (int b = -16; b < 0; ++b)
+ assert(__hwasan_test_shadow(x + b, real_sz) == 0);
+
+ // Inbound ranges.
+ for (int b = 0; b < real_sz; ++b)
+ for (int e = b; e <= real_sz; ++e)
+ assert(__hwasan_test_shadow(x + b, e - b) == -1);
+
+ // Overflow - the first byte after the buffer is bad.
+ for (int b = 0; b <= real_sz; ++b)
+ for (int e = real_sz + 1; e <= real_sz + 64; ++e)
+ assert(__hwasan_test_shadow(x + b, e - b) == (real_sz - b));
+
+ } while (0);
+ free(x);
+ }
+ return 0;
+}
More information about the llvm-commits
mailing list