cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
QEMU |
Fix Released
|
Undecided
|
Shahab Vahedi |
Bug Description
commit 377b155bde451d5
Merge: c876180938 328eb60dc1
Author: Peter Maydell <peter.x@x.x> ; masked for anti-spamming purposes
Date: Mon Mar 11 18:26:37 2019 +0000
https:/
-------
cpu_ld*_code() is used for loading code data as the name suggests. Although, it begins accessing memory with MMU_INST_FETCH access type, somewhere down
the road, when the "io_readx(..., access_
called, it is ignoring this "access_type" while calling the "tlb_fill()"
with a _hardcoded_ MMU_DATA_LOAD:
cputlb.c
--------
static uint64_t io_readx(..., MMUAccessType access_type, ...)
{
if (recheck) {
CPUTLBEntry *entry;
...
}
--------
This is an issue, because there can exist _small_ regions of memory (smaller
than the TARGET_PAGE_SIZE) that are only executable and not readable.
TL;DR
What happens is at first, a "tlb_fill(..., access_
is triggered by "tb_lookup_
stack which is good behavior:
---
#0 tlb_fill (cs=..., vaddr=684, size=0, access_
#1 get_page_addr_code (env=..., addr=684) at accel/tcg/
#2 tb_htable_lookup (cpu=..., pc=684, cs_base=0, flags=0, cf_mask=4278190080) at accel/tcg/
#3 tb_lookup_
#4 tb_find (cpu=..., last_tb=... <code_gen_
#5 cpu_exec (cpu=...) at accel/tcg/
#6 tcg_cpu_exec (cpu=...) at cpus.c:1430
#7 qemu_tcg_
#8 qemu_thread_start (args=...) at util/qemu-
---
After this call, TLB is filled with an entry that its size field is small,
say 32 bytes. This causes a TLB_RECHECK for consequent memory accesses, which
is logical. However, in our decoder, we use cpu_lduw_code() to read the
instructions and decode them. As mentioned, in the beginning, the
access_
and now THIS CAUSES A GUEST EXCEPTION BECAUSE THAT REGION IS NOT ALLOWED TO
BE READ. Here, comes that trace call of the _bad_ behavior:
---
#0 tlb_fill (..., access_
#1 io_readx (..., access_
#2 io_readw (..., access_
#3 helper_le_ldw_cmmu (..., oi=16, retaddr=0) at accel/tcg/
#4 cpu_lduw_code_ra (env=..., ptr=684, retaddr=0) at include/
#5 cpu_lduw_code (env=..., ptr=684) at include/
#6 read_and_
#7 arc_decode (ctx=...) at target/
#8 decode_opc (env=..., ctx=...) at target/
#9 arc_tr_
#10 translator_loop (.. <code_gen_
#11 gen_intermediat
#12 tb_gen_code (cpu=..., pc=684, cs_base=0, flags=0, cflags=-16711679) at accel/tcg/
#13 tb_find (cpu=..., last_tb=... <code_gen_
#14 cpu_exec (cpu=...) at accel/tcg/
#15 tcg_cpu_exec (cpu=...) at cpus.c:1430
---
Do you confirm if this is an issue? Maybe there are other ways to read an instruction with MMU_INST_FETCH access that I don't know about.
Last but not least, although this is not a security issue for QEMU per se, but it is hindering a security feature for the guest.
description: | updated |
Changed in qemu: | |
status: | Fix Committed → Fix Released |
Yeah, this looks like a bug -- we should pass the access_type through rather than using MMU_DATA_LOAD.