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
This commit is contained in:
Konstantin Belousov 2022-08-19 04:26:37 +03:00
parent a03e4799e7
commit dc4a2d1d0e

View File

@ -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)