-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[msan] Unwind stack before fatal reports #77168
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[msan] Unwind stack before fatal reports #77168
Conversation
@llvm/pr-subscribers-compiler-rt-sanitizer Author: Vitaly Buka (vitalybuka) ChangesMsan does not unwind stack in malloc without origins, but we still need trace Full diff: https://github.com/llvm/llvm-project/pull/77168.diff 4 Files Affected:
diff --git a/compiler-rt/lib/msan/msan.h b/compiler-rt/lib/msan/msan.h
index 25fa2212bdadd3..b717161577a1db 100644
--- a/compiler-rt/lib/msan/msan.h
+++ b/compiler-rt/lib/msan/msan.h
@@ -321,6 +321,9 @@ const int STACK_TRACE_TAG_VPTR = STACK_TRACE_TAG_FIELDS + 1;
stack.Unwind(pc, bp, nullptr, common_flags()->fast_unwind_on_fatal); \
}
+#define GET_FATAL_STACK_TRACE \
+ GET_FATAL_STACK_TRACE_PC_BP(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME())
+
class ScopedThreadLocalStateBackup {
public:
ScopedThreadLocalStateBackup() { Backup(); }
diff --git a/compiler-rt/lib/msan/msan_allocator.cpp b/compiler-rt/lib/msan/msan_allocator.cpp
index 72a7f980d39fb0..f71f59cedf820e 100644
--- a/compiler-rt/lib/msan/msan_allocator.cpp
+++ b/compiler-rt/lib/msan/msan_allocator.cpp
@@ -180,17 +180,19 @@ void MsanThreadLocalMallocStorage::CommitBack() {
static void *MsanAllocate(StackTrace *stack, uptr size, uptr alignment,
bool zeroise) {
- if (size > max_malloc_size) {
+ if (UNLIKELY(size > max_malloc_size)) {
if (AllocatorMayReturnNull()) {
Report("WARNING: MemorySanitizer failed to allocate 0x%zx bytes\n", size);
return nullptr;
}
- ReportAllocationSizeTooBig(size, max_malloc_size, stack);
+ GET_FATAL_STACK_TRACE;
+ ReportAllocationSizeTooBig(size, max_malloc_size, &stack);
}
if (UNLIKELY(IsRssLimitExceeded())) {
if (AllocatorMayReturnNull())
return nullptr;
- ReportRssLimitExceeded(stack);
+ GET_FATAL_STACK_TRACE;
+ ReportRssLimitExceeded(&stack);
}
MsanThread *t = GetCurrentThread();
void *allocated;
@@ -206,7 +208,8 @@ static void *MsanAllocate(StackTrace *stack, uptr size, uptr alignment,
SetAllocatorOutOfMemory();
if (AllocatorMayReturnNull())
return nullptr;
- ReportOutOfMemory(size, stack);
+ GET_FATAL_STACK_TRACE;
+ ReportOutOfMemory(size, &stack);
}
Metadata *meta =
reinterpret_cast<Metadata *>(allocator.GetMetaData(allocated));
@@ -288,7 +291,8 @@ static void *MsanCalloc(StackTrace *stack, uptr nmemb, uptr size) {
if (UNLIKELY(CheckForCallocOverflow(size, nmemb))) {
if (AllocatorMayReturnNull())
return nullptr;
- ReportCallocOverflow(nmemb, size, stack);
+ GET_FATAL_STACK_TRACE;
+ ReportCallocOverflow(nmemb, size, &stack);
}
return MsanAllocate(stack, nmemb * size, sizeof(u64), true);
}
@@ -343,7 +347,8 @@ void *msan_reallocarray(void *ptr, uptr nmemb, uptr size, StackTrace *stack) {
errno = errno_ENOMEM;
if (AllocatorMayReturnNull())
return nullptr;
- ReportReallocArrayOverflow(nmemb, size, stack);
+ GET_FATAL_STACK_TRACE;
+ ReportReallocArrayOverflow(nmemb, size, &stack);
}
return msan_realloc(ptr, nmemb * size, stack);
}
@@ -358,7 +363,8 @@ void *msan_pvalloc(uptr size, StackTrace *stack) {
errno = errno_ENOMEM;
if (AllocatorMayReturnNull())
return nullptr;
- ReportPvallocOverflow(size, stack);
+ GET_FATAL_STACK_TRACE;
+ ReportPvallocOverflow(size, &stack);
}
// pvalloc(0) should allocate one page.
size = size ? RoundUpTo(size, PageSize) : PageSize;
@@ -370,7 +376,8 @@ void *msan_aligned_alloc(uptr alignment, uptr size, StackTrace *stack) {
errno = errno_EINVAL;
if (AllocatorMayReturnNull())
return nullptr;
- ReportInvalidAlignedAllocAlignment(size, alignment, stack);
+ GET_FATAL_STACK_TRACE;
+ ReportInvalidAlignedAllocAlignment(size, alignment, &stack);
}
return SetErrnoOnNull(MsanAllocate(stack, size, alignment, false));
}
@@ -380,7 +387,8 @@ void *msan_memalign(uptr alignment, uptr size, StackTrace *stack) {
errno = errno_EINVAL;
if (AllocatorMayReturnNull())
return nullptr;
- ReportInvalidAllocationAlignment(alignment, stack);
+ GET_FATAL_STACK_TRACE;
+ ReportInvalidAllocationAlignment(alignment, &stack);
}
return SetErrnoOnNull(MsanAllocate(stack, size, alignment, false));
}
@@ -390,7 +398,8 @@ int msan_posix_memalign(void **memptr, uptr alignment, uptr size,
if (UNLIKELY(!CheckPosixMemalignAlignment(alignment))) {
if (AllocatorMayReturnNull())
return errno_EINVAL;
- ReportInvalidPosixMemalignAlignment(alignment, stack);
+ GET_FATAL_STACK_TRACE;
+ ReportInvalidPosixMemalignAlignment(alignment, &stack);
}
void *ptr = MsanAllocate(stack, size, alignment, false);
if (UNLIKELY(!ptr))
diff --git a/compiler-rt/lib/msan/msan_new_delete.cpp b/compiler-rt/lib/msan/msan_new_delete.cpp
index d4e95c0f65137d..3329a05cca2a86 100644
--- a/compiler-rt/lib/msan/msan_new_delete.cpp
+++ b/compiler-rt/lib/msan/msan_new_delete.cpp
@@ -30,16 +30,22 @@ namespace std {
// TODO(alekseys): throw std::bad_alloc instead of dying on OOM.
-#define OPERATOR_NEW_BODY(nothrow) \
- GET_MALLOC_STACK_TRACE; \
- void *res = msan_malloc(size, &stack);\
- if (!nothrow && UNLIKELY(!res)) ReportOutOfMemory(size, &stack);\
- return res
-#define OPERATOR_NEW_BODY_ALIGN(nothrow) \
- GET_MALLOC_STACK_TRACE;\
- void *res = msan_memalign((uptr)align, size, &stack);\
- if (!nothrow && UNLIKELY(!res)) ReportOutOfMemory(size, &stack);\
- return res;
+# define OPERATOR_NEW_BODY(nothrow) \
+ GET_MALLOC_STACK_TRACE; \
+ void *res = msan_malloc(size, &stack); \
+ if (!nothrow && UNLIKELY(!res)) { \
+ GET_FATAL_STACK_TRACE; \
+ ReportOutOfMemory(size, &stack); \
+ } \
+ return res
+# define OPERATOR_NEW_BODY_ALIGN(nothrow) \
+ GET_MALLOC_STACK_TRACE; \
+ void *res = msan_memalign((uptr)align, size, &stack); \
+ if (!nothrow && UNLIKELY(!res)) { \
+ GET_FATAL_STACK_TRACE; \
+ ReportOutOfMemory(size, &stack); \
+ } \
+ return res;
INTERCEPTOR_ATTRIBUTE
void *operator new(size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }
diff --git a/compiler-rt/test/sanitizer_common/TestCases/max_allocation_size.cpp b/compiler-rt/test/sanitizer_common/TestCases/max_allocation_size.cpp
index ace28965f3c1ba..c74f241c32b754 100644
--- a/compiler-rt/test/sanitizer_common/TestCases/max_allocation_size.cpp
+++ b/compiler-rt/test/sanitizer_common/TestCases/max_allocation_size.cpp
@@ -35,7 +35,7 @@
// RUN: | FileCheck %s --check-prefix=CHECK-nnCRASH
// RUN: %env_tool_opts=max_allocation_size_mb=2:allocator_may_return_null=1 \
// RUN: %run %t new-nothrow 2>&1 | FileCheck %s --check-prefix=CHECK-NULL
-// RUN: %env_tool_opts=max_allocation_size_mb=2:allocator_may_return_null=0 \
+// RUN: %env_tool_opts=max_allocation_size_mb=2:allocator_may_return_null=0:fast_unwind_on_malloc=0 \
// RUN: not %run %t strndup 2>&1 | FileCheck %s --check-prefix=CHECK-sCRASH
// RUN: %env_tool_opts=max_allocation_size_mb=2:allocator_may_return_null=1 \
// RUN: %run %t strndup 2>&1 | FileCheck %s --check-prefix=CHECK-NULL
@@ -123,20 +123,28 @@ int main(int Argc, char **Argv) {
}
// CHECK-mCRASH: malloc:
+// CHECK-mCRASH: #{{[0-9]+.*}}max_allocation_size.cpp
// CHECK-mCRASH: {{SUMMARY: .*Sanitizer: allocation-size-too-big}}
// CHECK-cCRASH: calloc:
+// CHECK-cCRASH: #{{[0-9]+.*}}max_allocation_size.cpp
// CHECK-cCRASH: {{SUMMARY: .*Sanitizer: allocation-size-too-big}}
// CHECK-rCRASH: realloc:
+// CHECK-rCRASH: #{{[0-9]+.*}}max_allocation_size.cpp
// CHECK-rCRASH: {{SUMMARY: .*Sanitizer: allocation-size-too-big}}
// CHECK-mrCRASH: realloc-after-malloc:
+// CHECK-mrCRASH: #{{[0-9]+.*}}max_allocation_size.cpp
// CHECK-mrCRASH: {{SUMMARY: .*Sanitizer: allocation-size-too-big}}
// CHECK-nCRASH: new:
+// CHECK-nCRASH: #{{[0-9]+.*}}max_allocation_size.cpp
// CHECK-nCRASH: {{SUMMARY: .*Sanitizer: allocation-size-too-big}}
// CHECK-nCRASH-OOM: new:
+// CHECK-nCRASH-OOM: #{{[0-9]+.*}}max_allocation_size.cpp
// CHECK-nCRASH-OOM: {{SUMMARY: .*Sanitizer: out-of-memory}}
// CHECK-nnCRASH: new-nothrow:
+// CHECK-nnCRASH: #{{[0-9]+.*}}max_allocation_size.cpp
// CHECK-nnCRASH: {{SUMMARY: .*Sanitizer: allocation-size-too-big}}
// CHECK-sCRASH: strndup:
+// CHECK-sCRASH: #{{[0-9]+.*}}max_allocation_size.cpp
// CHECK-sCRASH: {{SUMMARY: .*Sanitizer: allocation-size-too-big}}
// CHECK-NULL: {{malloc|calloc|calloc-overflow|realloc|realloc-after-malloc|new-nothrow|strndup}}
|
In some functions there is a parameter |
That's kind of convention for all sanitizers, if we have macro, it create |
4301f9a
to
1de5a3d
Compare
Ah, I'm not concerned. You make the call whether the parameter or the local variable (both named |
nvm. You changed the patch to reuse the variable |
Msan does not unwind stack in malloc without origins, but we still need trace for fatal errors.
Msan does not unwind stack in malloc without origins, but we still need trace
for fatal errors.