mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 16:12:44 +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:
		
							parent
							
								
									ef9ac8a8a2
								
							
						
					
					
						commit
						d4509647d8
					
				
					 5 changed files with 72 additions and 5 deletions
				
			
		|  | @ -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) | ||||||
|  |  | ||||||
|  | @ -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; } | ||||||
|  |  | ||||||
|  | @ -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()); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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) | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling