1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-24 06:05:08 +00:00

UserspaceEmulator: When auditing accesses, show nearest mallocation

Instead of always showing the preceding mallocation, prefer showing the
following one *if* it's closer to the audited address.

This makes it easier to find bugs where the access is just before an
allocation instead of just after it.
This commit is contained in:
Andreas Kling 2020-11-13 10:58:31 +01:00
parent 3a2727844c
commit ddc5ce1800
2 changed files with 37 additions and 8 deletions

View file

@ -136,6 +136,18 @@ MallocTracer::Mallocation* MallocTracer::find_mallocation_before(FlatPtr address
return found_mallocation; return found_mallocation;
} }
MallocTracer::Mallocation* MallocTracer::find_mallocation_after(FlatPtr address)
{
Mallocation* found_mallocation = nullptr;
for (auto& mallocation : m_mallocations) {
if (mallocation.address <= address)
continue;
if (!found_mallocation || (mallocation.address < found_mallocation->address))
found_mallocation = &mallocation;
}
return found_mallocation;
}
void MallocTracer::audit_read(FlatPtr address, size_t size) void MallocTracer::audit_read(FlatPtr address, size_t size)
{ {
if (!m_auditing_enabled) if (!m_auditing_enabled)
@ -149,10 +161,18 @@ void MallocTracer::audit_read(FlatPtr address, size_t size)
if (!mallocation) { if (!mallocation) {
reportln("\n=={}== \033[31;1mHeap buffer overflow\033[0m, invalid {}-byte read at address {:p}", getpid(), size, address); reportln("\n=={}== \033[31;1mHeap buffer overflow\033[0m, invalid {}-byte read at address {:p}", getpid(), size, address);
Emulator::the().dump_backtrace(); Emulator::the().dump_backtrace();
if ((mallocation = find_mallocation_before(address))) { auto* mallocation_before = find_mallocation_before(address);
size_t offset_into_mallocation = address - mallocation->address; auto* mallocation_after = find_mallocation_after(address);
reportln("=={}== Address is {} byte(s) after block of size {}, allocated at:", getpid(), offset_into_mallocation - mallocation->size, mallocation->size); size_t distance_to_mallocation_before = mallocation_before ? (address - mallocation_before->address - mallocation_before->size) : 0;
Emulator::the().dump_backtrace(mallocation->malloc_backtrace); size_t distance_to_mallocation_after = mallocation_after ? (mallocation_after->address - address) : 0;
if (mallocation_before && (!mallocation_after || distance_to_mallocation_before < distance_to_mallocation_after)) {
reportln("=={}== Address is {} byte(s) after block of size {}, identity {:p}, allocated at:", getpid(), distance_to_mallocation_before, mallocation_before->size, mallocation_before->address);
Emulator::the().dump_backtrace(mallocation_before->malloc_backtrace);
return;
}
if (mallocation_after && (!mallocation_before || distance_to_mallocation_after < distance_to_mallocation_before)) {
reportln("=={}== Address is {} byte(s) before block of size {}, identity {:p}, allocated at:", getpid(), distance_to_mallocation_after, mallocation_after->size, mallocation_after->address);
Emulator::the().dump_backtrace(mallocation_after->malloc_backtrace);
} }
return; return;
} }
@ -182,10 +202,18 @@ void MallocTracer::audit_write(FlatPtr address, size_t size)
if (!mallocation) { if (!mallocation) {
reportln("\n=={}== \033[31;1mHeap buffer overflow\033[0m, invalid {}-byte write at address {:p}", getpid(), size, address); reportln("\n=={}== \033[31;1mHeap buffer overflow\033[0m, invalid {}-byte write at address {:p}", getpid(), size, address);
Emulator::the().dump_backtrace(); Emulator::the().dump_backtrace();
if ((mallocation = find_mallocation_before(address))) { auto* mallocation_before = find_mallocation_before(address);
size_t offset_into_mallocation = address - mallocation->address; auto* mallocation_after = find_mallocation_after(address);
reportln("=={}== Address is {} byte(s) into block of size {}, allocated at:", getpid(), offset_into_mallocation, mallocation->size); size_t distance_to_mallocation_before = mallocation_before ? (address - mallocation_before->address - mallocation_before->size) : 0;
Emulator::the().dump_backtrace(mallocation->malloc_backtrace); size_t distance_to_mallocation_after = mallocation_after ? (mallocation_after->address - address) : 0;
if (mallocation_before && (!mallocation_after || distance_to_mallocation_before < distance_to_mallocation_after)) {
reportln("=={}== Address is {} byte(s) after block of size {}, identity {:p}, allocated at:", getpid(), distance_to_mallocation_before, mallocation_before->size, mallocation_before->address);
Emulator::the().dump_backtrace(mallocation_before->malloc_backtrace);
return;
}
if (mallocation_after && (!mallocation_before || distance_to_mallocation_after < distance_to_mallocation_before)) {
reportln("=={}== Address is {} byte(s) before block of size {}, identity {:p}, allocated at:", getpid(), distance_to_mallocation_after, mallocation_after->size, mallocation_after->address);
Emulator::the().dump_backtrace(mallocation_after->malloc_backtrace);
} }
return; return;
} }

View file

@ -64,6 +64,7 @@ private:
Mallocation* find_mallocation(FlatPtr); Mallocation* find_mallocation(FlatPtr);
Mallocation* find_mallocation_before(FlatPtr); Mallocation* find_mallocation_before(FlatPtr);
Mallocation* find_mallocation_after(FlatPtr);
bool is_reachable(const Mallocation&) const; bool is_reachable(const Mallocation&) const;
Vector<Mallocation> m_mallocations; Vector<Mallocation> m_mallocations;