git: 10e697949ada - stable/13 - amd64: Avoid enabling interrupts when handling kernel mode prot faults

Mark Johnston markj at FreeBSD.org
Mon Jun 7 01:03:13 UTC 2021


The branch stable/13 has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=10e697949adaf82070c67f375712b73c099e2017

commit 10e697949adaf82070c67f375712b73c099e2017
Author:     Mark Johnston <markj at FreeBSD.org>
AuthorDate: 2021-05-31 22:49:33 +0000
Commit:     Mark Johnston <markj at FreeBSD.org>
CommitDate: 2021-06-07 01:02:27 +0000

    amd64: Avoid enabling interrupts when handling kernel mode prot faults
    
    When PTI is enabled, we may have been on the trampoline stack when iret
    faults.  So, we have to switch back to the regular stack before
    re-entering trap().
    
    trap() has the somewhat strange behaviour of re-enabling interrupts when
    handling certain kernel-mode execeptions.  In particular, it was doing
    this for exceptions raised during execution of iret.  When switching
    away from the trampoline stack, however, the thread must not be migrated
    to a different CPU.  Fix the problem by simply leaving interrupts
    disabled during the window.
    
    Reported by:    syzbot+6cfa544fd86ad4647ffc at syzkaller.appspotmail.com
    Reported by:    syzbot+cfdfc9e5a8f28f11a7f5 at syzkaller.appspotmail.com
    Reviewed by:    kib
    Sponsored by:   The FreeBSD Foundation
    
    (cherry picked from commit 4a59cbc1253266ea70d6fa43b1a7c77cc33ec6cd)
---
 sys/amd64/amd64/trap.c | 40 ++++++++++++++++++++++++----------------
 1 file changed, 24 insertions(+), 16 deletions(-)

diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c
index 4ce31ce47a45..cc0b8fcf6c17 100644
--- a/sys/amd64/amd64/trap.c
+++ b/sys/amd64/amd64/trap.c
@@ -236,25 +236,31 @@ trap(struct trapframe *frame)
 		 * interrupts disabled until they are accidentally
 		 * enabled later.
 		 */
-		if (TRAPF_USERMODE(frame))
+		if (TRAPF_USERMODE(frame)) {
 			uprintf(
 			    "pid %ld (%s): trap %d with interrupts disabled\n",
 			    (long)curproc->p_pid, curthread->td_name, type);
-		else if (type != T_NMI && type != T_BPTFLT &&
-		    type != T_TRCTRAP) {
-			/*
-			 * XXX not quite right, since this may be for a
-			 * multiple fault in user mode.
-			 */
-			printf("kernel trap %d with interrupts disabled\n",
-			    type);
-
-			/*
-			 * We shouldn't enable interrupts while holding a
-			 * spin lock.
-			 */
-			if (td->td_md.md_spinlock_count == 0)
-				enable_intr();
+		} else {
+			switch (type) {
+			case T_NMI:
+			case T_BPTFLT:
+			case T_TRCTRAP:
+			case T_PROTFLT:
+			case T_SEGNPFLT:
+			case T_STKFLT:
+				break;
+			default:
+				printf(
+				    "kernel trap %d with interrupts disabled\n",
+				    type);
+
+				/*
+				 * We shouldn't enable interrupts while holding a
+				 * spin lock.
+				 */
+				if (td->td_md.md_spinlock_count == 0)
+					enable_intr();
+			}
 		}
 	}
 
@@ -444,6 +450,8 @@ 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) {
 				frame->tf_rip = (long)doreti_iret_fault;
 				if ((PCPU_GET(curpmap)->pm_ucr3 !=


More information about the dev-commits-src-all mailing list