Skip to content

[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

Merged
merged 1 commit into from
Feb 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler-rt/lib/scudo/standalone/chunk.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
16 changes: 13 additions & 3 deletions compiler-rt/lib/scudo/standalone/report.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "report.h"

#include "atomic_helpers.h"
#include "chunk.h"
#include "string_utils.h"

#include <stdarg.h>
Expand Down Expand Up @@ -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
Expand Down
3 changes: 1 addition & 2 deletions compiler-rt/lib/scudo/standalone/report.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
#include "internal_defs.h"

namespace scudo {

// Reports are *fatal* unless stated otherwise.

// Generic error, adds newline to end of message.
Expand All @@ -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);
Expand Down
18 changes: 17 additions & 1 deletion compiler-rt/lib/scudo/standalone/tests/report_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "tests/scudo_unit_test.h"

#include "chunk.h"
#include "report.h"

TEST(ScudoReportDeathTest, Check) {
Expand All @@ -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),
Expand Down Expand Up @@ -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"

Expand Down