From owner-dev-commits-src-all@freebsd.org Mon May 31 23:09:48 2021 Return-Path: Delivered-To: dev-commits-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 91B206325DE; Mon, 31 May 2021 23:09:48 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4Fv9wr3jsnz3PVb; Mon, 31 May 2021 23:09:48 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 5CF4818E41; Mon, 31 May 2021 23:09:48 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 14VN9m1Y040148; Mon, 31 May 2021 23:09:48 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 14VN9m67040147; Mon, 31 May 2021 23:09:48 GMT (envelope-from git) Date: Mon, 31 May 2021 23:09:48 GMT Message-Id: <202105312309.14VN9m67040147@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Mark Johnston Subject: git: 4a59cbc12532 - main - amd64: Avoid enabling interrupts when handling kernel mode prot faults MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: markj X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 4a59cbc1253266ea70d6fa43b1a7c77cc33ec6cd Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-all@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commit messages for all branches of the src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 31 May 2021 23:09:48 -0000 The branch main has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=4a59cbc1253266ea70d6fa43b1a7c77cc33ec6cd commit 4a59cbc1253266ea70d6fa43b1a7c77cc33ec6cd Author: Mark Johnston AuthorDate: 2021-05-31 22:49:33 +0000 Commit: Mark Johnston CommitDate: 2021-05-31 22:49:33 +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@syzkaller.appspotmail.com Reported by: syzbot+cfdfc9e5a8f28f11a7f5@syzkaller.appspotmail.com Reviewed by: kib MFC after: 1 week Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D30578 --- 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 !=