Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/i386/i386 If we fault on the 'iret' during return t...
details: https://anonhg.NetBSD.org/src/rev/2a616cf64edc
branches: trunk
changeset: 750677:2a616cf64edc
user: dsl <dsl%NetBSD.org@localhost>
date: Sun Jan 10 15:21:36 2010 +0000
description:
If we fault on the 'iret' during return to userpace (eg if %eip is outside
the bounds of %cs) then hack the stack to contain a normal fault frame
for the signal setup code (etc).
Previously the code assumed that the original user trap frame was still
present - at it is for faults when loading the segment registers.
diffstat:
sys/arch/i386/i386/trap.c | 43 +++++++++++++++++++++++++++++++++----------
sys/arch/i386/i386/vector.S | 8 ++++++--
2 files changed, 39 insertions(+), 12 deletions(-)
diffs (127 lines):
diff -r 313a514d786a -r 2a616cf64edc sys/arch/i386/i386/trap.c
--- a/sys/arch/i386/i386/trap.c Sun Jan 10 15:07:53 2010 +0000
+++ b/sys/arch/i386/i386/trap.c Sun Jan 10 15:21:36 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: trap.c,v 1.250 2009/11/21 03:11:00 rmind Exp $ */
+/* $NetBSD: trap.c,v 1.251 2010/01/10 15:21:36 dsl Exp $ */
/*-
* Copyright (c) 1998, 2000, 2005, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -68,7 +68,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.250 2009/11/21 03:11:00 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.251 2010/01/10 15:21:36 dsl Exp $");
#include "opt_ddb.h"
#include "opt_kgdb.h"
@@ -123,6 +123,7 @@
static inline int xmm_si_code(struct lwp *);
void trap(struct trapframe *);
void trap_tss(struct i386tss *, int, int);
+void trap_return_iret(struct trapframe *) __dead;
#ifdef KVM86
#include <machine/kvm86.h>
@@ -406,11 +407,33 @@
* the kernel stack; we presume here that we faulted while
* loading our registers out of the outer one.
*/
+
+ KSI_INIT_TRAP(&ksi);
+ ksi.ksi_signo = SIGSEGV;
+ /* There is no fault address! */
+ ksi.ksi_code = SEGV_ACCERR;
+ ksi.ksi_trap = type;
+
switch (*(u_char *)frame->tf_eip) {
case 0xcf: /* iret */
- vframe = (void *)((int)&frame->tf_esp -
+ /*
+ * The outer trap frame only contains the user space
+ * return address and stack pointer.
+ * The user registers are in the inner frame following
+ * the kernel address of the iret.
+ * We must copy the registers next to the userspace
+ * return address so we have a frame for md_regs.
+ */
+ vframe = (void *)((int *)frame + 3);
+ if (KERNELMODE(vframe->tf_cs, vframe->tf_eflags))
+ goto we_re_toast;
+ memmove(vframe, frame,
offsetof(struct trapframe, tf_eip));
- break;
+ l->l_md.md_regs = vframe;
+ ksi.ksi_addr = (void *)vframe->tf_eip;
+ (*p->p_emul->e_trapsignal)(l, &ksi);
+ trap_return_iret(vframe);
+ /* NOTREACHED */
case 0x8e:
switch (*(uint32_t *)frame->tf_eip) {
case 0x0c245c8e: /* movl 0xc(%esp,1),%ds */
@@ -421,11 +444,12 @@
default:
goto we_re_toast;
}
- vframe = (void *)(int)&frame->tf_esp;
break;
default:
goto we_re_toast;
}
+
+ vframe = (void *)(int)&frame->tf_esp;
if (KERNELMODE(vframe->tf_cs, vframe->tf_eflags))
goto we_re_toast;
@@ -445,17 +469,16 @@
* continue to generate traps infinitely with
* interrupts disabled.
*/
+ /* We don't want to fault unwinding the inner frame */
frame->tf_ds = GSEL(GDATA_SEL, SEL_KPL);
frame->tf_es = GSEL(GDATA_SEL, SEL_KPL);
frame->tf_gs = GSEL(GDATA_SEL, SEL_KPL);
frame->tf_fs = GSEL(GCPU_SEL, SEL_KPL);
+ /* Reload the entire outer (user) frame */
frame->tf_eip = (uintptr_t)trapreturn;
frame->tf_eflags = (frame->tf_eflags & ~PSL_NT) | PSL_I;
- KSI_INIT_TRAP(&ksi);
- ksi.ksi_signo = SIGSEGV;
- ksi.ksi_addr = (void *)rcr2();
- ksi.ksi_code = SEGV_ACCERR;
- ksi.ksi_trap = type & ~T_USER;
+ /* Save outer frame for any signal return */
+ l->l_md.md_regs = vframe;
(*p->p_emul->e_trapsignal)(l, &ksi);
return;
diff -r 313a514d786a -r 2a616cf64edc sys/arch/i386/i386/vector.S
--- a/sys/arch/i386/i386/vector.S Sun Jan 10 15:07:53 2010 +0000
+++ b/sys/arch/i386/i386/vector.S Sun Jan 10 15:21:36 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: vector.S,v 1.49 2009/11/25 14:28:50 rmind Exp $ */
+/* $NetBSD: vector.S,v 1.50 2010/01/10 15:21:36 dsl Exp $ */
/*
* Copyright 2002 (c) Wasabi Systems, Inc.
@@ -65,7 +65,7 @@
*/
#include <machine/asm.h>
-__KERNEL_RCSID(0, "$NetBSD: vector.S,v 1.49 2009/11/25 14:28:50 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vector.S,v 1.50 2010/01/10 15:21:36 dsl Exp $");
#include "opt_ddb.h"
#include "opt_multiprocessor.h"
@@ -1036,6 +1036,10 @@
iret
jmp 1b
+_C_LABEL(trap_return_iret): .globl trap_return_iret
+ mov 4(%esp),%esp /* frame for user return */
+ jmp _C_LABEL(trapreturn)
+
/* LINTSTUB: Ignore */
NENTRY(alltraps)
INTRENTRY
Home |
Main Index |
Thread Index |
Old Index