From db2af69d6ba836a264878dbf2cf676d3c1fc46b4 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 29 Sep 2021 09:05:28 -0400 Subject: [PATCH] linux-user: Add infrastructure for a signal trampoline page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allocate a page to hold the signal trampoline(s). Invoke a guest-specific hook to fill in the contents of the page before marking it read-execute again. Reviewed-by: Max Filippov Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-Id: <20210929130553.121567-2-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/elfload.c | 18 ++++++++++++++++++ linux-user/signal-common.h | 6 ++++++ linux-user/signal.c | 3 +++ 3 files changed, 27 insertions(+) diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 5f9e2141ad..459a26ef1d 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -7,6 +7,7 @@ #include "qemu.h" #include "user-internals.h" +#include "signal-common.h" #include "loader.h" #include "user-mmap.h" #include "disas/disas.h" @@ -17,6 +18,7 @@ #include "qemu/units.h" #include "qemu/selfmap.h" #include "qapi/error.h" +#include "target_signal.h" #ifdef _ARCH_PPC64 #undef ARCH_DLINFO @@ -28,6 +30,10 @@ #undef ELF_ARCH #endif +#ifndef TARGET_ARCH_HAS_SIGTRAMP_PAGE +#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 0 +#endif + #define ELF_OSABI ELFOSABI_SYSV /* from personality.h */ @@ -3249,6 +3255,18 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info) #endif } + /* + * TODO: load a vdso, which would also contain the signal trampolines. + * Otherwise, allocate a private page to hold them. + */ + if (TARGET_ARCH_HAS_SIGTRAMP_PAGE) { + abi_ulong tramp_page = target_mmap(0, TARGET_PAGE_SIZE, + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + setup_sigtramp(tramp_page); + target_mprotect(tramp_page, TARGET_PAGE_SIZE, PROT_READ | PROT_EXEC); + } + bprm->p = create_elf_tables(bprm->p, bprm->argc, bprm->envc, &elf_ex, info, (elf_interpreter ? &interp_info : NULL)); info->start_stack = bprm->p; diff --git a/linux-user/signal-common.h b/linux-user/signal-common.h index 79511becb4..7457f8025c 100644 --- a/linux-user/signal-common.h +++ b/linux-user/signal-common.h @@ -20,6 +20,12 @@ #ifndef SIGNAL_COMMON_H #define SIGNAL_COMMON_H +/* Fallback addresses into sigtramp page. */ +extern abi_ulong default_sigreturn; +extern abi_ulong default_rt_sigreturn; + +void setup_sigtramp(abi_ulong tramp_page); + int on_sig_stack(unsigned long sp); int sas_ss_flags(unsigned long sp); abi_ulong target_sigsp(abi_ulong sp, struct target_sigaction *ka); diff --git a/linux-user/signal.c b/linux-user/signal.c index 2038216455..14d8fdfde1 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -35,6 +35,9 @@ static struct target_sigaction sigact_table[TARGET_NSIG]; static void host_signal_handler(int host_signum, siginfo_t *info, void *puc); +/* Fallback addresses into sigtramp page. */ +abi_ulong default_sigreturn; +abi_ulong default_rt_sigreturn; /* * System includes define _NSIG as SIGRTMAX + 1,