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
This commit is contained in:
parent
8790fe3058
commit
4a59cbc125
@ -236,17 +236,22 @@ trap(struct trapframe *frame)
|
|||||||
* interrupts disabled until they are accidentally
|
* interrupts disabled until they are accidentally
|
||||||
* enabled later.
|
* enabled later.
|
||||||
*/
|
*/
|
||||||
if (TRAPF_USERMODE(frame))
|
if (TRAPF_USERMODE(frame)) {
|
||||||
uprintf(
|
uprintf(
|
||||||
"pid %ld (%s): trap %d with interrupts disabled\n",
|
"pid %ld (%s): trap %d with interrupts disabled\n",
|
||||||
(long)curproc->p_pid, curthread->td_name, type);
|
(long)curproc->p_pid, curthread->td_name, type);
|
||||||
else if (type != T_NMI && type != T_BPTFLT &&
|
} else {
|
||||||
type != T_TRCTRAP) {
|
switch (type) {
|
||||||
/*
|
case T_NMI:
|
||||||
* XXX not quite right, since this may be for a
|
case T_BPTFLT:
|
||||||
* multiple fault in user mode.
|
case T_TRCTRAP:
|
||||||
*/
|
case T_PROTFLT:
|
||||||
printf("kernel trap %d with interrupts disabled\n",
|
case T_SEGNPFLT:
|
||||||
|
case T_STKFLT:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf(
|
||||||
|
"kernel trap %d with interrupts disabled\n",
|
||||||
type);
|
type);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -257,6 +262,7 @@ trap(struct trapframe *frame)
|
|||||||
enable_intr();
|
enable_intr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (TRAPF_USERMODE(frame)) {
|
if (TRAPF_USERMODE(frame)) {
|
||||||
/* user trap */
|
/* user trap */
|
||||||
@ -444,6 +450,8 @@ trap(struct trapframe *frame)
|
|||||||
* Magic '5' is the number of qwords occupied by
|
* Magic '5' is the number of qwords occupied by
|
||||||
* the hardware trap frame.
|
* the hardware trap frame.
|
||||||
*/
|
*/
|
||||||
|
KASSERT((read_rflags() & PSL_I) == 0,
|
||||||
|
("interrupts enabled"));
|
||||||
if (frame->tf_rip == (long)doreti_iret) {
|
if (frame->tf_rip == (long)doreti_iret) {
|
||||||
frame->tf_rip = (long)doreti_iret_fault;
|
frame->tf_rip = (long)doreti_iret_fault;
|
||||||
if ((PCPU_GET(curpmap)->pm_ucr3 !=
|
if ((PCPU_GET(curpmap)->pm_ucr3 !=
|
||||||
|
Loading…
x
Reference in New Issue
Block a user