mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 04:18:12 +00:00
UserspaceEmulator: Catch use-after-frees by tracking malloc/free :^)
This patch introduces a "MallocTracer" to the UserspaceEmulator. If this object is present on the Emulator, it can be notified whenever the emulated program does a malloc() or free(). The notifications come in via a magic instruction sequence that we embed in the LibC malloc() and free() functions. The sequence is: "salc x2, push reg32 x2, pop reg32 x3" The data about the malloc/free operation is in the three pushes. We make sure the sequence is harmless when running natively. Memory accesses on MmapRegion are then audited to see if they fall inside a known-to-be-freed malloc chunk. If so, we complain loud and red in the debugger output. :^) This is very, very cool! :^) It's also a whole lot slower than before, since now we're auditing memory accesses against a new set of metadata. This will need to be optimized (and running in this mode should be opt-in, perhaps even a separate program, etc.)
This commit is contained in:
parent
d7c87e84f3
commit
c314292319
9 changed files with 274 additions and 5 deletions
|
@ -61,6 +61,13 @@ MmapRegion::~MmapRegion()
|
|||
free(m_data);
|
||||
}
|
||||
|
||||
bool MmapRegion::is_malloc_block() const
|
||||
{
|
||||
// FIXME: This is obviously incomplete!
|
||||
// We should somehow know which mmap regions are malloc blocks.
|
||||
return !m_file_backed;
|
||||
}
|
||||
|
||||
u8 MmapRegion::read8(FlatPtr offset)
|
||||
{
|
||||
if (!is_readable()) {
|
||||
|
@ -69,6 +76,11 @@ u8 MmapRegion::read8(FlatPtr offset)
|
|||
TODO();
|
||||
}
|
||||
|
||||
if (is_malloc_block()) {
|
||||
if (auto* tracer = Emulator::the().malloc_tracer())
|
||||
tracer->audit_read(base() + offset, 1);
|
||||
}
|
||||
|
||||
ASSERT(offset < size());
|
||||
return *reinterpret_cast<const u8*>(m_data + offset);
|
||||
}
|
||||
|
@ -81,6 +93,11 @@ u16 MmapRegion::read16(u32 offset)
|
|||
TODO();
|
||||
}
|
||||
|
||||
if (is_malloc_block()) {
|
||||
if (auto* tracer = Emulator::the().malloc_tracer())
|
||||
tracer->audit_read(base() + offset, 2);
|
||||
}
|
||||
|
||||
ASSERT(offset + 1 < size());
|
||||
return *reinterpret_cast<const u16*>(m_data + offset);
|
||||
}
|
||||
|
@ -93,6 +110,11 @@ u32 MmapRegion::read32(u32 offset)
|
|||
TODO();
|
||||
}
|
||||
|
||||
if (is_malloc_block()) {
|
||||
if (auto* tracer = Emulator::the().malloc_tracer())
|
||||
tracer->audit_read(base() + offset, 4);
|
||||
}
|
||||
|
||||
ASSERT(offset + 3 < size());
|
||||
return *reinterpret_cast<const u32*>(m_data + offset);
|
||||
}
|
||||
|
@ -105,6 +127,11 @@ void MmapRegion::write8(u32 offset, u8 value)
|
|||
TODO();
|
||||
}
|
||||
|
||||
if (is_malloc_block()) {
|
||||
if (auto* tracer = Emulator::the().malloc_tracer())
|
||||
tracer->audit_write(base() + offset, 1);
|
||||
}
|
||||
|
||||
ASSERT(offset < size());
|
||||
*reinterpret_cast<u8*>(m_data + offset) = value;
|
||||
}
|
||||
|
@ -117,6 +144,11 @@ void MmapRegion::write16(u32 offset, u16 value)
|
|||
TODO();
|
||||
}
|
||||
|
||||
if (is_malloc_block()) {
|
||||
if (auto* tracer = Emulator::the().malloc_tracer())
|
||||
tracer->audit_write(base() + offset, 2);
|
||||
}
|
||||
|
||||
ASSERT(offset + 1 < size());
|
||||
*reinterpret_cast<u16*>(m_data + offset) = value;
|
||||
}
|
||||
|
@ -129,6 +161,11 @@ void MmapRegion::write32(u32 offset, u32 value)
|
|||
TODO();
|
||||
}
|
||||
|
||||
if (is_malloc_block()) {
|
||||
if (auto* tracer = Emulator::the().malloc_tracer())
|
||||
tracer->audit_write(base() + offset, 4);
|
||||
}
|
||||
|
||||
ASSERT(offset + 3 < size());
|
||||
*reinterpret_cast<u32*>(m_data + offset) = value;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue