diff mbox series

[v5,1/4] linux-user: Clear tb_jmp_cache on mprotect()

Message ID 20220817150506.592862-2-iii@linux.ibm.com (mailing list archive)
State New, archived
Headers show
Series linux-user: Fix siginfo_t contents when jumping to non-readable pages | expand

Commit Message

Ilya Leoshkevich Aug. 17, 2022, 3:05 p.m. UTC
Currently it's possible to execute pages that do not have PAGE_EXEC if
there is an existing translation block. Fix by clearing tb_jmp_cache,
which forces HELPER(lookup_tb_ptr)() to recheck permission bits the
next time.

Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
---
 linux-user/mmap.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)
diff mbox series

Patch

diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index bbc674311b..bd96c876ba 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -115,6 +115,7 @@  int target_mprotect(abi_ulong start, abi_ulong len, int target_prot)
 {
     abi_ulong end, host_start, host_end, addr;
     int prot1, ret, page_flags, host_prot;
+    CPUState *cpu;
 
     trace_target_mprotect(start, len, target_prot);
 
@@ -178,6 +179,19 @@  int target_mprotect(abi_ulong start, abi_ulong len, int target_prot)
         }
     }
     page_set_flags(start, start + len, page_flags);
+
+    /*
+     * Unlike target_mmap(), target_munmap() and target_mremap(), we don't need
+     * to call tb_invalidate_phys_range() here, since pages still hold the same
+     * data.  However, tb_jmp_cache needs to be cleared, otherwise after
+     * clearing PAGE_EXEC it would still be possible to jump to the existing
+     * translation blocks.  We just clear the whole cache here: mprotect() is
+     * rare enough, so a more fine-grained approach is not necessary.
+     */
+    CPU_FOREACH(cpu) {
+        cpu_tb_jmp_cache_clear(cpu);
+    }
+
     mmap_unlock();
     return 0;
 error: