git: a47fd6929fe2 - main - aarch64: Fix get_fpcontext32() to work on non-curthread.

From: John Baldwin <jhb_at_FreeBSD.org>
Date: Wed, 23 Mar 2022 20:33:18 UTC
The branch main has been updated by jhb:

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

commit a47fd6929fe2008e28e3e697e449fb0904258d04
Author:     John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2022-03-23 20:33:06 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2022-03-23 20:33:06 +0000

    aarch64: Fix get_fpcontext32() to work on non-curthread.
    
    Similar to fill_fpregs(), only invoke vfp_save_state() for curthread.
    
    While here, zero the buffer if FP hasn't been started to avoid leaking
    kernel stack memory.
    
    Reviewed by:    andrew, markj
    Sponsored by:   University of Cambridge, Google, Inc.
    Differential Revision:  https://reviews.freebsd.org/D34525
---
 sys/arm64/arm64/freebsd32_machdep.c | 30 +++++++++++++++++-------------
 1 file changed, 17 insertions(+), 13 deletions(-)

diff --git a/sys/arm64/arm64/freebsd32_machdep.c b/sys/arm64/arm64/freebsd32_machdep.c
index 98f0bf784326..c4bb515becf7 100644
--- a/sys/arm64/arm64/freebsd32_machdep.c
+++ b/sys/arm64/arm64/freebsd32_machdep.c
@@ -130,29 +130,33 @@ freebsd32_sysarch(struct thread *td, struct freebsd32_sysarch_args *uap)
 static void
 get_fpcontext32(struct thread *td, mcontext32_vfp_t *mcp)
 {
-	struct pcb *curpcb;
+	struct pcb *pcb;
 	int i;
 
-	critical_enter();
-	curpcb = curthread->td_pcb;
+	KASSERT(td == curthread || TD_IS_SUSPENDED(td) ||
+	    P_SHOULDSTOP(td->td_proc),
+	    ("not suspended thread %p", td));
+
+	memset(mcp, 0, sizeof(*mcp));
+	pcb = td->td_pcb;
 
-	if ((curpcb->pcb_fpflags & PCB_FP_STARTED) != 0) {
+	if ((pcb->pcb_fpflags & PCB_FP_STARTED) != 0) {
 		/*
 		 * If we have just been running VFP instructions we will
 		 * need to save the state to memcpy it below.
 		 */
-		vfp_save_state(td, curpcb);
+		if (td == curthread)
+			vfp_save_state(td, pcb);
 
-		KASSERT(curpcb->pcb_fpusaved == &curpcb->pcb_fpustate,
-				("Called get_fpcontext while the kernel is using the VFP"));
-		KASSERT((curpcb->pcb_fpflags & ~PCB_FP_USERMASK) == 0,
-				("Non-userspace FPU flags set in get_fpcontext"));
+		KASSERT(pcb->pcb_fpusaved == &pcb->pcb_fpustate,
+		    ("Called get_fpcontext32 while the kernel is using the VFP"));
+		KASSERT((pcb->pcb_fpflags & ~PCB_FP_USERMASK) == 0,
+		    ("Non-userspace FPU flags set in get_fpcontext32"));
 		for (i = 0; i < 32; i++)
-			mcp->mcv_reg[i] = (uint64_t)curpcb->pcb_fpustate.vfp_regs[i];
-		mcp->mcv_fpscr = VFP_FPSCR_FROM_SRCR(curpcb->pcb_fpustate.vfp_fpcr,
-				curpcb->pcb_fpustate.vfp_fpsr);
+			mcp->mcv_reg[i] = (uint64_t)pcb->pcb_fpustate.vfp_regs[i];
+		mcp->mcv_fpscr = VFP_FPSCR_FROM_SRCR(pcb->pcb_fpustate.vfp_fpcr,
+		    pcb->pcb_fpustate.vfp_fpsr);
 	}
- critical_exit();
 }
 
 static void