Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/netbsd-8]: src/sys Pull up following revision(s) (requested by maxv):
details: https://anonhg.NetBSD.org/src/rev/9bdeb15ad991
branches: netbsd-8
changeset: 852322:9bdeb15ad991
user: martin <martin%NetBSD.org@localhost>
date: Fri Apr 05 07:48:05 2019 +0000
description:
Pull up following revision(s) (requested by maxv):
sys/arch/amd64/amd64/netbsd32_machdep.c: revision 1.120
sys/compat/linux/arch/amd64/linux_machdep.c: revision 1.57
sys/compat/linux32/arch/amd64/linux32_machdep.c: revision 1.44
sys/arch/amd64/amd64/machdep.c: revision 1.328
sys/arch/amd64/amd64/machdep.c: revision 1.329
Fix a tiny race in setregs and linux_setregs. Between the moment we set
pcb_flags to zero, and the moment cpu_segregs64_zero resets pcb_gs, we may
be preempted.
If this happens, and if the calling LWP was a 32bit thread, when switching
back to that LWP, the context switcher sees that PCB_COMPAT32 is not set in
pcb_flags and tries to perform a 64bit context switch; but pcb_gs contains
a 32bit GDT descriptor, and not a 64bit GS.base value. The wrmsr therefore
faults because the value is non-canonical, and this fault is fatal.
Rearrange the code so that the update of pcb_flags and pcb_gs/pcb_fs is non
interruptible. This fixes the problem, tested with a reproducer (which
therefore doesn't work anymore).
Likely fixes PR/53993.
Disable preemption when setting PCB_COMPAT32, to prevent a context switch
before cpu_fsgs_reload() finishes, otherwise we write garbage in the GDT.
On NetBSD-current it is harmless, however in NetBSD-8 it might cause
panics, because NetBSD-8 uses the old SegRegs model and under this model
we reload %fs and %gs during switches.
diffstat:
sys/arch/amd64/amd64/machdep.c | 12 +++++++-----
sys/arch/amd64/amd64/netbsd32_machdep.c | 16 +++++++++-------
sys/compat/linux/arch/amd64/linux_machdep.c | 11 ++++++-----
sys/compat/linux32/arch/amd64/linux32_machdep.c | 14 ++++++++------
4 files changed, 30 insertions(+), 23 deletions(-)
diffs (179 lines):
diff -r 223ec6a3ad99 -r 9bdeb15ad991 sys/arch/amd64/amd64/machdep.c
--- a/sys/arch/amd64/amd64/machdep.c Mon Apr 01 12:36:44 2019 +0000
+++ b/sys/arch/amd64/amd64/machdep.c Fri Apr 05 07:48:05 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: machdep.c,v 1.255.6.8 2018/11/29 08:51:01 martin Exp $ */
+/* $NetBSD: machdep.c,v 1.255.6.9 2019/04/05 07:48:05 martin Exp $ */
/*-
* Copyright (c) 1996, 1997, 1998, 2000, 2006, 2007, 2008, 2011
@@ -111,7 +111,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.255.6.8 2018/11/29 08:51:01 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.255.6.9 2019/04/05 07:48:05 martin Exp $");
/* #define XENDEBUG_LOW */
@@ -1350,20 +1350,22 @@
fpu_save_area_clear(l, pack->ep_osversion >= 699002600
? __NetBSD_NPXCW__ : __NetBSD_COMPAT_NPXCW__);
- pcb->pcb_flags = 0;
+
if (pcb->pcb_dbregs != NULL) {
pool_put(&x86_dbregspl, pcb->pcb_dbregs);
pcb->pcb_dbregs = NULL;
}
+ kpreempt_disable();
+ pcb->pcb_flags = 0;
l->l_proc->p_flag &= ~PK_32;
-
l->l_md.md_flags = MDL_IRET;
+ cpu_fsgs_zero(l);
+ kpreempt_enable();
tf = l->l_md.md_regs;
tf->tf_ds = LSEL(LUDATA_SEL, SEL_UPL);
tf->tf_es = LSEL(LUDATA_SEL, SEL_UPL);
- cpu_fsgs_zero(l);
tf->tf_rdi = 0;
tf->tf_rsi = 0;
tf->tf_rbp = 0;
diff -r 223ec6a3ad99 -r 9bdeb15ad991 sys/arch/amd64/amd64/netbsd32_machdep.c
--- a/sys/arch/amd64/amd64/netbsd32_machdep.c Mon Apr 01 12:36:44 2019 +0000
+++ b/sys/arch/amd64/amd64/netbsd32_machdep.c Fri Apr 05 07:48:05 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: netbsd32_machdep.c,v 1.105.2.2 2019/01/27 18:43:08 martin Exp $ */
+/* $NetBSD: netbsd32_machdep.c,v 1.105.2.3 2019/04/05 07:48:05 martin Exp $ */
/*
* Copyright (c) 2001 Wasabi Systems, Inc.
@@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.105.2.2 2019/01/27 18:43:08 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.105.2.3 2019/04/05 07:48:05 martin Exp $");
#ifdef _KERNEL_OPT
#include "opt_compat_netbsd.h"
@@ -132,9 +132,6 @@
netbsd32_adjust_limits(p);
- l->l_md.md_flags |= MDL_COMPAT32; /* Force iret not sysret */
- pcb->pcb_flags = PCB_COMPAT32;
-
fpu_save_area_clear(l, pack->ep_osversion >= 699002600
? __NetBSD_NPXCW__ : __NetBSD_COMPAT_NPXCW__);
@@ -143,13 +140,18 @@
pcb->pcb_dbregs = NULL;
}
+ kpreempt_disable();
+ pcb->pcb_flags = PCB_COMPAT32;
p->p_flag |= PK_32;
+ l->l_md.md_flags = MDL_COMPAT32; /* force iret not sysret */
+ cpu_fsgs_zero(l);
+ cpu_fsgs_reload(l, LSEL(LUDATA32_SEL, SEL_UPL),
+ LSEL(LUDATA32_SEL, SEL_UPL));
+ kpreempt_enable();
tf = l->l_md.md_regs;
tf->tf_ds = LSEL(LUDATA32_SEL, SEL_UPL);
tf->tf_es = LSEL(LUDATA32_SEL, SEL_UPL);
- cpu_fsgs_zero(l);
- cpu_fsgs_reload(l, tf->tf_ds, tf->tf_es);
tf->tf_rdi = 0;
tf->tf_rsi = 0;
tf->tf_rbp = 0;
diff -r 223ec6a3ad99 -r 9bdeb15ad991 sys/compat/linux/arch/amd64/linux_machdep.c
--- a/sys/compat/linux/arch/amd64/linux_machdep.c Mon Apr 01 12:36:44 2019 +0000
+++ b/sys/compat/linux/arch/amd64/linux_machdep.c Fri Apr 05 07:48:05 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: linux_machdep.c,v 1.51.6.1 2017/09/04 20:41:28 snj Exp $ */
+/* $NetBSD: linux_machdep.c,v 1.51.6.2 2019/04/05 07:48:05 martin Exp $ */
/*-
* Copyright (c) 2005 Emmanuel Dreyfus, all rights reserved.
@@ -33,7 +33,7 @@
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.51.6.1 2017/09/04 20:41:28 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.51.6.2 2019/04/05 07:48:05 martin Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -89,11 +89,13 @@
#endif
fpu_save_area_clear(l, __NetBSD_NPXCW__);
+
+ kpreempt_disable();
pcb->pcb_flags = 0;
-
l->l_proc->p_flag &= ~PK_32;
-
l->l_md.md_flags = MDL_IRET;
+ cpu_fsgs_zero(l);
+ kpreempt_enable();
tf = l->l_md.md_regs;
tf->tf_rax = 0;
@@ -118,7 +120,6 @@
tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL);
tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL);
tf->tf_es = 0;
- cpu_fsgs_zero(l);
return;
}
diff -r 223ec6a3ad99 -r 9bdeb15ad991 sys/compat/linux32/arch/amd64/linux32_machdep.c
--- a/sys/compat/linux32/arch/amd64/linux32_machdep.c Mon Apr 01 12:36:44 2019 +0000
+++ b/sys/compat/linux32/arch/amd64/linux32_machdep.c Fri Apr 05 07:48:05 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: linux32_machdep.c,v 1.38.6.1 2017/09/09 17:01:23 snj Exp $ */
+/* $NetBSD: linux32_machdep.c,v 1.38.6.2 2019/04/05 07:48:05 martin Exp $ */
/*-
* Copyright (c) 2006 Emmanuel Dreyfus, all rights reserved.
@@ -31,7 +31,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux32_machdep.c,v 1.38.6.1 2017/09/09 17:01:23 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux32_machdep.c,v 1.38.6.2 2019/04/05 07:48:05 martin Exp $");
#include <sys/param.h>
#include <sys/proc.h>
@@ -283,10 +283,14 @@
fpu_save_area_clear(l, __Linux_NPXCW__);
- l->l_md.md_flags |= MDL_COMPAT32; /* Forces iret not sysret */
+ kpreempt_disable();
pcb->pcb_flags = PCB_COMPAT32;
-
p->p_flag |= PK_32;
+ l->l_md.md_flags = MDL_COMPAT32; /* force iret not sysret */
+ cpu_fsgs_zero(l);
+ cpu_fsgs_reload(l, GSEL(GUDATA32_SEL, SEL_UPL),
+ GSEL(GUDATA32_SEL, SEL_UPL));
+ kpreempt_enable();
tf = l->l_md.md_regs;
tf->tf_rax = 0;
@@ -311,8 +315,6 @@
tf->tf_ss = GSEL(GUDATA32_SEL, SEL_UPL);
tf->tf_ds = GSEL(GUDATA32_SEL, SEL_UPL);
tf->tf_es = GSEL(GUDATA32_SEL, SEL_UPL);
- cpu_fsgs_zero(l);
- cpu_fsgs_reload(l, GSEL(GUDATA32_SEL, SEL_UPL), GSEL(GUDATA32_SEL, SEL_UPL));
}
static void
Home |
Main Index |
Thread Index |
Old Index