From 0365ccd2a1b3900491eef30b784f2ea13a4d073c Mon Sep 17 00:00:00 2001 From: Kirill Stoimenov Date: Fri, 14 Jul 2023 20:07:29 +0000 Subject: [PATCH] [HWASAN][LSAN] Fix false positive memory leak reports on X86_64 Before this patch when running HWASAN on x86_64 with with memory tagging support we got a bunch of false memory leak reports. The reason for that is that the heuristic used to detect if an 8 bytes could be a user pointer was not valid when memory tagging is used as the top byte could contain non-zero information. Reviewed By: vitalybuka Differential Revision: https://reviews.llvm.org/D155338 --- compiler-rt/lib/lsan/lsan_common.cpp | 11 ++++++++--- compiler-rt/test/lsan/TestCases/user_pointer.cpp | 17 +++++++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 compiler-rt/test/lsan/TestCases/user_pointer.cpp diff --git a/compiler-rt/lib/lsan/lsan_common.cpp b/compiler-rt/lib/lsan/lsan_common.cpp index 9101c70..9b73ddb 100644 --- a/compiler-rt/lib/lsan/lsan_common.cpp +++ b/compiler-rt/lib/lsan/lsan_common.cpp @@ -260,9 +260,14 @@ static inline bool MaybeUserPointer(uptr p) { if (p < kMinAddress) return false; # if defined(__x86_64__) - // TODO: add logic similar to ARM when Intel LAM is available. - // Accept only canonical form user-space addresses. - return ((p >> 47) == 0); + // TODO: support LAM48 and 5 level page tables. + // LAM_U57 mask format + // * top byte: 0x81 because the format is: [0] [6-bit tag] [0] + // * top-1 byte: 0xff because it should be 0 + // * top-2 byte: 0x80 because Linux uses 128 TB VMA ending at 0x7fffffffffff + constexpr uptr kLAM_U57Mask = 0x81ff80; + constexpr uptr kPointerMask = kLAM_U57Mask << 40; + return ((p & kPointerMask) == 0); # elif defined(__mips64) return ((p >> 40) == 0); # elif defined(__aarch64__) diff --git a/compiler-rt/test/lsan/TestCases/user_pointer.cpp b/compiler-rt/test/lsan/TestCases/user_pointer.cpp new file mode 100644 index 0000000..c3df859 --- /dev/null +++ b/compiler-rt/test/lsan/TestCases/user_pointer.cpp @@ -0,0 +1,17 @@ +// Checks if a user pointer is found by the leak sanitizer. +// RUN: %clang_lsan %s -o %t +// RUN: %run %t 2>&1 + +#include +#include +#include + +uintptr_t glob[1024]; + +int main() { + for (int i = 0; i < 1024; ++i) { + // Check that the pointers will not be falsely reported as leaks. + glob[i] = (uintptr_t)malloc(sizeof(int *)); + } + return 0; +} -- 2.7.4