Implement the meat of the sigaltstack(2) system call with do_sigaltstack. Signed-off-by: Stacey Son <s...@freebsd.org> Signed-off-by: Kyle Evans <kev...@freebsd.org> Signed-off-by: Warner Losh <i...@bsdimp.com> --- bsd-user/qemu.h | 1 + bsd-user/signal.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+)
diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h index c643d6ba246..fcdea460ed2 100644 --- a/bsd-user/qemu.h +++ b/bsd-user/qemu.h @@ -226,6 +226,7 @@ int host_to_target_signal(int sig); void host_to_target_sigset(target_sigset_t *d, const sigset_t *s); void target_to_host_sigset(sigset_t *d, const target_sigset_t *s); long do_sigreturn(CPUArchState *regs, abi_ulong addr); +abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp); int do_sigaction(int sig, const struct target_sigaction *act, struct target_sigaction *oact); void QEMU_NORETURN force_sig(int target_sig); diff --git a/bsd-user/signal.c b/bsd-user/signal.c index f055d1db407..e5e5e28c60c 100644 --- a/bsd-user/signal.c +++ b/bsd-user/signal.c @@ -528,6 +528,72 @@ static void host_signal_handler(int host_sig, siginfo_t *info, void *puc) cpu_exit(thread_cpu); } +/* do_sigaltstack() returns target values and errnos. */ +/* compare to kern/kern_sig.c sys_sigaltstack() and kern_sigaltstack() */ +abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp) +{ + int ret; + target_stack_t oss; + + if (uoss_addr) { + /* Save current signal stack params */ + oss.ss_sp = tswapl(target_sigaltstack_used.ss_sp); + oss.ss_size = tswapl(target_sigaltstack_used.ss_size); + oss.ss_flags = tswapl(sas_ss_flags(sp)); + } + + if (uss_addr) { + target_stack_t *uss; + target_stack_t ss; + size_t minstacksize = TARGET_MINSIGSTKSZ; + + 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)) { + 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; + } + } + + target_sigaltstack_used.ss_sp = ss.ss_sp; + target_sigaltstack_used.ss_size = ss.ss_size; + } + + if (uoss_addr) { + ret = -TARGET_EFAULT; + if (copy_to_user(uoss_addr, &oss, sizeof(oss))) { + goto out; + } + } + + ret = 0; +out: + return ret; +} + static int fatal_signal(int sig) { -- 2.33.1