diff options
Diffstat (limited to 'sys/arch/i386/i386/linux_machdep.c')
-rw-r--r-- | sys/arch/i386/i386/linux_machdep.c | 90 |
1 files changed, 46 insertions, 44 deletions
diff --git a/sys/arch/i386/i386/linux_machdep.c b/sys/arch/i386/i386/linux_machdep.c index b38e48cf9ed..b01926463ab 100644 --- a/sys/arch/i386/i386/linux_machdep.c +++ b/sys/arch/i386/i386/linux_machdep.c @@ -1,5 +1,5 @@ -/* $OpenBSD: linux_machdep.c,v 1.3 1996/03/11 11:16:48 mickey Exp $ */ -/* $NetBSD: linux_machdep.c,v 1.24 1996/01/04 22:21:57 jtc Exp $ */ +/* $OpenBSD: linux_machdep.c,v 1.4 1996/04/17 05:18:53 mickey Exp $ */ +/* $NetBSD: linux_machdep.c,v 1.26 1996/04/11 07:47:45 mycroft Exp $ */ /* * Copyright (c) 1995 Frank van der Linden @@ -66,6 +66,7 @@ #include <machine/segments.h> #include <machine/specialreg.h> #include <machine/sysarch.h> +#include <machine/vm86.h> #include <machine/linux_machdep.h> /* @@ -134,6 +135,8 @@ linux_sendsig(catcher, sig, mask, code) frame.sf_sc.sc_fs = tf->tf_vm86_fs; frame.sf_sc.sc_es = tf->tf_vm86_es; frame.sf_sc.sc_ds = tf->tf_vm86_ds; + frame.sf_sc.sc_eflags = get_vflags(p); + tf->tf_eflags &= ~PSL_VM; } else #endif { @@ -141,20 +144,20 @@ linux_sendsig(catcher, sig, mask, code) __asm("movl %%fs,%w0" : "=r" (frame.sf_sc.sc_fs)); frame.sf_sc.sc_es = tf->tf_es; frame.sf_sc.sc_ds = tf->tf_ds; + frame.sf_sc.sc_eflags = tf->tf_eflags; } - frame.sf_sc.sc_edi = tf->tf_edi; - frame.sf_sc.sc_esi = tf->tf_esi; - frame.sf_sc.sc_ebp = tf->tf_ebp; - frame.sf_sc.sc_ebx = tf->tf_ebx; - frame.sf_sc.sc_edx = tf->tf_edx; - frame.sf_sc.sc_ecx = tf->tf_ecx; - frame.sf_sc.sc_eax = tf->tf_eax; - frame.sf_sc.sc_eip = tf->tf_eip; - frame.sf_sc.sc_cs = tf->tf_cs; - frame.sf_sc.sc_eflags = tf->tf_eflags; + frame.sf_sc.sc_edi = tf->tf_edi; + frame.sf_sc.sc_esi = tf->tf_esi; + frame.sf_sc.sc_ebp = tf->tf_ebp; + frame.sf_sc.sc_ebx = tf->tf_ebx; + frame.sf_sc.sc_edx = tf->tf_edx; + frame.sf_sc.sc_ecx = tf->tf_ecx; + frame.sf_sc.sc_eax = tf->tf_eax; + frame.sf_sc.sc_eip = tf->tf_eip; + frame.sf_sc.sc_cs = tf->tf_cs; frame.sf_sc.sc_esp_at_signal = tf->tf_esp; - frame.sf_sc.sc_ss = tf->tf_ss; - frame.sf_sc.sc_err = tf->tf_err; + frame.sf_sc.sc_ss = tf->tf_ss; + frame.sf_sc.sc_err = tf->tf_err; frame.sf_sc.sc_trapno = tf->tf_trapno; if (copyout(&frame, fp, sizeof(frame)) != 0) { @@ -169,15 +172,12 @@ linux_sendsig(catcher, sig, mask, code) /* * Build context to run handler in. */ - tf->tf_esp = (int)fp; + tf->tf_es = GSEL(GUDATA_SEL, SEL_UPL); + tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL); tf->tf_eip = (int)(((char *)PS_STRINGS) - (linux_esigcode - linux_sigcode)); -#ifdef VM86 - tf->tf_eflags &= ~PSL_VM; -#endif tf->tf_cs = GSEL(GUCODE_SEL, SEL_UPL); - tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL); - tf->tf_es = GSEL(GUDATA_SEL, SEL_UPL); + tf->tf_esp = (int)fp; tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL); } @@ -215,16 +215,6 @@ linux_sys_sigreturn(p, v, retval) return (EFAULT); /* - * Check for security violations. - */ - if (((context.sc_eflags ^ tf->tf_eflags) & PSL_USERSTATIC) != 0 || - !USERMODE(context.sc_cs, context.sc_eflags)) - return (EINVAL); - - p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK; - p->p_sigmask = context.sc_mask & ~sigcantmask; - - /* * Restore signal context. */ #ifdef VM86 @@ -233,25 +223,39 @@ linux_sys_sigreturn(p, v, retval) tf->tf_vm86_fs = context.sc_fs; tf->tf_vm86_es = context.sc_es; tf->tf_vm86_ds = context.sc_ds; + set_vflags(p, context.sc_eflags); } else #endif { + /* + * Check for security violations. If we're returning to + * protected mode, the CPU will validate the segment registers + * automatically and generate a trap on violations. We handle + * the trap, rather than doing all of the checking here. + */ + if (((context.sc_eflags ^ tf->tf_eflags) & PSL_USERSTATIC) != 0 || + !USERMODE(context.sc_cs, context.sc_eflags)) + return (EINVAL); + /* %fs and %gs were restored by the trampoline. */ tf->tf_es = context.sc_es; tf->tf_ds = context.sc_ds; + tf->tf_eflags = context.sc_eflags; } - tf->tf_edi = context.sc_edi; - tf->tf_esi = context.sc_esi; - tf->tf_ebp = context.sc_ebp; - tf->tf_ebx = context.sc_ebx; - tf->tf_edx = context.sc_edx; - tf->tf_ecx = context.sc_ecx; - tf->tf_eax = context.sc_eax; - tf->tf_eip = context.sc_eip; - tf->tf_cs = context.sc_cs; - tf->tf_eflags = context.sc_eflags; - tf->tf_esp = context.sc_esp_at_signal; - tf->tf_ss = context.sc_ss; + tf->tf_edi = context.sc_edi; + tf->tf_esi = context.sc_esi; + tf->tf_ebp = context.sc_ebp; + tf->tf_ebx = context.sc_ebx; + tf->tf_edx = context.sc_edx; + tf->tf_ecx = context.sc_ecx; + tf->tf_eax = context.sc_eax; + tf->tf_eip = context.sc_eip; + tf->tf_cs = context.sc_cs; + tf->tf_esp = context.sc_esp_at_signal; + tf->tf_ss = context.sc_ss; + + p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK; + p->p_sigmask = context.sc_mask & ~sigcantmask; return (EJUSTRETURN); } @@ -503,9 +507,7 @@ linux_machdepioctl(p, v, retval) break; #endif default: -#ifdef DIAGNOSTIC printf("linux_machdepioctl: invalid ioctl %08x\n", com); -#endif return EINVAL; } SCARG(&bia, com) = com; |