[hwasan] Add a basic API.
authorEvgeniy Stepanov <eugeni.stepanov@gmail.com>
Wed, 15 Aug 2018 00:39:35 +0000 (00:39 +0000)
committerEvgeniy Stepanov <eugeni.stepanov@gmail.com>
Wed, 15 Aug 2018 00:39:35 +0000 (00:39 +0000)
Summary:
Add user tag manipulation functions:
  __hwasan_tag_memory
  __hwasan_tag_pointer
  __hwasan_print_shadow (very simple and ugly, for now)

Reviewers: vitalybuka, kcc

Subscribers: kubamracek, hiraditya, llvm-commits

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

llvm-svn: 339746

compiler-rt/include/sanitizer/hwasan_interface.h
compiler-rt/lib/hwasan/hwasan.cc
compiler-rt/lib/hwasan/hwasan_interface_internal.h
compiler-rt/test/hwasan/TestCases/hwasan-print-shadow.cc [new file with mode: 0644]
llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp

index 75d31a6..9ca73bc 100644 (file)
@@ -32,6 +32,18 @@ extern "C" {
   void __hwasan_enable_allocator_tagging(void);
   void __hwasan_disable_allocator_tagging(void);
 
+  // Mark region of memory with the given tag. Both address and size need to be
+  // 16-byte aligned.
+  void __hwasan_tag_memory(const volatile void *p, unsigned char tag,
+                           size_t size);
+
+  /// Set pointer tag. Previous tag is lost.
+  void *__hwasan_tag_pointer(const volatile void *p, unsigned char tag);
+
+  // Print shadow and origin for the memory range to stderr in a human-readable
+  // format.
+  void __hwasan_print_shadow(const volatile void *x, size_t size);
+
   int __sanitizer_posix_memalign(void **memptr, size_t alignment, size_t size);
   void * __sanitizer_memalign(size_t alignment, size_t size);
   void * __sanitizer_aligned_alloc(size_t alignment, size_t size);
index c11aec3..d4b5583 100644 (file)
@@ -224,9 +224,14 @@ void __hwasan_init() {
   hwasan_inited = 1;
 }
 
-void __hwasan_print_shadow(const void *x, uptr size) {
-  // FIXME:
-  Printf("FIXME: __hwasan_print_shadow unimplemented\n");
+void __hwasan_print_shadow(const void *p, uptr sz) {
+  uptr ptr_raw = GetAddressFromPointer((uptr)p);
+  uptr shadow_first = MEM_TO_SHADOW(ptr_raw);
+  uptr shadow_last = MEM_TO_SHADOW(ptr_raw + sz - 1);
+  Printf("HWASan shadow map for %zx .. %zx (pointer tag %x)\n", ptr_raw,
+         ptr_raw + sz, GetTagFromPointer((uptr)p));
+  for (uptr s = shadow_first; s <= shadow_last; ++s)
+    Printf("  %zx: %x\n", SHADOW_TO_MEM(s), *(tag_t *)s);
 }
 
 sptr __hwasan_test_shadow(const void *p, uptr sz) {
@@ -400,6 +405,10 @@ void __hwasan_tag_memory(uptr p, u8 tag, uptr sz) {
   TagMemoryAligned(p, sz, tag);
 }
 
+uptr __hwasan_tag_pointer(uptr p, u8 tag) {
+  return AddTagToPointer(p, tag);
+}
+
 static const u8 kFallbackTag = 0xBB;
 
 u8 __hwasan_generate_tag() {
index 94378ba..8aa0ed5 100644 (file)
@@ -94,6 +94,9 @@ SANITIZER_INTERFACE_ATTRIBUTE
 void __hwasan_tag_memory(uptr p, u8 tag, uptr sz);
 
 SANITIZER_INTERFACE_ATTRIBUTE
+uptr __hwasan_tag_pointer(uptr p, u8 tag);
+
+SANITIZER_INTERFACE_ATTRIBUTE
 u8 __hwasan_generate_tag();
 
 // Returns the offset of the first tag mismatch or -1 if the whole range is
diff --git a/compiler-rt/test/hwasan/TestCases/hwasan-print-shadow.cc b/compiler-rt/test/hwasan/TestCases/hwasan-print-shadow.cc
new file mode 100644 (file)
index 0000000..fa6330b
--- /dev/null
@@ -0,0 +1,29 @@
+// RUN: %clangxx_hwasan -DSIZE=16 -O0 %s -o %t && %run %t 2>&1 | FileCheck %s
+
+// REQUIRES: stable-runtime
+
+#include <assert.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <sanitizer/hwasan_interface.h>
+
+int main() {
+  char *p = (char *)mmap(nullptr, 4096, PROT_READ | PROT_WRITE,
+                         MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
+  assert(p);
+
+  __hwasan_tag_memory(p, 1, 32);
+  __hwasan_tag_memory(p + 32, 3, 16);
+  __hwasan_tag_memory(p + 48, 0, 32);
+  __hwasan_tag_memory(p + 80, 4, 16);
+
+  char *q = (char *)__hwasan_tag_pointer(p, 7);
+  __hwasan_print_shadow(q + 5, 89 - 5);
+  // CHECK:      HWASan shadow map for {{.*}}5 .. {{.*}}9 (pointer tag 7)
+  // CHECK-NEXT:   {{.*}}0: 1
+  // CHECK-NEXT:   {{.*}}0: 1
+  // CHECK-NEXT:   {{.*}}0: 3
+  // CHECK-NEXT:   {{.*}}0: 0
+  // CHECK-NEXT:   {{.*}}0: 0
+  // CHECK-NEXT:   {{.*}}0: 4
+}
index bc690cc..f3d8ae4 100644 (file)
@@ -199,6 +199,7 @@ private:
   ShadowMapping Mapping;
 
   Type *IntptrTy;
+  Type *Int8PtrTy;
   Type *Int8Ty;
 
   bool CompileKernel;
@@ -250,6 +251,7 @@ bool HWAddressSanitizer::doInitialization(Module &M) {
   C = &(M.getContext());
   IRBuilder<> IRB(*C);
   IntptrTy = IRB.getIntPtrTy(DL);
+  Int8PtrTy = IRB.getInt8PtrTy();
   Int8Ty = IRB.getInt8Ty();
 
   HwasanCtorFunction = nullptr;
@@ -286,7 +288,7 @@ void HWAddressSanitizer::initializeCallbacks(Module &M) {
   }
 
   HwasanTagMemoryFunc = checkSanitizerInterfaceFunction(M.getOrInsertFunction(
-      "__hwasan_tag_memory", IRB.getVoidTy(), IntptrTy, Int8Ty, IntptrTy));
+      "__hwasan_tag_memory", IRB.getVoidTy(), Int8PtrTy, Int8Ty, IntptrTy));
   HwasanGenerateTagFunc = checkSanitizerInterfaceFunction(
       M.getOrInsertFunction("__hwasan_generate_tag", Int8Ty));
 
@@ -426,8 +428,7 @@ void HWAddressSanitizer::instrumentMemAccessInline(Value *PtrLong, bool IsWrite,
                                   IRB.getInt8Ty());
   Value *AddrLong = untagPointer(IRB, PtrLong);
   Value *ShadowLong = memToShadow(AddrLong, PtrLong->getType(), IRB);
-  Value *MemTag =
-      IRB.CreateLoad(IRB.CreateIntToPtr(ShadowLong, IRB.getInt8PtrTy()));
+  Value *MemTag = IRB.CreateLoad(IRB.CreateIntToPtr(ShadowLong, Int8PtrTy));
   Value *TagMismatch = IRB.CreateICmpNE(PtrTag, MemTag);
 
   int matchAllTag = ClMatchAllTag.getNumOccurrences() > 0 ?
@@ -526,13 +527,13 @@ bool HWAddressSanitizer::tagAlloca(IRBuilder<> &IRB, AllocaInst *AI,
   Value *JustTag = IRB.CreateTrunc(Tag, IRB.getInt8Ty());
   if (ClInstrumentWithCalls) {
     IRB.CreateCall(HwasanTagMemoryFunc,
-                   {IRB.CreatePointerCast(AI, IntptrTy), JustTag,
+                   {IRB.CreatePointerCast(AI, Int8PtrTy), JustTag,
                     ConstantInt::get(IntptrTy, Size)});
   } else {
     size_t ShadowSize = Size >> Mapping.Scale;
     Value *ShadowPtr = IRB.CreateIntToPtr(
         memToShadow(IRB.CreatePointerCast(AI, IntptrTy), AI->getType(), IRB),
-        IRB.getInt8PtrTy());
+        Int8PtrTy);
     // If this memset is not inlined, it will be intercepted in the hwasan
     // runtime library. That's OK, because the interceptor skips the checks if
     // the address is in the shadow region.