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