Skip to content

Commit 77d81c2

Browse files
committed
[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
1 parent a6950c3 commit 77d81c2

File tree

5 files changed

+67
-23
lines changed

5 files changed

+67
-23
lines changed

libc/src/__support/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ add_header_library(
22
common
33
HDRS
44
common.h
5-
sanitizer_annotations.h
5+
sanitizer.h
66
)
77

88
add_header_library(

libc/src/__support/sanitizer.h

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
//===-- Convenient sanitizer macros ---------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_SRC_SUPPORT_SANITIZER_H
10+
#define LLVM_LIBC_SRC_SUPPORT_SANITIZER_H
11+
12+
#ifdef __has_feature
13+
#define LLVM_LIBC_HAVE_FEATURE(f) __has_feature(f)
14+
#else
15+
#define LLVM_LIBC_HAVE_FEATURE(f) 0
16+
#endif
17+
18+
// MemorySanitizer (MSan) is a detector of uninitialized reads. It consists of
19+
// a compiler instrumentation module and a run-time library.
20+
#ifdef LLVM_LIBC_HAVE_MEMORY_SANITIZER
21+
#error "LLVM_LIBC_HAVE_MEMORY_SANITIZER cannot be directly set."
22+
#elif defined(MEMORY_SANITIZER)
23+
// The MEMORY_SANITIZER macro is deprecated but we will continue to honor it
24+
// for now.
25+
#define LLVM_LIBC_HAVE_MEMORY_SANITIZER 1
26+
#elif defined(__SANITIZE_MEMORY__)
27+
#define LLVM_LIBC_HAVE_MEMORY_SANITIZER 1
28+
#elif !defined(__native_client__) && LLVM_LIBC_HAVE_FEATURE(memory_sanitizer)
29+
#define LLVM_LIBC_HAVE_MEMORY_SANITIZER 1
30+
#endif
31+
32+
// AddressSanitizer (ASan) is a fast memory error detector.
33+
#ifdef LLVM_LIBC_HAVE_ADDRESS_SANITIZER
34+
#error "LLVM_LIBC_HAVE_ADDRESS_SANITIZER cannot be directly set."
35+
#elif defined(ADDRESS_SANITIZER)
36+
// The ADDRESS_SANITIZER macro is deprecated but we will continue to honor it
37+
// for now.
38+
#define LLVM_LIBC_HAVE_ADDRESS_SANITIZER 1
39+
#elif defined(__SANITIZE_ADDRESS__)
40+
#define LLVM_LIBC_HAVE_ADDRESS_SANITIZER 1
41+
#elif LLVM_LIBC_HAVE_FEATURE(address_sanitizer)
42+
#define LLVM_LIBC_HAVE_ADDRESS_SANITIZER 1
43+
#endif
44+
45+
#if LLVM_LIBC_HAVE_MEMORY_SANITIZER
46+
#include <sanitizer/msan_interface.h>
47+
#define SANITIZER_MEMORY_INITIALIZED(addr, size) __msan_unpoison(addr, size)
48+
#else
49+
#define SANITIZER_MEMORY_INITIALIZED(ptr, size)
50+
#endif
51+
52+
#endif // LLVM_LIBC_SRC_SUPPORT_SANITIZER_H

libc/src/__support/sanitizer_annotations.h

Lines changed: 0 additions & 19 deletions
This file was deleted.

libc/src/string/memory_utils/memcpy_utils.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#ifndef LIBC_SRC_STRING_MEMORY_UTILS_MEMCPY_UTILS_H
1010
#define LIBC_SRC_STRING_MEMORY_UTILS_MEMCPY_UTILS_H
1111

12+
#include "src/__support/sanitizer.h"
1213
#include "src/string/memory_utils/utils.h"
1314
#include <stddef.h> // size_t
1415

@@ -30,18 +31,28 @@ extern "C" void LLVM_LIBC_MEMCPY_MONITOR(char *__restrict,
3031
const char *__restrict, size_t);
3132
#endif
3233

34+
// Copies `kBlockSize` bytes from `src` to `dst` using a for loop.
35+
// This code requires the use of `-fno-buitin-memcpy` to prevent the compiler
36+
// from turning the for-loop back into `__builtin_memcpy`.
37+
template <size_t kBlockSize>
38+
static void ForLoopCopy(char *__restrict dst, const char *__restrict src) {
39+
for (size_t i = 0; i < kBlockSize; ++i)
40+
dst[i] = src[i];
41+
}
42+
3343
// Copies `kBlockSize` bytes from `src` to `dst`.
3444
template <size_t kBlockSize>
3545
static void CopyBlock(char *__restrict dst, const char *__restrict src) {
3646
#if defined(LLVM_LIBC_MEMCPY_MONITOR)
3747
LLVM_LIBC_MEMCPY_MONITOR(dst, src, kBlockSize);
48+
#elif LLVM_LIBC_HAVE_MEMORY_SANITIZER || LLVM_LIBC_HAVE_ADDRESS_SANITIZER
49+
ForLoopCopy<kBlockSize>(dst, src);
3850
#elif defined(USE_BUILTIN_MEMCPY_INLINE)
3951
__builtin_memcpy_inline(dst, src, kBlockSize);
4052
#elif defined(USE_BUILTIN_MEMCPY)
4153
__builtin_memcpy(dst, src, kBlockSize);
4254
#else
43-
for (size_t i = 0; i < kBlockSize; ++i)
44-
dst[i] = src[i];
55+
ForLoopCopy<kBlockSize>(dst, src);
4556
#endif
4657
}
4758

libc/utils/FPUtil/x86_64/FEnv.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
#include <fenv.h>
1313
#include <stdint.h>
1414

15-
#include "src/__support/sanitizer_annotations.h"
15+
#include "src/__support/sanitizer.h"
1616

1717
namespace __llvm_libc {
1818
namespace fputil {

0 commit comments

Comments
 (0)