summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxim Ostapenko <m.ostapenko@samsung.com>2016-10-05 17:04:08 +0300
committerDongkyun Son <dongkyun.s@samsung.com>2024-05-09 16:37:38 +0900
commit3c2d48c911edf337d30f0e2efec1bef1fd5bdf4f (patch)
tree97d2c893d56879334e0af4b409c680c396e922c5
parent6342650b604c81ed9261892bd34908c982c8ff75 (diff)
downloadgcc-3c2d48c911edf337d30f0e2efec1bef1fd5bdf4f.tar.gz
gcc-3c2d48c911edf337d30f0e2efec1bef1fd5bdf4f.tar.bz2
gcc-3c2d48c911edf337d30f0e2efec1bef1fd5bdf4f.zip
Add mmap/munmap interceptors.
Some allocators may use mmap for their local pools that may cause false positive reports because LSan currently doesn't intercept mmap call mainly due to its complexity (we don't know whether a particular mmap would contain live pointers). However for some cases (e.g. anonymous rw mmaps) we can guess that they would contain live pointers thus we can add them into root regions. Thus, now we intercept mmap/munmap calls, add anonymous rw mappings into root regions and call real mmap. Change-Id: Ie0bde91497a31ab670f15d67b34d328969dc0981 Signed-off-by: Maxim Ostapenko <m.ostapenko@samsung.com>
-rw-r--r--libsanitizer/lsan/lsan.cpp1
-rw-r--r--libsanitizer/lsan/lsan.h1
-rw-r--r--libsanitizer/lsan/lsan_common.cpp9
-rw-r--r--libsanitizer/lsan/lsan_interceptors.cpp53
4 files changed, 60 insertions, 4 deletions
diff --git a/libsanitizer/lsan/lsan.cpp b/libsanitizer/lsan/lsan.cpp
index 3be2edac5c7..b716d082aa2 100644
--- a/libsanitizer/lsan/lsan.cpp
+++ b/libsanitizer/lsan/lsan.cpp
@@ -22,6 +22,7 @@
bool lsan_inited;
bool lsan_init_is_running;
+bool lsan_check_in_progress;
namespace __lsan {
diff --git a/libsanitizer/lsan/lsan.h b/libsanitizer/lsan/lsan.h
index bc596677905..608b7039b45 100644
--- a/libsanitizer/lsan/lsan.h
+++ b/libsanitizer/lsan/lsan.h
@@ -60,5 +60,6 @@ void InstallAtExitCheckLeaks();
extern bool lsan_inited;
extern bool lsan_init_is_running;
+extern bool lsan_check_in_progress;
extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __lsan_init();
diff --git a/libsanitizer/lsan/lsan_common.cpp b/libsanitizer/lsan/lsan_common.cpp
index d0776536e4c..494bc50137f 100644
--- a/libsanitizer/lsan/lsan_common.cpp
+++ b/libsanitizer/lsan/lsan_common.cpp
@@ -11,6 +11,7 @@
//
//===----------------------------------------------------------------------===//
+#include "lsan.h"
#include "lsan_common.h"
#include "sanitizer_common/sanitizer_common.h"
@@ -772,6 +773,7 @@ static bool CheckForLeaks() {
return false;
}
VReport(1, "LeakSanitizer: checking for leaks");
+ lsan_check_in_progress = true;
// Inside LockStuffAndStopTheWorld we can't run symbolizer, so we can't match
// suppressions. However if a stack id was previously suppressed, it should be
// suppressed in future checks as well.
@@ -797,6 +799,7 @@ static bool CheckForLeaks() {
}
LeakReport leak_report;
leak_report.AddLeakedChunks(param.leaks);
+ lsan_check_in_progress = false;
// No new suppressions stacks, so rerun will not help and we can report.
if (!leak_report.ApplySuppressions())
@@ -1036,7 +1039,6 @@ void __lsan_register_root_region(const void *begin, uptr size) {
uptr e = b + size;
CHECK_LT(b, e);
- Lock l(&global_mutex);
++GetRootRegionsLocked()[{b, e}];
#endif // CAN_SANITIZE_LEAKS
}
@@ -1050,18 +1052,17 @@ void __lsan_unregister_root_region(const void *begin, uptr size) {
VReport(1, "Unregistered root region at %p of size %zu\n", begin, size);
{
- Lock l(&global_mutex);
if (auto *f = GetRootRegionsLocked().find({b, e})) {
if (--(f->second) == 0)
GetRootRegionsLocked().erase(f);
return;
}
}
- Report(
+ VReport(1,
"__lsan_unregister_root_region(): region at %p of size %zu has not "
"been registered.\n",
begin, size);
- Die();
+ // Do nothing
#endif // CAN_SANITIZE_LEAKS
}
diff --git a/libsanitizer/lsan/lsan_interceptors.cpp b/libsanitizer/lsan/lsan_interceptors.cpp
index 885f7ad5ddb..d06246a5aa0 100644
--- a/libsanitizer/lsan/lsan_interceptors.cpp
+++ b/libsanitizer/lsan/lsan_interceptors.cpp
@@ -25,6 +25,7 @@
#include "sanitizer_common/sanitizer_platform_limits_posix.h"
#if SANITIZER_POSIX
#include "sanitizer_common/sanitizer_posix.h"
+#include "sanitizer_common/sanitizer_procmaps.h"
#endif
#include "sanitizer_common/sanitizer_tls_get_addr.h"
#include "lsan.h"
@@ -33,6 +34,7 @@
#include "lsan_thread.h"
#include <stddef.h>
+#include <sys/mman.h>
using namespace __lsan;
@@ -42,8 +44,12 @@ int pthread_attr_destroy(void *attr);
int pthread_attr_getdetachstate(void *attr, int *v);
int pthread_key_create(unsigned *key, void (*destructor)(void* v));
int pthread_setspecific(unsigned key, const void *v);
+void __lsan_register_root_region(const void *p, size_t size);
+void __lsan_unregister_root_region(const void *p, size_t size);
}
+Mutex mmap_mutex;
+
struct DlsymAlloc : DlSymAllocator<DlsymAlloc> {
static bool UseImpl() { return lsan_init_is_running; }
static void OnAllocate(const void *ptr, uptr size) {
@@ -532,6 +538,50 @@ INTERCEPTOR(void, _exit, int status) {
REAL(_exit)(status);
}
+static inline bool isSharedMmap(void *addr, int flags) {
+ return (flags & MAP_SHARED) && (addr == NULL);
+}
+
+static inline bool isAnonymousMmap(int flags, int fd) {
+ return ((flags & MAP_ANON) || (flags & MAP_ANONYMOUS)) &&
+ !(flags & MAP_STACK) && (fd == -1);
+}
+
+static inline bool isInterestingMmap(void *addr, int prot, int flags, int fd) {
+ return ((prot & PROT_WRITE) && (prot & PROT_READ)) &&
+ (isAnonymousMmap(flags, fd) || isSharedMmap(addr, flags));
+}
+
+static inline void MaybeRegisterMmapRegion(void *res, size_t length, void *addr,
+ int prot, int flags, int fd) {
+ if (!lsan_check_in_progress && isInterestingMmap(addr, prot, flags, fd)) {
+ Lock l(&mmap_mutex);
+ __lsan_register_root_region(res, length);
+ }
+}
+
+INTERCEPTOR(void *, mmap, void *addr, size_t length, int prot, int flags,
+ int fd, off_t offset) {
+ void *res = REAL(mmap)(addr, length, prot, flags, fd, offset);
+ MaybeRegisterMmapRegion(res, length, addr, prot, flags, fd);
+ return res;
+}
+
+INTERCEPTOR(void *, mmap64, void *addr, size_t length, int prot, int flags,
+ int fd, __off64_t offset) {
+ void *res = REAL(mmap64)(addr, length, prot, flags, fd, offset);
+ MaybeRegisterMmapRegion(res, length, addr, prot, flags, fd);
+ return res;
+}
+
+INTERCEPTOR(int, munmap, void *addr, size_t length) {
+ if (!lsan_check_in_progress) {
+ Lock l(&mmap_mutex);
+ __lsan_unregister_root_region(addr, length);
+ }
+ return REAL(munmap)(addr, length);
+}
+
#define COMMON_INTERCEPT_FUNCTION(name) INTERCEPT_FUNCTION(name)
#define SIGNAL_INTERCEPTOR_ENTER() ENSURE_LSAN_INITED
#include "sanitizer_common/sanitizer_signal_interceptors.inc"
@@ -566,6 +616,9 @@ void InitializeInterceptors() {
LSAN_MAYBE_INTERCEPT_TIMEDJOIN;
LSAN_MAYBE_INTERCEPT_TRYJOIN;
INTERCEPT_FUNCTION(_exit);
+ INTERCEPT_FUNCTION(mmap);
+ INTERCEPT_FUNCTION(mmap64);
+ INTERCEPT_FUNCTION(munmap);
LSAN_MAYBE_INTERCEPT__LWP_EXIT;
LSAN_MAYBE_INTERCEPT_THR_EXIT;