• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Commit MetaInfo

Revisión7399a337e4126f7c8c8af3336726f001378c4798 (tree)
Tiempo2016-07-09 05:17:38
AutorStanislav Shmarov <snarpix@gmai...>
CommiterRichard Henderson

Log Message

translate-all: Fix user-mode self-modifying code in 2 page long TB

In user-mode emulation Translation Block can consist of 2 guest pages.
In that case QEMU also mprotects 2 host pages that are dedicated for
guest memory, containing instructions. QEMU detects self-modifying code
with SEGFAULT signal processing.

In case if instruction in 1st page is modifying memory of 2nd
page (or vice versa) QEMU will mark 2nd page with PAGE_WRITE,
invalidate TB, generate new TB contatining 1 guest instruction and
exit to CPU loop. QEMU won't call mprotect, and new TB will cause
same SEGFAULT. Page will have both PAGE_WRITE_ORG and PAGE_WRITE
flags, so QEMU will handle the signal as guest binary problem,
and exit with guest SEGFAULT.

Solution is to do following: In case if current TB was invalidated
continue to invalidate TBs from remaining guest pages and mark pages
as PAGE_WRITE. After that disable host page protection with mprotect.
If current tb was invalidated longjmp to main loop. That is more
efficient, since we won't get SEGFAULT when executing new TB.

Reviewed-by: Sergey Fedorov <sergey.fedorov@linaro.org>
Signed-off-by: Stanislav Shmarov <snarpix@gmail.com>
Message-Id: <1467880392-1043630-1-git-send-email-snarpix@gmail.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>

Cambiar Resumen

Diferencia incremental

--- a/translate-all.c
+++ b/translate-all.c
@@ -2000,6 +2000,7 @@ int page_check_range(target_ulong start, target_ulong len, int flags)
20002000 int page_unprotect(target_ulong address, uintptr_t pc)
20012001 {
20022002 unsigned int prot;
2003+ bool current_tb_invalidated;
20032004 PageDesc *p;
20042005 target_ulong host_start, host_end, addr;
20052006
@@ -2021,6 +2022,7 @@ int page_unprotect(target_ulong address, uintptr_t pc)
20212022 host_end = host_start + qemu_host_page_size;
20222023
20232024 prot = 0;
2025+ current_tb_invalidated = false;
20242026 for (addr = host_start ; addr < host_end ; addr += TARGET_PAGE_SIZE) {
20252027 p = page_find(addr >> TARGET_PAGE_BITS);
20262028 p->flags |= PAGE_WRITE;
@@ -2028,10 +2030,7 @@ int page_unprotect(target_ulong address, uintptr_t pc)
20282030
20292031 /* and since the content will be modified, we must invalidate
20302032 the corresponding translated code. */
2031- if (tb_invalidate_phys_page(addr, pc)) {
2032- mmap_unlock();
2033- return 2;
2034- }
2033+ current_tb_invalidated |= tb_invalidate_phys_page(addr, pc);
20352034 #ifdef DEBUG_TB_CHECK
20362035 tb_invalidate_check(addr);
20372036 #endif
@@ -2040,7 +2039,8 @@ int page_unprotect(target_ulong address, uintptr_t pc)
20402039 prot & PAGE_BITS);
20412040
20422041 mmap_unlock();
2043- return 1;
2042+ /* If current TB was invalidated return to main loop */
2043+ return current_tb_invalidated ? 2 : 1;
20442044 }
20452045 mmap_unlock();
20462046 return 0;