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