Module Name:    src
Committed By:   martin
Date:           Thu Apr 12 13:08:16 UTC 2018

Modified Files:
        src/sys/arch/x86/x86 [netbsd-8]: dbregs.c

Log Message:
Pull up following revision(s) (requested by kamil in ticket #712):

        sys/arch/x86/x86/dbregs.c: revision 1.7-1.9

Fix the check, should be >=.

Hum, don't let userland set bit 13, because this can crash the kernel.

Add paranoid code to X86 Debug Registers

Reset certain bits in DR6 and DR7 in x86_dbregs_setup_initdbstate().
Reset X86_BREAKPOINT_CONDITION_DETECTED in DR6.
Reset X86_DR7_GENERAL_DETECT_ENABLE in DR7.

It's allowed by devices or software before the kernel boot, to
use these registers for their own purposes. Handle this paranoid case
explicitly setting the mentioned bits to zero.

Sponsored by <The NetBSD Foundation>


To generate a diff of this commit:
cvs rdiff -u -r1.6 -r1.6.6.1 src/sys/arch/x86/x86/dbregs.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/x86/x86/dbregs.c
diff -u src/sys/arch/x86/x86/dbregs.c:1.6 src/sys/arch/x86/x86/dbregs.c:1.6.6.1
--- src/sys/arch/x86/x86/dbregs.c:1.6	Thu Feb 23 12:01:12 2017
+++ src/sys/arch/x86/x86/dbregs.c	Thu Apr 12 13:08:16 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: dbregs.c,v 1.6 2017/02/23 12:01:12 martin Exp $	*/
+/*	$NetBSD: dbregs.c,v 1.6.6.1 2018/04/12 13:08:16 martin Exp $	*/
 
 /*-
  * Copyright (c) 2016 The NetBSD Foundation, Inc.
@@ -43,6 +43,18 @@ extern struct pool x86_dbregspl;
 
 static struct dbreg initdbstate;
 
+#define X86_BREAKPOINT_CONDITION_DETECTED	( \
+	X86_DR6_DR0_BREAKPOINT_CONDITION_DETECTED | \
+	X86_DR6_DR1_BREAKPOINT_CONDITION_DETECTED | \
+	X86_DR6_DR2_BREAKPOINT_CONDITION_DETECTED | \
+	X86_DR6_DR3_BREAKPOINT_CONDITION_DETECTED )
+
+#define X86_GLOBAL_BREAKPOINT	( \
+	X86_DR7_GLOBAL_DR0_BREAKPOINT | \
+	X86_DR7_GLOBAL_DR1_BREAKPOINT | \
+	X86_DR7_GLOBAL_DR2_BREAKPOINT | \
+	X86_DR7_GLOBAL_DR3_BREAKPOINT )
+
 void
 x86_dbregs_setup_initdbstate(void)
 {
@@ -56,19 +68,17 @@ x86_dbregs_setup_initdbstate(void)
 	initdbstate.dr[6] = rdr6();
 	initdbstate.dr[7] = rdr7();
 	/* DR8-DR15 are reserved - skip */
-}
 
-#define X86_BREAKPOINT_CONDITION_DETECTED	( \
-	X86_DR6_DR0_BREAKPOINT_CONDITION_DETECTED | \
-	X86_DR6_DR1_BREAKPOINT_CONDITION_DETECTED | \
-	X86_DR6_DR2_BREAKPOINT_CONDITION_DETECTED | \
-	X86_DR6_DR3_BREAKPOINT_CONDITION_DETECTED )
+	/*
+	 * Paranoid case.
+	 *
+	 * Explicitly reset some bits just in case they could be
+	 * set by brave software/hardware before the kernel boot.
+	 */
+	initdbstate.dr[6] &= ~X86_BREAKPOINT_CONDITION_DETECTED;
 
-#define X86_GLOBAL_BREAKPOINT	( \
-	X86_DR7_GLOBAL_DR0_BREAKPOINT | \
-	X86_DR7_GLOBAL_DR1_BREAKPOINT | \
-	X86_DR7_GLOBAL_DR2_BREAKPOINT | \
-	X86_DR7_GLOBAL_DR3_BREAKPOINT )
+	initdbstate.dr[7] &= ~X86_DR7_GENERAL_DETECT_ENABLE;
+}
 
 void
 x86_dbregs_clear(struct lwp *l)
@@ -188,14 +198,14 @@ x86_dbregs_validate(const struct dbreg *
 
 	/* Check that DR0-DR3 contain user-space address */
 	for (i = 0; i < X86_DBREGS; i++)
-		if (regs->dr[i] > (vaddr_t)VM_MAXUSER_ADDRESS)
+		if (regs->dr[i] >= (vaddr_t)VM_MAXUSER_ADDRESS)
 			return EINVAL;
 
+	if (regs->dr[7] & X86_DR7_GENERAL_DETECT_ENABLE)
+		return EINVAL;
+
 	/*
 	 * Skip checks for reserved registers (DR4-DR5, DR8-DR15).
-	 *
-	 * Don't validate DR6-DR7 as some bits are set by hardware and a user
-	 * cannot overwrite them.
 	 */
 
 	return 0;

Reply via email to