diff options
author | Guillaume Chatelet <gchatelet@google.com> | 2021-03-30 15:27:46 +0000 |
---|---|---|
committer | Guillaume Chatelet <gchatelet@google.com> | 2021-03-30 15:28:47 +0000 |
commit | 77d81c2270c6221a430aac17c2c0aa73b39cc0d2 (patch) | |
tree | 38fa8f9f04f63d9e03b1689e912ce850e680019c /libc | |
parent | [test, ARM] Fix use of var defined in CHECK-NOT (diff) | |
download | llvm-project-77d81c2270c6221a430aac17c2c0aa73b39cc0d2.tar.gz llvm-project-77d81c2270c6221a430aac17c2c0aa73b39cc0d2.tar.bz2 llvm-project-77d81c2270c6221a430aac17c2c0aa73b39cc0d2.zip |
[libc] Fix msan/asan memcpy reentrancy
This is needed to prevent asan/msan instrumentation to redirect CopyBlock to `__asan_memcpy` (resp. `__msan_memcpy`).
These functions would then differ operation to `memcpy` which leads to reentrancy issues.
With this patch, `memcpy` is fully instrumented and covered by asan/msan.
If this turns out to be too expensive, instrumentation can be selectively or fully disabled through the use of the `__attribute__((no_sanitize(address, memory)))` annotation.
Differential Revision: https://reviews.llvm.org/D99598
Diffstat (limited to 'libc')
-rw-r--r-- | libc/src/__support/CMakeLists.txt | 2 | ||||
-rw-r--r-- | libc/src/__support/sanitizer.h | 52 | ||||
-rw-r--r-- | libc/src/__support/sanitizer_annotations.h | 19 | ||||
-rw-r--r-- | libc/src/string/memory_utils/memcpy_utils.h | 15 | ||||
-rw-r--r-- | libc/utils/FPUtil/x86_64/FEnv.h | 2 |
5 files changed, 67 insertions, 23 deletions
diff --git a/libc/src/__support/CMakeLists.txt b/libc/src/__support/CMakeLists.txt index 23ac21439524..b20e8bc9a811 100644 --- a/libc/src/__support/CMakeLists.txt +++ b/libc/src/__support/CMakeLists.txt @@ -2,7 +2,7 @@ add_header_library( common HDRS common.h - sanitizer_annotations.h + sanitizer.h ) add_header_library( diff --git a/libc/src/__support/sanitizer.h b/libc/src/__support/sanitizer.h new file mode 100644 index 000000000000..16fe6ecc0644 --- /dev/null +++ b/libc/src/__support/sanitizer.h @@ -0,0 +1,52 @@ +//===-- Convenient sanitizer macros ---------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_SUPPORT_SANITIZER_H +#define LLVM_LIBC_SRC_SUPPORT_SANITIZER_H + +#ifdef __has_feature +#define LLVM_LIBC_HAVE_FEATURE(f) __has_feature(f) +#else +#define LLVM_LIBC_HAVE_FEATURE(f) 0 +#endif + +// MemorySanitizer (MSan) is a detector of uninitialized reads. It consists of +// a compiler instrumentation module and a run-time library. +#ifdef LLVM_LIBC_HAVE_MEMORY_SANITIZER +#error "LLVM_LIBC_HAVE_MEMORY_SANITIZER cannot be directly set." +#elif defined(MEMORY_SANITIZER) +// The MEMORY_SANITIZER macro is deprecated but we will continue to honor it +// for now. +#define LLVM_LIBC_HAVE_MEMORY_SANITIZER 1 +#elif defined(__SANITIZE_MEMORY__) +#define LLVM_LIBC_HAVE_MEMORY_SANITIZER 1 +#elif !defined(__native_client__) && LLVM_LIBC_HAVE_FEATURE(memory_sanitizer) +#define LLVM_LIBC_HAVE_MEMORY_SANITIZER 1 +#endif + +// AddressSanitizer (ASan) is a fast memory error detector. +#ifdef LLVM_LIBC_HAVE_ADDRESS_SANITIZER +#error "LLVM_LIBC_HAVE_ADDRESS_SANITIZER cannot be directly set." +#elif defined(ADDRESS_SANITIZER) +// The ADDRESS_SANITIZER macro is deprecated but we will continue to honor it +// for now. +#define LLVM_LIBC_HAVE_ADDRESS_SANITIZER 1 +#elif defined(__SANITIZE_ADDRESS__) +#define LLVM_LIBC_HAVE_ADDRESS_SANITIZER 1 +#elif LLVM_LIBC_HAVE_FEATURE(address_sanitizer) +#define LLVM_LIBC_HAVE_ADDRESS_SANITIZER 1 +#endif + +#if LLVM_LIBC_HAVE_MEMORY_SANITIZER +#include <sanitizer/msan_interface.h> +#define SANITIZER_MEMORY_INITIALIZED(addr, size) __msan_unpoison(addr, size) +#else +#define SANITIZER_MEMORY_INITIALIZED(ptr, size) +#endif + +#endif // LLVM_LIBC_SRC_SUPPORT_SANITIZER_H diff --git a/libc/src/__support/sanitizer_annotations.h b/libc/src/__support/sanitizer_annotations.h deleted file mode 100644 index ea1bb0af7e4c..000000000000 --- a/libc/src/__support/sanitizer_annotations.h +++ /dev/null @@ -1,19 +0,0 @@ -//===-- Convenient sanitizer annotations ----------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIBC_SRC_SUPPORT_SANITIZER_ANNOTATIONS_H -#define LLVM_LIBC_SRC_SUPPORT_SANITIZER_ANNOTATIONS_H - -#if __has_feature(memory_sanitizer) -#include <sanitizer/msan_interface.h> -#define SANITIZER_MEMORY_INITIALIZED(addr, size) __msan_unpoison(addr, size) -#else -#define SANITIZER_MEMORY_INITIALIZED(ptr, size) -#endif - -#endif // LLVM_LIBC_SRC_SUPPORT_SANITIZER_ANNOTATIONS_H diff --git a/libc/src/string/memory_utils/memcpy_utils.h b/libc/src/string/memory_utils/memcpy_utils.h index 44b88374e20f..8fb04915c37b 100644 --- a/libc/src/string/memory_utils/memcpy_utils.h +++ b/libc/src/string/memory_utils/memcpy_utils.h @@ -9,6 +9,7 @@ #ifndef LIBC_SRC_STRING_MEMORY_UTILS_MEMCPY_UTILS_H #define LIBC_SRC_STRING_MEMORY_UTILS_MEMCPY_UTILS_H +#include "src/__support/sanitizer.h" #include "src/string/memory_utils/utils.h" #include <stddef.h> // size_t @@ -30,18 +31,28 @@ extern "C" void LLVM_LIBC_MEMCPY_MONITOR(char *__restrict, const char *__restrict, size_t); #endif +// Copies `kBlockSize` bytes from `src` to `dst` using a for loop. +// This code requires the use of `-fno-buitin-memcpy` to prevent the compiler +// from turning the for-loop back into `__builtin_memcpy`. +template <size_t kBlockSize> +static void ForLoopCopy(char *__restrict dst, const char *__restrict src) { + for (size_t i = 0; i < kBlockSize; ++i) + dst[i] = src[i]; +} + // Copies `kBlockSize` bytes from `src` to `dst`. template <size_t kBlockSize> static void CopyBlock(char *__restrict dst, const char *__restrict src) { #if defined(LLVM_LIBC_MEMCPY_MONITOR) LLVM_LIBC_MEMCPY_MONITOR(dst, src, kBlockSize); +#elif LLVM_LIBC_HAVE_MEMORY_SANITIZER || LLVM_LIBC_HAVE_ADDRESS_SANITIZER + ForLoopCopy<kBlockSize>(dst, src); #elif defined(USE_BUILTIN_MEMCPY_INLINE) __builtin_memcpy_inline(dst, src, kBlockSize); #elif defined(USE_BUILTIN_MEMCPY) __builtin_memcpy(dst, src, kBlockSize); #else - for (size_t i = 0; i < kBlockSize; ++i) - dst[i] = src[i]; + ForLoopCopy<kBlockSize>(dst, src); #endif } diff --git a/libc/utils/FPUtil/x86_64/FEnv.h b/libc/utils/FPUtil/x86_64/FEnv.h index 1196aba29807..f654f0bab2d5 100644 --- a/libc/utils/FPUtil/x86_64/FEnv.h +++ b/libc/utils/FPUtil/x86_64/FEnv.h @@ -12,7 +12,7 @@ #include <fenv.h> #include <stdint.h> -#include "src/__support/sanitizer_annotations.h" +#include "src/__support/sanitizer.h" namespace __llvm_libc { namespace fputil { |