summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkettenis <kettenis@openbsd.org>2017-07-22 15:17:49 +0000
committerkettenis <kettenis@openbsd.org>2017-07-22 15:17:49 +0000
commita7957504d2ffe7b9a72b24eef39a0bb9674d8037 (patch)
tree3a953f69f9faa169bd007f8277de6670a960c93a
parentRename *_add_address to *_set_address to reflect that the (diff)
downloadwireguard-openbsd-a7957504d2ffe7b9a72b24eef39a0bb9674d8037.tar.xz
wireguard-openbsd-a7957504d2ffe7b9a72b24eef39a0bb9674d8037.zip
Fix the various SIGSEGV and SIGBUS scenarios to match what we do on
amd64/arm64/armv7/i386. ok visa@, deraadt@
-rw-r--r--sys/arch/sparc64/sparc64/trap.c69
1 files changed, 46 insertions, 23 deletions
diff --git a/sys/arch/sparc64/sparc64/trap.c b/sys/arch/sparc64/sparc64/trap.c
index b19fd57df07..55c8bd6213d 100644
--- a/sys/arch/sparc64/sparc64/trap.c
+++ b/sys/arch/sparc64/sparc64/trap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: trap.c,v 1.97 2017/01/21 05:42:04 guenther Exp $ */
+/* $OpenBSD: trap.c,v 1.98 2017/07/22 15:17:49 kettenis Exp $ */
/* $NetBSD: trap.c,v 1.73 2001/08/09 01:03:01 eeh Exp $ */
/*
@@ -832,18 +832,17 @@ data_access_fault(struct trapframe64 *tf, unsigned type, vaddr_t pc,
* the current limit and we need to reflect that as an access
* error.
*/
- if ((caddr_t)va >= vm->vm_maxsaddr) {
- if (rv == 0)
- uvm_grow(p, va);
- else if (rv == EACCES)
- rv = EFAULT;
- }
+ if (rv == 0 && (caddr_t)va >= vm->vm_maxsaddr)
+ uvm_grow(p, va);
+
if (rv != 0) {
/*
* Pagein failed. If doing copyin/out, return to onfault
* address. Any other page fault in kernel, die; if user
* fault, deliver SIGSEGV.
*/
+ int signal, sicode;
+
if (tstate & TSTATE_PRIV) {
kfault:
onfault = (long)p->p_addr->u_pcb.pcb_onfault;
@@ -864,14 +863,21 @@ kfault:
else
sv.sival_ptr = (void *)sfva;
+ signal = SIGSEGV;
+ sicode = SEGV_MAPERR;
if (rv == ENOMEM) {
printf("UVM: pid %d (%s), uid %d killed: out of swap\n",
p->p_p->ps_pid, p->p_p->ps_comm,
p->p_ucred ? (int)p->p_ucred->cr_uid : -1);
- trapsignal(p, SIGKILL, access_type, SEGV_MAPERR, sv);
- } else {
- trapsignal(p, SIGSEGV, access_type, SEGV_MAPERR, sv);
+ signal = SIGKILL;
}
+ if (rv == EACCES)
+ sicode = SEGV_ACCERR;
+ if (rv == EIO) {
+ signal = SIGBUS;
+ sicode = BUS_OBJERR;
+ }
+ trapsignal(p, signal, access_type, sicode, sv);
}
if ((tstate & TSTATE_PRIV) == 0) {
@@ -1010,23 +1016,31 @@ text_access_fault(struct trapframe64 *tf, unsigned type, vaddr_t pc,
* the current limit and we need to reflect that as an access
* error.
*/
- if ((caddr_t)va >= vm->vm_maxsaddr) {
- if (rv == 0)
- uvm_grow(p, va);
- else if (rv == EACCES)
- rv = EFAULT;
- }
+ if (rv == 0 && (caddr_t)va >= vm->vm_maxsaddr)
+ uvm_grow(p, va);
+
if (rv != 0) {
/*
* Pagein failed. Any other page fault in kernel, die; if user
* fault, deliver SIGSEGV.
*/
+ int signal, sicode;
+
if (tstate & TSTATE_PRIV) {
(void) splhigh();
panic("kernel text fault: pc=%llx", (unsigned long long)pc);
/* NOTREACHED */
}
- trapsignal(p, SIGSEGV, access_type, SEGV_MAPERR, sv);
+
+ signal = SIGSEGV;
+ sicode = SEGV_MAPERR;
+ if (rv == EACCES)
+ sicode = SEGV_ACCERR;
+ if (rv == EIO) {
+ signal = SIGBUS;
+ sicode = BUS_OBJERR;
+ }
+ trapsignal(p, signal, access_type, sicode, sv);
}
KERNEL_UNLOCK();
@@ -1106,25 +1120,34 @@ text_access_error(struct trapframe64 *tf, unsigned type, vaddr_t pc,
* the current limit and we need to reflect that as an access
* error.
*/
- if ((caddr_t)va >= vm->vm_maxsaddr) {
- if (rv == 0)
- uvm_grow(p, va);
- else if (rv == EACCES)
- rv = EFAULT;
+ if (rv == 0 && (caddr_t)va >= vm->vm_maxsaddr) {
+ uvm_grow(p, va);
}
+
if (rv != 0) {
/*
* Pagein failed. If doing copyin/out, return to onfault
* address. Any other page fault in kernel, die; if user
* fault, deliver SIGSEGV.
*/
+ int signal, sicode;
+
if (tstate & TSTATE_PRIV) {
(void) splhigh();
panic("kernel text error: pc=%lx sfsr=%lb", pc,
sfsr, SFSR_BITS);
/* NOTREACHED */
}
- trapsignal(p, SIGSEGV, access_type, SEGV_MAPERR, sv);
+
+ signal = SIGSEGV;
+ sicode = SEGV_MAPERR;
+ if (rv == EACCES)
+ sicode = SEGV_ACCERR;
+ if (rv == EIO) {
+ signal = SIGBUS;
+ sicode = BUS_OBJERR;
+ }
+ trapsignal(p, signal, access_type, sicode, sv);
}
KERNEL_UNLOCK();