git: dc4a2d1d0e83 - main - i386: do not allow userspace to set tf_trapno on sigreturn(2)

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Wed, 24 Aug 2022 19:25:11 UTC
The branch main has been updated by kib:

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

commit dc4a2d1d0e838579f21d9d1fef8655f902f06ab2
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2022-08-19 01:26:37 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2022-08-24 19:11:57 +0000

    i386: do not allow userspace to set tf_trapno on sigreturn(2)
    
    tf_trapno is checked on return from interrupt/exception to determine if
    special handling is needed for switching address space.  This is due to
    the possibility of NMI/MCHK/DBG to occur at arbitrary place in kernel,
    where both address space and stack used could be transient.  Kernel
    saves current %cr3 in tf_err for such events, to restore on return.
    
    If user is able to set tf_trapno, it can trigger that special handling,
    and since tf_err is also user-controlled by sigreturn(2), the result is
    undefined.
    
    PR:     265889
    Reported by:    lwhsu
    Reviewed by:    jhb
    Tested by:      pho
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D36302
---
 sys/i386/i386/exec_machdep.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/sys/i386/i386/exec_machdep.c b/sys/i386/i386/exec_machdep.c
index 29c06ff86ca8..45921193ec94 100644
--- a/sys/i386/i386/exec_machdep.c
+++ b/sys/i386/i386/exec_machdep.c
@@ -640,6 +640,7 @@ osigreturn(struct thread *td, struct osigreturn_args *uap)
 	regs->tf_esp = scp->sc_sp;
 	regs->tf_eip = scp->sc_pc;
 	regs->tf_eflags = eflags;
+	regs->tf_trapno = T_RESERVED;
 
 #if defined(COMPAT_43)
 	if (scp->sc_onstack & 1)
@@ -739,6 +740,7 @@ freebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap)
 
 		bcopy(&ucp->uc_mcontext.mc_fs, regs, sizeof(*regs));
 	}
+	regs->tf_trapno = T_RESERVED;
 
 #if defined(COMPAT_43)
 	if (ucp->uc_mcontext.mc_onstack & 1)
@@ -873,6 +875,7 @@ sys_sigreturn(struct thread *td, struct sigreturn_args *uap)
 			return (ret);
 		bcopy(&ucp->uc_mcontext.mc_fs, regs, sizeof(*regs));
 	}
+	regs->tf_trapno = T_RESERVED;
 
 #if defined(COMPAT_43)
 	if (ucp->uc_mcontext.mc_onstack & 1)