1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 06:58:11 +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:
Andreas Kling 2020-07-15 21:46:50 +02:00
parent d7c87e84f3
commit c314292319
9 changed files with 274 additions and 5 deletions

View file

@ -66,6 +66,7 @@ Emulator::Emulator(const Vector<String>& arguments, NonnullRefPtr<ELF::Loader> e
: m_elf(move(elf))
, m_cpu(*this)
{
m_malloc_tracer = make<MallocTracer>();
ASSERT(!s_the);
s_the = this;
setup_stack(arguments);
@ -167,12 +168,20 @@ int Emulator::exec()
return m_exit_status;
}
bool Emulator::is_in_malloc_or_free() const
{
auto symbol = m_elf->symbolicate(m_cpu.eip());
return symbol.starts_with("malloc") || symbol.starts_with("free");
}
static pid_t s_pid = getpid();
void Emulator::dump_backtrace()
{
u32 offset = 0;
String symbol = m_elf->symbolicate(m_cpu.eip(), &offset);
printf("> %#08x %s +%#x\n", m_cpu.eip(), symbol.characters(), offset);
dbgprintf("==%d== %#08x %s +%#x\n", s_pid, m_cpu.eip(), symbol.characters(), offset);
u32 frame_ptr = m_cpu.ebp();
while (frame_ptr) {
@ -181,7 +190,7 @@ void Emulator::dump_backtrace()
return;
symbol = m_elf->symbolicate(ret_ptr, &offset);
if (!symbol.is_null())
printf("> %#08x %s +%#x\n", ret_ptr, symbol.characters(), offset);
dbgprintf("==%d== %#08x %s +%#x\n", s_pid, ret_ptr, symbol.characters(), offset);
frame_ptr = m_mmu.read32({ 0x20, frame_ptr });
}