unicorn-engine / unicorn

Unicorn CPU emulator framework (ARM, AArch64, M68K, Mips, Sparc, PowerPC, RiscV, S390x, TriCore, X86)
http://www.unicorn-engine.org
GNU General Public License v2.0
7.67k stars 1.35k forks source link

Unicorn 2.1.0: UC_ERR_READ_UNMAPPED when using high virtual addresses #2010

Open Antelox opened 2 months ago

Antelox commented 2 months ago

Hi,

Since the 2.1.0 release, I've been observing a crash happening while using very high virtual addresses.

Below a snippet that reproduces the issue:

from unicorn import Uc
from unicorn.unicorn_const import UC_ARCH_X86, UC_MODE_64
from unicorn.x86_const import UC_X86_REG_RAX

u = Uc(UC_ARCH_X86, UC_MODE_64)
u.mem_map(0x30000000000000, 0x1000)
u.mem_write(0x30000000000000, b'\x31\x32\x33\x34\x35\x36\x37\x38')
print(u.mem_read(0x30000000000000, 8))
u.reg_write(UC_X86_REG_RAX, 0x30000000000000)
print(hex(u.reg_read(UC_X86_REG_RAX)))
u.mem_map(0x200000, 0x1000)
u.mem_write(0x200000, b'\x48\x8b\x00') # mov rax, [rax]
u.emu_start(0x200000, 0x200003)
print(hex(u.reg_read(UC_X86_REG_RAX)))

The crash is this:

unicorn.unicorn_py3.unicorn.UcError: Invalid memory read (UC_ERR_READ_UNMAPPED)

The same code works fine with the version 2.0.1.post1

Digging among the many changes from a release to the other, I have seen the introduction of a uc_ctl called TLB_MODE (https://github.com/unicorn-engine/unicorn/blob/master/docs/FAQ.md#is-there-anyway-to-disable-softmmu-to-speed-up-execution).

Setting it to VIRTUAL solves the issue but I'm not totally sure if this is proper fix or just a side effect.

Any ideas? Thanks in advance!

PhilippTakacs commented 1 month ago

Setting it to VIRTUAL solves the issue but I'm not totally sure if this is proper fix or just a side effect.

Yes this is the proper fix.

With this release unicorn enables the softmmu of qemu and defaults to the mmu of the emulated target. By default the mmu of X86 only allows access to a limit part of the address space. To use the full virtual address space you can either configure the mmu of your emulation target or use the virtual mmu with by default does a 1:1 mapping.

wtdcode commented 1 month ago

~Quick debugging shows that we by default don't enable long mode, which is the root cause.~

The root cause is that, long mode is enabled while paging is disabled. This is indeed resulting a 1:1 mapping but note x86_64 only supports 52 bits of physical memory space while the address you are accessing is 54 bits. Therefore, it's a limitation of x86_64 MMU implementation.

I tried to simply extend the mask to 64bits (physical memory address) and this works, but I have no idea if this has further side effects. The best workaround so far is using a lower address or vtlb mode as said above.

Antelox commented 1 month ago

Hi, Thanks a lot to both of you for the explanation! In short I need to enable the VIRTUAL mode as reported in my first comment. I will do it and report issues, should I find any of them (Hopefully not :P ), so far so good.