[libc-commits] [libc] 77d81c2 - [libc] Fix msan/asan memcpy reentrancy
Guillaume Chatelet via libc-commits
libc-commits at lists.llvm.org
Tue Mar 30 08:28:56 PDT 2021
Author: Guillaume Chatelet
Date: 2021-03-30T15:28:47Z
New Revision: 77d81c2270c6221a430aac17c2c0aa73b39cc0d2
URL: https://github.com/llvm/llvm-project/commit/77d81c2270c6221a430aac17c2c0aa73b39cc0d2
DIFF: https://github.com/llvm/llvm-project/commit/77d81c2270c6221a430aac17c2c0aa73b39cc0d2.diff
LOG: [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
Added:
libc/src/__support/sanitizer.h
Modified:
libc/src/__support/CMakeLists.txt
libc/src/string/memory_utils/memcpy_utils.h
libc/utils/FPUtil/x86_64/FEnv.h
Removed:
libc/src/__support/sanitizer_annotations.h
################################################################################
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 {
More information about the libc-commits
mailing list