[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