1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 19:07:35 +00:00

UserspaceEmulator: Honor the read/write/execute bits in mmap regions

UE will now correctly crash when accessing an mmap memory region in
some way it's not supposed to be accessed.
This commit is contained in:
Andreas Kling 2020-11-14 15:13:50 +01:00
parent ef9ac8a8a2
commit d4509647d8
5 changed files with 72 additions and 5 deletions

View file

@ -920,9 +920,17 @@ u32 Emulator::virt$unveil(u32)
return 0; return 0;
} }
u32 Emulator::virt$mprotect(FlatPtr, size_t, int) u32 Emulator::virt$mprotect(FlatPtr base, size_t size, int prot)
{ {
return 0; if (auto* region = mmu().find_region({ m_cpu.ds(), base })) {
if (!region->is_mmap())
return -EINVAL;
ASSERT(region->size() == size);
auto& mmap_region = *(MmapRegion*)region;
mmap_region.set_prot(prot);
return 0;
}
return -EINVAL;
} }
u32 Emulator::virt$madvise(FlatPtr, size_t, int) u32 Emulator::virt$madvise(FlatPtr, size_t, int)

View file

@ -50,13 +50,15 @@ public:
u8* data() { return m_data; } u8* data() { return m_data; }
u8* shadow_data() { return m_shadow_data; } u8* shadow_data() { return m_shadow_data; }
bool is_readable() const { return m_prot & PROT_READ; } virtual bool is_readable() const override { return m_prot & PROT_READ; }
bool is_writable() const { return m_prot & PROT_WRITE; } virtual bool is_writable() const override { return m_prot & PROT_WRITE; }
bool is_executable() const { return m_prot & PROT_EXEC; } virtual bool is_executable() const override { return m_prot & PROT_EXEC; }
bool is_malloc_block() const { return m_malloc; } bool is_malloc_block() const { return m_malloc; }
void set_malloc(bool b) { m_malloc = b; } void set_malloc(bool b) { m_malloc = b; }
void set_prot(int prot) { m_prot = prot; }
private: private:
MmapRegion(u32 base, u32 size, int prot); MmapRegion(u32 base, u32 size, int prot);
virtual bool is_mmap() const override { return true; } virtual bool is_mmap() const override { return true; }

View file

@ -134,6 +134,12 @@ void SoftCPU::update_code_cache()
auto* region = m_emulator.mmu().find_region({ cs(), eip() }); auto* region = m_emulator.mmu().find_region({ cs(), eip() });
ASSERT(region); ASSERT(region);
if (!region->is_executable()) {
reportln("SoftCPU::update_code_cache: Non-readable region @ {:p}", eip());
Emulator::the().dump_backtrace();
TODO();
}
m_cached_code_ptr = region->cacheable_ptr(eip() - region->base()); m_cached_code_ptr = region->cacheable_ptr(eip() - region->base());
m_cached_code_end = region->cacheable_ptr(region->size()); m_cached_code_end = region->cacheable_ptr(region->size());
} }

View file

@ -75,6 +75,12 @@ ValueWithShadow<u8> SoftMMU::read8(X86::LogicalAddress address)
TODO(); TODO();
} }
if (!region->is_readable()) {
reportln("SoftMMU::read8: Non-readable region @ {:p}", address.offset());
Emulator::the().dump_backtrace();
TODO();
}
return region->read8(address.offset() - region->base()); return region->read8(address.offset() - region->base());
} }
@ -87,6 +93,12 @@ ValueWithShadow<u16> SoftMMU::read16(X86::LogicalAddress address)
TODO(); TODO();
} }
if (!region->is_readable()) {
reportln("SoftMMU::read16: Non-readable region @ {:p}", address.offset());
Emulator::the().dump_backtrace();
TODO();
}
return region->read16(address.offset() - region->base()); return region->read16(address.offset() - region->base());
} }
@ -99,6 +111,12 @@ ValueWithShadow<u32> SoftMMU::read32(X86::LogicalAddress address)
TODO(); TODO();
} }
if (!region->is_readable()) {
reportln("SoftMMU::read32: Non-readable region @ {:p}", address.offset());
Emulator::the().dump_backtrace();
TODO();
}
return region->read32(address.offset() - region->base()); return region->read32(address.offset() - region->base());
} }
@ -111,6 +129,12 @@ ValueWithShadow<u64> SoftMMU::read64(X86::LogicalAddress address)
TODO(); TODO();
} }
if (!region->is_readable()) {
reportln("SoftMMU::read64: Non-readable region @ {:p}", address.offset());
Emulator::the().dump_backtrace();
TODO();
}
return region->read64(address.offset() - region->base()); return region->read64(address.offset() - region->base());
} }
@ -123,6 +147,11 @@ void SoftMMU::write8(X86::LogicalAddress address, ValueWithShadow<u8> value)
TODO(); TODO();
} }
if (!region->is_writable()) {
reportln("SoftMMU::write8: Non-writable region @ {:p}", address.offset());
Emulator::the().dump_backtrace();
TODO();
}
region->write8(address.offset() - region->base(), value); region->write8(address.offset() - region->base(), value);
} }
@ -135,6 +164,12 @@ void SoftMMU::write16(X86::LogicalAddress address, ValueWithShadow<u16> value)
TODO(); TODO();
} }
if (!region->is_writable()) {
reportln("SoftMMU::write16: Non-writable region @ {:p}", address.offset());
Emulator::the().dump_backtrace();
TODO();
}
region->write16(address.offset() - region->base(), value); region->write16(address.offset() - region->base(), value);
} }
@ -147,6 +182,12 @@ void SoftMMU::write32(X86::LogicalAddress address, ValueWithShadow<u32> value)
TODO(); TODO();
} }
if (!region->is_writable()) {
reportln("SoftMMU::write32: Non-writable region @ {:p}", address.offset());
Emulator::the().dump_backtrace();
TODO();
}
region->write32(address.offset() - region->base(), value); region->write32(address.offset() - region->base(), value);
} }
@ -159,6 +200,12 @@ void SoftMMU::write64(X86::LogicalAddress address, ValueWithShadow<u64> value)
TODO(); TODO();
} }
if (!region->is_writable()) {
reportln("SoftMMU::write64: Non-writable region @ {:p}", address.offset());
Emulator::the().dump_backtrace();
TODO();
}
region->write64(address.offset() - region->base(), value); region->write64(address.offset() - region->base(), value);
} }

View file

@ -69,6 +69,10 @@ public:
bool is_text() const { return m_text; } bool is_text() const { return m_text; }
void set_text(bool b) { m_text = b; } void set_text(bool b) { m_text = b; }
virtual bool is_readable() const { return true; }
virtual bool is_writable() const { return true; }
virtual bool is_executable() const { return true; }
protected: protected:
Region(u32 base, u32 size) Region(u32 base, u32 size)
: m_base(base) : m_base(base)