[compiler-rt] r349730 - [HWASAN] Add support for memory intrinsics

Eugene Leviant via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 20 01:10:03 PST 2018


Author: evgeny777
Date: Thu Dec 20 01:10:03 2018
New Revision: 349730

URL: http://llvm.org/viewvc/llvm-project?rev=349730&view=rev
Log:
[HWASAN] Add support for memory intrinsics

This is patch complements D55117 implementing __hwasan_mem*
functions in runtime

Differential revision: https://reviews.llvm.org/D55554

Added:
    compiler-rt/trunk/lib/hwasan/hwasan_checks.h
    compiler-rt/trunk/lib/hwasan/hwasan_memintrinsics.cc
    compiler-rt/trunk/test/hwasan/TestCases/mem-intrinsics.c
Modified:
    compiler-rt/trunk/lib/hwasan/CMakeLists.txt
    compiler-rt/trunk/lib/hwasan/hwasan.cc
    compiler-rt/trunk/lib/hwasan/hwasan_interface_internal.h

Modified: compiler-rt/trunk/lib/hwasan/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/CMakeLists.txt?rev=349730&r1=349729&r2=349730&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/hwasan/CMakeLists.txt Thu Dec 20 01:10:03 2018
@@ -7,6 +7,7 @@ set(HWASAN_RTL_SOURCES
   hwasan_dynamic_shadow.cc
   hwasan_interceptors.cc
   hwasan_linux.cc
+  hwasan_memintrinsics.cc
   hwasan_poisoning.cc
   hwasan_report.cc
   hwasan_thread.cc

Modified: compiler-rt/trunk/lib/hwasan/hwasan.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan.cc?rev=349730&r1=349729&r2=349730&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan.cc (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan.cc Thu Dec 20 01:10:03 2018
@@ -13,20 +13,20 @@
 //===----------------------------------------------------------------------===//
 
 #include "hwasan.h"
-#include "hwasan_mapping.h"
+#include "hwasan_checks.h"
 #include "hwasan_poisoning.h"
 #include "hwasan_report.h"
 #include "hwasan_thread.h"
 #include "hwasan_thread_list.h"
 #include "sanitizer_common/sanitizer_atomic.h"
 #include "sanitizer_common/sanitizer_common.h"
-#include "sanitizer_common/sanitizer_flags.h"
 #include "sanitizer_common/sanitizer_flag_parser.h"
+#include "sanitizer_common/sanitizer_flags.h"
 #include "sanitizer_common/sanitizer_libc.h"
 #include "sanitizer_common/sanitizer_procmaps.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
 #include "sanitizer_common/sanitizer_stacktrace.h"
 #include "sanitizer_common/sanitizer_symbolizer.h"
-#include "sanitizer_common/sanitizer_stackdepot.h"
 #include "ubsan/ubsan_flags.h"
 #include "ubsan/ubsan_init.h"
 
@@ -365,63 +365,6 @@ void __sanitizer_unaligned_store64(uu64
   *p = x;
 }
 
-template<unsigned X>
-__attribute__((always_inline))
-static void SigTrap(uptr p) {
-#if defined(__aarch64__)
-  (void)p;
-  // 0x900 is added to do not interfere with the kernel use of lower values of
-  // brk immediate.
-  // FIXME: Add a constraint to put the pointer into x0, the same as x86 branch.
-  asm("brk %0\n\t" ::"n"(0x900 + X));
-#elif defined(__x86_64__)
-  // INT3 + NOP DWORD ptr [EAX + X] to pass X to our signal handler, 5 bytes
-  // total. The pointer is passed via rdi.
-  // 0x40 is added as a safeguard, to help distinguish our trap from others and
-  // to avoid 0 offsets in the command (otherwise it'll be reduced to a
-  // different nop command, the three bytes one).
-  asm volatile(
-      "int3\n"
-      "nopl %c0(%%rax)\n"
-      :: "n"(0x40 + X), "D"(p));
-#else
-  // FIXME: not always sigill.
-  __builtin_trap();
-#endif
-  // __builtin_unreachable();
-}
-
-enum class ErrorAction { Abort, Recover };
-enum class AccessType { Load, Store };
-
-template <ErrorAction EA, AccessType AT, unsigned LogSize>
-__attribute__((always_inline, nodebug)) static void CheckAddress(uptr p) {
-  tag_t ptr_tag = GetTagFromPointer(p);
-  uptr ptr_raw = p & ~kAddressTagMask;
-  tag_t mem_tag = *(tag_t *)MemToShadow(ptr_raw);
-  if (UNLIKELY(ptr_tag != mem_tag)) {
-    SigTrap<0x20 * (EA == ErrorAction::Recover) +
-           0x10 * (AT == AccessType::Store) + LogSize>(p);
-    if (EA == ErrorAction::Abort) __builtin_unreachable();
-  }
-}
-
-template <ErrorAction EA, AccessType AT>
-__attribute__((always_inline, nodebug)) static void CheckAddressSized(uptr p,
-                                                                      uptr sz) {
-  CHECK_NE(0, sz);
-  tag_t ptr_tag = GetTagFromPointer(p);
-  uptr ptr_raw = p & ~kAddressTagMask;
-  tag_t *shadow_first = (tag_t *)MemToShadow(ptr_raw);
-  tag_t *shadow_last = (tag_t *)MemToShadow(ptr_raw + sz - 1);
-  for (tag_t *t = shadow_first; t <= shadow_last; ++t)
-    if (UNLIKELY(ptr_tag != *t)) {
-      SigTrap<0x20 * (EA == ErrorAction::Recover) +
-             0x10 * (AT == AccessType::Store) + 0xf>(p);
-      if (EA == ErrorAction::Abort) __builtin_unreachable();
-    }
-}
-
 void __hwasan_loadN(uptr p, uptr sz) {
   CheckAddressSized<ErrorAction::Abort, AccessType::Load>(p, sz);
 }

Added: compiler-rt/trunk/lib/hwasan/hwasan_checks.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan_checks.h?rev=349730&view=auto
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan_checks.h (added)
+++ compiler-rt/trunk/lib/hwasan/hwasan_checks.h Thu Dec 20 01:10:03 2018
@@ -0,0 +1,79 @@
+//===-- hwasan_checks.h -----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of HWAddressSanitizer.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef HWASAN_CHECKS_H
+#define HWASAN_CHECKS_H
+
+#include "hwasan_mapping.h"
+
+namespace __hwasan {
+template <unsigned X>
+__attribute__((always_inline)) static void SigTrap(uptr p) {
+#if defined(__aarch64__)
+  (void)p;
+  // 0x900 is added to do not interfere with the kernel use of lower values of
+  // brk immediate.
+  // FIXME: Add a constraint to put the pointer into x0, the same as x86 branch.
+  asm("brk %0\n\t" ::"n"(0x900 + X));
+#elif defined(__x86_64__)
+  // INT3 + NOP DWORD ptr [EAX + X] to pass X to our signal handler, 5 bytes
+  // total. The pointer is passed via rdi.
+  // 0x40 is added as a safeguard, to help distinguish our trap from others and
+  // to avoid 0 offsets in the command (otherwise it'll be reduced to a
+  // different nop command, the three bytes one).
+  asm volatile(
+      "int3\n"
+      "nopl %c0(%%rax)\n" ::"n"(0x40 + X),
+      "D"(p));
+#else
+  // FIXME: not always sigill.
+  __builtin_trap();
+#endif
+  // __builtin_unreachable();
+}
+
+enum class ErrorAction { Abort, Recover };
+enum class AccessType { Load, Store };
+
+template <ErrorAction EA, AccessType AT, unsigned LogSize>
+__attribute__((always_inline, nodebug)) static void CheckAddress(uptr p) {
+  tag_t ptr_tag = GetTagFromPointer(p);
+  uptr ptr_raw = p & ~kAddressTagMask;
+  tag_t mem_tag = *(tag_t *)MemToShadow(ptr_raw);
+  if (UNLIKELY(ptr_tag != mem_tag)) {
+    SigTrap<0x20 * (EA == ErrorAction::Recover) +
+            0x10 * (AT == AccessType::Store) + LogSize>(p);
+    if (EA == ErrorAction::Abort)
+      __builtin_unreachable();
+  }
+}
+
+template <ErrorAction EA, AccessType AT>
+__attribute__((always_inline, nodebug)) static void CheckAddressSized(uptr p,
+                                                                      uptr sz) {
+  CHECK_NE(0, sz);
+  tag_t ptr_tag = GetTagFromPointer(p);
+  uptr ptr_raw = p & ~kAddressTagMask;
+  tag_t *shadow_first = (tag_t *)MemToShadow(ptr_raw);
+  tag_t *shadow_last = (tag_t *)MemToShadow(ptr_raw + sz - 1);
+  for (tag_t *t = shadow_first; t <= shadow_last; ++t)
+    if (UNLIKELY(ptr_tag != *t)) {
+      SigTrap<0x20 * (EA == ErrorAction::Recover) +
+              0x10 * (AT == AccessType::Store) + 0xf>(p);
+      if (EA == ErrorAction::Abort)
+        __builtin_unreachable();
+    }
+}
+}  // end namespace __hwasan
+
+#endif  // HWASAN_CHECKS_H

Modified: compiler-rt/trunk/lib/hwasan/hwasan_interface_internal.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan_interface_internal.h?rev=349730&r1=349729&r2=349730&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan_interface_internal.h (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan_interface_internal.h Thu Dec 20 01:10:03 2018
@@ -194,6 +194,13 @@ void * __sanitizer_realloc(void *ptr, up
 
 SANITIZER_INTERFACE_ATTRIBUTE
 void * __sanitizer_malloc(uptr size);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__hwasan_memcpy(void *dst, const void *src, uptr size);
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__hwasan_memset(void *s, int c, uptr n);
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__hwasan_memmove(void *dest, const void *src, uptr n);
 }  // extern "C"
 
 #endif  // HWASAN_INTERFACE_INTERNAL_H

Added: compiler-rt/trunk/lib/hwasan/hwasan_memintrinsics.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan_memintrinsics.cc?rev=349730&view=auto
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan_memintrinsics.cc (added)
+++ compiler-rt/trunk/lib/hwasan/hwasan_memintrinsics.cc Thu Dec 20 01:10:03 2018
@@ -0,0 +1,45 @@
+//===-- hwasan_memintrinsics.cc ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file is a part of HWAddressSanitizer and contains HWASAN versions of
+/// memset, memcpy and memmove
+///
+//===----------------------------------------------------------------------===//
+
+#include <string.h>
+#include "hwasan.h"
+#include "hwasan_checks.h"
+#include "hwasan_flags.h"
+#include "hwasan_interface_internal.h"
+#include "sanitizer_common/sanitizer_libc.h"
+
+using namespace __hwasan;
+
+void *__hwasan_memset(void *block, int c, uptr size) {
+  CheckAddressSized<ErrorAction::Recover, AccessType::Store>(
+      reinterpret_cast<uptr>(block), size);
+  return memset(UntagPtr(block), c, size);
+}
+
+void *__hwasan_memcpy(void *to, const void *from, uptr size) {
+  CheckAddressSized<ErrorAction::Recover, AccessType::Store>(
+      reinterpret_cast<uptr>(to), size);
+  CheckAddressSized<ErrorAction::Recover, AccessType::Load>(
+      reinterpret_cast<uptr>(from), size);
+  return memcpy(UntagPtr(to), UntagPtr(from), size);
+}
+
+void *__hwasan_memmove(void *to, const void *from, uptr size) {
+  CheckAddressSized<ErrorAction::Recover, AccessType::Store>(
+      reinterpret_cast<uptr>(to), size);
+  CheckAddressSized<ErrorAction::Recover, AccessType::Load>(
+      reinterpret_cast<uptr>(from), size);
+  return memmove(UntagPtr(to), UntagPtr(from), size);
+}

Added: compiler-rt/trunk/test/hwasan/TestCases/mem-intrinsics.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/hwasan/TestCases/mem-intrinsics.c?rev=349730&view=auto
==============================================================================
--- compiler-rt/trunk/test/hwasan/TestCases/mem-intrinsics.c (added)
+++ compiler-rt/trunk/test/hwasan/TestCases/mem-intrinsics.c Thu Dec 20 01:10:03 2018
@@ -0,0 +1,37 @@
+// RUN: %clang_hwasan %s -DTEST_NO=1 -mllvm -hwasan-instrument-mem-intrinsics -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=WRITE
+// RUN: %clang_hwasan %s -DTEST_NO=2 -mllvm -hwasan-instrument-mem-intrinsics -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=READ
+// RUN: %clang_hwasan %s -DTEST_NO=3 -mllvm -hwasan-instrument-mem-intrinsics -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=WRITE
+// RUN: %clang_hwasan %s -DTEST_NO=2 -mllvm -hwasan-instrument-mem-intrinsics -o %t && not %env_hwasan_opts=halt_on_error=0 %run %t 2>&1 | FileCheck %s --check-prefix=RECOVER
+
+// REQUIRES: stable-runtime
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+int main() {
+  char Q[16];
+  char P[16];
+#if TEST_NO == 1
+  memset(Q, 0, 32);
+#elif TEST_NO == 2
+  memmove(Q, Q + 16, 16);
+#elif TEST_NO == 3
+  memcpy(Q, P, 32);
+#endif
+  write(STDOUT_FILENO, "recovered\n", 10);
+  // WRITE: ERROR: HWAddressSanitizer: tag-mismatch on address
+  // WRITE: WRITE {{.*}} tags: [[PTR_TAG:..]]/[[MEM_TAG:..]] (ptr/mem)
+  // WRITE: Memory tags around the buggy address (one tag corresponds to 16 bytes):
+  // WRITE: =>{{.*}}[[MEM_TAG]]
+  // WRITE-NOT: recovered
+
+  // READ: ERROR: HWAddressSanitizer: tag-mismatch on address
+  // READ: READ {{.*}} tags: [[PTR_TAG:..]]/[[MEM_TAG:..]] (ptr/mem)
+  // READ: Memory tags around the buggy address (one tag corresponds to 16 bytes):
+  // READ: =>{{.*}}[[MEM_TAG]]
+  // READ-NOT: recovered
+
+  // RECOVER: recovered
+  return 0;
+}




More information about the llvm-commits mailing list