-
Notifications
You must be signed in to change notification settings - Fork 14.4k
[scudo] Modify header corrupption error message #126812
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
Conversation
Update the error message to be explicit that this is likely due to memory corruption. In addition, check if the chunk header is all zero, which could mean corruption or an attempt to free a pointer after the memory has been released to the kernel. This case results in a slightly different error message to also indicate this could still be a double free.
@llvm/pr-subscribers-compiler-rt-sanitizer Author: Christopher Ferris (cferris1000) ChangesUpdate the error message to be explicit that this is likely due to memory corruption. In addition, check if the chunk header is all zero, which could mean corruption or an attempt to free a pointer after the memory has been released to the kernel. This case results in a slightly different error message to also indicate this could still be a double free. Full diff: https://github.com/llvm/llvm-project/pull/126812.diff 4 Files Affected:
diff --git a/compiler-rt/lib/scudo/standalone/chunk.h b/compiler-rt/lib/scudo/standalone/chunk.h
index 9228df0471890..a1b8e723d4cb5 100644
--- a/compiler-rt/lib/scudo/standalone/chunk.h
+++ b/compiler-rt/lib/scudo/standalone/chunk.h
@@ -125,7 +125,7 @@ inline void loadHeader(u32 Cookie, const void *Ptr,
*NewUnpackedHeader = bit_cast<UnpackedHeader>(NewPackedHeader);
if (UNLIKELY(NewUnpackedHeader->Checksum !=
computeHeaderChecksum(Cookie, Ptr, NewUnpackedHeader)))
- reportHeaderCorruption(const_cast<void *>(Ptr));
+ reportHeaderCorruption(NewUnpackedHeader, const_cast<void *>(Ptr));
}
inline bool isValid(u32 Cookie, const void *Ptr,
diff --git a/compiler-rt/lib/scudo/standalone/report.cpp b/compiler-rt/lib/scudo/standalone/report.cpp
index 9cef0adc0bb31..14a4066d37200 100644
--- a/compiler-rt/lib/scudo/standalone/report.cpp
+++ b/compiler-rt/lib/scudo/standalone/report.cpp
@@ -9,6 +9,7 @@
#include "report.h"
#include "atomic_helpers.h"
+#include "chunk.h"
#include "string_utils.h"
#include <stdarg.h>
@@ -65,9 +66,18 @@ void NORETURN reportInvalidFlag(const char *FlagType, const char *Value) {
// The checksum of a chunk header is invalid. This could be caused by an
// {over,under}write of the header, a pointer that is not an actual chunk.
-void NORETURN reportHeaderCorruption(void *Ptr) {
- ScopedErrorReport Report;
- Report.append("corrupted chunk header at address %p\n", Ptr);
+void NORETURN reportHeaderCorruption(void *Header, void *Ptr) {
+ ScopedErrorReport Report;
+ Report.append("corrupted chunk header at address %p", Ptr);
+ if (*static_cast<Chunk::PackedHeader *>(Header) == 0U) {
+ // Header all zero, which could indicate that this might be a pointer that
+ // has been double freed but the memory has been released to the kernel.
+ Report.append(": chunk header is zero and might indicate memory corruption "
+ "or a double free\n",
+ Ptr);
+ } else {
+ Report.append(": most likely due to memory corruption\n", Ptr);
+ }
}
// The allocator was compiled with parameters that conflict with field size
diff --git a/compiler-rt/lib/scudo/standalone/report.h b/compiler-rt/lib/scudo/standalone/report.h
index a510fdaebb6de..c0214b51560e9 100644
--- a/compiler-rt/lib/scudo/standalone/report.h
+++ b/compiler-rt/lib/scudo/standalone/report.h
@@ -12,7 +12,6 @@
#include "internal_defs.h"
namespace scudo {
-
// Reports are *fatal* unless stated otherwise.
// Generic error, adds newline to end of message.
@@ -25,7 +24,7 @@ void NORETURN reportRawError(const char *Message);
void NORETURN reportInvalidFlag(const char *FlagType, const char *Value);
// Chunk header related errors.
-void NORETURN reportHeaderCorruption(void *Ptr);
+void NORETURN reportHeaderCorruption(void *Header, void *Ptr);
// Sanity checks related error.
void NORETURN reportSanityCheckError(const char *Field);
diff --git a/compiler-rt/lib/scudo/standalone/tests/report_test.cpp b/compiler-rt/lib/scudo/standalone/tests/report_test.cpp
index 6c46243053d9e..514837df1a43a 100644
--- a/compiler-rt/lib/scudo/standalone/tests/report_test.cpp
+++ b/compiler-rt/lib/scudo/standalone/tests/report_test.cpp
@@ -8,6 +8,7 @@
#include "tests/scudo_unit_test.h"
+#include "chunk.h"
#include "report.h"
TEST(ScudoReportDeathTest, Check) {
@@ -20,9 +21,11 @@ TEST(ScudoReportDeathTest, Check) {
TEST(ScudoReportDeathTest, Generic) {
// Potentially unused if EXPECT_DEATH isn't defined.
UNUSED void *P = reinterpret_cast<void *>(0x42424242U);
+ UNUSED scudo::Chunk::PackedHeader Header = {};
EXPECT_DEATH(scudo::reportError("TEST123"), "Scudo ERROR.*TEST123");
EXPECT_DEATH(scudo::reportInvalidFlag("ABC", "DEF"), "Scudo ERROR.*ABC.*DEF");
- EXPECT_DEATH(scudo::reportHeaderCorruption(P), "Scudo ERROR.*42424242");
+ EXPECT_DEATH(scudo::reportHeaderCorruption(&Header, P),
+ "Scudo ERROR.*42424242");
EXPECT_DEATH(scudo::reportSanityCheckError("XYZ"), "Scudo ERROR.*XYZ");
EXPECT_DEATH(scudo::reportAlignmentTooBig(123, 456), "Scudo ERROR.*123.*456");
EXPECT_DEATH(scudo::reportAllocationSizeTooBig(123, 456, 789),
@@ -54,6 +57,19 @@ TEST(ScudoReportDeathTest, CSpecific) {
"Scudo ERROR.*123.*456");
}
+TEST(ScudoReportDeathTest, HeaderCorruption) {
+ UNUSED void *P = reinterpret_cast<void *>(0x42424242U);
+ UNUSED scudo::Chunk::PackedHeader Header = {};
+ EXPECT_DEATH(scudo::reportHeaderCorruption(&Header, P),
+ "Scudo ERROR.*corrupted chunk header at address 0x.*42424242: "
+ "chunk header is zero and might indicate memory "
+ "corruption or a double free");
+ Header = 10U;
+ EXPECT_DEATH(scudo::reportHeaderCorruption(&Header, P),
+ "Scudo ERROR.*corrupted chunk header at address 0x.*42424242: "
+ "most likely due to memory corruption");
+}
+
#if SCUDO_LINUX || SCUDO_TRUSTY || SCUDO_ANDROID
#include "report_linux.h"
|
Update the error message to be explicit that this is likely due to memory corruption. In addition, check if the chunk header is all zero, which could mean corruption or an attempt to free a pointer after the memory has been released to the kernel. This case results in a slightly different error message to also indicate this could still be a double free.
Update the error message to be explicit that this is likely due to memory corruption. In addition, check if the chunk header is all zero, which could mean corruption or an attempt to free a pointer after the memory has been released to the kernel. This case results in a slightly different error message to also indicate this could still be a double free.
Update the error message to be explicit that this is likely due to memory corruption. In addition, check if the chunk header is all zero, which could mean corruption or an attempt to free a pointer after the memory has been released to the kernel. This case results in a slightly different error message to also indicate this could still be a double free.
Update the error message to be explicit that this is likely due to memory corruption.
In addition, check if the chunk header is all zero, which could mean corruption or an attempt to free a pointer after the memory has been released to the kernel. This case results in a slightly different error message to also indicate this could still be a double free.