On 24/02/2026 22:05, Pierrick Bouvier wrote: > On 2/24/26 7:50 AM, Florian Hofhammer wrote: >> The syscall emulation code previously wasn't interruptible via >> cpu_loop_exit(), as this construct relies on a longjmp target that is not >> live anymore in the syscall handling code. Consequently, longjmp() would >> operate on a (potentially overwritten) stale jump buffer. This patch adds an >> additional >> setjmp and the necessary handling around it to make longjmp() (and by >> proxy cpu_loop_exit() safe to call even within a syscall context. >> >> Signed-off-by: Florian Hofhammer <[email protected]> >> --- >> linux-user/aarch64/cpu_loop.c | 2 +- >> linux-user/alpha/cpu_loop.c | 2 +- >> linux-user/arm/cpu_loop.c | 2 +- >> linux-user/hexagon/cpu_loop.c | 2 +- >> linux-user/hppa/cpu_loop.c | 4 ++++ >> linux-user/i386/cpu_loop.c | 8 +++++--- >> linux-user/include/special-errno.h | 8 ++++++++ >> linux-user/loongarch64/cpu_loop.c | 5 +++-- >> linux-user/m68k/cpu_loop.c | 2 +- >> linux-user/microblaze/cpu_loop.c | 2 +- >> linux-user/mips/cpu_loop.c | 5 +++-- >> linux-user/or1k/cpu_loop.c | 2 +- >> linux-user/ppc/cpu_loop.c | 6 ++++-- >> linux-user/riscv/cpu_loop.c | 2 +- >> linux-user/s390x/cpu_loop.c | 2 +- >> linux-user/sh4/cpu_loop.c | 2 +- >> linux-user/sparc/cpu_loop.c | 4 +++- >> linux-user/syscall.c | 16 ++++++++++++++++ >> linux-user/xtensa/cpu_loop.c | 3 +++ >> 19 files changed, 59 insertions(+), 20 deletions(-) >> >> diff --git a/linux-user/sparc/cpu_loop.c b/linux-user/sparc/cpu_loop.c >> index 7391e2add8..f054316dce 100644 >> --- a/linux-user/sparc/cpu_loop.c >> +++ b/linux-user/sparc/cpu_loop.c >> @@ -229,7 +229,9 @@ void cpu_loop (CPUSPARCState *env) >> env->regwptr[2], env->regwptr[3], >> env->regwptr[4], env->regwptr[5], >> 0, 0); >> - if (ret == -QEMU_ERESTARTSYS || ret == -QEMU_ESIGRETURN) { >> + if (ret == -QEMU_ERESTARTSYS >> + || ret == -QEMU_ESIGRETURN >> + || ret == -QEMU_ESETPC) { >> break; >> } > > Just a style nit: > if (ret == -QEMU_ERESTARTSYS || > ret == -QEMU_ESIGRETURN || > ret == -QEMU_ESETPC) { > >> if ((abi_ulong)ret >= (abi_ulong)(-515)) { >> diff --git a/linux-user/syscall.c b/linux-user/syscall.c >> index d466d0e32f..99e1ed97d9 100644 >> --- a/linux-user/syscall.c >> +++ b/linux-user/syscall.c >> @@ -43,6 +43,7 @@ >> #include <linux/capability.h> >> #include <sched.h> >> #include <sys/timex.h> >> +#include <setjmp.h> >> #include <sys/socket.h> >> #include <linux/sockios.h> >> #include <sys/un.h> >> @@ -600,6 +601,9 @@ const char *target_strerror(int err) >> if (err == QEMU_ESIGRETURN) { >> return "Successful exit from sigreturn"; >> } >> + if (err == QEMU_ESETPC) { >> + return "Successfully redirected control flow"; >> + } >> return strerror(target_to_host_errno(err)); >> } >> @@ -14410,6 +14414,18 @@ abi_long do_syscall(CPUArchState *cpu_env, int num, >> abi_long arg1, >> return -QEMU_ESIGRETURN; >> } >> + /* >> + * Set up a longjmp target here so that we can call cpu_loop_exit to >> + * redirect control flow back to the main loop even from within >> + * syscall-related plugin callbacks. >> + * For other types of callbacks or longjmp call sites, the longjmp >> target >> + * is set up in the cpu loop itself but in syscalls the target is not >> live >> + * anymore. >> + */ >> + if (unlikely(sigsetjmp(cpu->jmp_env, 0) != 0)) { >> + return -QEMU_ESETPC; >> + } >> + > > Makes sense, and I guess you found that when running the series test. > > Do you need all the new QEMU_FALLTHROUGH introduced here? Is it for removing > warnings?
I think they're not strictly necessary, but if I recall correctly, I had warnings otherwise. I can remove them if you prefer but I think making the fallthrough explicit encodes the intent better. > > Reviewed-by: Pierrick Bouvier <[email protected]>
smime.p7s
Description: S/MIME Cryptographic Signature
