diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2003-12-23 23:36:45 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2003-12-23 23:36:45 +0000 |
commit | bf12afad9df1e58e23a7aaa94786bfe009ae56d4 (patch) | |
tree | b99a8316073de10469a89be7432f77f63f1089ae /sys/arch | |
parent | 89fcf7c5bd134cb52bcd9bbad34944f112e2f594 (diff) |
Data access faults occuring inside copyin() or copyinstr() would get
treated as usermode traps, because they reference a user space address.
However, the tests for pcb_onfault being set were only present in the
kernelmode traps handling.
Since pcb_onfault is only set in those functions, move the associated
recovery code from the kernelmode part to the usermode part, and only
attempt to jump to pcb_onfault() if the access could not be resolved
by uvm_fault() earlier.
This lets things like setlogin(NULL) correctly return EFAULT, rather
than killing the process with SIGSEGV, and incidentally lets sendmail
in a non-default configuration run.
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/mvme88k/mvme88k/trap.c | 68 |
1 files changed, 35 insertions, 33 deletions
diff --git a/sys/arch/mvme88k/mvme88k/trap.c b/sys/arch/mvme88k/mvme88k/trap.c index 6ef14f1fc47..ebb26255ffa 100644 --- a/sys/arch/mvme88k/mvme88k/trap.c +++ b/sys/arch/mvme88k/mvme88k/trap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: trap.c,v 1.60 2003/12/23 00:40:02 miod Exp $ */ +/* $OpenBSD: trap.c,v 1.61 2003/12/23 23:36:44 miod Exp $ */ /* * Copyright (c) 1998 Steve Murphree, Jr. * Copyright (c) 1996 Nivas Madhur @@ -376,28 +376,8 @@ m88100_trap(unsigned type, struct m88100_saved_state *frame) printf ("PBUS Fault %d (%s) va = 0x%x\n", pbus_type, pbus_exception_type[pbus_type], va); #endif - /* - * if still the fault is not resolved ... - */ - if (p->p_addr->u_pcb.pcb_onfault == 0) - panictrap(frame->vector, frame); - - frame->snip = - ((unsigned)p->p_addr->u_pcb.pcb_onfault ) | FIP_V; - frame->sfip = - ((unsigned)p->p_addr->u_pcb.pcb_onfault + 4) | FIP_V; - frame->sxip = 0; - /* We sort of resolved the fault ourselves because - * we know where it came from [copyxxx()] - * But we must still think about the other possible - * transactions in dmt1 & dmt2. Mark dmt0 so that - * data_access_emulation skips it. XXX smurph - */ - frame->dmt0 |= DMT_SKIP; - data_access_emulation((unsigned *)frame); - frame->dpfsr = 0; - frame->dmt0 = 0; - return; + panictrap(frame->vector, frame); + /* NOTREACHED */ case T_INSTFLT+T_USER: /* User mode instruction access fault */ /* FALLTHROUGH */ @@ -450,6 +430,22 @@ user_fault: result = EFAULT; } + /* + * This could be a fault caused in copyin*() + * while accessing user space. + */ + if (result != 0 && p->p_addr->u_pcb.pcb_onfault != NULL) { + frame->snip = p->p_addr->u_pcb.pcb_onfault | NIP_V; + frame->sfip = (p->p_addr->u_pcb.pcb_onfault + 4) | FIP_V; + frame->sxip = 0; + /* + * Continue as if the fault had been resolved, but + * do not try to complete the faulting access. + */ + frame->dmt0 |= DMT_SKIP; + result = 0; + } + if (result == 0) { if (type == T_DATAFLT+T_USER) { /* @@ -473,7 +469,7 @@ user_fault: } else { sig = result == EACCES ? SIGBUS : SIGSEGV; fault_type = result == EACCES ? - BUS_ADRERR : SEGV_MAPERR; + BUS_ADRERR : SEGV_MAPERR; } break; case T_MISALGNFLT+T_USER: @@ -858,15 +854,8 @@ m88110_trap(unsigned type, struct m88100_saved_state *frame) #endif } } - - /* - * if still the fault is not resolved ... - */ - if (!p->p_addr->u_pcb.pcb_onfault) - panictrap(frame->vector, frame); - - frame->exip = ((unsigned)p->p_addr->u_pcb.pcb_onfault); - return; + panictrap(frame->vector, frame); + /* NOTREACHED */ case T_INSTFLT+T_USER: /* User mode instruction access fault */ /* FALLTHROUGH */ @@ -983,6 +972,19 @@ m88110_user_fault: result = EFAULT; } + /* + * This could be a fault caused in copyin*() + * while accessing user space. + */ + if (result != 0 && p->p_addr->u_pcb.pcb_onfault != NULL) { + frame->exip = p->p_addr->u_pcb.pcb_onfault; + frame->dsr = frame->isr = 0; + /* + * Continue as if the fault had been resolved. + */ + result = 0; + } + if (result != 0) { sig = result == EACCES ? SIGBUS : SIGSEGV; fault_type = result == EACCES ? |