All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [Bug 1825359] [NEW] cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH
@ 2019-04-18 12:00 Shahab Vahedi
  2019-04-18 12:31 ` [Qemu-devel] [Bug 1825359] " Peter Maydell
                   ` (12 more replies)
  0 siblings, 13 replies; 14+ messages in thread
From: Shahab Vahedi @ 2019-04-18 12:00 UTC (permalink / raw)
  To: qemu-devel

Public bug reported:

commit 377b155bde451d5ac545fbdcdfbf6ca17a4228f5
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://github.com/qemu/qemu/commit/377b155bde451d5ac545fbdcdfbf6ca17a4228f5
--------------------------------------------------

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_type=MMU_INST_FETCH, ...)" is
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;
        target_ulong tlb_addr;

        tlb_fill(cpu, addr, size, MMU_DATA_LOAD, mmu_idx, retaddr);
        ...
}
--------

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_type=MMU_INST_FETCH, ...)"
is triggered by "tb_lookup_cpu_state()". To be precise, this is the call
stack which is good behavior:
---
#0  tlb_fill (cs=..., vaddr=684, size=0, access_type=MMU_INST_FETCH, mmu_idx=0, retaddr=0) at target/arc/mmu.c:602
#1  get_page_addr_code (env=..., addr=684) at accel/tcg/cputlb.c:1045
#2  tb_htable_lookup (cpu=..., pc=684, cs_base=0, flags=0, cf_mask=4278190080) at accel/tcg/cpu-exec.c:337
#3  tb_lookup__cpu_state (cpu=..., pc=..., cs_base=..., flags=..., cf_mask=4278190080) at include/exec/tb-lookup.h:43
#4  tb_find (cpu=..., last_tb=... <code_gen_buffer+17811>, tb_exit=0, cf_mask=0) at accel/tcg/cpu-exec.c:404
#5  cpu_exec (cpu=...) at accel/tcg/cpu-exec.c:729
#6  tcg_cpu_exec (cpu=...) at cpus.c:1430
#7  qemu_tcg_rr_cpu_thread_fn (arg=...) at cpus.c:1531
#8  qemu_thread_start (args=...) at util/qemu-thread-posix.c:502
---

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_type=MMU_INST_FETCH is lost in "io_readx()" while calling tlb_fill()",
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_type=MMU_DATA_LOAD, ...) at target/arc/mmu.c:605
#1  io_readx (..., access_type=MMU_INST_FETCH, size=2) at accel/tcg/cputlb.c:881
#2  io_readw (..., access_type=MMU_INST_FETCH) at accel/tcg/softmmu_template.h:106
#3  helper_le_ldw_cmmu (..., oi=16, retaddr=0) at accel/tcg/softmmu_template.h:146
#4  cpu_lduw_code_ra (env=..., ptr=684, retaddr=0) at include/exec/cpu_ldst_template.h:102
#5  cpu_lduw_code (env=..., ptr=684) at include/exec/cpu_ldst_template.h:114
#6  read_and_decode_context (ctx=..., opcode_p=...) at target/arc/arc-decoder.c:1479
#7  arc_decode (ctx=...) at target/arc/arc-decoder.c:1736
#8  decode_opc (env=..., ctx=...) at target/arc/translate.c:313
#9  arc_tr_translate_insn (dcbase=..., cpu=...) at target/arc/translate.c:335
#10 translator_loop (.. <code_gen_buffer+18131>) at accel/tcg/translator.c:107
#11 gen_intermediate_code (cpu=..., tb=... <code_gen_buffer+18131>) at target/arc/translate.c:413
#12 tb_gen_code (cpu=..., pc=684, cs_base=0, flags=0, cflags=-16711679) at accel/tcg/translate-all.c:1723
#13 tb_find (cpu=..., last_tb=... <code_gen_buffer+17811>, tb_exit=0, cf_mask=0) at accel/tcg/cpu-exec.c:407
#14 cpu_exec (cpu=...) at accel/tcg/cpu-exec.c:729
#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.

** Affects: qemu
     Importance: Undecided
         Status: New


** Tags: fetch mmu mpu

** Description changed:

  commit 377b155bde451d5ac545fbdcdfbf6ca17a4228f5
  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://github.com/qemu/qemu/commit/377b155bde451d5ac545fbdcdfbf6ca17a4228f5
  --------------------------------------------------
  
- 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_type=MMU_INST_FETCH, ...)" is called, it is ignoring this "access_type"
- while calling the "tlb_fill()" with a _hardcoded_ MMU_DATA_LOAD:
+ 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_type=MMU_INST_FETCH, ...)" is
+ 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;
-         target_ulong tlb_addr;
-     
-         tlb_fill(cpu, addr, size, MMU_DATA_LOAD, mmu_idx, retaddr);
-         ...
+     if (recheck) {
+         CPUTLBEntry *entry;
+         target_ulong tlb_addr;
+ 
+         tlb_fill(cpu, addr, size, MMU_DATA_LOAD, mmu_idx, retaddr);
+         ...
  }
  --------
  
- 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.
+ 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_type=MMU_INST_FETCH, ...)" is
- triggered by "tb_lookup_cpu_state()". To be precise, this is the call stack which is good behavior:
+ What happens is at first, a "tlb_fill(..., access_type=MMU_INST_FETCH, ...)"
+ is triggered by "tb_lookup_cpu_state()". To be precise, this is the call
+ stack which is good behavior:
  ---
  #0  tlb_fill (cs=..., vaddr=684, size=0, access_type=MMU_INST_FETCH, mmu_idx=0, retaddr=0) at target/arc/mmu.c:602
  #1  get_page_addr_code (env=..., addr=684) at accel/tcg/cputlb.c:1045
  #2  tb_htable_lookup (cpu=..., pc=684, cs_base=0, flags=0, cf_mask=4278190080) at accel/tcg/cpu-exec.c:337
  #3  tb_lookup__cpu_state (cpu=..., pc=..., cs_base=..., flags=..., cf_mask=4278190080) at include/exec/tb-lookup.h:43
  #4  tb_find (cpu=..., last_tb=... <code_gen_buffer+17811>, tb_exit=0, cf_mask=0) at accel/tcg/cpu-exec.c:404
  #5  cpu_exec (cpu=...) at accel/tcg/cpu-exec.c:729
  #6  tcg_cpu_exec (cpu=...) at cpus.c:1430
  #7  qemu_tcg_rr_cpu_thread_fn (arg=...) at cpus.c:1531
  #8  qemu_thread_start (args=...) at util/qemu-thread-posix.c:502
  ---
  
- 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_type=MMU_INST_FETCH is lost in "io_readx()" while calling "tlb_fill()",
- 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:
+ 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_type=MMU_INST_FETCH is lost in "io_readx()" while calling tlb_fill()",
+ 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_type=MMU_DATA_LOAD, ...) at target/arc/mmu.c:605
  #1  io_readx (..., access_type=MMU_INST_FETCH, size=2) at accel/tcg/cputlb.c:881
  #2  io_readw (..., access_type=MMU_INST_FETCH) at accel/tcg/softmmu_template.h:106
  #3  helper_le_ldw_cmmu (..., oi=16, retaddr=0) at accel/tcg/softmmu_template.h:146
  #4  cpu_lduw_code_ra (env=..., ptr=684, retaddr=0) at include/exec/cpu_ldst_template.h:102
  #5  cpu_lduw_code (env=..., ptr=684) at include/exec/cpu_ldst_template.h:114
  #6  read_and_decode_context (ctx=..., opcode_p=...) at target/arc/arc-decoder.c:1479
- #7  arc_decode (ctx=...) at target/arc/arc-decoder.c:1736              
+ #7  arc_decode (ctx=...) at target/arc/arc-decoder.c:1736
  #8  decode_opc (env=..., ctx=...) at target/arc/translate.c:313
  #9  arc_tr_translate_insn (dcbase=..., cpu=...) at target/arc/translate.c:335
  #10 translator_loop (.. <code_gen_buffer+18131>) at accel/tcg/translator.c:107
  #11 gen_intermediate_code (cpu=..., tb=... <code_gen_buffer+18131>) at target/arc/translate.c:413
  #12 tb_gen_code (cpu=..., pc=684, cs_base=0, flags=0, cflags=-16711679) at accel/tcg/translate-all.c:1723
  #13 tb_find (cpu=..., last_tb=... <code_gen_buffer+17811>, tb_exit=0, cf_mask=0) at accel/tcg/cpu-exec.c:407
- #14 cpu_exec (cpu=...) at accel/tcg/cpu-exec.c:729                     
+ #14 cpu_exec (cpu=...) at accel/tcg/cpu-exec.c:729
  #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.
+ 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.
+ 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.

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1825359

Title:
  cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH

Status in QEMU:
  New

Bug description:
  commit 377b155bde451d5ac545fbdcdfbf6ca17a4228f5
  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://github.com/qemu/qemu/commit/377b155bde451d5ac545fbdcdfbf6ca17a4228f5
  --------------------------------------------------

  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_type=MMU_INST_FETCH, ...)" is
  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;
          target_ulong tlb_addr;

          tlb_fill(cpu, addr, size, MMU_DATA_LOAD, mmu_idx, retaddr);
          ...
  }
  --------

  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_type=MMU_INST_FETCH, ...)"
  is triggered by "tb_lookup_cpu_state()". To be precise, this is the call
  stack which is good behavior:
  ---
  #0  tlb_fill (cs=..., vaddr=684, size=0, access_type=MMU_INST_FETCH, mmu_idx=0, retaddr=0) at target/arc/mmu.c:602
  #1  get_page_addr_code (env=..., addr=684) at accel/tcg/cputlb.c:1045
  #2  tb_htable_lookup (cpu=..., pc=684, cs_base=0, flags=0, cf_mask=4278190080) at accel/tcg/cpu-exec.c:337
  #3  tb_lookup__cpu_state (cpu=..., pc=..., cs_base=..., flags=..., cf_mask=4278190080) at include/exec/tb-lookup.h:43
  #4  tb_find (cpu=..., last_tb=... <code_gen_buffer+17811>, tb_exit=0, cf_mask=0) at accel/tcg/cpu-exec.c:404
  #5  cpu_exec (cpu=...) at accel/tcg/cpu-exec.c:729
  #6  tcg_cpu_exec (cpu=...) at cpus.c:1430
  #7  qemu_tcg_rr_cpu_thread_fn (arg=...) at cpus.c:1531
  #8  qemu_thread_start (args=...) at util/qemu-thread-posix.c:502
  ---

  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_type=MMU_INST_FETCH is lost in "io_readx()" while calling tlb_fill()",
  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_type=MMU_DATA_LOAD, ...) at target/arc/mmu.c:605
  #1  io_readx (..., access_type=MMU_INST_FETCH, size=2) at accel/tcg/cputlb.c:881
  #2  io_readw (..., access_type=MMU_INST_FETCH) at accel/tcg/softmmu_template.h:106
  #3  helper_le_ldw_cmmu (..., oi=16, retaddr=0) at accel/tcg/softmmu_template.h:146
  #4  cpu_lduw_code_ra (env=..., ptr=684, retaddr=0) at include/exec/cpu_ldst_template.h:102
  #5  cpu_lduw_code (env=..., ptr=684) at include/exec/cpu_ldst_template.h:114
  #6  read_and_decode_context (ctx=..., opcode_p=...) at target/arc/arc-decoder.c:1479
  #7  arc_decode (ctx=...) at target/arc/arc-decoder.c:1736
  #8  decode_opc (env=..., ctx=...) at target/arc/translate.c:313
  #9  arc_tr_translate_insn (dcbase=..., cpu=...) at target/arc/translate.c:335
  #10 translator_loop (.. <code_gen_buffer+18131>) at accel/tcg/translator.c:107
  #11 gen_intermediate_code (cpu=..., tb=... <code_gen_buffer+18131>) at target/arc/translate.c:413
  #12 tb_gen_code (cpu=..., pc=684, cs_base=0, flags=0, cflags=-16711679) at accel/tcg/translate-all.c:1723
  #13 tb_find (cpu=..., last_tb=... <code_gen_buffer+17811>, tb_exit=0, cf_mask=0) at accel/tcg/cpu-exec.c:407
  #14 cpu_exec (cpu=...) at accel/tcg/cpu-exec.c:729
  #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.

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1825359/+subscriptions

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Qemu-devel] [Bug 1825359] Re: cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH
  2019-04-18 12:00 [Qemu-devel] [Bug 1825359] [NEW] cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH Shahab Vahedi
@ 2019-04-18 12:31 ` Peter Maydell
  2019-04-18 13:24 ` Shahab Vahedi
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Peter Maydell @ 2019-04-18 12:31 UTC (permalink / raw)
  To: qemu-devel

Yeah, this looks like a bug -- we should pass the access_type through
rather than using MMU_DATA_LOAD.


** Changed in: qemu
       Status: New => Confirmed

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1825359

Title:
  cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH

Status in QEMU:
  Confirmed

Bug description:
  commit 377b155bde451d5ac545fbdcdfbf6ca17a4228f5
  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://github.com/qemu/qemu/commit/377b155bde451d5ac545fbdcdfbf6ca17a4228f5
  --------------------------------------------------

  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_type=MMU_INST_FETCH, ...)" is
  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;
          target_ulong tlb_addr;

          tlb_fill(cpu, addr, size, MMU_DATA_LOAD, mmu_idx, retaddr);
          ...
  }
  --------

  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_type=MMU_INST_FETCH, ...)"
  is triggered by "tb_lookup_cpu_state()". To be precise, this is the call
  stack which is good behavior:
  ---
  #0  tlb_fill (cs=..., vaddr=684, size=0, access_type=MMU_INST_FETCH, mmu_idx=0, retaddr=0) at target/arc/mmu.c:602
  #1  get_page_addr_code (env=..., addr=684) at accel/tcg/cputlb.c:1045
  #2  tb_htable_lookup (cpu=..., pc=684, cs_base=0, flags=0, cf_mask=4278190080) at accel/tcg/cpu-exec.c:337
  #3  tb_lookup__cpu_state (cpu=..., pc=..., cs_base=..., flags=..., cf_mask=4278190080) at include/exec/tb-lookup.h:43
  #4  tb_find (cpu=..., last_tb=... <code_gen_buffer+17811>, tb_exit=0, cf_mask=0) at accel/tcg/cpu-exec.c:404
  #5  cpu_exec (cpu=...) at accel/tcg/cpu-exec.c:729
  #6  tcg_cpu_exec (cpu=...) at cpus.c:1430
  #7  qemu_tcg_rr_cpu_thread_fn (arg=...) at cpus.c:1531
  #8  qemu_thread_start (args=...) at util/qemu-thread-posix.c:502
  ---

  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_type=MMU_INST_FETCH is lost in "io_readx()" while calling tlb_fill()",
  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_type=MMU_DATA_LOAD, ...) at target/arc/mmu.c:605
  #1  io_readx (..., access_type=MMU_INST_FETCH, size=2) at accel/tcg/cputlb.c:881
  #2  io_readw (..., access_type=MMU_INST_FETCH) at accel/tcg/softmmu_template.h:106
  #3  helper_le_ldw_cmmu (..., oi=16, retaddr=0) at accel/tcg/softmmu_template.h:146
  #4  cpu_lduw_code_ra (env=..., ptr=684, retaddr=0) at include/exec/cpu_ldst_template.h:102
  #5  cpu_lduw_code (env=..., ptr=684) at include/exec/cpu_ldst_template.h:114
  #6  read_and_decode_context (ctx=..., opcode_p=...) at target/arc/arc-decoder.c:1479
  #7  arc_decode (ctx=...) at target/arc/arc-decoder.c:1736
  #8  decode_opc (env=..., ctx=...) at target/arc/translate.c:313
  #9  arc_tr_translate_insn (dcbase=..., cpu=...) at target/arc/translate.c:335
  #10 translator_loop (.. <code_gen_buffer+18131>) at accel/tcg/translator.c:107
  #11 gen_intermediate_code (cpu=..., tb=... <code_gen_buffer+18131>) at target/arc/translate.c:413
  #12 tb_gen_code (cpu=..., pc=684, cs_base=0, flags=0, cflags=-16711679) at accel/tcg/translate-all.c:1723
  #13 tb_find (cpu=..., last_tb=... <code_gen_buffer+17811>, tb_exit=0, cf_mask=0) at accel/tcg/cpu-exec.c:407
  #14 cpu_exec (cpu=...) at accel/tcg/cpu-exec.c:729
  #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.

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1825359/+subscriptions

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Qemu-devel] [Bug 1825359] Re: cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH
  2019-04-18 12:00 [Qemu-devel] [Bug 1825359] [NEW] cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH Shahab Vahedi
  2019-04-18 12:31 ` [Qemu-devel] [Bug 1825359] " Peter Maydell
@ 2019-04-18 13:24 ` Shahab Vahedi
  2019-04-18 13:27 ` Shahab Vahedi
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Shahab Vahedi @ 2019-04-18 13:24 UTC (permalink / raw)
  To: qemu-devel

Should I make a patch then?

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1825359

Title:
  cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH

Status in QEMU:
  Confirmed

Bug description:
  commit 377b155bde451d5ac545fbdcdfbf6ca17a4228f5
  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://github.com/qemu/qemu/commit/377b155bde451d5ac545fbdcdfbf6ca17a4228f5
  --------------------------------------------------

  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_type=MMU_INST_FETCH, ...)" is
  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;
          target_ulong tlb_addr;

          tlb_fill(cpu, addr, size, MMU_DATA_LOAD, mmu_idx, retaddr);
          ...
  }
  --------

  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_type=MMU_INST_FETCH, ...)"
  is triggered by "tb_lookup_cpu_state()". To be precise, this is the call
  stack which is good behavior:
  ---
  #0  tlb_fill (cs=..., vaddr=684, size=0, access_type=MMU_INST_FETCH, mmu_idx=0, retaddr=0) at target/arc/mmu.c:602
  #1  get_page_addr_code (env=..., addr=684) at accel/tcg/cputlb.c:1045
  #2  tb_htable_lookup (cpu=..., pc=684, cs_base=0, flags=0, cf_mask=4278190080) at accel/tcg/cpu-exec.c:337
  #3  tb_lookup__cpu_state (cpu=..., pc=..., cs_base=..., flags=..., cf_mask=4278190080) at include/exec/tb-lookup.h:43
  #4  tb_find (cpu=..., last_tb=... <code_gen_buffer+17811>, tb_exit=0, cf_mask=0) at accel/tcg/cpu-exec.c:404
  #5  cpu_exec (cpu=...) at accel/tcg/cpu-exec.c:729
  #6  tcg_cpu_exec (cpu=...) at cpus.c:1430
  #7  qemu_tcg_rr_cpu_thread_fn (arg=...) at cpus.c:1531
  #8  qemu_thread_start (args=...) at util/qemu-thread-posix.c:502
  ---

  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_type=MMU_INST_FETCH is lost in "io_readx()" while calling tlb_fill()",
  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_type=MMU_DATA_LOAD, ...) at target/arc/mmu.c:605
  #1  io_readx (..., access_type=MMU_INST_FETCH, size=2) at accel/tcg/cputlb.c:881
  #2  io_readw (..., access_type=MMU_INST_FETCH) at accel/tcg/softmmu_template.h:106
  #3  helper_le_ldw_cmmu (..., oi=16, retaddr=0) at accel/tcg/softmmu_template.h:146
  #4  cpu_lduw_code_ra (env=..., ptr=684, retaddr=0) at include/exec/cpu_ldst_template.h:102
  #5  cpu_lduw_code (env=..., ptr=684) at include/exec/cpu_ldst_template.h:114
  #6  read_and_decode_context (ctx=..., opcode_p=...) at target/arc/arc-decoder.c:1479
  #7  arc_decode (ctx=...) at target/arc/arc-decoder.c:1736
  #8  decode_opc (env=..., ctx=...) at target/arc/translate.c:313
  #9  arc_tr_translate_insn (dcbase=..., cpu=...) at target/arc/translate.c:335
  #10 translator_loop (.. <code_gen_buffer+18131>) at accel/tcg/translator.c:107
  #11 gen_intermediate_code (cpu=..., tb=... <code_gen_buffer+18131>) at target/arc/translate.c:413
  #12 tb_gen_code (cpu=..., pc=684, cs_base=0, flags=0, cflags=-16711679) at accel/tcg/translate-all.c:1723
  #13 tb_find (cpu=..., last_tb=... <code_gen_buffer+17811>, tb_exit=0, cf_mask=0) at accel/tcg/cpu-exec.c:407
  #14 cpu_exec (cpu=...) at accel/tcg/cpu-exec.c:729
  #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.

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1825359/+subscriptions

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Qemu-devel] [Bug 1825359] Re: cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH
  2019-04-18 12:00 [Qemu-devel] [Bug 1825359] [NEW] cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH Shahab Vahedi
  2019-04-18 12:31 ` [Qemu-devel] [Bug 1825359] " Peter Maydell
  2019-04-18 13:24 ` Shahab Vahedi
@ 2019-04-18 13:27 ` Shahab Vahedi
  2019-04-18 13:57 ` Peter Maydell
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Shahab Vahedi @ 2019-04-18 13:27 UTC (permalink / raw)
  To: qemu-devel

** Patch added: "bug1825359_io_readx.patch"
   https://bugs.launchpad.net/qemu/+bug/1825359/+attachment/5256724/+files/bug1825359_io_readx.patch

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1825359

Title:
  cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH

Status in QEMU:
  Confirmed

Bug description:
  commit 377b155bde451d5ac545fbdcdfbf6ca17a4228f5
  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://github.com/qemu/qemu/commit/377b155bde451d5ac545fbdcdfbf6ca17a4228f5
  --------------------------------------------------

  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_type=MMU_INST_FETCH, ...)" is
  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;
          target_ulong tlb_addr;

          tlb_fill(cpu, addr, size, MMU_DATA_LOAD, mmu_idx, retaddr);
          ...
  }
  --------

  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_type=MMU_INST_FETCH, ...)"
  is triggered by "tb_lookup_cpu_state()". To be precise, this is the call
  stack which is good behavior:
  ---
  #0  tlb_fill (cs=..., vaddr=684, size=0, access_type=MMU_INST_FETCH, mmu_idx=0, retaddr=0) at target/arc/mmu.c:602
  #1  get_page_addr_code (env=..., addr=684) at accel/tcg/cputlb.c:1045
  #2  tb_htable_lookup (cpu=..., pc=684, cs_base=0, flags=0, cf_mask=4278190080) at accel/tcg/cpu-exec.c:337
  #3  tb_lookup__cpu_state (cpu=..., pc=..., cs_base=..., flags=..., cf_mask=4278190080) at include/exec/tb-lookup.h:43
  #4  tb_find (cpu=..., last_tb=... <code_gen_buffer+17811>, tb_exit=0, cf_mask=0) at accel/tcg/cpu-exec.c:404
  #5  cpu_exec (cpu=...) at accel/tcg/cpu-exec.c:729
  #6  tcg_cpu_exec (cpu=...) at cpus.c:1430
  #7  qemu_tcg_rr_cpu_thread_fn (arg=...) at cpus.c:1531
  #8  qemu_thread_start (args=...) at util/qemu-thread-posix.c:502
  ---

  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_type=MMU_INST_FETCH is lost in "io_readx()" while calling tlb_fill()",
  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_type=MMU_DATA_LOAD, ...) at target/arc/mmu.c:605
  #1  io_readx (..., access_type=MMU_INST_FETCH, size=2) at accel/tcg/cputlb.c:881
  #2  io_readw (..., access_type=MMU_INST_FETCH) at accel/tcg/softmmu_template.h:106
  #3  helper_le_ldw_cmmu (..., oi=16, retaddr=0) at accel/tcg/softmmu_template.h:146
  #4  cpu_lduw_code_ra (env=..., ptr=684, retaddr=0) at include/exec/cpu_ldst_template.h:102
  #5  cpu_lduw_code (env=..., ptr=684) at include/exec/cpu_ldst_template.h:114
  #6  read_and_decode_context (ctx=..., opcode_p=...) at target/arc/arc-decoder.c:1479
  #7  arc_decode (ctx=...) at target/arc/arc-decoder.c:1736
  #8  decode_opc (env=..., ctx=...) at target/arc/translate.c:313
  #9  arc_tr_translate_insn (dcbase=..., cpu=...) at target/arc/translate.c:335
  #10 translator_loop (.. <code_gen_buffer+18131>) at accel/tcg/translator.c:107
  #11 gen_intermediate_code (cpu=..., tb=... <code_gen_buffer+18131>) at target/arc/translate.c:413
  #12 tb_gen_code (cpu=..., pc=684, cs_base=0, flags=0, cflags=-16711679) at accel/tcg/translate-all.c:1723
  #13 tb_find (cpu=..., last_tb=... <code_gen_buffer+17811>, tb_exit=0, cf_mask=0) at accel/tcg/cpu-exec.c:407
  #14 cpu_exec (cpu=...) at accel/tcg/cpu-exec.c:729
  #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.

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1825359/+subscriptions

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Qemu-devel] [Bug 1825359] Re: cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH
  2019-04-18 12:00 [Qemu-devel] [Bug 1825359] [NEW] cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH Shahab Vahedi
                   ` (2 preceding siblings ...)
  2019-04-18 13:27 ` Shahab Vahedi
@ 2019-04-18 13:57 ` Peter Maydell
  2019-04-18 14:09 ` Shahab Vahedi
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Peter Maydell @ 2019-04-18 13:57 UTC (permalink / raw)
  To: qemu-devel

The patch looks OK code-wise, but could you submit it to the mailing list, please?
https://wiki.qemu.org/Contribute/SubmitAPatch has the details, but the most important part is that it needs a Signed-off-by: line from you that says you have the legal right and are willing to contribute it to QEMU under our license. Otherwise we can't use the patch.

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1825359

Title:
  cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH

Status in QEMU:
  Confirmed

Bug description:
  commit 377b155bde451d5ac545fbdcdfbf6ca17a4228f5
  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://github.com/qemu/qemu/commit/377b155bde451d5ac545fbdcdfbf6ca17a4228f5
  --------------------------------------------------

  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_type=MMU_INST_FETCH, ...)" is
  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;
          target_ulong tlb_addr;

          tlb_fill(cpu, addr, size, MMU_DATA_LOAD, mmu_idx, retaddr);
          ...
  }
  --------

  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_type=MMU_INST_FETCH, ...)"
  is triggered by "tb_lookup_cpu_state()". To be precise, this is the call
  stack which is good behavior:
  ---
  #0  tlb_fill (cs=..., vaddr=684, size=0, access_type=MMU_INST_FETCH, mmu_idx=0, retaddr=0) at target/arc/mmu.c:602
  #1  get_page_addr_code (env=..., addr=684) at accel/tcg/cputlb.c:1045
  #2  tb_htable_lookup (cpu=..., pc=684, cs_base=0, flags=0, cf_mask=4278190080) at accel/tcg/cpu-exec.c:337
  #3  tb_lookup__cpu_state (cpu=..., pc=..., cs_base=..., flags=..., cf_mask=4278190080) at include/exec/tb-lookup.h:43
  #4  tb_find (cpu=..., last_tb=... <code_gen_buffer+17811>, tb_exit=0, cf_mask=0) at accel/tcg/cpu-exec.c:404
  #5  cpu_exec (cpu=...) at accel/tcg/cpu-exec.c:729
  #6  tcg_cpu_exec (cpu=...) at cpus.c:1430
  #7  qemu_tcg_rr_cpu_thread_fn (arg=...) at cpus.c:1531
  #8  qemu_thread_start (args=...) at util/qemu-thread-posix.c:502
  ---

  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_type=MMU_INST_FETCH is lost in "io_readx()" while calling tlb_fill()",
  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_type=MMU_DATA_LOAD, ...) at target/arc/mmu.c:605
  #1  io_readx (..., access_type=MMU_INST_FETCH, size=2) at accel/tcg/cputlb.c:881
  #2  io_readw (..., access_type=MMU_INST_FETCH) at accel/tcg/softmmu_template.h:106
  #3  helper_le_ldw_cmmu (..., oi=16, retaddr=0) at accel/tcg/softmmu_template.h:146
  #4  cpu_lduw_code_ra (env=..., ptr=684, retaddr=0) at include/exec/cpu_ldst_template.h:102
  #5  cpu_lduw_code (env=..., ptr=684) at include/exec/cpu_ldst_template.h:114
  #6  read_and_decode_context (ctx=..., opcode_p=...) at target/arc/arc-decoder.c:1479
  #7  arc_decode (ctx=...) at target/arc/arc-decoder.c:1736
  #8  decode_opc (env=..., ctx=...) at target/arc/translate.c:313
  #9  arc_tr_translate_insn (dcbase=..., cpu=...) at target/arc/translate.c:335
  #10 translator_loop (.. <code_gen_buffer+18131>) at accel/tcg/translator.c:107
  #11 gen_intermediate_code (cpu=..., tb=... <code_gen_buffer+18131>) at target/arc/translate.c:413
  #12 tb_gen_code (cpu=..., pc=684, cs_base=0, flags=0, cflags=-16711679) at accel/tcg/translate-all.c:1723
  #13 tb_find (cpu=..., last_tb=... <code_gen_buffer+17811>, tb_exit=0, cf_mask=0) at accel/tcg/cpu-exec.c:407
  #14 cpu_exec (cpu=...) at accel/tcg/cpu-exec.c:729
  #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.

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1825359/+subscriptions

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Qemu-devel] [Bug 1825359] Re: cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH
  2019-04-18 12:00 [Qemu-devel] [Bug 1825359] [NEW] cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH Shahab Vahedi
                   ` (3 preceding siblings ...)
  2019-04-18 13:57 ` Peter Maydell
@ 2019-04-18 14:09 ` Shahab Vahedi
  2019-04-18 14:11 ` Shahab Vahedi
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Shahab Vahedi @ 2019-04-18 14:09 UTC (permalink / raw)
  To: qemu-devel

I have to say, after applying this patch, my test still fails while
fetching the instructions from this _small_ region. Although there is no
MMU_DATA_LOAD anymore, a few iterations later (while guest code has just
jumped to the beginning of the executable region), QEmu segfaults (call
stack is attached):

memory.c
--------
static MemTxResult
memory_region_read_with_attrs_accessor(MemoryRegion *mr,
                                       ...)
{
    uint64_t tmp = 0;
    MemTxResult r;

    r = mr->ops->read_with_attrs(mr->opaque, addr, &tmp, size, attrs);
    ...
}
--------

Here, "read_with_attrs" is null. The call stack looks like:
---
#0  memory_region_read_with_attrs_accessor at memory.c:465
#1  access_with_adjusted_size at memory.c:568
#2  memory_region_dispatch_read1 at memory.c:1425
#3  memory_region_dispatch_read at memory.c:1446
#4  io_readx at accel/tcg/cputlb.c:909
#5  io_readw at accel/tcg/softmmu_template.h:106
#6  helper_le_ldw_cmmu at accel/tcg/softmmu_template.h:146
#7  cpu_lduw_code_ra at include/exec/cpu_ldst_template.h:102
#8  cpu_lduw_code at include/exec/cpu_ldst_template.h:114
#9  read_and_decode_context at target/arc/arc-decoder.c:1479
#10 arc_decode at target/arc/arc-decoder.c:1736
#11 decode_opc at target/arc/translate.c:313
#12 arc_tr_translate_insn at target/arc/translate.c:335
#13 translator_loop at accel/tcg/translator.c:107
#14 gen_intermediate_code at target/arc/translate.c:413
#15 tb_gen_code at accel/tcg/translate-all.c:1723
#16 tb_find at accel/tcg/cpu-exec.c:407
#17 cpu_exec at accel/tcg/cpu-exec.c:729
#18 tcg_cpu_exec at cpus.c:1430
---
more detailed call stack is attached.

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1825359

Title:
  cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH

Status in QEMU:
  Confirmed

Bug description:
  commit 377b155bde451d5ac545fbdcdfbf6ca17a4228f5
  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://github.com/qemu/qemu/commit/377b155bde451d5ac545fbdcdfbf6ca17a4228f5
  --------------------------------------------------

  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_type=MMU_INST_FETCH, ...)" is
  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;
          target_ulong tlb_addr;

          tlb_fill(cpu, addr, size, MMU_DATA_LOAD, mmu_idx, retaddr);
          ...
  }
  --------

  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_type=MMU_INST_FETCH, ...)"
  is triggered by "tb_lookup_cpu_state()". To be precise, this is the call
  stack which is good behavior:
  ---
  #0  tlb_fill (cs=..., vaddr=684, size=0, access_type=MMU_INST_FETCH, mmu_idx=0, retaddr=0) at target/arc/mmu.c:602
  #1  get_page_addr_code (env=..., addr=684) at accel/tcg/cputlb.c:1045
  #2  tb_htable_lookup (cpu=..., pc=684, cs_base=0, flags=0, cf_mask=4278190080) at accel/tcg/cpu-exec.c:337
  #3  tb_lookup__cpu_state (cpu=..., pc=..., cs_base=..., flags=..., cf_mask=4278190080) at include/exec/tb-lookup.h:43
  #4  tb_find (cpu=..., last_tb=... <code_gen_buffer+17811>, tb_exit=0, cf_mask=0) at accel/tcg/cpu-exec.c:404
  #5  cpu_exec (cpu=...) at accel/tcg/cpu-exec.c:729
  #6  tcg_cpu_exec (cpu=...) at cpus.c:1430
  #7  qemu_tcg_rr_cpu_thread_fn (arg=...) at cpus.c:1531
  #8  qemu_thread_start (args=...) at util/qemu-thread-posix.c:502
  ---

  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_type=MMU_INST_FETCH is lost in "io_readx()" while calling tlb_fill()",
  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_type=MMU_DATA_LOAD, ...) at target/arc/mmu.c:605
  #1  io_readx (..., access_type=MMU_INST_FETCH, size=2) at accel/tcg/cputlb.c:881
  #2  io_readw (..., access_type=MMU_INST_FETCH) at accel/tcg/softmmu_template.h:106
  #3  helper_le_ldw_cmmu (..., oi=16, retaddr=0) at accel/tcg/softmmu_template.h:146
  #4  cpu_lduw_code_ra (env=..., ptr=684, retaddr=0) at include/exec/cpu_ldst_template.h:102
  #5  cpu_lduw_code (env=..., ptr=684) at include/exec/cpu_ldst_template.h:114
  #6  read_and_decode_context (ctx=..., opcode_p=...) at target/arc/arc-decoder.c:1479
  #7  arc_decode (ctx=...) at target/arc/arc-decoder.c:1736
  #8  decode_opc (env=..., ctx=...) at target/arc/translate.c:313
  #9  arc_tr_translate_insn (dcbase=..., cpu=...) at target/arc/translate.c:335
  #10 translator_loop (.. <code_gen_buffer+18131>) at accel/tcg/translator.c:107
  #11 gen_intermediate_code (cpu=..., tb=... <code_gen_buffer+18131>) at target/arc/translate.c:413
  #12 tb_gen_code (cpu=..., pc=684, cs_base=0, flags=0, cflags=-16711679) at accel/tcg/translate-all.c:1723
  #13 tb_find (cpu=..., last_tb=... <code_gen_buffer+17811>, tb_exit=0, cf_mask=0) at accel/tcg/cpu-exec.c:407
  #14 cpu_exec (cpu=...) at accel/tcg/cpu-exec.c:729
  #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.

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1825359/+subscriptions

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Qemu-devel] [Bug 1825359] Re: cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH
  2019-04-18 12:00 [Qemu-devel] [Bug 1825359] [NEW] cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH Shahab Vahedi
                   ` (4 preceding siblings ...)
  2019-04-18 14:09 ` Shahab Vahedi
@ 2019-04-18 14:11 ` Shahab Vahedi
  2019-04-18 14:11 ` Peter Maydell
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Shahab Vahedi @ 2019-04-18 14:11 UTC (permalink / raw)
  To: qemu-devel

call stack for SEGFAULT that happens during the execution of small
region. This will go away IF THE ENTRY ADDED TO TLB FOR THIS REGION IS
OF SIZE TARGET_PAGE_SIZE. However, that would not be correct behavior.

** Attachment added: "segfault_bt.txt"
   https://bugs.launchpad.net/qemu/+bug/1825359/+attachment/5256726/+files/segfault_bt.txt

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1825359

Title:
  cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH

Status in QEMU:
  Confirmed

Bug description:
  commit 377b155bde451d5ac545fbdcdfbf6ca17a4228f5
  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://github.com/qemu/qemu/commit/377b155bde451d5ac545fbdcdfbf6ca17a4228f5
  --------------------------------------------------

  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_type=MMU_INST_FETCH, ...)" is
  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;
          target_ulong tlb_addr;

          tlb_fill(cpu, addr, size, MMU_DATA_LOAD, mmu_idx, retaddr);
          ...
  }
  --------

  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_type=MMU_INST_FETCH, ...)"
  is triggered by "tb_lookup_cpu_state()". To be precise, this is the call
  stack which is good behavior:
  ---
  #0  tlb_fill (cs=..., vaddr=684, size=0, access_type=MMU_INST_FETCH, mmu_idx=0, retaddr=0) at target/arc/mmu.c:602
  #1  get_page_addr_code (env=..., addr=684) at accel/tcg/cputlb.c:1045
  #2  tb_htable_lookup (cpu=..., pc=684, cs_base=0, flags=0, cf_mask=4278190080) at accel/tcg/cpu-exec.c:337
  #3  tb_lookup__cpu_state (cpu=..., pc=..., cs_base=..., flags=..., cf_mask=4278190080) at include/exec/tb-lookup.h:43
  #4  tb_find (cpu=..., last_tb=... <code_gen_buffer+17811>, tb_exit=0, cf_mask=0) at accel/tcg/cpu-exec.c:404
  #5  cpu_exec (cpu=...) at accel/tcg/cpu-exec.c:729
  #6  tcg_cpu_exec (cpu=...) at cpus.c:1430
  #7  qemu_tcg_rr_cpu_thread_fn (arg=...) at cpus.c:1531
  #8  qemu_thread_start (args=...) at util/qemu-thread-posix.c:502
  ---

  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_type=MMU_INST_FETCH is lost in "io_readx()" while calling tlb_fill()",
  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_type=MMU_DATA_LOAD, ...) at target/arc/mmu.c:605
  #1  io_readx (..., access_type=MMU_INST_FETCH, size=2) at accel/tcg/cputlb.c:881
  #2  io_readw (..., access_type=MMU_INST_FETCH) at accel/tcg/softmmu_template.h:106
  #3  helper_le_ldw_cmmu (..., oi=16, retaddr=0) at accel/tcg/softmmu_template.h:146
  #4  cpu_lduw_code_ra (env=..., ptr=684, retaddr=0) at include/exec/cpu_ldst_template.h:102
  #5  cpu_lduw_code (env=..., ptr=684) at include/exec/cpu_ldst_template.h:114
  #6  read_and_decode_context (ctx=..., opcode_p=...) at target/arc/arc-decoder.c:1479
  #7  arc_decode (ctx=...) at target/arc/arc-decoder.c:1736
  #8  decode_opc (env=..., ctx=...) at target/arc/translate.c:313
  #9  arc_tr_translate_insn (dcbase=..., cpu=...) at target/arc/translate.c:335
  #10 translator_loop (.. <code_gen_buffer+18131>) at accel/tcg/translator.c:107
  #11 gen_intermediate_code (cpu=..., tb=... <code_gen_buffer+18131>) at target/arc/translate.c:413
  #12 tb_gen_code (cpu=..., pc=684, cs_base=0, flags=0, cflags=-16711679) at accel/tcg/translate-all.c:1723
  #13 tb_find (cpu=..., last_tb=... <code_gen_buffer+17811>, tb_exit=0, cf_mask=0) at accel/tcg/cpu-exec.c:407
  #14 cpu_exec (cpu=...) at accel/tcg/cpu-exec.c:729
  #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.

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1825359/+subscriptions

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Qemu-devel] [Bug 1825359] Re: cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH
  2019-04-18 12:00 [Qemu-devel] [Bug 1825359] [NEW] cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH Shahab Vahedi
                   ` (5 preceding siblings ...)
  2019-04-18 14:11 ` Shahab Vahedi
@ 2019-04-18 14:11 ` Peter Maydell
  2019-04-18 18:26 ` Shahab Vahedi
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Peter Maydell @ 2019-04-18 14:11 UTC (permalink / raw)
  To: qemu-devel

That should not happen unless you have some device that is incorrectly
not providing a suitable read function in its MemoryRegionOps. If you
look at 'mr' in the debugger you should be able to figure out which
device is the problem.

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1825359

Title:
  cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH

Status in QEMU:
  Confirmed

Bug description:
  commit 377b155bde451d5ac545fbdcdfbf6ca17a4228f5
  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://github.com/qemu/qemu/commit/377b155bde451d5ac545fbdcdfbf6ca17a4228f5
  --------------------------------------------------

  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_type=MMU_INST_FETCH, ...)" is
  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;
          target_ulong tlb_addr;

          tlb_fill(cpu, addr, size, MMU_DATA_LOAD, mmu_idx, retaddr);
          ...
  }
  --------

  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_type=MMU_INST_FETCH, ...)"
  is triggered by "tb_lookup_cpu_state()". To be precise, this is the call
  stack which is good behavior:
  ---
  #0  tlb_fill (cs=..., vaddr=684, size=0, access_type=MMU_INST_FETCH, mmu_idx=0, retaddr=0) at target/arc/mmu.c:602
  #1  get_page_addr_code (env=..., addr=684) at accel/tcg/cputlb.c:1045
  #2  tb_htable_lookup (cpu=..., pc=684, cs_base=0, flags=0, cf_mask=4278190080) at accel/tcg/cpu-exec.c:337
  #3  tb_lookup__cpu_state (cpu=..., pc=..., cs_base=..., flags=..., cf_mask=4278190080) at include/exec/tb-lookup.h:43
  #4  tb_find (cpu=..., last_tb=... <code_gen_buffer+17811>, tb_exit=0, cf_mask=0) at accel/tcg/cpu-exec.c:404
  #5  cpu_exec (cpu=...) at accel/tcg/cpu-exec.c:729
  #6  tcg_cpu_exec (cpu=...) at cpus.c:1430
  #7  qemu_tcg_rr_cpu_thread_fn (arg=...) at cpus.c:1531
  #8  qemu_thread_start (args=...) at util/qemu-thread-posix.c:502
  ---

  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_type=MMU_INST_FETCH is lost in "io_readx()" while calling tlb_fill()",
  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_type=MMU_DATA_LOAD, ...) at target/arc/mmu.c:605
  #1  io_readx (..., access_type=MMU_INST_FETCH, size=2) at accel/tcg/cputlb.c:881
  #2  io_readw (..., access_type=MMU_INST_FETCH) at accel/tcg/softmmu_template.h:106
  #3  helper_le_ldw_cmmu (..., oi=16, retaddr=0) at accel/tcg/softmmu_template.h:146
  #4  cpu_lduw_code_ra (env=..., ptr=684, retaddr=0) at include/exec/cpu_ldst_template.h:102
  #5  cpu_lduw_code (env=..., ptr=684) at include/exec/cpu_ldst_template.h:114
  #6  read_and_decode_context (ctx=..., opcode_p=...) at target/arc/arc-decoder.c:1479
  #7  arc_decode (ctx=...) at target/arc/arc-decoder.c:1736
  #8  decode_opc (env=..., ctx=...) at target/arc/translate.c:313
  #9  arc_tr_translate_insn (dcbase=..., cpu=...) at target/arc/translate.c:335
  #10 translator_loop (.. <code_gen_buffer+18131>) at accel/tcg/translator.c:107
  #11 gen_intermediate_code (cpu=..., tb=... <code_gen_buffer+18131>) at target/arc/translate.c:413
  #12 tb_gen_code (cpu=..., pc=684, cs_base=0, flags=0, cflags=-16711679) at accel/tcg/translate-all.c:1723
  #13 tb_find (cpu=..., last_tb=... <code_gen_buffer+17811>, tb_exit=0, cf_mask=0) at accel/tcg/cpu-exec.c:407
  #14 cpu_exec (cpu=...) at accel/tcg/cpu-exec.c:729
  #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.

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1825359/+subscriptions

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Qemu-devel] [Bug 1825359] Re: cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH
  2019-04-18 12:00 [Qemu-devel] [Bug 1825359] [NEW] cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH Shahab Vahedi
                   ` (6 preceding siblings ...)
  2019-04-18 14:11 ` Peter Maydell
@ 2019-04-18 18:26 ` Shahab Vahedi
  2019-04-18 18:40 ` Shahab Vahedi
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Shahab Vahedi @ 2019-04-18 18:26 UTC (permalink / raw)
  To: qemu-devel

The problem seems to be this piece of code:

cputlb.c
--------
static uint64_t io_readx(...)
{

    if (recheck) {
        ...

        tlb_fill(cpu, addr, size, MMU_DATA_LOAD, mmu_idx, retaddr);

        entry = tlb_entry(env, mmu_idx, addr);
        tlb_addr = entry->addr_read;
        ...
}
--------

"entry->addr_read" is indeed looking for a "reading address". in this case, it must look for an
"executing address", i.e. "entry->addr_code".

I see softmmu_template.h does something like this:
----
...
#ifdef SOFTMMU_CODE_ACCESS
#define READ_ACCESS_TYPE MMU_INST_FETCH
#define ADDR_READ addr_code
#else
#define READ_ACCESS_TYPE MMU_DATA_LOAD
#define ADDR_READ addr_read
#endif
...

WORD_TYPE helper_le_ld_name(...)
{
    ...
    target_ulong tlb_addr = entry->ADDR_READ;
    ...
}
----

** Changed in: qemu
     Assignee: (unassigned) => Shahab Vahedi (shahab-vahedi)

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1825359

Title:
  cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH

Status in QEMU:
  Confirmed

Bug description:
  commit 377b155bde451d5ac545fbdcdfbf6ca17a4228f5
  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://github.com/qemu/qemu/commit/377b155bde451d5ac545fbdcdfbf6ca17a4228f5
  --------------------------------------------------

  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_type=MMU_INST_FETCH, ...)" is
  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;
          target_ulong tlb_addr;

          tlb_fill(cpu, addr, size, MMU_DATA_LOAD, mmu_idx, retaddr);
          ...
  }
  --------

  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_type=MMU_INST_FETCH, ...)"
  is triggered by "tb_lookup_cpu_state()". To be precise, this is the call
  stack which is good behavior:
  ---
  #0  tlb_fill (cs=..., vaddr=684, size=0, access_type=MMU_INST_FETCH, mmu_idx=0, retaddr=0) at target/arc/mmu.c:602
  #1  get_page_addr_code (env=..., addr=684) at accel/tcg/cputlb.c:1045
  #2  tb_htable_lookup (cpu=..., pc=684, cs_base=0, flags=0, cf_mask=4278190080) at accel/tcg/cpu-exec.c:337
  #3  tb_lookup__cpu_state (cpu=..., pc=..., cs_base=..., flags=..., cf_mask=4278190080) at include/exec/tb-lookup.h:43
  #4  tb_find (cpu=..., last_tb=... <code_gen_buffer+17811>, tb_exit=0, cf_mask=0) at accel/tcg/cpu-exec.c:404
  #5  cpu_exec (cpu=...) at accel/tcg/cpu-exec.c:729
  #6  tcg_cpu_exec (cpu=...) at cpus.c:1430
  #7  qemu_tcg_rr_cpu_thread_fn (arg=...) at cpus.c:1531
  #8  qemu_thread_start (args=...) at util/qemu-thread-posix.c:502
  ---

  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_type=MMU_INST_FETCH is lost in "io_readx()" while calling tlb_fill()",
  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_type=MMU_DATA_LOAD, ...) at target/arc/mmu.c:605
  #1  io_readx (..., access_type=MMU_INST_FETCH, size=2) at accel/tcg/cputlb.c:881
  #2  io_readw (..., access_type=MMU_INST_FETCH) at accel/tcg/softmmu_template.h:106
  #3  helper_le_ldw_cmmu (..., oi=16, retaddr=0) at accel/tcg/softmmu_template.h:146
  #4  cpu_lduw_code_ra (env=..., ptr=684, retaddr=0) at include/exec/cpu_ldst_template.h:102
  #5  cpu_lduw_code (env=..., ptr=684) at include/exec/cpu_ldst_template.h:114
  #6  read_and_decode_context (ctx=..., opcode_p=...) at target/arc/arc-decoder.c:1479
  #7  arc_decode (ctx=...) at target/arc/arc-decoder.c:1736
  #8  decode_opc (env=..., ctx=...) at target/arc/translate.c:313
  #9  arc_tr_translate_insn (dcbase=..., cpu=...) at target/arc/translate.c:335
  #10 translator_loop (.. <code_gen_buffer+18131>) at accel/tcg/translator.c:107
  #11 gen_intermediate_code (cpu=..., tb=... <code_gen_buffer+18131>) at target/arc/translate.c:413
  #12 tb_gen_code (cpu=..., pc=684, cs_base=0, flags=0, cflags=-16711679) at accel/tcg/translate-all.c:1723
  #13 tb_find (cpu=..., last_tb=... <code_gen_buffer+17811>, tb_exit=0, cf_mask=0) at accel/tcg/cpu-exec.c:407
  #14 cpu_exec (cpu=...) at accel/tcg/cpu-exec.c:729
  #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.

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1825359/+subscriptions

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Qemu-devel] [Bug 1825359] Re: cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH
  2019-04-18 12:00 [Qemu-devel] [Bug 1825359] [NEW] cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH Shahab Vahedi
                   ` (7 preceding siblings ...)
  2019-04-18 18:26 ` Shahab Vahedi
@ 2019-04-18 18:40 ` Shahab Vahedi
  2019-04-18 18:46 ` Shahab Vahedi
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Shahab Vahedi @ 2019-04-18 18:40 UTC (permalink / raw)
  To: qemu-devel

** Patch removed: "bug1825359_io_readx.patch"
   https://bugs.launchpad.net/qemu/+bug/1825359/+attachment/5256724/+files/bug1825359_io_readx.patch

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1825359

Title:
  cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH

Status in QEMU:
  Confirmed

Bug description:
  commit 377b155bde451d5ac545fbdcdfbf6ca17a4228f5
  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://github.com/qemu/qemu/commit/377b155bde451d5ac545fbdcdfbf6ca17a4228f5
  --------------------------------------------------

  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_type=MMU_INST_FETCH, ...)" is
  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;
          target_ulong tlb_addr;

          tlb_fill(cpu, addr, size, MMU_DATA_LOAD, mmu_idx, retaddr);
          ...
  }
  --------

  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_type=MMU_INST_FETCH, ...)"
  is triggered by "tb_lookup_cpu_state()". To be precise, this is the call
  stack which is good behavior:
  ---
  #0  tlb_fill (cs=..., vaddr=684, size=0, access_type=MMU_INST_FETCH, mmu_idx=0, retaddr=0) at target/arc/mmu.c:602
  #1  get_page_addr_code (env=..., addr=684) at accel/tcg/cputlb.c:1045
  #2  tb_htable_lookup (cpu=..., pc=684, cs_base=0, flags=0, cf_mask=4278190080) at accel/tcg/cpu-exec.c:337
  #3  tb_lookup__cpu_state (cpu=..., pc=..., cs_base=..., flags=..., cf_mask=4278190080) at include/exec/tb-lookup.h:43
  #4  tb_find (cpu=..., last_tb=... <code_gen_buffer+17811>, tb_exit=0, cf_mask=0) at accel/tcg/cpu-exec.c:404
  #5  cpu_exec (cpu=...) at accel/tcg/cpu-exec.c:729
  #6  tcg_cpu_exec (cpu=...) at cpus.c:1430
  #7  qemu_tcg_rr_cpu_thread_fn (arg=...) at cpus.c:1531
  #8  qemu_thread_start (args=...) at util/qemu-thread-posix.c:502
  ---

  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_type=MMU_INST_FETCH is lost in "io_readx()" while calling tlb_fill()",
  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_type=MMU_DATA_LOAD, ...) at target/arc/mmu.c:605
  #1  io_readx (..., access_type=MMU_INST_FETCH, size=2) at accel/tcg/cputlb.c:881
  #2  io_readw (..., access_type=MMU_INST_FETCH) at accel/tcg/softmmu_template.h:106
  #3  helper_le_ldw_cmmu (..., oi=16, retaddr=0) at accel/tcg/softmmu_template.h:146
  #4  cpu_lduw_code_ra (env=..., ptr=684, retaddr=0) at include/exec/cpu_ldst_template.h:102
  #5  cpu_lduw_code (env=..., ptr=684) at include/exec/cpu_ldst_template.h:114
  #6  read_and_decode_context (ctx=..., opcode_p=...) at target/arc/arc-decoder.c:1479
  #7  arc_decode (ctx=...) at target/arc/arc-decoder.c:1736
  #8  decode_opc (env=..., ctx=...) at target/arc/translate.c:313
  #9  arc_tr_translate_insn (dcbase=..., cpu=...) at target/arc/translate.c:335
  #10 translator_loop (.. <code_gen_buffer+18131>) at accel/tcg/translator.c:107
  #11 gen_intermediate_code (cpu=..., tb=... <code_gen_buffer+18131>) at target/arc/translate.c:413
  #12 tb_gen_code (cpu=..., pc=684, cs_base=0, flags=0, cflags=-16711679) at accel/tcg/translate-all.c:1723
  #13 tb_find (cpu=..., last_tb=... <code_gen_buffer+17811>, tb_exit=0, cf_mask=0) at accel/tcg/cpu-exec.c:407
  #14 cpu_exec (cpu=...) at accel/tcg/cpu-exec.c:729
  #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.

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1825359/+subscriptions

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Qemu-devel] [Bug 1825359] Re: cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH
  2019-04-18 12:00 [Qemu-devel] [Bug 1825359] [NEW] cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH Shahab Vahedi
                   ` (8 preceding siblings ...)
  2019-04-18 18:40 ` Shahab Vahedi
@ 2019-04-18 18:46 ` Shahab Vahedi
  2019-05-03 16:33 ` Peter Maydell
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Shahab Vahedi @ 2019-04-18 18:46 UTC (permalink / raw)
  To: qemu-devel

This patch has fixed for me both issues. Although I am not very proud of
the changes in the second hunk. Please let me know if there is a better
way.


** Patch added: "respect address type for tlb_fill() and while using the address from "tlb_entry""
   https://bugs.launchpad.net/qemu/+bug/1825359/+attachment/5256796/+files/bug1825359_io_readx.patch

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1825359

Title:
  cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH

Status in QEMU:
  Confirmed

Bug description:
  commit 377b155bde451d5ac545fbdcdfbf6ca17a4228f5
  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://github.com/qemu/qemu/commit/377b155bde451d5ac545fbdcdfbf6ca17a4228f5
  --------------------------------------------------

  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_type=MMU_INST_FETCH, ...)" is
  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;
          target_ulong tlb_addr;

          tlb_fill(cpu, addr, size, MMU_DATA_LOAD, mmu_idx, retaddr);
          ...
  }
  --------

  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_type=MMU_INST_FETCH, ...)"
  is triggered by "tb_lookup_cpu_state()". To be precise, this is the call
  stack which is good behavior:
  ---
  #0  tlb_fill (cs=..., vaddr=684, size=0, access_type=MMU_INST_FETCH, mmu_idx=0, retaddr=0) at target/arc/mmu.c:602
  #1  get_page_addr_code (env=..., addr=684) at accel/tcg/cputlb.c:1045
  #2  tb_htable_lookup (cpu=..., pc=684, cs_base=0, flags=0, cf_mask=4278190080) at accel/tcg/cpu-exec.c:337
  #3  tb_lookup__cpu_state (cpu=..., pc=..., cs_base=..., flags=..., cf_mask=4278190080) at include/exec/tb-lookup.h:43
  #4  tb_find (cpu=..., last_tb=... <code_gen_buffer+17811>, tb_exit=0, cf_mask=0) at accel/tcg/cpu-exec.c:404
  #5  cpu_exec (cpu=...) at accel/tcg/cpu-exec.c:729
  #6  tcg_cpu_exec (cpu=...) at cpus.c:1430
  #7  qemu_tcg_rr_cpu_thread_fn (arg=...) at cpus.c:1531
  #8  qemu_thread_start (args=...) at util/qemu-thread-posix.c:502
  ---

  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_type=MMU_INST_FETCH is lost in "io_readx()" while calling tlb_fill()",
  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_type=MMU_DATA_LOAD, ...) at target/arc/mmu.c:605
  #1  io_readx (..., access_type=MMU_INST_FETCH, size=2) at accel/tcg/cputlb.c:881
  #2  io_readw (..., access_type=MMU_INST_FETCH) at accel/tcg/softmmu_template.h:106
  #3  helper_le_ldw_cmmu (..., oi=16, retaddr=0) at accel/tcg/softmmu_template.h:146
  #4  cpu_lduw_code_ra (env=..., ptr=684, retaddr=0) at include/exec/cpu_ldst_template.h:102
  #5  cpu_lduw_code (env=..., ptr=684) at include/exec/cpu_ldst_template.h:114
  #6  read_and_decode_context (ctx=..., opcode_p=...) at target/arc/arc-decoder.c:1479
  #7  arc_decode (ctx=...) at target/arc/arc-decoder.c:1736
  #8  decode_opc (env=..., ctx=...) at target/arc/translate.c:313
  #9  arc_tr_translate_insn (dcbase=..., cpu=...) at target/arc/translate.c:335
  #10 translator_loop (.. <code_gen_buffer+18131>) at accel/tcg/translator.c:107
  #11 gen_intermediate_code (cpu=..., tb=... <code_gen_buffer+18131>) at target/arc/translate.c:413
  #12 tb_gen_code (cpu=..., pc=684, cs_base=0, flags=0, cflags=-16711679) at accel/tcg/translate-all.c:1723
  #13 tb_find (cpu=..., last_tb=... <code_gen_buffer+17811>, tb_exit=0, cf_mask=0) at accel/tcg/cpu-exec.c:407
  #14 cpu_exec (cpu=...) at accel/tcg/cpu-exec.c:729
  #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.

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1825359/+subscriptions

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Qemu-devel] [Bug 1825359] Re: cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH
  2019-04-18 12:00 [Qemu-devel] [Bug 1825359] [NEW] cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH Shahab Vahedi
                   ` (9 preceding siblings ...)
  2019-04-18 18:46 ` Shahab Vahedi
@ 2019-05-03 16:33 ` Peter Maydell
  2019-05-04 14:39 ` Shahab Vahedi
  2019-08-16  4:44 ` Thomas Huth
  12 siblings, 0 replies; 14+ messages in thread
From: Peter Maydell @ 2019-05-03 16:33 UTC (permalink / raw)
  To: qemu-devel

Your patch is now in git master as commit ef5dae6805cce7b59d129 --
thanks!


** Changed in: qemu
       Status: Confirmed => Fix Committed

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1825359

Title:
  cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH

Status in QEMU:
  Fix Committed

Bug description:
  commit 377b155bde451d5ac545fbdcdfbf6ca17a4228f5
  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://github.com/qemu/qemu/commit/377b155bde451d5ac545fbdcdfbf6ca17a4228f5
  --------------------------------------------------

  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_type=MMU_INST_FETCH, ...)" is
  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;
          target_ulong tlb_addr;

          tlb_fill(cpu, addr, size, MMU_DATA_LOAD, mmu_idx, retaddr);
          ...
  }
  --------

  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_type=MMU_INST_FETCH, ...)"
  is triggered by "tb_lookup_cpu_state()". To be precise, this is the call
  stack which is good behavior:
  ---
  #0  tlb_fill (cs=..., vaddr=684, size=0, access_type=MMU_INST_FETCH, mmu_idx=0, retaddr=0) at target/arc/mmu.c:602
  #1  get_page_addr_code (env=..., addr=684) at accel/tcg/cputlb.c:1045
  #2  tb_htable_lookup (cpu=..., pc=684, cs_base=0, flags=0, cf_mask=4278190080) at accel/tcg/cpu-exec.c:337
  #3  tb_lookup__cpu_state (cpu=..., pc=..., cs_base=..., flags=..., cf_mask=4278190080) at include/exec/tb-lookup.h:43
  #4  tb_find (cpu=..., last_tb=... <code_gen_buffer+17811>, tb_exit=0, cf_mask=0) at accel/tcg/cpu-exec.c:404
  #5  cpu_exec (cpu=...) at accel/tcg/cpu-exec.c:729
  #6  tcg_cpu_exec (cpu=...) at cpus.c:1430
  #7  qemu_tcg_rr_cpu_thread_fn (arg=...) at cpus.c:1531
  #8  qemu_thread_start (args=...) at util/qemu-thread-posix.c:502
  ---

  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_type=MMU_INST_FETCH is lost in "io_readx()" while calling tlb_fill()",
  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_type=MMU_DATA_LOAD, ...) at target/arc/mmu.c:605
  #1  io_readx (..., access_type=MMU_INST_FETCH, size=2) at accel/tcg/cputlb.c:881
  #2  io_readw (..., access_type=MMU_INST_FETCH) at accel/tcg/softmmu_template.h:106
  #3  helper_le_ldw_cmmu (..., oi=16, retaddr=0) at accel/tcg/softmmu_template.h:146
  #4  cpu_lduw_code_ra (env=..., ptr=684, retaddr=0) at include/exec/cpu_ldst_template.h:102
  #5  cpu_lduw_code (env=..., ptr=684) at include/exec/cpu_ldst_template.h:114
  #6  read_and_decode_context (ctx=..., opcode_p=...) at target/arc/arc-decoder.c:1479
  #7  arc_decode (ctx=...) at target/arc/arc-decoder.c:1736
  #8  decode_opc (env=..., ctx=...) at target/arc/translate.c:313
  #9  arc_tr_translate_insn (dcbase=..., cpu=...) at target/arc/translate.c:335
  #10 translator_loop (.. <code_gen_buffer+18131>) at accel/tcg/translator.c:107
  #11 gen_intermediate_code (cpu=..., tb=... <code_gen_buffer+18131>) at target/arc/translate.c:413
  #12 tb_gen_code (cpu=..., pc=684, cs_base=0, flags=0, cflags=-16711679) at accel/tcg/translate-all.c:1723
  #13 tb_find (cpu=..., last_tb=... <code_gen_buffer+17811>, tb_exit=0, cf_mask=0) at accel/tcg/cpu-exec.c:407
  #14 cpu_exec (cpu=...) at accel/tcg/cpu-exec.c:729
  #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.

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1825359/+subscriptions

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Qemu-devel] [Bug 1825359] Re: cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH
  2019-04-18 12:00 [Qemu-devel] [Bug 1825359] [NEW] cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH Shahab Vahedi
                   ` (10 preceding siblings ...)
  2019-05-03 16:33 ` Peter Maydell
@ 2019-05-04 14:39 ` Shahab Vahedi
  2019-08-16  4:44 ` Thomas Huth
  12 siblings, 0 replies; 14+ messages in thread
From: Shahab Vahedi @ 2019-05-04 14:39 UTC (permalink / raw)
  To: qemu-devel

Thank YOU for all the supports along the way :)

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1825359

Title:
  cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH

Status in QEMU:
  Fix Committed

Bug description:
  commit 377b155bde451d5ac545fbdcdfbf6ca17a4228f5
  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://github.com/qemu/qemu/commit/377b155bde451d5ac545fbdcdfbf6ca17a4228f5
  --------------------------------------------------

  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_type=MMU_INST_FETCH, ...)" is
  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;
          target_ulong tlb_addr;

          tlb_fill(cpu, addr, size, MMU_DATA_LOAD, mmu_idx, retaddr);
          ...
  }
  --------

  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_type=MMU_INST_FETCH, ...)"
  is triggered by "tb_lookup_cpu_state()". To be precise, this is the call
  stack which is good behavior:
  ---
  #0  tlb_fill (cs=..., vaddr=684, size=0, access_type=MMU_INST_FETCH, mmu_idx=0, retaddr=0) at target/arc/mmu.c:602
  #1  get_page_addr_code (env=..., addr=684) at accel/tcg/cputlb.c:1045
  #2  tb_htable_lookup (cpu=..., pc=684, cs_base=0, flags=0, cf_mask=4278190080) at accel/tcg/cpu-exec.c:337
  #3  tb_lookup__cpu_state (cpu=..., pc=..., cs_base=..., flags=..., cf_mask=4278190080) at include/exec/tb-lookup.h:43
  #4  tb_find (cpu=..., last_tb=... <code_gen_buffer+17811>, tb_exit=0, cf_mask=0) at accel/tcg/cpu-exec.c:404
  #5  cpu_exec (cpu=...) at accel/tcg/cpu-exec.c:729
  #6  tcg_cpu_exec (cpu=...) at cpus.c:1430
  #7  qemu_tcg_rr_cpu_thread_fn (arg=...) at cpus.c:1531
  #8  qemu_thread_start (args=...) at util/qemu-thread-posix.c:502
  ---

  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_type=MMU_INST_FETCH is lost in "io_readx()" while calling tlb_fill()",
  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_type=MMU_DATA_LOAD, ...) at target/arc/mmu.c:605
  #1  io_readx (..., access_type=MMU_INST_FETCH, size=2) at accel/tcg/cputlb.c:881
  #2  io_readw (..., access_type=MMU_INST_FETCH) at accel/tcg/softmmu_template.h:106
  #3  helper_le_ldw_cmmu (..., oi=16, retaddr=0) at accel/tcg/softmmu_template.h:146
  #4  cpu_lduw_code_ra (env=..., ptr=684, retaddr=0) at include/exec/cpu_ldst_template.h:102
  #5  cpu_lduw_code (env=..., ptr=684) at include/exec/cpu_ldst_template.h:114
  #6  read_and_decode_context (ctx=..., opcode_p=...) at target/arc/arc-decoder.c:1479
  #7  arc_decode (ctx=...) at target/arc/arc-decoder.c:1736
  #8  decode_opc (env=..., ctx=...) at target/arc/translate.c:313
  #9  arc_tr_translate_insn (dcbase=..., cpu=...) at target/arc/translate.c:335
  #10 translator_loop (.. <code_gen_buffer+18131>) at accel/tcg/translator.c:107
  #11 gen_intermediate_code (cpu=..., tb=... <code_gen_buffer+18131>) at target/arc/translate.c:413
  #12 tb_gen_code (cpu=..., pc=684, cs_base=0, flags=0, cflags=-16711679) at accel/tcg/translate-all.c:1723
  #13 tb_find (cpu=..., last_tb=... <code_gen_buffer+17811>, tb_exit=0, cf_mask=0) at accel/tcg/cpu-exec.c:407
  #14 cpu_exec (cpu=...) at accel/tcg/cpu-exec.c:729
  #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.

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1825359/+subscriptions

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Qemu-devel] [Bug 1825359] Re: cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH
  2019-04-18 12:00 [Qemu-devel] [Bug 1825359] [NEW] cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH Shahab Vahedi
                   ` (11 preceding siblings ...)
  2019-05-04 14:39 ` Shahab Vahedi
@ 2019-08-16  4:44 ` Thomas Huth
  12 siblings, 0 replies; 14+ messages in thread
From: Thomas Huth @ 2019-08-16  4:44 UTC (permalink / raw)
  To: qemu-devel

** Changed in: qemu
       Status: Fix Committed => Fix Released

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1825359

Title:
  cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH

Status in QEMU:
  Fix Released

Bug description:
  commit 377b155bde451d5ac545fbdcdfbf6ca17a4228f5
  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://github.com/qemu/qemu/commit/377b155bde451d5ac545fbdcdfbf6ca17a4228f5
  --------------------------------------------------

  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_type=MMU_INST_FETCH, ...)" is
  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;
          target_ulong tlb_addr;

          tlb_fill(cpu, addr, size, MMU_DATA_LOAD, mmu_idx, retaddr);
          ...
  }
  --------

  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_type=MMU_INST_FETCH, ...)"
  is triggered by "tb_lookup_cpu_state()". To be precise, this is the call
  stack which is good behavior:
  ---
  #0  tlb_fill (cs=..., vaddr=684, size=0, access_type=MMU_INST_FETCH, mmu_idx=0, retaddr=0) at target/arc/mmu.c:602
  #1  get_page_addr_code (env=..., addr=684) at accel/tcg/cputlb.c:1045
  #2  tb_htable_lookup (cpu=..., pc=684, cs_base=0, flags=0, cf_mask=4278190080) at accel/tcg/cpu-exec.c:337
  #3  tb_lookup__cpu_state (cpu=..., pc=..., cs_base=..., flags=..., cf_mask=4278190080) at include/exec/tb-lookup.h:43
  #4  tb_find (cpu=..., last_tb=... <code_gen_buffer+17811>, tb_exit=0, cf_mask=0) at accel/tcg/cpu-exec.c:404
  #5  cpu_exec (cpu=...) at accel/tcg/cpu-exec.c:729
  #6  tcg_cpu_exec (cpu=...) at cpus.c:1430
  #7  qemu_tcg_rr_cpu_thread_fn (arg=...) at cpus.c:1531
  #8  qemu_thread_start (args=...) at util/qemu-thread-posix.c:502
  ---

  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_type=MMU_INST_FETCH is lost in "io_readx()" while calling tlb_fill()",
  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_type=MMU_DATA_LOAD, ...) at target/arc/mmu.c:605
  #1  io_readx (..., access_type=MMU_INST_FETCH, size=2) at accel/tcg/cputlb.c:881
  #2  io_readw (..., access_type=MMU_INST_FETCH) at accel/tcg/softmmu_template.h:106
  #3  helper_le_ldw_cmmu (..., oi=16, retaddr=0) at accel/tcg/softmmu_template.h:146
  #4  cpu_lduw_code_ra (env=..., ptr=684, retaddr=0) at include/exec/cpu_ldst_template.h:102
  #5  cpu_lduw_code (env=..., ptr=684) at include/exec/cpu_ldst_template.h:114
  #6  read_and_decode_context (ctx=..., opcode_p=...) at target/arc/arc-decoder.c:1479
  #7  arc_decode (ctx=...) at target/arc/arc-decoder.c:1736
  #8  decode_opc (env=..., ctx=...) at target/arc/translate.c:313
  #9  arc_tr_translate_insn (dcbase=..., cpu=...) at target/arc/translate.c:335
  #10 translator_loop (.. <code_gen_buffer+18131>) at accel/tcg/translator.c:107
  #11 gen_intermediate_code (cpu=..., tb=... <code_gen_buffer+18131>) at target/arc/translate.c:413
  #12 tb_gen_code (cpu=..., pc=684, cs_base=0, flags=0, cflags=-16711679) at accel/tcg/translate-all.c:1723
  #13 tb_find (cpu=..., last_tb=... <code_gen_buffer+17811>, tb_exit=0, cf_mask=0) at accel/tcg/cpu-exec.c:407
  #14 cpu_exec (cpu=...) at accel/tcg/cpu-exec.c:729
  #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.

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1825359/+subscriptions


^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2019-08-16  4:52 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-04-18 12:00 [Qemu-devel] [Bug 1825359] [NEW] cpu_ld*_code() triggers MMU_DATA_LOAD i.s.o. MMU_INST_FETCH Shahab Vahedi
2019-04-18 12:31 ` [Qemu-devel] [Bug 1825359] " Peter Maydell
2019-04-18 13:24 ` Shahab Vahedi
2019-04-18 13:27 ` Shahab Vahedi
2019-04-18 13:57 ` Peter Maydell
2019-04-18 14:09 ` Shahab Vahedi
2019-04-18 14:11 ` Shahab Vahedi
2019-04-18 14:11 ` Peter Maydell
2019-04-18 18:26 ` Shahab Vahedi
2019-04-18 18:40 ` Shahab Vahedi
2019-04-18 18:46 ` Shahab Vahedi
2019-05-03 16:33 ` Peter Maydell
2019-05-04 14:39 ` Shahab Vahedi
2019-08-16  4:44 ` Thomas Huth

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.