[compiler-rt] 0984b8d - tsan: don't leave unmapped hole in non-app memory
Dmitry Vyukov via llvm-commits
llvm-commits at lists.llvm.org
Tue Feb 16 23:37:32 PST 2021
Author: Dmitry Vyukov
Date: 2021-02-17T08:37:04+01:00
New Revision: 0984b8de0b0d5d178a8e6e5de1eb89f29493a89e
URL: https://github.com/llvm/llvm-project/commit/0984b8de0b0d5d178a8e6e5de1eb89f29493a89e
DIFF: https://github.com/llvm/llvm-project/commit/0984b8de0b0d5d178a8e6e5de1eb89f29493a89e.diff
LOG: tsan: don't leave unmapped hole in non-app memory
If an app mmaps lots of memory, a user mmap may end up
in the tsan region for traces. Shadow for this range
overlaps with shadow for other user regions.
This causes havok: from false positives to crashes.
Don't leave unmapped holes in the traces region.
Reviewed-in: https://reviews.llvm.org/D96697
Added:
compiler-rt/test/tsan/mmap_lots.cpp
Modified:
compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
compiler-rt/lib/tsan/rtl/tsan_rtl.cpp
Removed:
################################################################################
diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
index 6c49ccd6dd5b..b8b964cda58b 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
@@ -769,6 +769,11 @@ static void *mmap_interceptor(ThreadState *thr, uptr pc, Mmap real_mmap,
if (!fix_mmap_addr(&addr, sz, flags)) return MAP_FAILED;
void *res = real_mmap(addr, sz, prot, flags, fd, off);
if (res != MAP_FAILED) {
+ if (!IsAppMem((uptr)res) || !IsAppMem((uptr)res + sz - 1)) {
+ Report("ThreadSanitizer: mmap at bad address: addr=%p size=%p res=%p\n",
+ addr, (void*)sz, res);
+ Die();
+ }
if (fd > 0) FdAccess(thr, pc, fd);
MemoryRangeImitateWriteOrResetRange(thr, pc, (uptr)res, sz);
}
diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp b/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp
index 3d721eb95a2c..4dda62054d8d 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp
@@ -77,12 +77,19 @@ static ThreadContextBase *CreateThreadContext(u32 tid) {
new((void*)hdr) Trace();
// We are going to use only a small part of the trace with the default
// value of history_size. However, the constructor writes to the whole trace.
- // Unmap the unused part.
+ // Release the unused part.
uptr hdr_end = hdr + sizeof(Trace);
hdr_end -= sizeof(TraceHeader) * (kTraceParts - TraceParts());
hdr_end = RoundUp(hdr_end, GetPageSizeCached());
- if (hdr_end < hdr + sizeof(Trace))
- UnmapOrDie((void*)hdr_end, hdr + sizeof(Trace) - hdr_end);
+ if (hdr_end < hdr + sizeof(Trace)) {
+ ReleaseMemoryPagesToOS(hdr_end, hdr + sizeof(Trace));
+ uptr unused = hdr + sizeof(Trace) - hdr_end;
+ if (hdr_end != (uptr)MmapFixedNoAccess(hdr_end, unused)) {
+ Report("ThreadSanitizer: failed to mprotect(%p, %p)\n",
+ hdr_end, unused);
+ CHECK("unable to mprotect" && 0);
+ }
+ }
void *mem = internal_alloc(MBlockThreadContex, sizeof(ThreadContext));
return new(mem) ThreadContext(tid);
}
diff --git a/compiler-rt/test/tsan/mmap_lots.cpp b/compiler-rt/test/tsan/mmap_lots.cpp
new file mode 100644
index 000000000000..e1e8ac157bda
--- /dev/null
+++ b/compiler-rt/test/tsan/mmap_lots.cpp
@@ -0,0 +1,29 @@
+// RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
+
+// Test that mmap does not return unexpected addresses
+// (the check is in the interceptor).
+
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+int main() {
+ int fd = open("/dev/zero", O_RDWR);
+ if (fd == -1) perror("open(/dev/zero)"), exit(1);
+ for (size_t mmap_size = 64ull << 30; mmap_size >= 4 << 10; mmap_size /= 2) {
+ size_t allocated = 0;
+ while (mmap(0, mmap_size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE,
+ fd, 0) != MAP_FAILED) {
+ allocated += mmap_size;
+ }
+ fprintf(stderr, "allocated %zu with size %zu\n", allocated, mmap_size);
+ }
+ fprintf(stderr, "DONE\n");
+}
+
+// CHECK: DONE
More information about the llvm-commits
mailing list