summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkettenis <kettenis@openbsd.org>2018-06-23 22:15:14 +0000
committerkettenis <kettenis@openbsd.org>2018-06-23 22:15:14 +0000
commit74f6b3c1e3aba38f8feec08c2adb8e8ca18686b6 (patch)
treea0f47643146a177da4d759dde84f665cd9985b84
parentAdd -z notext and -z norelro to prevent fatal warnings with ld.lld(1). (diff)
downloadwireguard-openbsd-74f6b3c1e3aba38f8feec08c2adb8e8ca18686b6.tar.xz
wireguard-openbsd-74f6b3c1e3aba38f8feec08c2adb8e8ca18686b6.zip
Save and restore FPU registers around signal handlers.
Fixes the random crashes in sh(1). ok guenther@
-rw-r--r--sys/arch/arm/arm/sig_machdep.c30
-rw-r--r--sys/arch/arm/include/signal.h6
2 files changed, 32 insertions, 4 deletions
diff --git a/sys/arch/arm/arm/sig_machdep.c b/sys/arch/arm/arm/sig_machdep.c
index 8808158457a..4c7b9789b0e 100644
--- a/sys/arch/arm/arm/sig_machdep.c
+++ b/sys/arch/arm/arm/sig_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sig_machdep.c,v 1.16 2018/04/12 17:13:43 deraadt Exp $ */
+/* $OpenBSD: sig_machdep.c,v 1.17 2018/06/23 22:15:14 kettenis Exp $ */
/* $NetBSD: sig_machdep.c,v 1.22 2003/10/08 00:28:41 thorpej Exp $ */
/*
@@ -51,11 +51,11 @@
#include <sys/systm.h>
#include <sys/user.h>
-#include <arm/armreg.h>
-
#include <machine/cpu.h>
#include <machine/frame.h>
#include <machine/pcb.h>
+
+#include <arm/armreg.h>
#include <arm/cpufunc.h>
#include <uvm/uvm_extern.h>
@@ -80,6 +80,7 @@ sendsig(sig_t catcher, int sig, int returnmask, u_long code, int type,
union sigval val)
{
struct proc *p = curproc;
+ struct pcb *pcb = &p->p_addr->u_pcb;
struct trapframe *tf;
struct sigframe *fp, frame;
struct sigacts *psp = p->p_p->ps_sigacts;
@@ -130,6 +131,16 @@ sendsig(sig_t catcher, int sig, int returnmask, u_long code, int type,
/* Save signal mask. */
frame.sf_sc.sc_mask = returnmask;
+ /* Save FPU registers. */
+ frame.sf_sc.sc_fpused = pcb->pcb_flags & PCB_FPU;
+ if (frame.sf_sc.sc_fpused) {
+ frame.sf_sc.sc_fpscr = pcb->pcb_fpstate.fp_scr;
+ memcpy(&frame.sf_sc.sc_fpreg, &pcb->pcb_fpstate.fp_reg,
+ sizeof(pcb->pcb_fpstate.fp_reg));
+ pcb->pcb_flags &= ~PCB_FPU;
+ pcb->pcb_fpcpu = NULL;
+ }
+
if (psp->ps_siginfo & sigmask(sig)) {
frame.sf_sip = &fp->sf_si;
initsiginfo(&frame.sf_si, sig, code, type, val);
@@ -176,6 +187,7 @@ sys_sigreturn(struct proc *p, void *v, register_t *retval)
syscallarg(struct sigcontext *) sigcntxp;
} */ *uap = v;
struct sigcontext ksc, *scp = SCARG(uap, sigcntxp);
+ struct pcb *pcb = &p->p_addr->u_pcb;
struct trapframe *tf;
if (PROC_PC(p) != p->p_p->ps_sigcoderet) {
@@ -228,5 +240,17 @@ sys_sigreturn(struct proc *p, void *v, register_t *retval)
/* Restore signal mask. */
p->p_sigmask = ksc.sc_mask & ~sigcantmask;
+ /* Restore FPU registers. */
+ if (ksc.sc_fpused) {
+ pcb->pcb_fpstate.fp_scr = ksc.sc_fpscr;
+ memcpy(&pcb->pcb_fpstate.fp_reg, &ksc.sc_fpreg,
+ sizeof(pcb->pcb_fpstate.fp_reg));
+ pcb->pcb_flags |= PCB_FPU;
+ pcb->pcb_fpcpu = NULL;
+ } else {
+ pcb->pcb_flags &= ~PCB_FPU;
+ pcb->pcb_fpcpu = NULL;
+ }
+
return (EJUSTRETURN);
}
diff --git a/sys/arch/arm/include/signal.h b/sys/arch/arm/include/signal.h
index 773fdc89dc0..38303b02aa7 100644
--- a/sys/arch/arm/include/signal.h
+++ b/sys/arch/arm/include/signal.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: signal.h,v 1.9 2016/05/10 18:39:43 deraadt Exp $ */
+/* $OpenBSD: signal.h,v 1.10 2018/06/23 22:15:14 kettenis Exp $ */
/* $NetBSD: signal.h,v 1.5 2003/10/18 17:57:21 briggs Exp $ */
/*
@@ -82,6 +82,10 @@ struct sigcontext {
unsigned int sc_usr_lr;
unsigned int sc_svc_lr;
unsigned int sc_pc;
+
+ unsigned int sc_fpused;
+ unsigned int sc_fpscr;
+ unsigned long long sc_fpreg[32];
};
#endif /* __BSD_VISIBLE || __XPG_VISIBLE >= 420 */
#endif /* !_LOCORE */