diff options
author | Konstantin Belousov <kib@FreeBSD.org> | 2022-08-19 01:26:37 +0000 |
---|---|---|
committer | Konstantin Belousov <kib@FreeBSD.org> | 2022-08-24 19:11:57 +0000 |
commit | dc4a2d1d0e838579f21d9d1fef8655f902f06ab2 (patch) | |
tree | 2cc5568d1a0b2361be5d281e9a96e907546ebd98 | |
parent | a03e4799e76bdfe432f560d96448895ba6ee6133 (diff) | |
download | src-dc4a2d1d0e838579f21d9d1fef8655f902f06ab2.tar.gz src-dc4a2d1d0e838579f21d9d1fef8655f902f06ab2.zip |
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
-rw-r--r-- | sys/i386/i386/exec_machdep.c | 3 |
1 files changed, 3 insertions, 0 deletions
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) |