svn commit: r357344 - head/sys/riscv/riscv
John Baldwin
jhb at FreeBSD.org
Fri Jan 31 19:00:48 UTC 2020
Author: jhb
Date: Fri Jan 31 19:00:48 2020
New Revision: 357344
URL: https://svnweb.freebsd.org/changeset/base/357344
Log:
Add stricter checks on user changes to SSTATUS.
Rather than trying to blacklist which bits userland can't write to via
sigreturn() or setcontext(), only permit changes to whitelisted bits.
- Permit arbitrary writes to bits in the user-writable USTATUS
register that shadows SSTATUS.
- Ignore changes in write-only bits maintained by the CPU.
- Ignore the user-supplied value of the FS field used to track
floating point state and instead set it to a value matching the
actions taken by set_fpcontext().
Discussed with: mhorne
MFC after: 2 weeks
Sponsored by: DARPA
Differential Revision: https://reviews.freebsd.org/D23338
Modified:
head/sys/riscv/riscv/machdep.c
Modified: head/sys/riscv/riscv/machdep.c
==============================================================================
--- head/sys/riscv/riscv/machdep.c Fri Jan 31 18:55:21 2020 (r357343)
+++ head/sys/riscv/riscv/machdep.c Fri Jan 31 19:00:48 2020 (r357344)
@@ -368,11 +368,16 @@ set_mcontext(struct thread *td, mcontext_t *mcp)
tf = td->td_frame;
/*
- * Make sure the processor mode has not been tampered with and
- * interrupts have not been disabled.
- * Supervisor interrupts in user mode are always enabled.
+ * Permit changes to the USTATUS bits of SSTATUS.
+ *
+ * Ignore writes to read-only bits (SD, XS).
+ *
+ * Ignore writes to the FS field as set_fpcontext() will set
+ * it explicitly.
*/
- if ((mcp->mc_gpregs.gp_sstatus & SSTATUS_SPP) != 0)
+ if (((mcp->mc_gpregs.gp_sstatus ^ tf->tf_sstatus) &
+ ~(SSTATUS_SD | SSTATUS_XS_MASK | SSTATUS_FS_MASK | SSTATUS_UPIE |
+ SSTATUS_UIE)) != 0)
return (EINVAL);
memcpy(tf->tf_t, mcp->mc_gpregs.gp_t, sizeof(tf->tf_t));
@@ -426,7 +431,12 @@ set_fpcontext(struct thread *td, mcontext_t *mcp)
{
#ifdef FPE
struct pcb *curpcb;
+#endif
+ td->td_frame->tf_sstatus &= ~SSTATUS_FS_MASK;
+ td->td_frame->tf_sstatus |= SSTATUS_FS_OFF;
+
+#ifdef FPE
critical_enter();
if ((mcp->mc_flags & _MC_FP_VALID) != 0) {
@@ -436,6 +446,7 @@ set_fpcontext(struct thread *td, mcontext_t *mcp)
sizeof(mcp->mc_fpregs));
curpcb->pcb_fcsr = mcp->mc_fpregs.fp_fcsr;
curpcb->pcb_fpflags = mcp->mc_fpregs.fp_flags & PCB_FP_USERMASK;
+ td->td_frame->tf_sstatus |= SSTATUS_FS_CLEAN;
}
critical_exit();
More information about the svn-src-all
mailing list