]> xenbits.xensource.com Git - people/royger/freebsd.git/commitdiff
amd64: Relax the assertion added in commit 4a59cbc12
authorMark Johnston <markj@FreeBSD.org>
Tue, 1 Jun 2021 23:38:09 +0000 (19:38 -0400)
committerMark Johnston <markj@FreeBSD.org>
Tue, 1 Jun 2021 23:38:09 +0000 (19:38 -0400)
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

index cc0b8fcf6c1703f1ac735b42a6edc1acf25ff05c..e67e188bb4fd9165057c1203a3a655fe9a8a1497 100644 (file)
@@ -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;