From 92bad948367c4b8a58f6bb81b45750f1d583f274 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 25 Apr 2021 19:53:10 -0700 Subject: linux-user: Split out target_restore_altstack Create a function to match target_save_altstack. Fix some style and unlock issues in do_sigaltstack. Signed-off-by: Richard Henderson Message-Id: <20210426025334.1168495-2-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/signal.c | 115 +++++++++++++++++++++++++++++----------------------- 1 file changed, 65 insertions(+), 50 deletions(-) (limited to 'linux-user/signal.c') diff --git a/linux-user/signal.c b/linux-user/signal.c index 7eecec46c4..9daa89eac5 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -297,6 +297,50 @@ void target_save_altstack(target_stack_t *uss, CPUArchState *env) __put_user(ts->sigaltstack_used.ss_size, &uss->ss_size); } +abi_long target_restore_altstack(target_stack_t *uss, abi_ulong sp) +{ + TaskState *ts = (TaskState *)thread_cpu->opaque; + size_t minstacksize = TARGET_MINSIGSTKSZ; + target_stack_t ss; + +#if defined(TARGET_PPC64) + /* ELF V2 for PPC64 has a 4K minimum stack size for signal handlers */ + struct image_info *image = ts->info; + if (get_ppc64_abi(image) > 1) { + minstacksize = 4096; + } +#endif + + __get_user(ss.ss_sp, &uss->ss_sp); + __get_user(ss.ss_size, &uss->ss_size); + __get_user(ss.ss_flags, &uss->ss_flags); + + if (on_sig_stack(sp)) { + return -TARGET_EPERM; + } + + switch (ss.ss_flags) { + default: + return -TARGET_EINVAL; + + case TARGET_SS_DISABLE: + ss.ss_size = 0; + ss.ss_sp = 0; + break; + + case TARGET_SS_ONSTACK: + case 0: + if (ss.ss_size < minstacksize) { + return -TARGET_ENOMEM; + } + break; + } + + ts->sigaltstack_used.ss_sp = ss.ss_sp; + ts->sigaltstack_used.ss_size = ss.ss_size; + return 0; +} + /* siginfo conversion */ static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo, @@ -758,73 +802,44 @@ static void host_signal_handler(int host_signum, siginfo_t *info, /* compare linux/kernel/signal.c:do_sigaltstack() */ abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp) { - int ret; - struct target_sigaltstack oss; - TaskState *ts = (TaskState *)thread_cpu->opaque; + target_stack_t oss, *uoss = NULL; + abi_long ret = -TARGET_EFAULT; + + if (uoss_addr) { + TaskState *ts = (TaskState *)thread_cpu->opaque; - /* XXX: test errors */ - if(uoss_addr) - { + /* Verify writability now, but do not alter user memory yet. */ + if (!lock_user_struct(VERIFY_WRITE, uoss, uoss_addr, 0)) { + goto out; + } __put_user(ts->sigaltstack_used.ss_sp, &oss.ss_sp); __put_user(ts->sigaltstack_used.ss_size, &oss.ss_size); __put_user(sas_ss_flags(sp), &oss.ss_flags); } - if(uss_addr) - { - struct target_sigaltstack *uss; - struct target_sigaltstack ss; - size_t minstacksize = TARGET_MINSIGSTKSZ; + if (uss_addr) { + target_stack_t *uss; -#if defined(TARGET_PPC64) - /* ELF V2 for PPC64 has a 4K minimum stack size for signal handlers */ - struct image_info *image = ((TaskState *)thread_cpu->opaque)->info; - if (get_ppc64_abi(image) > 1) { - minstacksize = 4096; - } -#endif - - ret = -TARGET_EFAULT; if (!lock_user_struct(VERIFY_READ, uss, uss_addr, 1)) { goto out; } - __get_user(ss.ss_sp, &uss->ss_sp); - __get_user(ss.ss_size, &uss->ss_size); - __get_user(ss.ss_flags, &uss->ss_flags); - unlock_user_struct(uss, uss_addr, 0); - - ret = -TARGET_EPERM; - if (on_sig_stack(sp)) + ret = target_restore_altstack(uss, sp); + if (ret) { goto out; - - ret = -TARGET_EINVAL; - if (ss.ss_flags != TARGET_SS_DISABLE - && ss.ss_flags != TARGET_SS_ONSTACK - && ss.ss_flags != 0) - goto out; - - if (ss.ss_flags == TARGET_SS_DISABLE) { - ss.ss_size = 0; - ss.ss_sp = 0; - } else { - ret = -TARGET_ENOMEM; - if (ss.ss_size < minstacksize) { - goto out; - } } - - ts->sigaltstack_used.ss_sp = ss.ss_sp; - ts->sigaltstack_used.ss_size = ss.ss_size; } if (uoss_addr) { - ret = -TARGET_EFAULT; - if (copy_to_user(uoss_addr, &oss, sizeof(oss))) - goto out; + memcpy(uoss, &oss, sizeof(oss)); + unlock_user_struct(uoss, uoss_addr, 1); + uoss = NULL; } - ret = 0; -out: + + out: + if (uoss) { + unlock_user_struct(uoss, uoss_addr, 0); + } return ret; } -- cgit v1.2.3-55-g7522 From 6b2087550345e87320f777c4db8254323d0d4123 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 25 Apr 2021 19:53:12 -0700 Subject: linux-user: Pass CPUArchState to do_sigaltstack Now that we have exactly one call, it's easy to pass in env instead of passing in the sp value. Use target_save_altstack, which required env. Signed-off-by: Richard Henderson Message-Id: <20210426025334.1168495-4-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/qemu.h | 3 ++- linux-user/signal.c | 11 ++++------- linux-user/syscall.c | 3 +-- 3 files changed, 7 insertions(+), 10 deletions(-) (limited to 'linux-user/signal.c') diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 74e06e7121..3b0b6b75fe 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -432,7 +432,8 @@ int target_to_host_signal(int sig); int host_to_target_signal(int sig); long do_sigreturn(CPUArchState *env); long do_rt_sigreturn(CPUArchState *env); -abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp); +abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, + CPUArchState *env); int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset); abi_long do_swapcontext(CPUArchState *env, abi_ulong uold_ctx, abi_ulong unew_ctx, abi_long ctx_size); diff --git a/linux-user/signal.c b/linux-user/signal.c index 9daa89eac5..2e1095055b 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -800,21 +800,18 @@ static void host_signal_handler(int host_signum, siginfo_t *info, /* do_sigaltstack() returns target values and errnos. */ /* compare linux/kernel/signal.c:do_sigaltstack() */ -abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp) +abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, + CPUArchState *env) { target_stack_t oss, *uoss = NULL; abi_long ret = -TARGET_EFAULT; if (uoss_addr) { - TaskState *ts = (TaskState *)thread_cpu->opaque; - /* Verify writability now, but do not alter user memory yet. */ if (!lock_user_struct(VERIFY_WRITE, uoss, uoss_addr, 0)) { goto out; } - __put_user(ts->sigaltstack_used.ss_sp, &oss.ss_sp); - __put_user(ts->sigaltstack_used.ss_size, &oss.ss_size); - __put_user(sas_ss_flags(sp), &oss.ss_flags); + target_save_altstack(&oss, env); } if (uss_addr) { @@ -823,7 +820,7 @@ abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp) if (!lock_user_struct(VERIFY_READ, uss, uss_addr, 1)) { goto out; } - ret = target_restore_altstack(uss, sp); + ret = target_restore_altstack(uss, get_sp_from_cpustate(env)); if (ret) { goto out; } diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 95d79ddc43..4d52b2cfe3 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -11195,8 +11195,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, return ret; } case TARGET_NR_sigaltstack: - return do_sigaltstack(arg1, arg2, - get_sp_from_cpustate((CPUArchState *)cpu_env)); + return do_sigaltstack(arg1, arg2, cpu_env); #ifdef CONFIG_SENDFILE #ifdef TARGET_NR_sendfile -- cgit v1.2.3-55-g7522 From ddc3e74d9c5ac76562ce8abe9e5908c4ff7cb8f0 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 25 Apr 2021 19:53:13 -0700 Subject: linux-user: Pass CPUArchState to target_restore_altstack In most cases we were already passing get_sp_from_cpustate directly to the function. In other cases, we were passing a local variable which already contained the same value. In the rest of the cases, we were passing the stack pointer out of env directly. Reviewed by: Warner Losh Signed-off-by: Richard Henderson Message-Id: <20210426025334.1168495-5-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/aarch64/signal.c | 2 +- linux-user/alpha/signal.c | 2 +- linux-user/arm/signal.c | 4 ++-- linux-user/hexagon/signal.c | 2 +- linux-user/hppa/signal.c | 2 +- linux-user/i386/signal.c | 2 +- linux-user/m68k/signal.c | 2 +- linux-user/microblaze/signal.c | 2 +- linux-user/mips/signal.c | 2 +- linux-user/nios2/signal.c | 2 +- linux-user/openrisc/signal.c | 2 +- linux-user/ppc/signal.c | 2 +- linux-user/riscv/signal.c | 2 +- linux-user/s390x/signal.c | 2 +- linux-user/sh4/signal.c | 2 +- linux-user/signal-common.h | 2 +- linux-user/signal.c | 6 +++--- linux-user/xtensa/signal.c | 2 +- 18 files changed, 21 insertions(+), 21 deletions(-) (limited to 'linux-user/signal.c') diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c index 2a1b7dbcdc..662bcd1c4e 100644 --- a/linux-user/aarch64/signal.c +++ b/linux-user/aarch64/signal.c @@ -561,7 +561,7 @@ long do_rt_sigreturn(CPUARMState *env) goto badframe; } - target_restore_altstack(&frame->uc.tuc_stack, get_sp_from_cpustate(env)); + target_restore_altstack(&frame->uc.tuc_stack, env); unlock_user_struct(frame, frame_addr, 0); return -TARGET_QEMU_ESIGRETURN; diff --git a/linux-user/alpha/signal.c b/linux-user/alpha/signal.c index 0af0227118..d4e4666874 100644 --- a/linux-user/alpha/signal.c +++ b/linux-user/alpha/signal.c @@ -257,7 +257,7 @@ long do_rt_sigreturn(CPUAlphaState *env) set_sigmask(&set); restore_sigcontext(env, &frame->uc.tuc_mcontext); - target_restore_altstack(&frame->uc.tuc_stack, env->ir[IR_SP]); + target_restore_altstack(&frame->uc.tuc_stack, env); unlock_user_struct(frame, frame_addr, 0); return -TARGET_QEMU_ESIGRETURN; diff --git a/linux-user/arm/signal.c b/linux-user/arm/signal.c index b7a772302f..32b68ee302 100644 --- a/linux-user/arm/signal.c +++ b/linux-user/arm/signal.c @@ -685,7 +685,7 @@ static int do_sigframe_return_v2(CPUARMState *env, } } - target_restore_altstack(&uc->tuc_stack, get_sp_from_cpustate(env)); + target_restore_altstack(&uc->tuc_stack, env); #if 0 /* Send SIGTRAP if we're single-stepping */ @@ -769,7 +769,7 @@ static long do_rt_sigreturn_v1(CPUARMState *env) goto badframe; } - target_restore_altstack(&frame->uc.tuc_stack, get_sp_from_cpustate(env)); + target_restore_altstack(&frame->uc.tuc_stack, env); #if 0 /* Send SIGTRAP if we're single-stepping */ diff --git a/linux-user/hexagon/signal.c b/linux-user/hexagon/signal.c index 3854eb4709..85eab5e943 100644 --- a/linux-user/hexagon/signal.c +++ b/linux-user/hexagon/signal.c @@ -260,7 +260,7 @@ long do_rt_sigreturn(CPUHexagonState *env) } restore_ucontext(env, &frame->uc); - target_restore_altstack(&frame->uc.uc_stack, get_sp_from_cpustate(env)); + target_restore_altstack(&frame->uc.uc_stack, env); unlock_user_struct(frame, frame_addr, 0); return -TARGET_QEMU_ESIGRETURN; diff --git a/linux-user/hppa/signal.c b/linux-user/hppa/signal.c index 578874cf27..0e266f472d 100644 --- a/linux-user/hppa/signal.c +++ b/linux-user/hppa/signal.c @@ -187,7 +187,7 @@ long do_rt_sigreturn(CPUArchState *env) set_sigmask(&set); restore_sigcontext(env, &frame->uc.tuc_mcontext); - target_restore_altstack(&frame->uc.tuc_stack, env->gr[30]); + target_restore_altstack(&frame->uc.tuc_stack, env); unlock_user_struct(frame, frame_addr, 0); return -TARGET_QEMU_ESIGRETURN; diff --git a/linux-user/i386/signal.c b/linux-user/i386/signal.c index 3a0a1546a6..8701774e37 100644 --- a/linux-user/i386/signal.c +++ b/linux-user/i386/signal.c @@ -581,7 +581,7 @@ long do_rt_sigreturn(CPUX86State *env) goto badframe; } - target_restore_altstack(&frame->uc.tuc_stack, get_sp_from_cpustate(env)); + target_restore_altstack(&frame->uc.tuc_stack, env); unlock_user_struct(frame, frame_addr, 0); return -TARGET_QEMU_ESIGRETURN; diff --git a/linux-user/m68k/signal.c b/linux-user/m68k/signal.c index 004b59fb61..d06230655e 100644 --- a/linux-user/m68k/signal.c +++ b/linux-user/m68k/signal.c @@ -400,7 +400,7 @@ long do_rt_sigreturn(CPUM68KState *env) if (target_rt_restore_ucontext(env, &frame->uc)) goto badframe; - target_restore_altstack(&frame->uc.tuc_stack, get_sp_from_cpustate(env)); + target_restore_altstack(&frame->uc.tuc_stack, env); unlock_user_struct(frame, frame_addr, 0); return -TARGET_QEMU_ESIGRETURN; diff --git a/linux-user/microblaze/signal.c b/linux-user/microblaze/signal.c index f59a1faf47..4c483bd8c6 100644 --- a/linux-user/microblaze/signal.c +++ b/linux-user/microblaze/signal.c @@ -209,7 +209,7 @@ long do_rt_sigreturn(CPUMBState *env) restore_sigcontext(&frame->uc.tuc_mcontext, env); - target_restore_altstack(&frame->uc.tuc_stack, get_sp_from_cpustate(env)); + target_restore_altstack(&frame->uc.tuc_stack, env); unlock_user_struct(frame, frame_addr, 0); return -TARGET_QEMU_ESIGRETURN; diff --git a/linux-user/mips/signal.c b/linux-user/mips/signal.c index 456fa64f41..e6be807a81 100644 --- a/linux-user/mips/signal.c +++ b/linux-user/mips/signal.c @@ -368,7 +368,7 @@ long do_rt_sigreturn(CPUMIPSState *env) set_sigmask(&blocked); restore_sigcontext(env, &frame->rs_uc.tuc_mcontext); - target_restore_altstack(&frame->rs_uc.tuc_stack, get_sp_from_cpustate(env)); + target_restore_altstack(&frame->rs_uc.tuc_stack, env); env->active_tc.PC = env->CP0_EPC; mips_set_hflags_isa_mode_from_pc(env); diff --git a/linux-user/nios2/signal.c b/linux-user/nios2/signal.c index 751ea88811..cc3872f11d 100644 --- a/linux-user/nios2/signal.c +++ b/linux-user/nios2/signal.c @@ -128,7 +128,7 @@ static int rt_restore_ucontext(CPUNios2State *env, struct target_ucontext *uc, __get_user(env->regs[R_RA], &gregs[23]); __get_user(env->regs[R_SP], &gregs[28]); - target_restore_altstack(&uc->tuc_stack, get_sp_from_cpustate(env)); + target_restore_altstack(&uc->tuc_stack, env); *pr2 = env->regs[2]; return 0; diff --git a/linux-user/openrisc/signal.c b/linux-user/openrisc/signal.c index 86f94d7f76..5c5640a284 100644 --- a/linux-user/openrisc/signal.c +++ b/linux-user/openrisc/signal.c @@ -158,7 +158,7 @@ long do_rt_sigreturn(CPUOpenRISCState *env) set_sigmask(&set); restore_sigcontext(env, &frame->uc.tuc_mcontext); - target_restore_altstack(&frame->uc.tuc_stack, frame_addr); + target_restore_altstack(&frame->uc.tuc_stack, env); unlock_user_struct(frame, frame_addr, 0); return cpu_get_gpr(env, 11); diff --git a/linux-user/ppc/signal.c b/linux-user/ppc/signal.c index b44d5ce73c..edfad28a37 100644 --- a/linux-user/ppc/signal.c +++ b/linux-user/ppc/signal.c @@ -655,7 +655,7 @@ long do_rt_sigreturn(CPUPPCState *env) if (do_setcontext(&rt_sf->uc, env, 1)) goto sigsegv; - target_restore_altstack(&rt_sf->uc.tuc_stack, env->gpr[1]); + target_restore_altstack(&rt_sf->uc.tuc_stack, env); unlock_user_struct(rt_sf, rt_sf_addr, 1); return -TARGET_QEMU_ESIGRETURN; diff --git a/linux-user/riscv/signal.c b/linux-user/riscv/signal.c index 81d1129da3..9405c7fd9a 100644 --- a/linux-user/riscv/signal.c +++ b/linux-user/riscv/signal.c @@ -192,7 +192,7 @@ long do_rt_sigreturn(CPURISCVState *env) } restore_ucontext(env, &frame->uc); - target_restore_altstack(&frame->uc.uc_stack, get_sp_from_cpustate(env)); + target_restore_altstack(&frame->uc.uc_stack, env); unlock_user_struct(frame, frame_addr, 0); return -TARGET_QEMU_ESIGRETURN; diff --git a/linux-user/s390x/signal.c b/linux-user/s390x/signal.c index 73806f5472..b68b44ae7e 100644 --- a/linux-user/s390x/signal.c +++ b/linux-user/s390x/signal.c @@ -307,7 +307,7 @@ long do_rt_sigreturn(CPUS390XState *env) goto badframe; } - target_restore_altstack(&frame->uc.tuc_stack, get_sp_from_cpustate(env)); + target_restore_altstack(&frame->uc.tuc_stack, env); unlock_user_struct(frame, frame_addr, 0); return -TARGET_QEMU_ESIGRETURN; diff --git a/linux-user/sh4/signal.c b/linux-user/sh4/signal.c index 684f18da58..0451e65806 100644 --- a/linux-user/sh4/signal.c +++ b/linux-user/sh4/signal.c @@ -323,7 +323,7 @@ long do_rt_sigreturn(CPUSH4State *regs) set_sigmask(&blocked); restore_sigcontext(regs, &frame->uc.tuc_mcontext); - target_restore_altstack(&frame->uc.tuc_stack, get_sp_from_cpustate(regs)); + target_restore_altstack(&frame->uc.tuc_stack, regs); unlock_user_struct(frame, frame_addr, 0); return -TARGET_QEMU_ESIGRETURN; diff --git a/linux-user/signal-common.h b/linux-user/signal-common.h index 34b963af9a..ea86328b28 100644 --- a/linux-user/signal-common.h +++ b/linux-user/signal-common.h @@ -24,7 +24,7 @@ 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); void target_save_altstack(target_stack_t *uss, CPUArchState *env); -abi_long target_restore_altstack(target_stack_t *uss, abi_ulong sp); +abi_long target_restore_altstack(target_stack_t *uss, CPUArchState *env); static inline void target_sigemptyset(target_sigset_t *set) { diff --git a/linux-user/signal.c b/linux-user/signal.c index 2e1095055b..cbd80b28cf 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -297,7 +297,7 @@ void target_save_altstack(target_stack_t *uss, CPUArchState *env) __put_user(ts->sigaltstack_used.ss_size, &uss->ss_size); } -abi_long target_restore_altstack(target_stack_t *uss, abi_ulong sp) +abi_long target_restore_altstack(target_stack_t *uss, CPUArchState *env) { TaskState *ts = (TaskState *)thread_cpu->opaque; size_t minstacksize = TARGET_MINSIGSTKSZ; @@ -315,7 +315,7 @@ abi_long target_restore_altstack(target_stack_t *uss, abi_ulong sp) __get_user(ss.ss_size, &uss->ss_size); __get_user(ss.ss_flags, &uss->ss_flags); - if (on_sig_stack(sp)) { + if (on_sig_stack(get_sp_from_cpustate(env))) { return -TARGET_EPERM; } @@ -820,7 +820,7 @@ abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, if (!lock_user_struct(VERIFY_READ, uss, uss_addr, 1)) { goto out; } - ret = target_restore_altstack(uss, get_sp_from_cpustate(env)); + ret = target_restore_altstack(uss, env); if (ret) { goto out; } diff --git a/linux-user/xtensa/signal.c b/linux-user/xtensa/signal.c index 22ec6cdeb9..72771e1294 100644 --- a/linux-user/xtensa/signal.c +++ b/linux-user/xtensa/signal.c @@ -253,7 +253,7 @@ long do_rt_sigreturn(CPUXtensaState *env) set_sigmask(&set); restore_sigcontext(env, frame); - target_restore_altstack(&frame->uc.tuc_stack, get_sp_from_cpustate(env)); + target_restore_altstack(&frame->uc.tuc_stack, env); unlock_user_struct(frame, frame_addr, 0); return -TARGET_QEMU_ESIGRETURN; -- cgit v1.2.3-55-g7522 From 02fb28e8effe5090ded4d36ea1c947a615099c26 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 22 Apr 2021 16:02:23 -0700 Subject: linux-user: Pass ka_restorer to do_sigaction The value of ka_restorer needs to be saved in sigact_table. At the moment, the attempt to save it in do_syscall is improperly clobbering user memory. Signed-off-by: Richard Henderson Reviewed-by: Alex Bennée Message-Id: <20210422230227.314751-4-richard.henderson@linaro.org> [lv: remove tab] Signed-off-by: Laurent Vivier --- linux-user/signal.c | 5 ++++- linux-user/syscall.c | 19 ++++++------------- linux-user/syscall_defs.h | 2 +- 3 files changed, 11 insertions(+), 15 deletions(-) (limited to 'linux-user/signal.c') diff --git a/linux-user/signal.c b/linux-user/signal.c index cbd80b28cf..9016896dcd 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -842,7 +842,7 @@ abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, /* do_sigaction() return target values and host errnos */ int do_sigaction(int sig, const struct target_sigaction *act, - struct target_sigaction *oact) + struct target_sigaction *oact, abi_ulong ka_restorer) { struct target_sigaction *k; struct sigaction act1; @@ -875,6 +875,9 @@ int do_sigaction(int sig, const struct target_sigaction *act, __get_user(k->sa_flags, &act->sa_flags); #ifdef TARGET_ARCH_HAS_SA_RESTORER __get_user(k->sa_restorer, &act->sa_restorer); +#endif +#ifdef TARGET_ARCH_HAS_KA_RESTORER + k->ka_restorer = ka_restorer; #endif /* To be swapped in target_to_host_sigset. */ k->sa_mask = act->sa_mask; diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 82736540eb..15b3af257b 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -8989,11 +8989,10 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, act._sa_handler = old_act->_sa_handler; target_siginitset(&act.sa_mask, old_act->sa_mask); act.sa_flags = old_act->sa_flags; - act.ka_restorer = 0; unlock_user_struct(old_act, arg2, 0); pact = &act; } - ret = get_errno(do_sigaction(arg1, pact, &oact)); + ret = get_errno(do_sigaction(arg1, pact, &oact, 0)); if (!is_error(ret) && arg3) { if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0)) return -TARGET_EFAULT; @@ -9017,7 +9016,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, pact = NULL; } - ret = get_errno(do_sigaction(arg1, pact, &oact)); + ret = get_errno(do_sigaction(arg1, pact, &oact, 0)); if (!is_error(ret) && arg3) { if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0)) @@ -9040,15 +9039,12 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, target_siginitset(&act.sa_mask, old_act->sa_mask); act.sa_flags = old_act->sa_flags; act.sa_restorer = old_act->sa_restorer; -#ifdef TARGET_ARCH_HAS_KA_RESTORER - act.ka_restorer = 0; -#endif unlock_user_struct(old_act, arg2, 0); pact = &act; } else { pact = NULL; } - ret = get_errno(do_sigaction(arg1, pact, &oact)); + ret = get_errno(do_sigaction(arg1, pact, &oact, 0)); if (!is_error(ret) && arg3) { if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0)) return -TARGET_EFAULT; @@ -9085,11 +9081,10 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, act._sa_handler = rt_act->_sa_handler; act.sa_mask = rt_act->sa_mask; act.sa_flags = rt_act->sa_flags; - act.ka_restorer = arg5; unlock_user_struct(rt_act, arg2, 0); pact = &act; } - ret = get_errno(do_sigaction(arg1, pact, &oact)); + ret = get_errno(do_sigaction(arg1, pact, &oact, arg5)); if (!is_error(ret) && arg3) { if (!lock_user_struct(VERIFY_WRITE, rt_act, arg3, 0)) return -TARGET_EFAULT; @@ -9104,6 +9099,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, target_ulong sigsetsize = arg5; #else target_ulong sigsetsize = arg4; + target_ulong restorer = 0; #endif struct target_sigaction *act; struct target_sigaction *oact; @@ -9115,9 +9111,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, if (!lock_user_struct(VERIFY_READ, act, arg2, 1)) { return -TARGET_EFAULT; } -#ifdef TARGET_ARCH_HAS_KA_RESTORER - act->ka_restorer = restorer; -#endif } else { act = NULL; } @@ -9128,7 +9121,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, } } else oact = NULL; - ret = get_errno(do_sigaction(arg1, act, oact)); + ret = get_errno(do_sigaction(arg1, act, oact, restorer)); rt_sigaction_fail: if (act) unlock_user_struct(act, arg2, 0); diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 693d4f3788..e4aaf8412f 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -492,7 +492,7 @@ void target_to_host_old_sigset(sigset_t *sigset, const abi_ulong *old_sigset); struct target_sigaction; int do_sigaction(int sig, const struct target_sigaction *act, - struct target_sigaction *oact); + struct target_sigaction *oact, abi_ulong ka_restorer); #include "target_signal.h" -- cgit v1.2.3-55-g7522