Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 1 Jun 2021 23:51:08 GMT
From:      Mark Johnston <markj@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 6cda62755612 - main - amd64: Relax the assertion added in commit 4a59cbc12
Message-ID:  <202106012351.151Np83P020574@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=6cda62755612d706f30a99f70ff13ffa0f3f2422

commit 6cda62755612d706f30a99f70ff13ffa0f3f2422
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2021-06-01 23:38:09 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2021-06-01 23:38:09 +0000

    amd64: Relax the assertion added in commit 4a59cbc12
    
    We only need to ensure that interrupts are disabled when handling a
    fault from iret.  Otherwise it's possible to trigger the assertion
    legitimately, e.g., by copying in from an invalid address.
    
    Fixes:          4a59cbc12
    Reported by:    pho
    Reviewed by:    kib
    MFC after:      1 week
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D30594
---
 sys/amd64/amd64/trap.c | 70 ++++++++++++++++++++++++++++++++------------------
 1 file changed, 45 insertions(+), 25 deletions(-)

diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c
index cc0b8fcf6c17..e67e188bb4fd 100644
--- a/sys/amd64/amd64/trap.c
+++ b/sys/amd64/amd64/trap.c
@@ -172,6 +172,39 @@ SYSCTL_INT(_machdep, OID_AUTO, nmi_flush_l1d_sw, CTLFLAG_RWTUN,
     &nmi_flush_l1d_sw, 0,
     "Flush L1 Data Cache on NMI exit, software bhyve L1TF mitigation assist");
 
+/*
+ * Table of handlers for various segment load faults.
+ */
+static const struct {
+	uintptr_t	faddr;
+	uintptr_t	fhandler;
+} sfhandlers[] = {
+	{
+		.faddr = (uintptr_t)ld_ds,
+		.fhandler = (uintptr_t)ds_load_fault,
+	},
+	{
+		.faddr = (uintptr_t)ld_es,
+		.fhandler = (uintptr_t)es_load_fault,
+	},
+	{
+		.faddr = (uintptr_t)ld_fs,
+		.fhandler = (uintptr_t)fs_load_fault,
+	},
+	{
+		.faddr = (uintptr_t)ld_gs,
+		.fhandler = (uintptr_t)gs_load_fault,
+	},
+	{
+		.faddr = (uintptr_t)ld_gsbase,
+		.fhandler = (uintptr_t)gsbase_load_fault
+	},
+	{
+		.faddr = (uintptr_t)ld_fsbase,
+		.fhandler = (uintptr_t)fsbase_load_fault,
+	},
+};
+
 /*
  * Exception, fault, and trap interface to the FreeBSD kernel.
  * This common code is called from assembly language IDT gate entry
@@ -186,6 +219,7 @@ trap(struct trapframe *frame)
 	struct thread *td;
 	struct proc *p;
 	register_t addr, dr6;
+	size_t i;
 	int pf, signo, ucode;
 	u_int type;
 
@@ -450,9 +484,9 @@ trap(struct trapframe *frame)
 			 * Magic '5' is the number of qwords occupied by
 			 * the hardware trap frame.
 			 */
-			KASSERT((read_rflags() & PSL_I) == 0,
-			    ("interrupts enabled"));
 			if (frame->tf_rip == (long)doreti_iret) {
+				KASSERT((read_rflags() & PSL_I) == 0,
+				    ("interrupts enabled"));
 				frame->tf_rip = (long)doreti_iret_fault;
 				if ((PCPU_GET(curpmap)->pm_ucr3 !=
 				    PMAP_NO_CR3) &&
@@ -463,30 +497,16 @@ trap(struct trapframe *frame)
 				}
 				return;
 			}
-			if (frame->tf_rip == (long)ld_ds) {
-				frame->tf_rip = (long)ds_load_fault;
-				return;
-			}
-			if (frame->tf_rip == (long)ld_es) {
-				frame->tf_rip = (long)es_load_fault;
-				return;
-			}
-			if (frame->tf_rip == (long)ld_fs) {
-				frame->tf_rip = (long)fs_load_fault;
-				return;
-			}
-			if (frame->tf_rip == (long)ld_gs) {
-				frame->tf_rip = (long)gs_load_fault;
-				return;
-			}
-			if (frame->tf_rip == (long)ld_gsbase) {
-				frame->tf_rip = (long)gsbase_load_fault;
-				return;
-			}
-			if (frame->tf_rip == (long)ld_fsbase) {
-				frame->tf_rip = (long)fsbase_load_fault;
-				return;
+
+			for (i = 0; i < nitems(sfhandlers); i++) {
+				if (frame->tf_rip == sfhandlers[i].faddr) {
+					KASSERT((read_rflags() & PSL_I) == 0,
+					    ("interrupts enabled"));
+					frame->tf_rip = sfhandlers[i].fhandler;
+					return;
+				}
 			}
+
 			if (curpcb->pcb_onfault != NULL) {
 				frame->tf_rip = (long)curpcb->pcb_onfault;
 				return;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202106012351.151Np83P020574>