X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=bsd-user%2Fsignal.c;h=ea82241b70be40cf4d1126f1c32a9df7767721e6;hb=0c3529888a427cefe248227423f7a89c8f665fab;hp=5c94bd02e38b9eac31e5fa7ae65cd2d31de43074;hpb=394cf694273caf8ab8838588954d0fc2909ae2fa;p=mirror_qemu.git diff --git a/bsd-user/signal.c b/bsd-user/signal.c index 5c94bd02e3..ea82241b70 100644 --- a/bsd-user/signal.c +++ b/bsd-user/signal.c @@ -19,17 +19,14 @@ */ #include "qemu/osdep.h" +#include "qemu/log.h" #include "qemu.h" +#include "gdbstub/user.h" #include "signal-common.h" #include "trace.h" #include "hw/core/tcg-cpu-ops.h" #include "host-signal.h" -/* - * Stubbed out routines until we merge signal support from bsd-user - * fork. - */ - static struct target_sigaction sigact_table[TARGET_NSIG]; static void host_signal_handler(int host_sig, siginfo_t *info, void *puc); static void target_to_host_sigset_internal(sigset_t *d, @@ -47,7 +44,7 @@ static inline int sas_ss_flags(TaskState *ts, unsigned long sp) } /* - * The BSD ABIs use the same singal numbers across all the CPU architectures, so + * The BSD ABIs use the same signal numbers across all the CPU architectures, so * (unlike Linux) these functions are just the identity mapping. This might not * be true for XyzBSD running on AbcBSD, which doesn't currently work. */ @@ -227,6 +224,7 @@ static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo, * We have to go based on the signal number now to figure out * what's valid. */ + si_type = QEMU_SI_NOINFO; if (has_trapno(sig)) { tinfo->_reason._fault._trapno = info->_reason._fault._trapno; si_type = QEMU_SI_FAULT; @@ -243,14 +241,16 @@ static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo, #endif /* * Unsure that this can actually be generated, and our support for - * capsicum is somewhere between weak and non-existant, but if we get + * capsicum is somewhere between weak and non-existent, but if we get * one, then we know what to save. */ +#ifdef QEMU_SI_CAPSICUM if (sig == TARGET_SIGTRAP) { tinfo->_reason._capsicum._syscall = info->_reason._capsicum._syscall; si_type = QEMU_SI_CAPSICUM; } +#endif break; } tinfo->si_code = deposit32(si_code, 24, 8, si_type); @@ -300,15 +300,23 @@ static void tswap_siginfo(target_siginfo_t *tinfo, const target_siginfo_t *info) /* Note: Not generated on FreeBSD */ __put_user(info->_reason._poll._band, &tinfo->_reason._poll._band); break; +#ifdef QEMU_SI_CAPSICUM case QEMU_SI_CAPSICUM: __put_user(info->_reason._capsicum._syscall, &tinfo->_reason._capsicum._syscall); break; +#endif default: g_assert_not_reached(); } } +void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info) +{ + host_to_target_siginfo_noswap(tinfo, info); + tswap_siginfo(tinfo, tinfo); +} + int block_signals(void) { TaskState *ts = (TaskState *)thread_cpu->opaque; @@ -317,7 +325,7 @@ int block_signals(void) /* * It's OK to block everything including SIGSEGV, because we won't run any * further guest code before unblocking signals in - * process_pending_signals(). We depend on the FreeBSD behaivor here where + * process_pending_signals(). We depend on the FreeBSD behavior here where * this will only affect this thread's signal mask. We don't use * pthread_sigmask which might seem more correct because that routine also * does odd things with SIGCANCEL to implement pthread_cancel(). @@ -346,7 +354,8 @@ static int core_dump_signal(int sig) } /* Abort execution with signal. */ -static void QEMU_NORETURN dump_core_and_abort(int target_sig) +static G_NORETURN +void dump_core_and_abort(int target_sig) { CPUArchState *env = thread_cpu->env_ptr; CPUState *cpu = env_cpu(env); @@ -573,6 +582,73 @@ 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) +{ + TaskState *ts = (TaskState *)thread_cpu->opaque; + int ret; + target_stack_t oss; + + if (uoss_addr) { + /* Save current signal stack params */ + oss.ss_sp = tswapl(ts->sigaltstack_used.ss_sp); + oss.ss_size = tswapl(ts->sigaltstack_used.ss_size); + oss.ss_flags = tswapl(sas_ss_flags(ts, 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(ts, 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; + } + } + + 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; + } + } + + ret = 0; +out: + return ret; +} + /* do_sigaction() return host values and errnos */ int do_sigaction(int sig, const struct target_sigaction *act, struct target_sigaction *oact) @@ -717,10 +793,7 @@ static int reset_signal_mask(target_ucontext_t *ucontext) TaskState *ts = (TaskState *)thread_cpu->opaque; for (i = 0; i < TARGET_NSIG_WORDS; i++) { - if (__get_user(target_set.__bits[i], - &ucontext->uc_sigmask.__bits[i])) { - return -TARGET_EFAULT; - } + __get_user(target_set.__bits[i], &ucontext->uc_sigmask.__bits[i]); } target_to_host_sigset_internal(&blocked, &target_set); ts->signal_mask = blocked;