* [PATCH v3 0/4] linux-user: Fix siginfo_t contents when jumping to non-readable pages
@ 2022-08-08 17:10 Ilya Leoshkevich
2022-08-08 17:10 ` [PATCH v3 1/4] accel/tcg: Invalidate translations when clearing PAGE_EXEC Ilya Leoshkevich
` (3 more replies)
0 siblings, 4 replies; 13+ messages in thread
From: Ilya Leoshkevich @ 2022-08-08 17:10 UTC (permalink / raw)
To: Laurent Vivier, Eduardo Habkost, Marcel Apfelbaum,
Philippe Mathieu-Daudé, Yanan Wang, Richard Henderson,
Paolo Bonzini, David Hildenbrand, Peter Maydell
Cc: qemu-devel, qemu-s390x, Christian Borntraeger, Ilya Leoshkevich
Hi,
I noticed that when we get a SEGV due to jumping to non-readable
memory, sometimes si_addr and program counter in siginfo_t are slightly
off. I tracked this down to the assumption that translators stop before
the end of a page, while in reality they may stop right after it.
Patch 1 fixes a minor invalidation issue, which may prevent SEGV from
happening altogether.
Patches 2-3 fix the main issue on x86_64 and s390x. Many other
architectures have fixed-size instructions and are not affected.
Patch 4 adds tests.
Best regards,
Ilya
v1: https://lists.gnu.org/archive/html/qemu-devel/2022-08/msg00822.html
v1 -> v2: Fix individual translators instead of translator_loop
(Peter).
v2: https://lists.gnu.org/archive/html/qemu-devel/2022-08/msg01079.html
v2 -> v3: Peek at the next instruction on s390x (Richard).
Undo more on i386 (Richard).
Check PAGE_EXEC, not PAGE_READ (Peter, Richard).
Ilya Leoshkevich (4):
accel/tcg: Invalidate translations when clearing PAGE_EXEC
target/s390x: Make translator stop before the end of a page
target/i386: Make translator stop before the end of a page
tests/tcg: Test siginfo_t contents when jumping to non-readable pages
accel/tcg/translate-all.c | 17 ++--
accel/tcg/translator.c | 8 ++
include/exec/translator.h | 13 +++
target/i386/tcg/translate.c | 21 ++++-
target/s390x/tcg/translate.c | 15 +++-
tests/tcg/multiarch/noexec.h | 114 ++++++++++++++++++++++++
tests/tcg/s390x/Makefile.target | 1 +
tests/tcg/s390x/noexec.c | 145 +++++++++++++++++++++++++++++++
tests/tcg/x86_64/Makefile.target | 3 +-
tests/tcg/x86_64/noexec.c | 116 +++++++++++++++++++++++++
10 files changed, 442 insertions(+), 11 deletions(-)
create mode 100644 tests/tcg/multiarch/noexec.h
create mode 100644 tests/tcg/s390x/noexec.c
create mode 100644 tests/tcg/x86_64/noexec.c
--
2.37.1
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v3 1/4] accel/tcg: Invalidate translations when clearing PAGE_EXEC
2022-08-08 17:10 [PATCH v3 0/4] linux-user: Fix siginfo_t contents when jumping to non-readable pages Ilya Leoshkevich
@ 2022-08-08 17:10 ` Ilya Leoshkevich
2022-08-10 20:29 ` Richard Henderson
2022-08-08 17:10 ` [PATCH v3 2/4] target/s390x: Make translator stop before the end of a page Ilya Leoshkevich
` (2 subsequent siblings)
3 siblings, 1 reply; 13+ messages in thread
From: Ilya Leoshkevich @ 2022-08-08 17:10 UTC (permalink / raw)
To: Laurent Vivier, Eduardo Habkost, Marcel Apfelbaum,
Philippe Mathieu-Daudé, Yanan Wang, Richard Henderson,
Paolo Bonzini, David Hildenbrand, Peter Maydell
Cc: qemu-devel, qemu-s390x, Christian Borntraeger, Ilya Leoshkevich
After mprotect(addr, PROT_NONE), addr can still be executed if there
are cached translations. Drop them.
Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
---
accel/tcg/translate-all.c | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index ef62a199c7..32ea5f0adf 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -2295,12 +2295,19 @@ void page_set_flags(target_ulong start, target_ulong end, int flags)
len != 0;
len -= TARGET_PAGE_SIZE, addr += TARGET_PAGE_SIZE) {
PageDesc *p = page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
+ bool write_set, exec_cleared;
- /* If the write protection bit is set, then we invalidate
- the code inside. */
- if (!(p->flags & PAGE_WRITE) &&
- (flags & PAGE_WRITE) &&
- p->first_tb) {
+ /*
+ * If the write protection bit is set, then we invalidate the code
+ * inside.
+ */
+ write_set = !(p->flags & PAGE_WRITE) && (flags & PAGE_WRITE);
+ /*
+ * If PAGE_EXEC is cleared, we also need to invalidate the code in
+ * order to force a fault when trying to run it.
+ */
+ exec_cleared = (p->flags & PAGE_EXEC) && !(flags & PAGE_EXEC);
+ if ((write_set || exec_cleared) && p->first_tb) {
tb_invalidate_phys_page(addr, 0);
}
if (reset_target_data) {
--
2.37.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v3 2/4] target/s390x: Make translator stop before the end of a page
2022-08-08 17:10 [PATCH v3 0/4] linux-user: Fix siginfo_t contents when jumping to non-readable pages Ilya Leoshkevich
2022-08-08 17:10 ` [PATCH v3 1/4] accel/tcg: Invalidate translations when clearing PAGE_EXEC Ilya Leoshkevich
@ 2022-08-08 17:10 ` Ilya Leoshkevich
2022-08-10 20:30 ` Richard Henderson
2022-08-11 4:08 ` Richard Henderson
2022-08-08 17:10 ` [PATCH v3 3/4] target/i386: " Ilya Leoshkevich
2022-08-08 17:10 ` [PATCH v3 4/4] tests/tcg: Test siginfo_t contents when jumping to non-readable pages Ilya Leoshkevich
3 siblings, 2 replies; 13+ messages in thread
From: Ilya Leoshkevich @ 2022-08-08 17:10 UTC (permalink / raw)
To: Laurent Vivier, Eduardo Habkost, Marcel Apfelbaum,
Philippe Mathieu-Daudé, Yanan Wang, Richard Henderson,
Paolo Bonzini, David Hildenbrand, Peter Maydell
Cc: qemu-devel, qemu-s390x, Christian Borntraeger, Ilya Leoshkevich
Right now translator stops right *after* the end of a page, which
breaks reporting of fault locations when the last instruction of a
multi-insn translation block crosses a page boundary.
Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
---
include/exec/translator.h | 10 ++++++++++
target/s390x/tcg/translate.c | 15 +++++++++++----
2 files changed, 21 insertions(+), 4 deletions(-)
diff --git a/include/exec/translator.h b/include/exec/translator.h
index 7db6845535..d27f8c33b6 100644
--- a/include/exec/translator.h
+++ b/include/exec/translator.h
@@ -187,4 +187,14 @@ FOR_EACH_TRANSLATOR_LD(GEN_TRANSLATOR_LD)
#undef GEN_TRANSLATOR_LD
+/*
+ * Return whether addr is on the same page as where disassembly started.
+ * Translators can use this to enforce the rule that only single-insn
+ * translation blocks are allowed to cross page boundaries.
+ */
+static inline bool is_same_page(DisasContextBase *db, target_ulong addr)
+{
+ return ((addr ^ db->pc_first) & TARGET_PAGE_MASK) == 0;
+}
+
#endif /* EXEC__TRANSLATOR_H */
diff --git a/target/s390x/tcg/translate.c b/target/s390x/tcg/translate.c
index e2ee005671..8e45a0e0d3 100644
--- a/target/s390x/tcg/translate.c
+++ b/target/s390x/tcg/translate.c
@@ -6609,6 +6609,14 @@ static void s390x_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
dc->insn_start = tcg_last_op();
}
+static target_ulong get_next_pc(CPUS390XState *env, DisasContext *s,
+ uint64_t pc)
+{
+ uint64_t insn = ld_code2(env, s, pc);
+
+ return pc + get_ilen((insn >> 8) & 0xff);
+}
+
static void s390x_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
{
CPUS390XState *env = cs->env_ptr;
@@ -6616,10 +6624,9 @@ static void s390x_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
dc->base.is_jmp = translate_one(env, dc);
if (dc->base.is_jmp == DISAS_NEXT) {
- uint64_t page_start;
-
- page_start = dc->base.pc_first & TARGET_PAGE_MASK;
- if (dc->base.pc_next - page_start >= TARGET_PAGE_SIZE || dc->ex_value) {
+ if (!is_same_page(dcbase, dc->base.pc_next) ||
+ !is_same_page(dcbase, get_next_pc(env, dc, dc->base.pc_next)) ||
+ dc->ex_value) {
dc->base.is_jmp = DISAS_TOO_MANY;
}
}
--
2.37.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v3 3/4] target/i386: Make translator stop before the end of a page
2022-08-08 17:10 [PATCH v3 0/4] linux-user: Fix siginfo_t contents when jumping to non-readable pages Ilya Leoshkevich
2022-08-08 17:10 ` [PATCH v3 1/4] accel/tcg: Invalidate translations when clearing PAGE_EXEC Ilya Leoshkevich
2022-08-08 17:10 ` [PATCH v3 2/4] target/s390x: Make translator stop before the end of a page Ilya Leoshkevich
@ 2022-08-08 17:10 ` Ilya Leoshkevich
2022-08-10 20:35 ` Richard Henderson
2022-08-08 17:10 ` [PATCH v3 4/4] tests/tcg: Test siginfo_t contents when jumping to non-readable pages Ilya Leoshkevich
3 siblings, 1 reply; 13+ messages in thread
From: Ilya Leoshkevich @ 2022-08-08 17:10 UTC (permalink / raw)
To: Laurent Vivier, Eduardo Habkost, Marcel Apfelbaum,
Philippe Mathieu-Daudé, Yanan Wang, Richard Henderson,
Paolo Bonzini, David Hildenbrand, Peter Maydell
Cc: qemu-devel, qemu-s390x, Christian Borntraeger, Ilya Leoshkevich
Right now translator stops right *after* the end of a page, which
breaks reporting of fault locations when the last instruction of a
multi-insn translation block crosses a page boundary.
An implementation, like the one arm and s390x have, would require an
i386 length disassembler, which is burdensome to maintain. Another
alternative would be to single-step at the end of a guest page, but
this may come with a performance impact.
Fix by snapshotting disassembly state and restoring it after we figure
out we crossed a page boundary. This includes rolling back cc_op
updates and emitted ops. Even though i386 is the only architecture that
does rollback, split it into common and architecture-dependent parts to
improve readability.
Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
---
accel/tcg/translator.c | 8 ++++++++
include/exec/translator.h | 3 +++
target/i386/tcg/translate.c | 21 ++++++++++++++++++++-
3 files changed, 31 insertions(+), 1 deletion(-)
diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
index fe7af9b943..2c4dd09df8 100644
--- a/accel/tcg/translator.c
+++ b/accel/tcg/translator.c
@@ -56,6 +56,7 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
{
uint32_t cflags = tb_cflags(tb);
bool plugin_enabled;
+ TCGOp *last_op;
/* Initialize DisasContext */
db->tb = tb;
@@ -82,6 +83,7 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
while (true) {
db->num_insns++;
+ last_op = tcg_last_op();
ops->insn_start(db, cpu);
tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */
@@ -103,6 +105,12 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
ops->translate_insn(db, cpu);
}
+ if (db->is_jmp == DISAS_TOO_MANY_UNDO) {
+ db->num_insns--;
+ tcg_remove_ops_after(last_op);
+ db->is_jmp = DISAS_TOO_MANY;
+ }
+
/* Stop translation if translate_insn so indicated. */
if (db->is_jmp != DISAS_NEXT) {
break;
diff --git a/include/exec/translator.h b/include/exec/translator.h
index d27f8c33b6..e1533aee87 100644
--- a/include/exec/translator.h
+++ b/include/exec/translator.h
@@ -31,6 +31,8 @@
* DisasJumpType:
* @DISAS_NEXT: Next instruction in program order.
* @DISAS_TOO_MANY: Too many instructions translated.
+ * @DISAS_TOO_MANY_UNDO: Too many instructions translated. Everything that was
+ * done for the current instruction must be undone.
* @DISAS_NORETURN: Following code is dead.
* @DISAS_TARGET_*: Start of target-specific conditions.
*
@@ -39,6 +41,7 @@
typedef enum DisasJumpType {
DISAS_NEXT,
DISAS_TOO_MANY,
+ DISAS_TOO_MANY_UNDO,
DISAS_NORETURN,
DISAS_TARGET_0,
DISAS_TARGET_1,
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index b7972f0ff5..14d4ed1412 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -2008,6 +2008,12 @@ static uint64_t advance_pc(CPUX86State *env, DisasContext *s, int num_bytes)
{
uint64_t pc = s->pc;
+ /* This is a subsequent insn that crosses a page boundary. */
+ if (s->base.num_insns > 1 &&
+ !is_same_page(&s->base, s->pc + num_bytes - 1)) {
+ siglongjmp(s->jmpbuf, 2);
+ }
+
s->pc += num_bytes;
if (unlikely(s->pc - s->pc_start > X86_MAX_INSN_LENGTH)) {
/* If the instruction's 16th byte is on a different page than the 1st, a
@@ -4556,6 +4562,8 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
int modrm, reg, rm, mod, op, opreg, val;
target_ulong next_eip, tval;
target_ulong pc_start = s->base.pc_next;
+ bool orig_cc_op_dirty = s->cc_op_dirty;
+ CCOp orig_cc_op = s->cc_op;
s->pc_start = s->pc = pc_start;
s->override = -1;
@@ -4568,9 +4576,20 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
s->rip_offset = 0; /* for relative ip address */
s->vex_l = 0;
s->vex_v = 0;
- if (sigsetjmp(s->jmpbuf, 0) != 0) {
+ switch (sigsetjmp(s->jmpbuf, 0)) {
+ case 0:
+ break;
+ case 1:
gen_exception_gpf(s);
return s->pc;
+ case 2:
+ /* Restore state that may affect the next instruction. */
+ s->cc_op_dirty = orig_cc_op_dirty;
+ s->cc_op = orig_cc_op;
+ s->base.is_jmp = DISAS_TOO_MANY_UNDO;
+ return pc_start;
+ default:
+ g_assert_not_reached();
}
prefixes = 0;
--
2.37.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v3 4/4] tests/tcg: Test siginfo_t contents when jumping to non-readable pages
2022-08-08 17:10 [PATCH v3 0/4] linux-user: Fix siginfo_t contents when jumping to non-readable pages Ilya Leoshkevich
` (2 preceding siblings ...)
2022-08-08 17:10 ` [PATCH v3 3/4] target/i386: " Ilya Leoshkevich
@ 2022-08-08 17:10 ` Ilya Leoshkevich
3 siblings, 0 replies; 13+ messages in thread
From: Ilya Leoshkevich @ 2022-08-08 17:10 UTC (permalink / raw)
To: Laurent Vivier, Eduardo Habkost, Marcel Apfelbaum,
Philippe Mathieu-Daudé, Yanan Wang, Richard Henderson,
Paolo Bonzini, David Hildenbrand, Peter Maydell
Cc: qemu-devel, qemu-s390x, Christian Borntraeger, Ilya Leoshkevich
Add x86_64 and s390x tests to prevent regressions.
Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
---
tests/tcg/multiarch/noexec.h | 114 ++++++++++++++++++++++++
tests/tcg/s390x/Makefile.target | 1 +
tests/tcg/s390x/noexec.c | 145 +++++++++++++++++++++++++++++++
tests/tcg/x86_64/Makefile.target | 3 +-
tests/tcg/x86_64/noexec.c | 116 +++++++++++++++++++++++++
5 files changed, 378 insertions(+), 1 deletion(-)
create mode 100644 tests/tcg/multiarch/noexec.h
create mode 100644 tests/tcg/s390x/noexec.c
create mode 100644 tests/tcg/x86_64/noexec.c
diff --git a/tests/tcg/multiarch/noexec.h b/tests/tcg/multiarch/noexec.h
new file mode 100644
index 0000000000..a76e0aa9ea
--- /dev/null
+++ b/tests/tcg/multiarch/noexec.h
@@ -0,0 +1,114 @@
+/*
+ * Common code for arch-specific MMU_INST_FETCH fault testing.
+ *
+ * Declare struct arch_noexec_test before including this file and define
+ * arch_check_mcontext() after that.
+ */
+
+#include <assert.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/ucontext.h>
+#include <unistd.h>
+
+/* Forward declarations. */
+
+static void arch_check_mcontext(const struct arch_noexec_test *test,
+ const mcontext_t *ctx);
+
+/* Utility functions. */
+
+static void safe_print(const char *s)
+{
+ write(0, s, strlen(s));
+}
+
+static void safe_puts(const char *s)
+{
+ safe_print(s);
+ safe_print("\n");
+}
+
+#define PAGE_ALIGN(p) (void *)((unsigned long)(p) & ~0xfffUL)
+
+/* Testing infrastructure. */
+
+struct noexec_test {
+ const char *name;
+ void (*func)(int);
+ void *page;
+ void *expected_si_addr;
+ struct arch_noexec_test arch;
+};
+
+static const struct noexec_test *current_noexec_test;
+
+static void handle_segv(int sig, siginfo_t *info, void *ucontext)
+{
+ int err;
+
+ if (current_noexec_test == NULL) {
+ safe_puts("[ FAILED ] unexpected SEGV");
+ _exit(1);
+ }
+
+ if (info->si_addr != current_noexec_test->expected_si_addr) {
+ safe_puts("[ FAILED ] wrong si_addr");
+ _exit(1);
+ }
+
+ arch_check_mcontext(¤t_noexec_test->arch,
+ &((ucontext_t *)ucontext)->uc_mcontext);
+
+ err = mprotect(current_noexec_test->page, 0x1000, PROT_READ | PROT_EXEC);
+ if (err != 0) {
+ safe_puts("[ FAILED ] mprotect() failed");
+ _exit(1);
+ }
+
+ current_noexec_test = NULL;
+}
+
+static void test_noexec_1(const struct noexec_test *test)
+{
+ int ret;
+
+ /* Trigger TB creation in order to test invalidation. */
+ test->func(0);
+
+ ret = mprotect(test->page, 0x1000, PROT_NONE);
+ assert(ret == 0);
+
+ /* Trigger SEGV and check that handle_segv() ran. */
+ current_noexec_test = test;
+ test->func(0);
+ assert(current_noexec_test == NULL);
+}
+
+static int test_noexec(struct noexec_test *tests, size_t n_tests)
+{
+ struct sigaction act;
+ size_t i;
+ int err;
+
+ memset(&act, 0, sizeof(act));
+ act.sa_sigaction = handle_segv;
+ act.sa_flags = SA_SIGINFO;
+ err = sigaction(SIGSEGV, &act, NULL);
+ assert(err == 0);
+
+ for (i = 0; i < n_tests; i++) {
+ struct noexec_test *test = &tests[i];
+
+ safe_print("[ RUN ] ");
+ safe_puts(test->name);
+ test_noexec_1(test);
+ safe_puts("[ OK ]");
+ }
+
+ safe_puts("[ PASSED ]");
+
+ return EXIT_SUCCESS;
+}
diff --git a/tests/tcg/s390x/Makefile.target b/tests/tcg/s390x/Makefile.target
index 1a7a4a2f59..5e13a41c3f 100644
--- a/tests/tcg/s390x/Makefile.target
+++ b/tests/tcg/s390x/Makefile.target
@@ -16,6 +16,7 @@ TESTS+=shift
TESTS+=trap
TESTS+=signals-s390x
TESTS+=branch-relative-long
+TESTS+=noexec
Z14_TESTS=vfminmax
vfminmax: LDFLAGS+=-lm
diff --git a/tests/tcg/s390x/noexec.c b/tests/tcg/s390x/noexec.c
new file mode 100644
index 0000000000..2dfc9ee817
--- /dev/null
+++ b/tests/tcg/s390x/noexec.c
@@ -0,0 +1,145 @@
+#define _GNU_SOURCE
+
+struct arch_noexec_test {
+ void *expected_pswa;
+ unsigned long expected_r2;
+};
+
+#include "../multiarch/noexec.h"
+
+static void arch_check_mcontext(const struct arch_noexec_test *test,
+ const mcontext_t *ctx) {
+ if (ctx->psw.addr != (unsigned long)test->expected_pswa) {
+ safe_puts("[ FAILED ] wrong psw.addr");
+ _exit(1);
+ }
+
+ if (ctx->gregs[2] != test->expected_r2) {
+ safe_puts("[ FAILED ] wrong r2");
+ _exit(1);
+ }
+}
+
+#define DEFINE_NX(name, offset) \
+ void name ## _1(int); \
+ void name ## _2(int); \
+ void name ## _exrl(int); \
+ extern const short name ## _end[]; \
+ asm(/* Go to the specified page offset. */ \
+ ".align 0x1000\n" \
+ ".org .+" #offset "\n" \
+ /* %r2 is 0 on entry, overwrite it with 1. */ \
+ ".globl " #name "_1\n" \
+ #name "_1:\n" \
+ ".cfi_startproc\n" \
+ "lgfi %r2,1\n" \
+ /* Overwrite %2 with 2. */ \
+ ".globl " #name "_2\n" \
+ #name "_2:\n" \
+ "lgfi %r2,2\n" \
+ "br %r14\n" \
+ /* End of code. */ \
+ ".globl " #name "_end\n" \
+ #name "_end:\n" \
+ ".cfi_endproc\n" \
+ /* Go to the next page. */ \
+ ".align 0x1000\n" \
+ /* Break alignment. */ \
+ "nopr %r7\n" \
+ ".globl " #name "_exrl\n" \
+ #name "_exrl:\n" \
+ ".cfi_startproc\n" \
+ "exrl %r0," #name "_2\n" \
+ "br %r14\n" \
+ ".cfi_endproc");
+
+/* noexec_1 is executable, noexec_2 is non-executable. */
+DEFINE_NX(noexec, 0xffa);
+
+/*
+ * noexec_cross_1 is executable, noexec_cross_2 crosses non-executable page
+ * boundary.
+ */
+DEFINE_NX(noexec_cross, 0xff8);
+
+/* noexec_full_1 and noexec_full_2 are non-executable. */
+DEFINE_NX(noexec_full, 0x322);
+
+int main(void)
+{
+ struct noexec_test noexec_tests[] = {
+ {
+ .name = "Fallthrough",
+ .func = noexec_1,
+ .page = noexec_2,
+ .expected_si_addr = noexec_2,
+ .arch = {
+ .expected_pswa = noexec_2,
+ .expected_r2 = 1,
+ },
+ },
+ {
+ .name = "Jump",
+ .func = noexec_2,
+ .page = noexec_2,
+ .expected_si_addr = noexec_2,
+ .arch = {
+ .expected_pswa = noexec_2,
+ .expected_r2 = 0,
+ },
+ },
+ {
+ .name = "EXRL",
+ .func = noexec_exrl,
+ .page = noexec_2,
+ .expected_si_addr = PAGE_ALIGN(noexec_end),
+ .arch = {
+ .expected_pswa = noexec_exrl,
+ .expected_r2 = 0,
+ },
+ },
+ {
+ .name = "Fallthrough [cross]",
+ .func = noexec_cross_1,
+ .page = PAGE_ALIGN(noexec_cross_end),
+ .expected_si_addr = PAGE_ALIGN(noexec_cross_end),
+ .arch = {
+ .expected_pswa = noexec_cross_2,
+ .expected_r2 = 1,
+ },
+ },
+ {
+ .name = "Jump [cross]",
+ .func = noexec_cross_2,
+ .page = PAGE_ALIGN(noexec_cross_end),
+ .expected_si_addr = PAGE_ALIGN(noexec_cross_end),
+ .arch = {
+ .expected_pswa = noexec_cross_2,
+ .expected_r2 = 0,
+ },
+ },
+ {
+ .name = "EXRL [cross]",
+ .func = noexec_cross_exrl,
+ .page = PAGE_ALIGN(noexec_cross_end),
+ .expected_si_addr = PAGE_ALIGN(noexec_cross_end),
+ .arch = {
+ .expected_pswa = noexec_cross_exrl,
+ .expected_r2 = 0,
+ },
+ },
+ {
+ .name = "Jump [full]",
+ .func = noexec_full_1,
+ .page = PAGE_ALIGN(noexec_full_1),
+ .expected_si_addr = PAGE_ALIGN(noexec_full_1),
+ .arch = {
+ .expected_pswa = noexec_full_1,
+ .expected_r2 = 0,
+ },
+ },
+ };
+
+ return test_noexec(noexec_tests,
+ sizeof(noexec_tests) / sizeof(noexec_tests[0]));
+}
diff --git a/tests/tcg/x86_64/Makefile.target b/tests/tcg/x86_64/Makefile.target
index b71a6bcd5e..c0e7e5b005 100644
--- a/tests/tcg/x86_64/Makefile.target
+++ b/tests/tcg/x86_64/Makefile.target
@@ -10,6 +10,7 @@ include $(SRC_PATH)/tests/tcg/i386/Makefile.target
ifeq ($(filter %-linux-user, $(TARGET)),$(TARGET))
X86_64_TESTS += vsyscall
+X86_64_TESTS += noexec
TESTS=$(MULTIARCH_TESTS) $(X86_64_TESTS) test-x86_64
else
TESTS=$(MULTIARCH_TESTS)
@@ -20,5 +21,5 @@ test-x86_64: LDFLAGS+=-lm -lc
test-x86_64: test-i386.c test-i386.h test-i386-shift.h test-i386-muldiv.h
$(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
-vsyscall: $(SRC_PATH)/tests/tcg/x86_64/vsyscall.c
+%: $(SRC_PATH)/tests/tcg/x86_64/%.c
$(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
diff --git a/tests/tcg/x86_64/noexec.c b/tests/tcg/x86_64/noexec.c
new file mode 100644
index 0000000000..ec07c9f0ba
--- /dev/null
+++ b/tests/tcg/x86_64/noexec.c
@@ -0,0 +1,116 @@
+#define _GNU_SOURCE
+
+struct arch_noexec_test {
+ void *expected_rip;
+ unsigned long expected_rdi;
+};
+
+#include "../multiarch/noexec.h"
+
+static void arch_check_mcontext(const struct arch_noexec_test *test,
+ const mcontext_t *ctx) {
+ if (ctx->gregs[REG_RIP] != (unsigned long)test->expected_rip) {
+ safe_puts("[ FAILED ] wrong rip");
+ _exit(1);
+ }
+
+ if (ctx->gregs[REG_RDI] != test->expected_rdi) {
+ safe_puts("[ FAILED ] wrong rdi");
+ _exit(1);
+ }
+}
+
+#define DEFINE_NX(name, offset) \
+ void name ## _1(int); \
+ void name ## _2(int); \
+ extern const short name ## _end[]; \
+ asm(/* Go to the specified page offset. */ \
+ ".align 0x1000\n" \
+ ".org .+" #offset "\n" \
+ /* %rdi is 0 on entry, overwrite it with 1. */ \
+ ".globl " #name "_1\n" \
+ #name "_1:\n" \
+ ".cfi_startproc\n" \
+ "movq $1,%rdi\n" \
+ /* Overwrite %rdi with 2. */ \
+ ".globl " #name "_2\n" \
+ #name "_2:\n" \
+ "movq $2,%rdi\n" \
+ "ret\n" \
+ /* End of code. */ \
+ ".globl " #name "_end\n" \
+ #name "_end:\n" \
+ ".cfi_endproc\n" \
+ /* Go to the next page. */ \
+ ".align 0x1000");
+
+/* noexec_1 is executable, noexec_2 is non-executable. */
+DEFINE_NX(noexec, 0xff9);
+
+/*
+ * noexec_cross_1 is executable, noexec_cross_2 crosses non-executable page
+ * boundary.
+ */
+DEFINE_NX(noexec_cross, 0xff8);
+
+/* noexec_full_1 and noexec_full_2 are non-executable. */
+DEFINE_NX(noexec_full, 0x321);
+
+int main(void)
+{
+ struct noexec_test noexec_tests[] = {
+ {
+ .name = "Fallthrough",
+ .func = noexec_1,
+ .page = noexec_2,
+ .expected_si_addr = noexec_2,
+ .arch = {
+ .expected_rip = noexec_2,
+ .expected_rdi = 1,
+ },
+ },
+ {
+ .name = "Jump",
+ .func = noexec_2,
+ .page = noexec_2,
+ .expected_si_addr = noexec_2,
+ .arch = {
+ .expected_rip = noexec_2,
+ .expected_rdi = 0,
+ },
+ },
+ {
+ .name = "Fallthrough [cross]",
+ .func = noexec_cross_1,
+ .page = PAGE_ALIGN(noexec_cross_end),
+ .expected_si_addr = PAGE_ALIGN(noexec_cross_end),
+ .arch = {
+ .expected_rip = noexec_cross_2,
+ .expected_rdi = 1,
+ },
+ },
+ {
+ .name = "Jump [cross]",
+ .func = noexec_cross_2,
+ .page = PAGE_ALIGN(noexec_cross_end),
+ .expected_si_addr = PAGE_ALIGN(noexec_cross_end),
+ .arch = {
+ .expected_rip = noexec_cross_2,
+ .expected_rdi = 0,
+ },
+ },
+ {
+ .name = "Jump [full]",
+ .func = noexec_full_1,
+ .page = PAGE_ALIGN(noexec_full_1),
+ .expected_si_addr = noexec_full_1,
+ .arch = {
+ .expected_rip = noexec_full_1,
+ .expected_rdi = 0,
+ },
+ },
+ };
+
+ return test_noexec(noexec_tests,
+ sizeof(noexec_tests) / sizeof(noexec_tests[0]));
+}
--
2.37.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH v3 1/4] accel/tcg: Invalidate translations when clearing PAGE_EXEC
2022-08-08 17:10 ` [PATCH v3 1/4] accel/tcg: Invalidate translations when clearing PAGE_EXEC Ilya Leoshkevich
@ 2022-08-10 20:29 ` Richard Henderson
2022-08-11 9:28 ` Ilya Leoshkevich
0 siblings, 1 reply; 13+ messages in thread
From: Richard Henderson @ 2022-08-10 20:29 UTC (permalink / raw)
To: Ilya Leoshkevich, Laurent Vivier, Eduardo Habkost,
Marcel Apfelbaum, Philippe Mathieu-Daudé, Yanan Wang,
Paolo Bonzini, David Hildenbrand, Peter Maydell
Cc: qemu-devel, qemu-s390x, Christian Borntraeger
On 8/8/22 10:10, Ilya Leoshkevich wrote:
> After mprotect(addr, PROT_NONE), addr can still be executed if there
> are cached translations. Drop them.
>
> Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
> ---
> accel/tcg/translate-all.c | 17 ++++++++++++-----
> 1 file changed, 12 insertions(+), 5 deletions(-)
>
> diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
> index ef62a199c7..32ea5f0adf 100644
> --- a/accel/tcg/translate-all.c
> +++ b/accel/tcg/translate-all.c
> @@ -2295,12 +2295,19 @@ void page_set_flags(target_ulong start, target_ulong end, int flags)
> len != 0;
> len -= TARGET_PAGE_SIZE, addr += TARGET_PAGE_SIZE) {
> PageDesc *p = page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
> + bool write_set, exec_cleared;
>
> - /* If the write protection bit is set, then we invalidate
> - the code inside. */
> - if (!(p->flags & PAGE_WRITE) &&
> - (flags & PAGE_WRITE) &&
> - p->first_tb) {
> + /*
> + * If the write protection bit is set, then we invalidate the code
> + * inside.
> + */
> + write_set = !(p->flags & PAGE_WRITE) && (flags & PAGE_WRITE);
> + /*
> + * If PAGE_EXEC is cleared, we also need to invalidate the code in
> + * order to force a fault when trying to run it.
> + */
> + exec_cleared = (p->flags & PAGE_EXEC) && !(flags & PAGE_EXEC);
> + if ((write_set || exec_cleared) && p->first_tb) {
I believe the bug you're trying to fix is in get_page_addr_code, which for USER_ONLY is
currently a no-op. It ought to be checking the page permissions there, as we do for softmmu.
I have a patch for get_page_addr_code in the works, because I was working on pther stuff
in the area.
r~
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 2/4] target/s390x: Make translator stop before the end of a page
2022-08-08 17:10 ` [PATCH v3 2/4] target/s390x: Make translator stop before the end of a page Ilya Leoshkevich
@ 2022-08-10 20:30 ` Richard Henderson
2022-08-11 4:08 ` Richard Henderson
1 sibling, 0 replies; 13+ messages in thread
From: Richard Henderson @ 2022-08-10 20:30 UTC (permalink / raw)
To: Ilya Leoshkevich, Laurent Vivier, Eduardo Habkost,
Marcel Apfelbaum, Philippe Mathieu-Daudé, Yanan Wang,
Paolo Bonzini, David Hildenbrand, Peter Maydell
Cc: qemu-devel, qemu-s390x, Christian Borntraeger
On 8/8/22 10:10, Ilya Leoshkevich wrote:
> Right now translator stops right*after* the end of a page, which
> breaks reporting of fault locations when the last instruction of a
> multi-insn translation block crosses a page boundary.
>
> Signed-off-by: Ilya Leoshkevich<iii@linux.ibm.com>
> ---
> include/exec/translator.h | 10 ++++++++++
> target/s390x/tcg/translate.c | 15 +++++++++++----
> 2 files changed, 21 insertions(+), 4 deletions(-)
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 3/4] target/i386: Make translator stop before the end of a page
2022-08-08 17:10 ` [PATCH v3 3/4] target/i386: " Ilya Leoshkevich
@ 2022-08-10 20:35 ` Richard Henderson
0 siblings, 0 replies; 13+ messages in thread
From: Richard Henderson @ 2022-08-10 20:35 UTC (permalink / raw)
To: Ilya Leoshkevich, Laurent Vivier, Eduardo Habkost,
Marcel Apfelbaum, Philippe Mathieu-Daudé, Yanan Wang,
Paolo Bonzini, David Hildenbrand, Peter Maydell
Cc: qemu-devel, qemu-s390x, Christian Borntraeger
On 8/8/22 10:10, Ilya Leoshkevich wrote:
> Right now translator stops right *after* the end of a page, which
> breaks reporting of fault locations when the last instruction of a
> multi-insn translation block crosses a page boundary.
>
> An implementation, like the one arm and s390x have, would require an
> i386 length disassembler, which is burdensome to maintain. Another
> alternative would be to single-step at the end of a guest page, but
> this may come with a performance impact.
>
> Fix by snapshotting disassembly state and restoring it after we figure
> out we crossed a page boundary. This includes rolling back cc_op
> updates and emitted ops. Even though i386 is the only architecture that
> does rollback, split it into common and architecture-dependent parts to
> improve readability.
>
> Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
> ---
> accel/tcg/translator.c | 8 ++++++++
> include/exec/translator.h | 3 +++
> target/i386/tcg/translate.c | 21 ++++++++++++++++++++-
> 3 files changed, 31 insertions(+), 1 deletion(-)
>
> diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
> index fe7af9b943..2c4dd09df8 100644
> --- a/accel/tcg/translator.c
> +++ b/accel/tcg/translator.c
> @@ -56,6 +56,7 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
> {
> uint32_t cflags = tb_cflags(tb);
> bool plugin_enabled;
> + TCGOp *last_op;
>
> /* Initialize DisasContext */
> db->tb = tb;
> @@ -82,6 +83,7 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
>
> while (true) {
> db->num_insns++;
> + last_op = tcg_last_op();
> ops->insn_start(db, cpu);
> tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */
>
> @@ -103,6 +105,12 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
> ops->translate_insn(db, cpu);
> }
>
> + if (db->is_jmp == DISAS_TOO_MANY_UNDO) {
> + db->num_insns--;
> + tcg_remove_ops_after(last_op);
> + db->is_jmp = DISAS_TOO_MANY;
> + }
> +
> /* Stop translation if translate_insn so indicated. */
> if (db->is_jmp != DISAS_NEXT) {
> break;
> diff --git a/include/exec/translator.h b/include/exec/translator.h
> index d27f8c33b6..e1533aee87 100644
> --- a/include/exec/translator.h
> +++ b/include/exec/translator.h
> @@ -31,6 +31,8 @@
> * DisasJumpType:
> * @DISAS_NEXT: Next instruction in program order.
> * @DISAS_TOO_MANY: Too many instructions translated.
> + * @DISAS_TOO_MANY_UNDO: Too many instructions translated. Everything that was
> + * done for the current instruction must be undone.
> * @DISAS_NORETURN: Following code is dead.
> * @DISAS_TARGET_*: Start of target-specific conditions.
> *
> @@ -39,6 +41,7 @@
> typedef enum DisasJumpType {
> DISAS_NEXT,
> DISAS_TOO_MANY,
> + DISAS_TOO_MANY_UNDO,
Hmm, maybe. I'm not overly keen on the generic change, because I think it would be easy
to use incorrectly.
> + case 2:
> + /* Restore state that may affect the next instruction. */
> + s->cc_op_dirty = orig_cc_op_dirty;
> + s->cc_op = orig_cc_op;
> + s->base.is_jmp = DISAS_TOO_MANY_UNDO;
I think you can simply set s->prev_insn_end in i386_tr_insn_start, for discarding opcodes.
r~
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 2/4] target/s390x: Make translator stop before the end of a page
2022-08-08 17:10 ` [PATCH v3 2/4] target/s390x: Make translator stop before the end of a page Ilya Leoshkevich
2022-08-10 20:30 ` Richard Henderson
@ 2022-08-11 4:08 ` Richard Henderson
1 sibling, 0 replies; 13+ messages in thread
From: Richard Henderson @ 2022-08-11 4:08 UTC (permalink / raw)
To: Ilya Leoshkevich, Laurent Vivier, Eduardo Habkost,
Marcel Apfelbaum, Philippe Mathieu-Daudé, Yanan Wang,
Paolo Bonzini, David Hildenbrand, Peter Maydell
Cc: qemu-devel, qemu-s390x, Christian Borntraeger
On 8/8/22 10:10, Ilya Leoshkevich wrote:
> Right now translator stops right *after* the end of a page, which
> breaks reporting of fault locations when the last instruction of a
> multi-insn translation block crosses a page boundary.
>
> Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
> ---
> include/exec/translator.h | 10 ++++++++++
> target/s390x/tcg/translate.c | 15 +++++++++++----
> 2 files changed, 21 insertions(+), 4 deletions(-)
>
> diff --git a/include/exec/translator.h b/include/exec/translator.h
> index 7db6845535..d27f8c33b6 100644
> --- a/include/exec/translator.h
> +++ b/include/exec/translator.h
> @@ -187,4 +187,14 @@ FOR_EACH_TRANSLATOR_LD(GEN_TRANSLATOR_LD)
>
> #undef GEN_TRANSLATOR_LD
>
> +/*
> + * Return whether addr is on the same page as where disassembly started.
> + * Translators can use this to enforce the rule that only single-insn
> + * translation blocks are allowed to cross page boundaries.
> + */
> +static inline bool is_same_page(DisasContextBase *db, target_ulong addr)
> +{
> + return ((addr ^ db->pc_first) & TARGET_PAGE_MASK) == 0;
> +}
FYI, I've had occasion to pull this out to a separate patch locally.
r~
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 1/4] accel/tcg: Invalidate translations when clearing PAGE_EXEC
2022-08-10 20:29 ` Richard Henderson
@ 2022-08-11 9:28 ` Ilya Leoshkevich
2022-08-11 15:42 ` Richard Henderson
0 siblings, 1 reply; 13+ messages in thread
From: Ilya Leoshkevich @ 2022-08-11 9:28 UTC (permalink / raw)
To: Richard Henderson, Laurent Vivier, Eduardo Habkost,
Marcel Apfelbaum, Philippe Mathieu-Daudé, Yanan Wang,
Paolo Bonzini, David Hildenbrand, Peter Maydell
Cc: qemu-devel, qemu-s390x, Christian Borntraeger
On Wed, 2022-08-10 at 13:29 -0700, Richard Henderson wrote:
> On 8/8/22 10:10, Ilya Leoshkevich wrote:
> > After mprotect(addr, PROT_NONE), addr can still be executed if
> > there
> > are cached translations. Drop them.
> >
> > Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
> > ---
> > accel/tcg/translate-all.c | 17 ++++++++++++-----
> > 1 file changed, 12 insertions(+), 5 deletions(-)
> >
> > diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
> > index ef62a199c7..32ea5f0adf 100644
> > --- a/accel/tcg/translate-all.c
> > +++ b/accel/tcg/translate-all.c
> > @@ -2295,12 +2295,19 @@ void page_set_flags(target_ulong start,
> > target_ulong end, int flags)
> > len != 0;
> > len -= TARGET_PAGE_SIZE, addr += TARGET_PAGE_SIZE) {
> > PageDesc *p = page_find_alloc(addr >> TARGET_PAGE_BITS,
> > 1);
> > + bool write_set, exec_cleared;
> >
> > - /* If the write protection bit is set, then we invalidate
> > - the code inside. */
> > - if (!(p->flags & PAGE_WRITE) &&
> > - (flags & PAGE_WRITE) &&
> > - p->first_tb) {
> > + /*
> > + * If the write protection bit is set, then we invalidate
> > the code
> > + * inside.
> > + */
> > + write_set = !(p->flags & PAGE_WRITE) && (flags &
> > PAGE_WRITE);
> > + /*
> > + * If PAGE_EXEC is cleared, we also need to invalidate the
> > code in
> > + * order to force a fault when trying to run it.
> > + */
> > + exec_cleared = (p->flags & PAGE_EXEC) && !(flags &
> > PAGE_EXEC);
> > + if ((write_set || exec_cleared) && p->first_tb) {
>
> I believe the bug you're trying to fix is in get_page_addr_code,
> which for USER_ONLY is
> currently a no-op. It ought to be checking the page permissions
> there, as we do for softmmu.
>
> I have a patch for get_page_addr_code in the works, because I was
> working on pther stuff
> in the area.
How is qemu-user's get_page_addr_code() involved here?
I tried to experiment with it, and while I agree that it looks buggy,
it's called only from translation code paths. If we already have a
translation block, these code paths are not used.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 1/4] accel/tcg: Invalidate translations when clearing PAGE_EXEC
2022-08-11 9:28 ` Ilya Leoshkevich
@ 2022-08-11 15:42 ` Richard Henderson
2022-08-12 15:02 ` Ilya Leoshkevich
0 siblings, 1 reply; 13+ messages in thread
From: Richard Henderson @ 2022-08-11 15:42 UTC (permalink / raw)
To: Ilya Leoshkevich, Laurent Vivier, Eduardo Habkost,
Marcel Apfelbaum, Philippe Mathieu-Daudé, Yanan Wang,
Paolo Bonzini, David Hildenbrand, Peter Maydell
Cc: qemu-devel, qemu-s390x, Christian Borntraeger
On 8/11/22 02:28, Ilya Leoshkevich wrote:
> How is qemu-user's get_page_addr_code() involved here?
>
> I tried to experiment with it, and while I agree that it looks buggy,
> it's called only from translation code paths. If we already have a
> translation block, these code paths are not used.
It's called from tb_lookup too, when we're trying to find an existing TB.
r~
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 1/4] accel/tcg: Invalidate translations when clearing PAGE_EXEC
2022-08-11 15:42 ` Richard Henderson
@ 2022-08-12 15:02 ` Ilya Leoshkevich
2022-08-12 17:59 ` Richard Henderson
0 siblings, 1 reply; 13+ messages in thread
From: Ilya Leoshkevich @ 2022-08-12 15:02 UTC (permalink / raw)
To: Richard Henderson, Laurent Vivier, Eduardo Habkost,
Marcel Apfelbaum, Philippe Mathieu-Daudé, Yanan Wang,
Paolo Bonzini, David Hildenbrand, Peter Maydell
Cc: qemu-devel, qemu-s390x, Christian Borntraeger
On Thu, 2022-08-11 at 08:42 -0700, Richard Henderson wrote:
> On 8/11/22 02:28, Ilya Leoshkevich wrote:
> > How is qemu-user's get_page_addr_code() involved here?
> >
> > I tried to experiment with it, and while I agree that it looks
> > buggy,
> > it's called only from translation code paths. If we already have a
> > translation block, these code paths are not used.
>
> It's called from tb_lookup too, when we're trying to find an existing
> TB.
>
>
> r~
>
Oh, I see. I was first worried about direct block chaining with
goto_tb, but it turned out that translator_use_goto_tb() prevented it.
tb_lookup() skips get_page_addr_code() if tb is found in tb_jmp_cache.
I assume it's a bug?
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 1/4] accel/tcg: Invalidate translations when clearing PAGE_EXEC
2022-08-12 15:02 ` Ilya Leoshkevich
@ 2022-08-12 17:59 ` Richard Henderson
0 siblings, 0 replies; 13+ messages in thread
From: Richard Henderson @ 2022-08-12 17:59 UTC (permalink / raw)
To: Ilya Leoshkevich, Laurent Vivier, Eduardo Habkost,
Marcel Apfelbaum, Philippe Mathieu-Daudé, Yanan Wang,
Paolo Bonzini, David Hildenbrand, Peter Maydell
Cc: qemu-devel, qemu-s390x, Christian Borntraeger
On 8/12/22 08:02, Ilya Leoshkevich wrote:
> tb_lookup() skips get_page_addr_code() if tb is found in tb_jmp_cache.
> I assume it's a bug?
Yes, I think so. I've rearranged that for other reasons, and so may have inadvertently
fix this. I'll post the in-progress work in a moment.
r~
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2022-08-12 18:01 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-08-08 17:10 [PATCH v3 0/4] linux-user: Fix siginfo_t contents when jumping to non-readable pages Ilya Leoshkevich
2022-08-08 17:10 ` [PATCH v3 1/4] accel/tcg: Invalidate translations when clearing PAGE_EXEC Ilya Leoshkevich
2022-08-10 20:29 ` Richard Henderson
2022-08-11 9:28 ` Ilya Leoshkevich
2022-08-11 15:42 ` Richard Henderson
2022-08-12 15:02 ` Ilya Leoshkevich
2022-08-12 17:59 ` Richard Henderson
2022-08-08 17:10 ` [PATCH v3 2/4] target/s390x: Make translator stop before the end of a page Ilya Leoshkevich
2022-08-10 20:30 ` Richard Henderson
2022-08-11 4:08 ` Richard Henderson
2022-08-08 17:10 ` [PATCH v3 3/4] target/i386: " Ilya Leoshkevich
2022-08-10 20:35 ` Richard Henderson
2022-08-08 17:10 ` [PATCH v3 4/4] tests/tcg: Test siginfo_t contents when jumping to non-readable pages Ilya Leoshkevich
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).