From nobody Sun May 24 19:33:05 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 16B793C5827 for ; Fri, 22 May 2026 09:56:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779443804; cv=none; b=L2qYUpkwLrLigf1duz2zg8sAbmwHX/KpdiLI1pQ4YW+oscpN4nZT6p95oAkDj+UriCgG65H5TBnebsisICIs6UV2XzIwBfrNoW6S0Qdn8OBKzsnLHY5QFwDGJQ2hhFnY0r7IQiil8eiJgUr+JBZ+gIVdhKIPi6ni4ct1QPAV8pA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779443804; c=relaxed/simple; bh=NudAOrXGuk31+TSU2hNrOuNcV501EprG3myB9gtNJ/8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=NTxZbWEe8FJXGD/rlKL4ppUQX1mAiBwlfHFPG1zneB/2CLvttKhenijaNaWBVF8ZubWxs4BMO3K03xMEE7Vyo3URgnaoKVTgmj1N2uhmSFTDs9/2GTfqch8l5VqTwLU8GCyQhH0dCz0DdEcg/ovyApYQSrxgUmlV8MpIza/axBE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=G1STLolY; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="G1STLolY" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B10121F00A3E; Fri, 22 May 2026 09:56:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779443802; bh=1vwc/KR3sNRx33HkEWDynGkEORnc/I5YEMTBxDajIjw=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=G1STLolYO+SraoIg1d6I+351k8nR4Q13rMfr5bSSL1x4AqnLT5ha0iFrgszQiGZ/H MU6UeI5dc4dhex9oyCck3EvAS+Dt/cFRMcjZ5YaHaZRaOPMJ+/HHdSyTw9CQouPVZV VLHgZZTCHq+4amTMELMH0JpTNHEAnhtwL/v+C04odIH51HRn8CpeTFHQnhYUuqsZ/3 uyOJz7/q1adsSs5JiyYlYlDI1EDNzRiRvK3kPYGYU9GVSyABlzvDIcGvrPsoqhgbt2 D+8CAXa9lz6GuwnUV0dDSHsS5VvgdvqlrzpTF/iwmRB4lR0XozepNe7WKo2d/q/C8V p6cuEqqiM6rWw== From: "Christophe Leroy (CS GROUP)" To: Michael Ellerman , Nicholas Piggin , Madhavan Srinivasan Cc: "Christophe Leroy (CS GROUP)" , linux-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org Subject: [PATCH v1 1/8] powerpc/signal32: Convert to scoped user access Date: Fri, 22 May 2026 11:56:01 +0200 Message-ID: <4d101e232543f54dfb4eb7a2806e180e63f6c918.1779441786.git.chleroy@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=23207; i=chleroy@kernel.org; h=from:subject:message-id; bh=NudAOrXGuk31+TSU2hNrOuNcV501EprG3myB9gtNJ/8=; b=owGbwMvMwCV2d0KB2p7V54MZT6slMWQJaNg+nHPu3btd4RmpparCZgr/LoTUN71VNH5YLbb8v NeLyYzCHaUsDGJcDLJiiizH/3PvmtH1JTV/6i59mDmsTCBDGLg4BWAiZ00Z/of8flTLv8NSMkY3 KGDVLuGphhv6l662EKqrrd0U3r2ItYXhf5XR34xf5sdZJDhLNwbue/5hHV/0dttTB7dMZ3WYosn zixUA X-Developer-Key: i=chleroy@kernel.org; a=openpgp; fpr=10FFE6F8B390DE17ACC2632368A92FEB01B8DD78 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Commit 861574d51bbd ("powerpc/uaccess: Implement masked user access") provides optimised user access by avoiding the cost of access_ok(). Convert signal32 functions to scoped user access. Scoped user access also make the code simpler. Signed-off-by: Christophe Leroy (CS GROUP) --- arch/powerpc/kernel/signal_32.c | 456 +++++++++++++++----------------- 1 file changed, 217 insertions(+), 239 deletions(-) diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_3= 2.c index 7a718ed32b27..f5d5139a1426 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c @@ -468,98 +468,98 @@ static long restore_user_regs(struct pt_regs *regs, { unsigned int save_r2 =3D 0; unsigned long msr; -#ifdef CONFIG_VSX - int i; -#endif =20 - if (!user_read_access_begin(sr, sizeof(*sr))) - return 1; - /* - * restore general registers but not including MSR or SOFTE. Also - * take care of keeping r2 (TLS) intact if not a signal - */ - if (!sig) - save_r2 =3D (unsigned int)regs->gpr[2]; - unsafe_restore_general_regs(regs, sr, failed); - set_trap_norestart(regs); - unsafe_get_user(msr, &sr->mc_gregs[PT_MSR], failed); - if (!sig) - regs->gpr[2] =3D (unsigned long) save_r2; - - /* if doing signal return, restore the previous little-endian mode */ - if (sig) - regs_set_return_msr(regs, (regs->msr & ~MSR_LE) | (msr & MSR_LE)); + scoped_user_read_access(sr, failed) { + /* + * restore general registers but not including MSR or SOFTE. Also + * take care of keeping r2 (TLS) intact if not a signal + */ + if (!sig) + save_r2 =3D (unsigned int)regs->gpr[2]; + unsafe_restore_general_regs(regs, sr, failed); + set_trap_norestart(regs); + unsafe_get_user(msr, &sr->mc_gregs[PT_MSR], failed); + if (!sig) + regs->gpr[2] =3D (unsigned long)save_r2; + + /* if doing signal return, restore the previous little-endian mode */ + if (sig) + regs_set_return_msr(regs, (regs->msr & ~MSR_LE) | (msr & MSR_LE)); =20 #ifdef CONFIG_ALTIVEC - /* - * Force the process to reload the altivec registers from - * current->thread when it next does altivec instructions - */ - regs_set_return_msr(regs, regs->msr & ~MSR_VEC); - if (msr & MSR_VEC) { - /* restore altivec registers from the stack */ - unsafe_copy_from_user(¤t->thread.vr_state, &sr->mc_vregs, - sizeof(sr->mc_vregs), failed); - current->thread.used_vr =3D true; - } else if (current->thread.used_vr) - memset(¤t->thread.vr_state, 0, - ELF_NVRREG * sizeof(vector128)); - - /* Always get VRSAVE back */ - unsafe_get_user(current->thread.vrsave, (u32 __user *)&sr->mc_vregs[32], = failed); - if (cpu_has_feature(CPU_FTR_ALTIVEC)) - mtspr(SPRN_VRSAVE, current->thread.vrsave); + /* + * Force the process to reload the altivec registers from + * current->thread when it next does altivec instructions + */ + regs_set_return_msr(regs, regs->msr & ~MSR_VEC); + if (msr & MSR_VEC) { + /* restore altivec registers from the stack */ + unsafe_copy_from_user(¤t->thread.vr_state, &sr->mc_vregs, + sizeof(sr->mc_vregs), failed); + current->thread.used_vr =3D true; + } else if (current->thread.used_vr) { + memset(¤t->thread.vr_state, 0, + ELF_NVRREG * sizeof(vector128)); + } + + /* Always get VRSAVE back */ + unsafe_get_user(current->thread.vrsave, (u32 __user *)&sr->mc_vregs[32],= failed); + if (cpu_has_feature(CPU_FTR_ALTIVEC)) + mtspr(SPRN_VRSAVE, current->thread.vrsave); #endif /* CONFIG_ALTIVEC */ - unsafe_copy_fpr_from_user(current, &sr->mc_fregs, failed); + unsafe_copy_fpr_from_user(current, &sr->mc_fregs, failed); =20 #ifdef CONFIG_VSX - /* - * Force the process to reload the VSX registers from - * current->thread when it next does VSX instruction. - */ - regs_set_return_msr(regs, regs->msr & ~MSR_VSX); - if (msr & MSR_VSX) { /* - * Restore altivec registers from the stack to a local - * buffer, then write this out to the thread_struct + * Force the process to reload the VSX registers from + * current->thread when it next does VSX instruction. */ - unsafe_copy_vsx_from_user(current, &sr->mc_vsregs, failed); - current->thread.used_vsr =3D true; - } else if (current->thread.used_vsr) - for (i =3D 0; i < 32 ; i++) - current->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] =3D 0; + regs_set_return_msr(regs, regs->msr & ~MSR_VSX); + if (msr & MSR_VSX) { + /* + * Restore altivec registers from the stack to a local + * buffer, then write this out to the thread_struct + */ + unsafe_copy_vsx_from_user(current, &sr->mc_vsregs, failed); + current->thread.used_vsr =3D true; + } else if (current->thread.used_vsr) { + int i; + + for (i =3D 0; i < 32 ; i++) + current->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] =3D 0; + } #endif /* CONFIG_VSX */ - /* - * force the process to reload the FP registers from - * current->thread when it next does FP instructions - */ - regs_set_return_msr(regs, regs->msr & ~(MSR_FP | MSR_FE0 | MSR_FE1)); + /* + * force the process to reload the FP registers from + * current->thread when it next does FP instructions + */ + regs_set_return_msr(regs, regs->msr & ~(MSR_FP | MSR_FE0 | MSR_FE1)); =20 #ifdef CONFIG_SPE - /* - * Force the process to reload the spe registers from - * current->thread when it next does spe instructions. - * Since this is user ABI, we must enforce the sizing. - */ - BUILD_BUG_ON(sizeof(current->thread.spe) !=3D ELF_NEVRREG * sizeof(u32)); - regs_set_return_msr(regs, regs->msr & ~MSR_SPE); - if (msr & MSR_SPE) { - /* restore spe registers from the stack */ - unsafe_copy_from_user(¤t->thread.spe, &sr->mc_vregs, - sizeof(current->thread.spe), failed); - current->thread.used_spe =3D true; - } else if (current->thread.used_spe) - memset(¤t->thread.spe, 0, sizeof(current->thread.spe)); - - /* Always get SPEFSCR back */ - unsafe_get_user(current->thread.spefscr, (u32 __user *)&sr->mc_vregs + EL= F_NEVRREG, failed); -#endif /* CONFIG_SPE */ + /* + * Force the process to reload the spe registers from + * current->thread when it next does spe instructions. + * Since this is user ABI, we must enforce the sizing. + */ + BUILD_BUG_ON(sizeof(current->thread.spe) !=3D ELF_NEVRREG * sizeof(u32)); + regs_set_return_msr(regs, regs->msr & ~MSR_SPE); + if (msr & MSR_SPE) { + /* restore spe registers from the stack */ + unsafe_copy_from_user(¤t->thread.spe, &sr->mc_vregs, + sizeof(current->thread.spe), failed); + current->thread.used_spe =3D true; + } else if (current->thread.used_spe) { + memset(¤t->thread.spe, 0, sizeof(current->thread.spe)); + } =20 - user_read_access_end(); + /* Always get SPEFSCR back */ + unsafe_get_user(current->thread.spefscr, + (u32 __user *)&sr->mc_vregs + ELF_NEVRREG, failed); +#endif /* CONFIG_SPE */ + } return 0; =20 failed: - user_read_access_end(); return 1; } =20 @@ -574,7 +574,6 @@ static long restore_tm_user_regs(struct pt_regs *regs, struct mcontext __user *tm_sr) { unsigned long msr, msr_hi; - int i; =20 if (tm_suspend_disabled) return 1; @@ -585,86 +584,81 @@ static long restore_tm_user_regs(struct pt_regs *regs, * TFHAR is restored from the checkpointed NIP; TEXASR and TFIAR * were set by the signal delivery. */ - if (!user_read_access_begin(sr, sizeof(*sr))) - return 1; - - unsafe_restore_general_regs(¤t->thread.ckpt_regs, sr, failed); - unsafe_get_user(current->thread.tm_tfhar, &sr->mc_gregs[PT_NIP], failed); - unsafe_get_user(msr, &sr->mc_gregs[PT_MSR], failed); + scoped_user_read_access(sr, failed) { + unsafe_restore_general_regs(¤t->thread.ckpt_regs, sr, failed); + unsafe_get_user(current->thread.tm_tfhar, &sr->mc_gregs[PT_NIP], failed); + unsafe_get_user(msr, &sr->mc_gregs[PT_MSR], failed); =20 - /* Restore the previous little-endian mode */ - regs_set_return_msr(regs, (regs->msr & ~MSR_LE) | (msr & MSR_LE)); + /* Restore the previous little-endian mode */ + regs_set_return_msr(regs, (regs->msr & ~MSR_LE) | (msr & MSR_LE)); =20 - regs_set_return_msr(regs, regs->msr & ~MSR_VEC); - if (msr & MSR_VEC) { - /* restore altivec registers from the stack */ - unsafe_copy_from_user(¤t->thread.ckvr_state, &sr->mc_vregs, - sizeof(sr->mc_vregs), failed); - current->thread.used_vr =3D true; - } else if (current->thread.used_vr) { - memset(¤t->thread.vr_state, 0, - ELF_NVRREG * sizeof(vector128)); - memset(¤t->thread.ckvr_state, 0, - ELF_NVRREG * sizeof(vector128)); - } + regs_set_return_msr(regs, regs->msr & ~MSR_VEC); + if (msr & MSR_VEC) { + /* restore altivec registers from the stack */ + unsafe_copy_from_user(¤t->thread.ckvr_state, &sr->mc_vregs, + sizeof(sr->mc_vregs), failed); + current->thread.used_vr =3D true; + } else if (current->thread.used_vr) { + memset(¤t->thread.vr_state, 0, ELF_NVRREG * sizeof(vector128)); + memset(¤t->thread.ckvr_state, 0, ELF_NVRREG * sizeof(vector128)); + } =20 - /* Always get VRSAVE back */ - unsafe_get_user(current->thread.ckvrsave, - (u32 __user *)&sr->mc_vregs[32], failed); - if (cpu_has_feature(CPU_FTR_ALTIVEC)) - mtspr(SPRN_VRSAVE, current->thread.ckvrsave); + /* Always get VRSAVE back */ + unsafe_get_user(current->thread.ckvrsave, + (u32 __user *)&sr->mc_vregs[32], failed); + if (cpu_has_feature(CPU_FTR_ALTIVEC)) + mtspr(SPRN_VRSAVE, current->thread.ckvrsave); =20 - regs_set_return_msr(regs, regs->msr & ~(MSR_FP | MSR_FE0 | MSR_FE1)); + regs_set_return_msr(regs, regs->msr & ~(MSR_FP | MSR_FE0 | MSR_FE1)); =20 - unsafe_copy_fpr_from_user(current, &sr->mc_fregs, failed); + unsafe_copy_fpr_from_user(current, &sr->mc_fregs, failed); =20 - regs_set_return_msr(regs, regs->msr & ~MSR_VSX); - if (msr & MSR_VSX) { - /* - * Restore altivec registers from the stack to a local - * buffer, then write this out to the thread_struct - */ - unsafe_copy_ckvsx_from_user(current, &sr->mc_vsregs, failed); - current->thread.used_vsr =3D true; - } else if (current->thread.used_vsr) - for (i =3D 0; i < 32 ; i++) { - current->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] =3D 0; - current->thread.ckfp_state.fpr[i][TS_VSRLOWOFFSET] =3D 0; + regs_set_return_msr(regs, regs->msr & ~MSR_VSX); + if (msr & MSR_VSX) { + /* + * Restore altivec registers from the stack to a local + * buffer, then write this out to the thread_struct + */ + unsafe_copy_ckvsx_from_user(current, &sr->mc_vsregs, failed); + current->thread.used_vsr =3D true; + } else if (current->thread.used_vsr) { + int i; + + for (i =3D 0; i < 32 ; i++) { + current->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] =3D 0; + current->thread.ckfp_state.fpr[i][TS_VSRLOWOFFSET] =3D 0; + } } + } =20 - user_read_access_end(); - - if (!user_read_access_begin(tm_sr, sizeof(*tm_sr))) - return 1; + scoped_user_read_access(tm_sr, failed) { + unsafe_restore_general_regs(regs, tm_sr, failed); =20 - unsafe_restore_general_regs(regs, tm_sr, failed); + /* restore altivec registers from the stack */ + if (msr & MSR_VEC) + unsafe_copy_from_user(¤t->thread.vr_state, &tm_sr->mc_vregs, + sizeof(sr->mc_vregs), failed); =20 - /* restore altivec registers from the stack */ - if (msr & MSR_VEC) - unsafe_copy_from_user(¤t->thread.vr_state, &tm_sr->mc_vregs, - sizeof(sr->mc_vregs), failed); + /* Always get VRSAVE back */ + unsafe_get_user(current->thread.vrsave, + (u32 __user *)&tm_sr->mc_vregs[32], failed); =20 - /* Always get VRSAVE back */ - unsafe_get_user(current->thread.vrsave, - (u32 __user *)&tm_sr->mc_vregs[32], failed); + unsafe_copy_ckfpr_from_user(current, &tm_sr->mc_fregs, failed); =20 - unsafe_copy_ckfpr_from_user(current, &tm_sr->mc_fregs, failed); + if (msr & MSR_VSX) { + /* + * Restore altivec registers from the stack to a local + * buffer, then write this out to the thread_struct + */ + unsafe_copy_vsx_from_user(current, &tm_sr->mc_vsregs, failed); + current->thread.used_vsr =3D true; + } =20 - if (msr & MSR_VSX) { - /* - * Restore altivec registers from the stack to a local - * buffer, then write this out to the thread_struct - */ - unsafe_copy_vsx_from_user(current, &tm_sr->mc_vsregs, failed); - current->thread.used_vsr =3D true; + /* Get the top half of the MSR from the user context */ + unsafe_get_user(msr_hi, &tm_sr->mc_gregs[PT_MSR], failed); + msr_hi <<=3D 32; } =20 - /* Get the top half of the MSR from the user context */ - unsafe_get_user(msr_hi, &tm_sr->mc_gregs[PT_MSR], failed); - msr_hi <<=3D 32; - - user_read_access_end(); - /* If TM bits are set to the reserved value, it's an invalid context */ if (MSR_TM_RESV(msr_hi)) return 1; @@ -712,7 +706,6 @@ static long restore_tm_user_regs(struct pt_regs *regs, return 0; =20 failed: - user_read_access_end(); return 1; } #else @@ -737,8 +730,6 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t *= oldset, struct task_struct *tsk) { struct rt_sigframe __user *frame; - struct mcontext __user *mctx; - struct mcontext __user *tm_mctx =3D NULL; unsigned long newsp =3D 0; unsigned long tramp; struct pt_regs *regs =3D tsk->thread.regs; @@ -747,52 +738,53 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t= *oldset, =20 /* Set up Signal Frame */ frame =3D get_sigframe(ksig, tsk, sizeof(*frame), 1); - mctx =3D &frame->uc.uc_mcontext; -#ifdef CONFIG_PPC_TRANSACTIONAL_MEM - tm_mctx =3D &frame->uc_transact.uc_mcontext; -#endif if (MSR_TM_ACTIVE(msr)) prepare_save_tm_user_regs(); else prepare_save_user_regs(1); =20 - if (!user_access_begin(frame, sizeof(*frame))) - goto badframe; + scoped_user_rw_access(frame, badframe) { + struct mcontext __user *mctx; + struct mcontext __user *tm_mctx =3D NULL; =20 - /* Put the siginfo & fill in most of the ucontext */ - unsafe_put_user(0, &frame->uc.uc_flags, failed); + mctx =3D &frame->uc.uc_mcontext; +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM + tm_mctx =3D &frame->uc_transact.uc_mcontext; +#endif + /* Put the siginfo & fill in most of the ucontext */ + unsafe_put_user(0, &frame->uc.uc_flags, badframe); #ifdef CONFIG_PPC64 - unsafe_compat_save_altstack(&frame->uc.uc_stack, regs->gpr[1], failed); + unsafe_compat_save_altstack(&frame->uc.uc_stack, regs->gpr[1], badframe); #else - unsafe_save_altstack(&frame->uc.uc_stack, regs->gpr[1], failed); + unsafe_save_altstack(&frame->uc.uc_stack, regs->gpr[1], badframe); #endif - unsafe_put_user(to_user_ptr(&frame->uc.uc_mcontext), &frame->uc.uc_regs, = failed); + unsafe_put_user(to_user_ptr(&frame->uc.uc_mcontext), &frame->uc.uc_regs,= badframe); =20 - if (MSR_TM_ACTIVE(msr)) { + if (MSR_TM_ACTIVE(msr)) { #ifdef CONFIG_PPC_TRANSACTIONAL_MEM - unsafe_put_user((unsigned long)&frame->uc_transact, - &frame->uc.uc_link, failed); - unsafe_put_user((unsigned long)tm_mctx, - &frame->uc_transact.uc_regs, failed); + unsafe_put_user((unsigned long)&frame->uc_transact, + &frame->uc.uc_link, badframe); + unsafe_put_user((unsigned long)tm_mctx, + &frame->uc_transact.uc_regs, badframe); #endif - unsafe_save_tm_user_regs(regs, mctx, tm_mctx, msr, failed); - } else { - unsafe_put_user(0, &frame->uc.uc_link, failed); - unsafe_save_user_regs(regs, mctx, tm_mctx, 1, failed); - } + unsafe_save_tm_user_regs(regs, mctx, tm_mctx, msr, badframe); + } else { + unsafe_put_user(0, &frame->uc.uc_link, badframe); + unsafe_save_user_regs(regs, mctx, tm_mctx, 1, badframe); + } =20 - /* Save user registers on the stack */ - if (tsk->mm->context.vdso) { - tramp =3D VDSO32_SYMBOL(tsk->mm->context.vdso, sigtramp_rt32); - } else { - tramp =3D (unsigned long)mctx->mc_pad; - unsafe_put_user(PPC_RAW_LI(_R0, __NR_rt_sigreturn), &mctx->mc_pad[0], fa= iled); - unsafe_put_user(PPC_RAW_SC(), &mctx->mc_pad[1], failed); - asm("dcbst %y0; sync; icbi %y0; sync" :: "Z" (mctx->mc_pad[0])); + /* Save user registers on the stack */ + if (tsk->mm->context.vdso) { + tramp =3D VDSO32_SYMBOL(tsk->mm->context.vdso, sigtramp_rt32); + } else { + tramp =3D (unsigned long)mctx->mc_pad; + unsafe_put_user(PPC_RAW_LI(_R0, __NR_rt_sigreturn), &mctx->mc_pad[0], + badframe); + unsafe_put_user(PPC_RAW_SC(), &mctx->mc_pad[1], badframe); + asm("dcbst %y0; sync; icbi %y0; sync" :: "Z" (mctx->mc_pad[0])); + } + unsafe_put_sigset_t(&frame->uc.uc_sigmask, oldset, badframe); } - unsafe_put_sigset_t(&frame->uc.uc_sigmask, oldset, failed); - - user_access_end(); =20 if (copy_siginfo_to_user(&frame->info, &ksig->info)) goto badframe; @@ -820,9 +812,6 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t *= oldset, =20 return 0; =20 -failed: - user_access_end(); - badframe: signal_fault(tsk, regs, "handle_rt_signal32", frame); =20 @@ -837,8 +826,6 @@ int handle_signal32(struct ksignal *ksig, sigset_t *old= set, { struct sigcontext __user *sc; struct sigframe __user *frame; - struct mcontext __user *mctx; - struct mcontext __user *tm_mctx =3D NULL; unsigned long newsp =3D 0; unsigned long tramp; struct pt_regs *regs =3D tsk->thread.regs; @@ -847,46 +834,49 @@ int handle_signal32(struct ksignal *ksig, sigset_t *o= ldset, =20 /* Set up Signal Frame */ frame =3D get_sigframe(ksig, tsk, sizeof(*frame), 1); - mctx =3D &frame->mctx; -#ifdef CONFIG_PPC_TRANSACTIONAL_MEM - tm_mctx =3D &frame->mctx_transact; -#endif if (MSR_TM_ACTIVE(msr)) prepare_save_tm_user_regs(); else prepare_save_user_regs(1); =20 - if (!user_access_begin(frame, sizeof(*frame))) - goto badframe; - sc =3D (struct sigcontext __user *) &frame->sctx; + scoped_user_rw_access(frame, badframe) { + struct mcontext __user *mctx; + struct mcontext __user *tm_mctx =3D NULL; + + mctx =3D &frame->mctx; +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM + tm_mctx =3D &frame->mctx_transact; +#endif + sc =3D (struct sigcontext __user *)&frame->sctx; =20 #if _NSIG !=3D 64 #error "Please adjust handle_signal()" #endif - unsafe_put_user(to_user_ptr(ksig->ka.sa.sa_handler), &sc->handler, failed= ); - unsafe_put_user(oldset->sig[0], &sc->oldmask, failed); + unsafe_put_user(to_user_ptr(ksig->ka.sa.sa_handler), &sc->handler, badfr= ame); + unsafe_put_user(oldset->sig[0], &sc->oldmask, badframe); #ifdef CONFIG_PPC64 - unsafe_put_user((oldset->sig[0] >> 32), &sc->_unused[3], failed); + unsafe_put_user((oldset->sig[0] >> 32), &sc->_unused[3], badframe); #else - unsafe_put_user(oldset->sig[1], &sc->_unused[3], failed); + unsafe_put_user(oldset->sig[1], &sc->_unused[3], badframe); #endif - unsafe_put_user(to_user_ptr(mctx), &sc->regs, failed); - unsafe_put_user(ksig->sig, &sc->signal, failed); + unsafe_put_user(to_user_ptr(mctx), &sc->regs, badframe); + unsafe_put_user(ksig->sig, &sc->signal, badframe); =20 - if (MSR_TM_ACTIVE(msr)) - unsafe_save_tm_user_regs(regs, mctx, tm_mctx, msr, failed); - else - unsafe_save_user_regs(regs, mctx, tm_mctx, 1, failed); - - if (tsk->mm->context.vdso) { - tramp =3D VDSO32_SYMBOL(tsk->mm->context.vdso, sigtramp32); - } else { - tramp =3D (unsigned long)mctx->mc_pad; - unsafe_put_user(PPC_RAW_LI(_R0, __NR_sigreturn), &mctx->mc_pad[0], faile= d); - unsafe_put_user(PPC_RAW_SC(), &mctx->mc_pad[1], failed); - asm("dcbst %y0; sync; icbi %y0; sync" :: "Z" (mctx->mc_pad[0])); + if (MSR_TM_ACTIVE(msr)) + unsafe_save_tm_user_regs(regs, mctx, tm_mctx, msr, badframe); + else + unsafe_save_user_regs(regs, mctx, tm_mctx, 1, badframe); + + if (tsk->mm->context.vdso) { + tramp =3D VDSO32_SYMBOL(tsk->mm->context.vdso, sigtramp32); + } else { + tramp =3D (unsigned long)mctx->mc_pad; + unsafe_put_user(PPC_RAW_LI(_R0, __NR_sigreturn), &mctx->mc_pad[0], + badframe); + unsafe_put_user(PPC_RAW_SC(), &mctx->mc_pad[1], badframe); + asm("dcbst %y0; sync; icbi %y0; sync" :: "Z" (mctx->mc_pad[0])); + } } - user_access_end(); =20 regs->link =3D tramp; =20 @@ -908,9 +898,6 @@ int handle_signal32(struct ksignal *ksig, sigset_t *old= set, =20 return 0; =20 -failed: - user_access_end(); - badframe: signal_fault(tsk, regs, "handle_signal32", frame); =20 @@ -922,21 +909,19 @@ static int do_setcontext(struct ucontext __user *ucp,= struct pt_regs *regs, int sigset_t set; struct mcontext __user *mcp; =20 - if (!user_read_access_begin(ucp, sizeof(*ucp))) - return -EFAULT; - - unsafe_get_sigset_t(&set, &ucp->uc_sigmask, failed); + scoped_user_read_access(ucp, failed) { + unsafe_get_sigset_t(&set, &ucp->uc_sigmask, failed); #ifdef CONFIG_PPC64 - { - u32 cmcp; + { + u32 cmcp; =20 - unsafe_get_user(cmcp, &ucp->uc_regs, failed); - mcp =3D (struct mcontext __user *)(u64)cmcp; - } + unsafe_get_user(cmcp, &ucp->uc_regs, failed); + mcp =3D (struct mcontext __user *)(u64)cmcp; + } #else - unsafe_get_user(mcp, &ucp->uc_regs, failed); + unsafe_get_user(mcp, &ucp->uc_regs, failed); #endif - user_read_access_end(); + } =20 set_current_blocked(&set); if (restore_user_regs(regs, mcp, sig)) @@ -945,7 +930,6 @@ static int do_setcontext(struct ucontext __user *ucp, s= truct pt_regs *regs, int return 0; =20 failed: - user_read_access_end(); return -EFAULT; } =20 @@ -960,13 +944,10 @@ static int do_setcontext_tm(struct ucontext __user *u= cp, u32 cmcp; u32 tm_cmcp; =20 - if (!user_read_access_begin(ucp, sizeof(*ucp))) - return -EFAULT; - - unsafe_get_sigset_t(&set, &ucp->uc_sigmask, failed); - unsafe_get_user(cmcp, &ucp->uc_regs, failed); - - user_read_access_end(); + scoped_user_read_access(ucp, failed) { + unsafe_get_sigset_t(&set, &ucp->uc_sigmask, failed); + unsafe_get_user(cmcp, &ucp->uc_regs, failed); + } =20 if (__get_user(tm_cmcp, &tm_ucp->uc_regs)) return -EFAULT; @@ -981,7 +962,6 @@ static int do_setcontext_tm(struct ucontext __user *ucp, return 0; =20 failed: - user_read_access_end(); return -EFAULT; } #endif @@ -1051,12 +1031,11 @@ SYSCALL_DEFINE3(swapcontext, struct ucontext __user= *, old_ctx, mctx =3D (struct mcontext __user *) ((unsigned long) &old_ctx->uc_mcontext & ~0xfUL); prepare_save_user_regs(ctx_has_vsx_region); - if (!user_write_access_begin(old_ctx, ctx_size)) - return -EFAULT; - unsafe_save_user_regs(regs, mctx, NULL, ctx_has_vsx_region, failed); - unsafe_put_sigset_t(&old_ctx->uc_sigmask, ¤t->blocked, failed); - unsafe_put_user(to_user_ptr(mctx), &old_ctx->uc_regs, failed); - user_write_access_end(); + scoped_user_write_access_size(old_ctx, ctx_size, failed) { + unsafe_save_user_regs(regs, mctx, NULL, ctx_has_vsx_region, failed); + unsafe_put_sigset_t(&old_ctx->uc_sigmask, ¤t->blocked, failed); + unsafe_put_user(to_user_ptr(mctx), &old_ctx->uc_regs, failed); + } } if (new_ctx =3D=3D NULL) return 0; @@ -1084,7 +1063,6 @@ SYSCALL_DEFINE3(swapcontext, struct ucontext __user *= , old_ctx, return 0; =20 failed: - user_write_access_end(); return -EFAULT; } =20 --=20 2.54.0 From nobody Sun May 24 19:33:05 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 369253B52E1 for ; Fri, 22 May 2026 09:56:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779443806; cv=none; b=kaRqRmgoaFbVhEffP0RmALGSgBUGtG0sWN3N+1O7Cs+mS6vcgf4HE5+SdBaOTLGtqv/0BZLw22fca23mSKVKUwY0wlsE2Rb1lHd1OKFT8Bx4CZCTBH0Pvtu7lcp7RK61PdQ28u0T/Y3L5pnz9iNQwBr3trKcMADIw0byQwnHrlM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779443806; c=relaxed/simple; bh=Icgb4f+mxemIv2zrP3yaLp1RI/4pQz56H5O4k1XMi/M=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=HEFViOYQQvxkX4N84cXkE8wC8CjuZEhQ9uObcvlGGxDBXMt4c01czxSh6MhVxZ67nTAMOhpkrbPdL3/n9Ahqd747qgvolIjCCvUUV7A3Ly1YF2LAIQQwgxeUUwXuB6eLMutRuuOJwi89M+2d0JDATDgxjdzkGH0g65tk+fc7R1I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=kj6lTiSv; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="kj6lTiSv" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 388591F000E9; Fri, 22 May 2026 09:56:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779443804; bh=PS+M11qxsK7pLF5VPFqgaibCX0XcuKhFH5IihJWdaY8=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=kj6lTiSveeDGvsRklW3EJORl7IkNohMN97x6WztN4Clsn87Ehipo81jvybhsDOzii JMBw4YecyzlZ+5eeOW0AtHlBJymgoRl7gEQ4WW1Ut7H8wTJiqMCedC7HYrlrFr80OG WJ5ggfvNRexBNdqVtDH7oizi2CVnMZHnGKuSG9/Pado3gU6ANilOsxUUAAfUROXwOq UtqBgGaOvBTSKUP1Lq2QcgR0OtXTDKIfsrZbvvMrAfpQeX+CeZ6/xrMVvZYsKtEGxn 4l0Ya+tfQLYgpYi43rLHKuR5faiRbKiGAqLwxd7qX/xlQgbqtArN/n82PFgzyEXTmm 8JdR2tpy5giQw== From: "Christophe Leroy (CS GROUP)" To: Michael Ellerman , Nicholas Piggin , Madhavan Srinivasan Cc: "Christophe Leroy (CS GROUP)" , linux-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org Subject: [PATCH v1 2/8] powerpc/signal64: Untangle setup_tm_sigcontexts() and user_access_begin() Date: Fri, 22 May 2026 11:56:02 +0200 Message-ID: <7c83fe5a596514a02fde37da987a48d638d0d097.1779441786.git.chleroy@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=1675; i=chleroy@kernel.org; h=from:subject:message-id; bh=Icgb4f+mxemIv2zrP3yaLp1RI/4pQz56H5O4k1XMi/M=; b=owGbwMvMwCV2d0KB2p7V54MZT6slMWQJaNi5LT5ezLDXTnb26dvLuiYsOuJuvDM0W3je6gOC3 zmnd0h97ShlYRDjYpAVU2Q5/p9714yuL6n5U3fpw8xhZQIZwsDFKQATsVFjZFgfrJPHW6hc/qhR Od334o7VRftkvIRa3fgCplVa6K7UVGVkeCvk9+7Xs+lSMvnixyU2HRT7mc5cbX3uaXVnl3We3M+ j/AA= X-Developer-Key: i=chleroy@kernel.org; a=openpgp; fpr=10FFE6F8B390DE17ACC2632368A92FEB01B8DD78 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Call setup_tm_sigcontexts() before opening user access to avoid having to close and open again. Signed-off-by: Christophe Leroy (CS GROUP) --- arch/powerpc/kernel/signal_64.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_6= 4.c index 86bb5bb4c143..3849af21e1d8 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c @@ -873,6 +873,15 @@ int handle_rt_signal64(struct ksignal *ksig, sigset_t = *set, if (!MSR_TM_ACTIVE(msr)) prepare_setup_sigcontext(tsk); =20 +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM + if (MSR_TM_ACTIVE(msr)) + err |=3D setup_tm_sigcontexts(&frame->uc.uc_mcontext, + &frame->uc_transact.uc_mcontext, + tsk, ksig->sig, NULL, + (unsigned long)ksig->ka.sa.sa_handler, + msr); + +#endif if (!user_write_access_begin(frame, sizeof(*frame))) goto badframe; =20 @@ -889,19 +898,6 @@ int handle_rt_signal64(struct ksignal *ksig, sigset_t = *set, * ucontext_t (for transactional state) with its uc_link ptr. */ unsafe_put_user(&frame->uc_transact, &frame->uc.uc_link, badframe_block); - - user_write_access_end(); - - err |=3D setup_tm_sigcontexts(&frame->uc.uc_mcontext, - &frame->uc_transact.uc_mcontext, - tsk, ksig->sig, NULL, - (unsigned long)ksig->ka.sa.sa_handler, - msr); - - if (!user_write_access_begin(&frame->uc.uc_sigmask, - sizeof(frame->uc.uc_sigmask))) - goto badframe; - #endif } else { unsafe_put_user(0, &frame->uc.uc_link, badframe_block); --=20 2.54.0 From nobody Sun May 24 19:33:05 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8D7B33905E4 for ; Fri, 22 May 2026 09:56:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779443808; cv=none; b=EnLyD0cFahsxe92NhzaL8wHybHfdWq1LJO4ljLJdbf5I7vdgYhN2+NXD4Ep07q2fKE+YIjzUMMPBkMc5iceVi/x9t1DFInSjWvERx6a8Gmlcal9XoB8KcV0v2vk4cTJhEec9IQSa/uoGFRQHuQeU0lLR/fd//sEmocpjUHXh9Q4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779443808; c=relaxed/simple; bh=C5JhuyEfp54V0XGnJp4rC0v3uRomMit7scuJT0Im8VA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=icaOtl2szJhRmU5N2Jr9JOzCaudO2/LGaD8gldGnrCbMhqSVCrXI70fAOpXlxhoEozTCCFZzVavevvkHkHOFYxLuKWd1iFA48nPE+/HV27lWJANJUSYCooSCE0fxvezvUdBD9deCYvF+LoicUsExz0WkG8M/AsTSPozufI76wbU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=dgZIGngG; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="dgZIGngG" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4E4B91F00A3E; Fri, 22 May 2026 09:56:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779443807; bh=I62BTjgwegdEBrRMDa3/7GAx+tB373Hahc+eIo9iR+g=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=dgZIGngGxOdzJ3x2/nVOdBOhLtJqHNnRsuRT6U3sY5FJ9K+cuLOTPZeIxjDXzG5Nn BuFByJPS30dubfxvx3PvHCFJq0nrxPGO1EVuMW4ekNXo3ngpI36nIGcSiBIa4dy7iW yfD1WsoRkR9PfTcSQbfXGG3cGcC4Oglptv9fr7MfymSD+cW/H+LqjdqKXf6kEzmNf0 QBHoOjmHxQYZ05okYYWVOUEG/NANYPkwiqWaKKC50y9uK0VfhNC8Y+tJ1jOQhy/ZEj EklUcdcp8ByTyEeZXM4sQVmzdxeUJrt/EozaRdNv+hGmpW+tAQpRvlNth/UBG0i7eE h+6/dQhHyzK5w== From: "Christophe Leroy (CS GROUP)" To: Michael Ellerman , Nicholas Piggin , Madhavan Srinivasan Cc: "Christophe Leroy (CS GROUP)" , linux-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org Subject: [PATCH v1 3/8] powerpc/signal64: Convert to scoped user access Date: Fri, 22 May 2026 11:56:03 +0200 Message-ID: X-Mailer: git-send-email 2.54.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=5583; i=chleroy@kernel.org; h=from:subject:message-id; bh=C5JhuyEfp54V0XGnJp4rC0v3uRomMit7scuJT0Im8VA=; b=owGbwMvMwCV2d0KB2p7V54MZT6slMWQJaNiZvDHsvsOWEDPBP3XyHtvT/AsLL7ueNX15/ob+0 5DZCbOzOkpZGMS4GGTFFFmO/+feNaPrS2r+1F36MHNYmUCGMHBxCsBEcoMZGc5pVPzRqW76c3ej saDROWe3KN23HkF/5nEzpv5pC2Wf9JWR4cf32brr4ks6/p5+2JPy7r3Q37M+h/s9fronP7c0l7l 6nQMA X-Developer-Key: i=chleroy@kernel.org; a=openpgp; fpr=10FFE6F8B390DE17ACC2632368A92FEB01B8DD78 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Commit 861574d51bbd ("powerpc/uaccess: Implement masked user access") provides optimised user access by avoiding the cost of access_ok(). Convert signal64 functions to scoped user access. Scoped user access also make the code simpler. Signed-off-by: Christophe Leroy (CS GROUP) --- arch/powerpc/kernel/signal_64.c | 81 +++++++++++++-------------------- 1 file changed, 32 insertions(+), 49 deletions(-) diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_6= 4.c index 3849af21e1d8..ee8166fd83dc 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c @@ -683,15 +683,12 @@ SYSCALL_DEFINE3(swapcontext, struct ucontext __user *= , old_ctx, =20 if (old_ctx !=3D NULL) { prepare_setup_sigcontext(current); - if (!user_write_access_begin(old_ctx, ctx_size)) - return -EFAULT; - - unsafe_setup_sigcontext(&old_ctx->uc_mcontext, current, 0, NULL, - 0, ctx_has_vsx_region, efault_out); - unsafe_copy_to_user(&old_ctx->uc_sigmask, ¤t->blocked, - sizeof(sigset_t), efault_out); - - user_write_access_end(); + scoped_user_write_access_size(old_ctx, ctx_size, efault_out) { + unsafe_setup_sigcontext(&old_ctx->uc_mcontext, current, 0, NULL, + 0, ctx_has_vsx_region, efault_out); + unsafe_copy_to_user(&old_ctx->uc_sigmask, ¤t->blocked, + sizeof(sigset_t), efault_out); + } } if (new_ctx =3D=3D NULL) return 0; @@ -717,14 +714,12 @@ SYSCALL_DEFINE3(swapcontext, struct ucontext __user *= , old_ctx, } set_current_blocked(&set); =20 - if (!user_read_access_begin(new_ctx, ctx_size)) - return -EFAULT; - if (__unsafe_restore_sigcontext(current, NULL, 0, &new_ctx->uc_mcontext))= { - user_read_access_end(); - force_exit_sig(SIGSEGV); - return -EFAULT; + scoped_user_read_access_size(new_ctx, ctx_size, efault_out) { + if (__unsafe_restore_sigcontext(current, NULL, 0, &new_ctx->uc_mcontext)= ) { + force_exit_sig(SIGSEGV); + return -EFAULT; + } } - user_read_access_end(); =20 /* This returns like rt_sigreturn */ set_thread_flag(TIF_RESTOREALL); @@ -732,7 +727,6 @@ SYSCALL_DEFINE3(swapcontext, struct ucontext __user *, = old_ctx, return 0; =20 efault_out: - user_write_access_end(); return -EFAULT; } =20 @@ -815,6 +809,7 @@ SYSCALL_DEFINE0(rt_sigreturn) &uc_transact->uc_mcontext)) goto badframe; } else { + struct sigcontext __user *uc_mcontext =3D &uc->uc_mcontext; /* * Fall through, for non-TM restore * @@ -829,13 +824,8 @@ SYSCALL_DEFINE0(rt_sigreturn) */ regs_set_return_msr(current->thread.regs, current->thread.regs->msr & ~MSR_TS_MASK); - if (!user_read_access_begin(&uc->uc_mcontext, sizeof(uc->uc_mcontext))) - goto badframe; - - unsafe_restore_sigcontext(current, NULL, 1, &uc->uc_mcontext, - badframe_block); - - user_read_access_end(); + scoped_user_read_access(uc_mcontext, badframe) + unsafe_restore_sigcontext(current, NULL, 1, uc_mcontext, badframe); } =20 if (restore_altstack(&uc->uc_stack)) @@ -845,8 +835,6 @@ SYSCALL_DEFINE0(rt_sigreturn) =20 return 0; =20 -badframe_block: - user_read_access_end(); badframe: signal_fault(current, regs, "rt_sigreturn", uc); =20 @@ -882,32 +870,29 @@ int handle_rt_signal64(struct ksignal *ksig, sigset_t= *set, msr); =20 #endif - if (!user_write_access_begin(frame, sizeof(*frame))) - goto badframe; + scoped_user_write_access(frame, badframe) { + unsafe_put_user(&frame->info, &frame->pinfo, badframe); + unsafe_put_user(&frame->uc, &frame->puc, badframe); =20 - unsafe_put_user(&frame->info, &frame->pinfo, badframe_block); - unsafe_put_user(&frame->uc, &frame->puc, badframe_block); + /* Create the ucontext. */ + unsafe_put_user(0, &frame->uc.uc_flags, badframe); + unsafe_save_altstack(&frame->uc.uc_stack, regs->gpr[1], badframe); =20 - /* Create the ucontext. */ - unsafe_put_user(0, &frame->uc.uc_flags, badframe_block); - unsafe_save_altstack(&frame->uc.uc_stack, regs->gpr[1], badframe_block); - - if (MSR_TM_ACTIVE(msr)) { + if (MSR_TM_ACTIVE(msr)) { #ifdef CONFIG_PPC_TRANSACTIONAL_MEM - /* The ucontext_t passed to userland points to the second - * ucontext_t (for transactional state) with its uc_link ptr. - */ - unsafe_put_user(&frame->uc_transact, &frame->uc.uc_link, badframe_block); + /* The ucontext_t passed to userland points to the second + * ucontext_t (for transactional state) with its uc_link ptr. + */ + unsafe_put_user(&frame->uc_transact, &frame->uc.uc_link, badframe); #endif - } else { - unsafe_put_user(0, &frame->uc.uc_link, badframe_block); - unsafe_setup_sigcontext(&frame->uc.uc_mcontext, tsk, ksig->sig, - NULL, (unsigned long)ksig->ka.sa.sa_handler, - 1, badframe_block); - } + } else { + unsafe_put_user(0, &frame->uc.uc_link, badframe); + unsafe_setup_sigcontext(&frame->uc.uc_mcontext, tsk, ksig->sig, NULL, + (unsigned long)ksig->ka.sa.sa_handler, 1, badframe); + } =20 - unsafe_copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set), badframe_bl= ock); - user_write_access_end(); + unsafe_copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set), badframe); + } =20 /* Save the siginfo outside of the unsafe block. */ if (copy_siginfo_to_user(&frame->info, &ksig->info)) @@ -964,8 +949,6 @@ int handle_rt_signal64(struct ksignal *ksig, sigset_t *= set, =20 return 0; =20 -badframe_block: - user_write_access_end(); badframe: signal_fault(current, regs, "handle_rt_signal64", frame); =20 --=20 2.54.0 From nobody Sun May 24 19:33:05 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 862473C552B for ; Fri, 22 May 2026 09:56:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779443811; cv=none; b=urRP+Y3iMRkncEM0AN897FEVXP9sQz38OpDDImg6E/7OwGOi4quoeErb44ztCG2RTIckm7XVZR/NwQiJqT+9U9B1YlWTX1fPFPnqAVJYWzLO3XfKbrccLCwlR1or1My4IHsm8Tpfv1mt7/apoGny8Xi+Dc7ty7HODM60L6/dgT8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779443811; c=relaxed/simple; bh=9S3bhpCCSnE4Jl8KeXsH0H6BKtYWsCDOtF5KfH9qYcE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=cJ0uAnjiyafuJFWfyCKvhwxUxFnHtn3MfBS6h0LFZbBAJWQEQ8eX/ihgM5GW8SX/UW+jxSeD6bZkRWTFTa6mH37IlUPkghFCcyqBIqp4NwH6PR96IyiTwkqjYW1G3/gBl1zy98FYk9h59+9SsIOVQByHXgClToUuI9U9i1/lp4A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=DaL4UJRY; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="DaL4UJRY" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B17D51F00A3D; Fri, 22 May 2026 09:56:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779443809; bh=8vN/NoLezPEDsyDS+onUAQhVhhGZl3+ewdKbIEUAKPE=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=DaL4UJRYwHkj/GX5iunjonDR90BGEe/s2tZteURXKh9dnWNBeiNFQJ5SCTQFlKWc1 IoaN/VFqllJIOmXFbYD/My1O0WPky09e88AD6UxjVLilQ74X2qsQf8eSwcHofKxqkp x2fdFtCWVg8CEvDVsWKDR1hbk9aG9JxRgeryG4+OFZJudEgZXJDz/DG0Ncb/Z/L3Zl FcyQtSxoRElzlt8LBUbY+7CjFGmxm00rqV2ad1H3MH+/t2d29/BxTspVyKkJZnZXjx BTHvomF/B5ZoCQD727ef7OuEQR53uXXLGpyfYaf52Dg9gQr95KnaA15gWPQ4303Td0 pe0/usVMBo6WQ== From: "Christophe Leroy (CS GROUP)" To: Michael Ellerman , Nicholas Piggin , Madhavan Srinivasan Cc: "Christophe Leroy (CS GROUP)" , linux-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org Subject: [PATCH v1 4/8] powerpc/signal64: Access function descriptor with scoped user access Date: Fri, 22 May 2026 11:56:04 +0200 Message-ID: X-Mailer: git-send-email 2.54.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=1246; i=chleroy@kernel.org; h=from:subject:message-id; bh=9S3bhpCCSnE4Jl8KeXsH0H6BKtYWsCDOtF5KfH9qYcE=; b=owGbwMvMwCV2d0KB2p7V54MZT6slMWQJaNhVMD3/0x8wLWxBudhz28rPhauPvNqj3X9PZ4W+l Hj+ncMuHaUsDGJcDLJiiizH/3PvmtH1JTV/6i59mDmsTCBDGLg4BWAiQu8Y/nvO2p3Dviv4nkrW Hr49bW41toeaP0a0/17yU6Sz7/Sn50IMv5i7EjR8fPbPWj1R6bs3V/eFjd8bt1TN59eUOq9n5td eyw4A X-Developer-Key: i=chleroy@kernel.org; a=openpgp; fpr=10FFE6F8B390DE17ACC2632368A92FEB01B8DD78 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Access the function descriptor of the handler within a scoped user access block. Signed-off-by: Christophe Leroy (CS GROUP) --- arch/powerpc/kernel/signal_64.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_6= 4.c index ee8166fd83dc..bf7fc579d572 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c @@ -928,8 +928,10 @@ int handle_rt_signal64(struct ksignal *ksig, sigset_t = *set, struct func_desc __user *ptr =3D (struct func_desc __user *)ksig->ka.sa.sa_handler; =20 - err |=3D get_user(regs->ctr, &ptr->addr); - err |=3D get_user(regs->gpr[2], &ptr->toc); + scoped_user_read_access(ptr, badfunc) { + unsafe_get_user(regs->ctr, &ptr->addr, badfunc); + unsafe_get_user(regs->gpr[2], &ptr->toc, badfunc); + } } =20 /* enter the signal handler in native-endian mode */ @@ -952,5 +954,10 @@ int handle_rt_signal64(struct ksignal *ksig, sigset_t = *set, badframe: signal_fault(current, regs, "handle_rt_signal64", frame); =20 + return 1; + +badfunc: + signal_fault(current, regs, __func__, (void __user *)ksig->ka.sa.sa_handl= er); + return 1; } --=20 2.54.0 From nobody Sun May 24 19:33:05 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E8BA03C6A38 for ; Fri, 22 May 2026 09:56:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779443813; cv=none; b=hT/kf/GTWT+G6d5e6TTa59jSPPVNKpn3N1pTH8x6Sjyaf00uTBT0kcDW6D+56qIUNIVRZQRxHd5B/meI0lYNXZGCpq/VkwIBKsvts+QMVQPw/kyRrsgP2hVXS4CmviJtTzKpmhp+gq3Ax7+47rjSEoAy73bkqHM6WyKDOPy6ZuI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779443813; c=relaxed/simple; bh=Sv4X8VTWrdN2udw9liQNQS0v17NX1w7EdMh1y0n3YiI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=daalSzy0gYY1PlM1Ml448qjHk9guxTpXH5xsG5n1AnqE3l4vstImelDY0bFyC1d1n3lrv4Jt8kikeV8VO39Hl7QJRz5zWYcAEblvaZzOmI7AJH7gI0q2wmCp6lv1MXo5pJdS59GOwmPpC2Zg0y82agTaSbNMigPu8gRmhMl7/lQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=juefcFJ4; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="juefcFJ4" Received: by smtp.kernel.org (Postfix) with ESMTPSA id DFDAA1F00A3E; Fri, 22 May 2026 09:56:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779443811; bh=CdobDuTOgoolQVkszSDKLRqhHkRLaU01XRBQ3D9Mjb0=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=juefcFJ4bFlo8QZ7FNxJNiejm93GsvrXCg1TNQD1hAuE+y1FKJpAQoMvvxCRivbEG hdgPB4fbp5jD7aenObJW8g7Hk+q55Ur/xHf24c2vAl4LhJq8+qeVfp81zXe1QzzhSK JdnOjTgzZDwIc2pvghim70C9WDU9ICY/LTLFSfyRVZK1NiIzhURdJ7ee9SDyZxaO3C fkDyLRgGC7zIItQ5e9NJRQt4Ol2xbslmqx4LGVBIYKaUm0NyzRmKuvbNlBj63T8G3N Ly82hDjNWwgL3Y6hBB90HHxgsRJJRa/YlcKG38vk2bkkYSu46DnGHTF6GdjCSuT3ZD Jex2zxw4BgBZg== From: "Christophe Leroy (CS GROUP)" To: Michael Ellerman , Nicholas Piggin , Madhavan Srinivasan Cc: "Christophe Leroy (CS GROUP)" , linux-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org Subject: [PATCH v1 5/8] powerpc/signal: Include the new stack frame inside the user access block Date: Fri, 22 May 2026 11:56:05 +0200 Message-ID: <287fc000d2f51fde862db0db643801c0ff22cfb7.1779441786.git.chleroy@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=6733; i=chleroy@kernel.org; h=from:subject:message-id; bh=Sv4X8VTWrdN2udw9liQNQS0v17NX1w7EdMh1y0n3YiI=; b=owGbwMvMwCV2d0KB2p7V54MZT6slMWQJaNj9kHp1pe6KY2VMntFlFxFx3eub/nzT/rW4dvqp/ WHvLtcv6ChlYRDjYpAVU2Q5/p9714yuL6n5U3fpw8xhZQIZwsDFKQATsRFj+O964lSV4bMTdoI+ jY/bF//vuXW1huOF7KI2tSSJ81/9InoZ/vDvW5fR8OWMsX5NWGbW8315kqzMgfb3P65a7eyX1MZ 4jRUA X-Developer-Key: i=chleroy@kernel.org; a=openpgp; fpr=10FFE6F8B390DE17ACC2632368A92FEB01B8DD78 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Include the new stack frame inside the user access block and set it up using unsafe_put_user(). On an mpc 8321 (book3s/32) the improvment is about 4% on a process sending a signal to itself. Signed-off-by: Christophe Leroy (CS GROUP) --- arch/powerpc/kernel/signal_32.c | 28 ++++++++++++---------------- arch/powerpc/kernel/signal_64.c | 13 ++++++------- 2 files changed, 18 insertions(+), 23 deletions(-) diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_3= 2.c index f5d5139a1426..6b1fbd95b07d 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c @@ -730,7 +730,7 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t *= oldset, struct task_struct *tsk) { struct rt_sigframe __user *frame; - unsigned long newsp =3D 0; + unsigned long __user *newsp; unsigned long tramp; struct pt_regs *regs =3D tsk->thread.regs; /* Save the thread's msr before get_tm_stackpointer() changes it */ @@ -738,12 +738,13 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t= *oldset, =20 /* Set up Signal Frame */ frame =3D get_sigframe(ksig, tsk, sizeof(*frame), 1); + newsp =3D (unsigned long __user *)((unsigned long)frame - (__SIGNAL_FRAME= SIZE + 16)); if (MSR_TM_ACTIVE(msr)) prepare_save_tm_user_regs(); else prepare_save_user_regs(1); =20 - scoped_user_rw_access(frame, badframe) { + scoped_user_rw_access_size(newsp, __SIGNAL_FRAMESIZE + 16 + sizeof(*frame= ), badframe) { struct mcontext __user *mctx; struct mcontext __user *tm_mctx =3D NULL; =20 @@ -784,6 +785,9 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t *= oldset, asm("dcbst %y0; sync; icbi %y0; sync" :: "Z" (mctx->mc_pad[0])); } unsafe_put_sigset_t(&frame->uc.uc_sigmask, oldset, badframe); + + /* create a stack frame for the caller of the handler */ + unsafe_put_user(regs->gpr[1], newsp, badframe); } =20 if (copy_siginfo_to_user(&frame->info, &ksig->info)) @@ -795,13 +799,8 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t = *oldset, tsk->thread.fp_state.fpscr =3D 0; /* turn off all fp exceptions */ #endif =20 - /* create a stack frame for the caller of the handler */ - newsp =3D ((unsigned long)frame) - (__SIGNAL_FRAMESIZE + 16); - if (put_user(regs->gpr[1], (u32 __user *)newsp)) - goto badframe; - /* Fill registers for signal handler */ - regs->gpr[1] =3D newsp; + regs->gpr[1] =3D (unsigned long)newsp; regs->gpr[3] =3D ksig->sig; regs->gpr[4] =3D (unsigned long)&frame->info; regs->gpr[5] =3D (unsigned long)&frame->uc; @@ -826,7 +825,7 @@ int handle_signal32(struct ksignal *ksig, sigset_t *old= set, { struct sigcontext __user *sc; struct sigframe __user *frame; - unsigned long newsp =3D 0; + unsigned long __user *newsp; unsigned long tramp; struct pt_regs *regs =3D tsk->thread.regs; /* Save the thread's msr before get_tm_stackpointer() changes it */ @@ -834,12 +833,13 @@ int handle_signal32(struct ksignal *ksig, sigset_t *o= ldset, =20 /* Set up Signal Frame */ frame =3D get_sigframe(ksig, tsk, sizeof(*frame), 1); + newsp =3D (unsigned long __user *)((unsigned long)frame - __SIGNAL_FRAMES= IZE); if (MSR_TM_ACTIVE(msr)) prepare_save_tm_user_regs(); else prepare_save_user_regs(1); =20 - scoped_user_rw_access(frame, badframe) { + scoped_user_rw_access_size(newsp, __SIGNAL_FRAMESIZE + sizeof(*frame), ba= dframe) { struct mcontext __user *mctx; struct mcontext __user *tm_mctx =3D NULL; =20 @@ -876,6 +876,7 @@ int handle_signal32(struct ksignal *ksig, sigset_t *old= set, unsafe_put_user(PPC_RAW_SC(), &mctx->mc_pad[1], badframe); asm("dcbst %y0; sync; icbi %y0; sync" :: "Z" (mctx->mc_pad[0])); } + unsafe_put_user(regs->gpr[1], newsp, badframe); } =20 regs->link =3D tramp; @@ -884,12 +885,7 @@ int handle_signal32(struct ksignal *ksig, sigset_t *ol= dset, tsk->thread.fp_state.fpscr =3D 0; /* turn off all fp exceptions */ #endif =20 - /* create a stack frame for the caller of the handler */ - newsp =3D ((unsigned long)frame) - __SIGNAL_FRAMESIZE; - if (put_user(regs->gpr[1], (u32 __user *)newsp)) - goto badframe; - - regs->gpr[1] =3D newsp; + regs->gpr[1] =3D (unsigned long)newsp; regs->gpr[3] =3D ksig->sig; regs->gpr[4] =3D (unsigned long) sc; regs_set_return_ip(regs, (unsigned long) ksig->ka.sa.sa_handler); diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_6= 4.c index bf7fc579d572..67de29cf581a 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c @@ -846,13 +846,14 @@ int handle_rt_signal64(struct ksignal *ksig, sigset_t= *set, struct task_struct *tsk) { struct rt_sigframe __user *frame; - unsigned long newsp =3D 0; + unsigned long __user *newsp; long err =3D 0; struct pt_regs *regs =3D tsk->thread.regs; /* Save the thread's msr before get_tm_stackpointer() changes it */ unsigned long msr =3D regs->msr; =20 frame =3D get_sigframe(ksig, tsk, sizeof(*frame), 0); + newsp =3D (unsigned long __user *)((unsigned long)frame - __SIGNAL_FRAMES= IZE); =20 /* * This only applies when calling unsafe_setup_sigcontext() and must be @@ -870,7 +871,7 @@ int handle_rt_signal64(struct ksignal *ksig, sigset_t *= set, msr); =20 #endif - scoped_user_write_access(frame, badframe) { + scoped_user_write_access_size(newsp, __SIGNAL_FRAMESIZE + sizeof(*frame),= badframe) { unsafe_put_user(&frame->info, &frame->pinfo, badframe); unsafe_put_user(&frame->uc, &frame->puc, badframe); =20 @@ -892,6 +893,8 @@ int handle_rt_signal64(struct ksignal *ksig, sigset_t *= set, } =20 unsafe_copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set), badframe); + /* Allocate a dummy caller frame for the signal handler. */ + unsafe_put_user(regs->gpr[1], newsp, badframe); } =20 /* Save the siginfo outside of the unsafe block. */ @@ -911,10 +914,6 @@ int handle_rt_signal64(struct ksignal *ksig, sigset_t = *set, regs_set_return_ip(regs, (unsigned long) &frame->tramp[0]); } =20 - /* Allocate a dummy caller frame for the signal handler. */ - newsp =3D ((unsigned long)frame) - __SIGNAL_FRAMESIZE; - err |=3D put_user(regs->gpr[1], (unsigned long __user *)newsp); - /* Set up "regs" so we "return" to the signal handler. */ if (is_elf2_task()) { regs->ctr =3D (unsigned long) ksig->ka.sa.sa_handler; @@ -936,7 +935,7 @@ int handle_rt_signal64(struct ksignal *ksig, sigset_t *= set, =20 /* enter the signal handler in native-endian mode */ regs_set_return_msr(regs, (regs->msr & ~MSR_LE) | (MSR_KERNEL & MSR_LE)); - regs->gpr[1] =3D newsp; + regs->gpr[1] =3D (unsigned long)newsp; regs->gpr[3] =3D ksig->sig; regs->result =3D 0; if (ksig->ka.sa.sa_flags & SA_SIGINFO) { --=20 2.54.0 From nobody Sun May 24 19:33:05 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 198693C76A0 for ; Fri, 22 May 2026 09:56:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779443815; cv=none; b=NRSHFUblw9HsX2lDQmZM5zzBfXl3XCKrDGhSRyPsVIpci3CJLt4XaCz8dzCSoETbZtNhWwe/hSBnDP5JRcNp/JDIxn2WscZmQwX+/zXnrcFhjtA16u1TrM8FL4YmfFoJ8ewHr7IzmYTDs1m11dxa0qD1AlCHDhQJo6nsf+/ekD0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779443815; c=relaxed/simple; bh=CxukwNaaHfPCgLLuHd8f2xWMx67xuC8tWT39iKS4wZo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=MKpRSPtG4wgN5o1QRnp6/BtBpHn8zzp3sHIyclpXfrXzU5l9gW5VYboao7jfyaFDwwHgCkjg3EsSxFLimn3zU1Y2d8BQu9LXhMYMwPDzutEjsd5HnHWqOzUcHVWveB21qC/kBrrYjpXPyIMuNj3y653f9hZYNtQmrjtfb7LHJWo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=GK/+SCV1; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="GK/+SCV1" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1B38C1F00A3D; Fri, 22 May 2026 09:56:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779443813; bh=qIFh0EHf36xuaiQUrsEboCGTYqr33D+g0zvT7LVweRs=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=GK/+SCV19DAEftkWYjgk7KGHdZ26g54nGTimIvMTlmEhHFo2m7E4L3ZMiSkWmRjl9 LebQlYbpBMcDeyeowHBXdMpuNXCgGi4Eu4FKT+FdkFj2VbOtkr//nZPpuy6dbGOb5A 9Bx6QOLPalVGAj6A/SQG2+vTL8jBZ31/LtTA6ckpnSa2ubouz+qeLakiQfrYUoOxBf 3WkL6+qAS/KaszDC/ZXhZcajoroGm3oXukSR8XAd0S9lC5TsvARsLcu3+wFeV0lgxk HBCfvARIHuN9Zmhq96C2HqgJr6tJk/oGBWQUVy0IYQ9lH76UBLqERH6lKnBmBgQA+w Id6FLoY1W/yug== From: "Christophe Leroy (CS GROUP)" To: Michael Ellerman , Nicholas Piggin , Madhavan Srinivasan Cc: "Christophe Leroy (CS GROUP)" , linux-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org Subject: [PATCH v1 6/8] signal: Add unsafe_copy_siginfo_to_user() Date: Fri, 22 May 2026 11:56:06 +0200 Message-ID: <07697a42c8ac6ea6ac600cbf0dabbdcbf814da31.1779441786.git.chleroy@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=2953; i=chleroy@kernel.org; h=from:subject:message-id; bh=CxukwNaaHfPCgLLuHd8f2xWMx67xuC8tWT39iKS4wZo=; b=owGbwMvMwCV2d0KB2p7V54MZT6slMWQJaNhfqth079aduR3nLp8+V6t/eN3eGzvOZTu0qwbf/ XhckW9vREcpC4MYF4OsmCLL8f/cu2Z0fUnNn7pLH2YOKxPIEAYuTgGYSNghRoaOKz3vFjPEsF7s ey3xdqeW1IL3oUHBYvVCQidv75VJXsbDyPAp4sfTzolvkqRnxjd/neo2u6hi+odXVcmaO4rd2hK Dq/kA X-Developer-Key: i=chleroy@kernel.org; a=openpgp; fpr=10FFE6F8B390DE17ACC2632368A92FEB01B8DD78 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" In the same spirit as commit fb05121fd6a2 ("signal: Add unsafe_get_compat_sigset()"), implement an 'unsafe' version of copy_siginfo_to_user() in order to use it within user access blocks. For that, also add an 'unsafe' version of clear_user(). This commit adds the generic fallback for unsafe_clear_user(). Architectures wanting to use unsafe_copy_siginfo_to_user() within a user_access_begin() section have to make sure they have their own unsafe_clear_user(). Signed-off-by: Christophe Leroy (CS GROUP) --- include/linux/signal.h | 15 +++++++++++++++ include/linux/uaccess.h | 1 + kernel/signal.c | 5 ----- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/include/linux/signal.h b/include/linux/signal.h index f19816832f05..3ee6c9463f8b 100644 --- a/include/linux/signal.h +++ b/include/linux/signal.h @@ -36,6 +36,21 @@ static inline void copy_siginfo_to_external(siginfo_t *t= o, int copy_siginfo_to_user(siginfo_t __user *to, const kernel_siginfo_t *fro= m); int copy_siginfo_from_user(kernel_siginfo_t *to, const siginfo_t __user *f= rom); =20 +static __always_inline char __user *si_expansion(const siginfo_t __user *i= nfo) +{ + return ((char __user *)info) + sizeof(struct kernel_siginfo); +} + +#define unsafe_copy_siginfo_to_user(to, from, label) do { \ + siginfo_t __user *__ucs_to =3D to; \ + const kernel_siginfo_t *__ucs_from =3D from; \ + char __user *__ucs_expansion =3D si_expansion(__ucs_to); \ + \ + unsafe_copy_to_user(__ucs_to, __ucs_from, \ + sizeof(struct kernel_siginfo), label); \ + unsafe_clear_user(__ucs_expansion, SI_EXPANSION_SIZE, label); \ +} while (0) + enum siginfo_layout { SIL_KILL, SIL_TIMER, diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h index 56328601218c..43e573b172a2 100644 --- a/include/linux/uaccess.h +++ b/include/linux/uaccess.h @@ -636,6 +636,7 @@ do { \ #define unsafe_put_user(x,p,e) unsafe_op_wrap(__put_user(x,p),e) #define unsafe_copy_to_user(d,s,l,e) unsafe_op_wrap(__copy_to_user(d,s,l),= e) #define unsafe_copy_from_user(d,s,l,e) unsafe_op_wrap(__copy_from_user(d,s= ,l),e) +#define unsafe_clear_user(d, l, e) unsafe_op_wrap(__clear_user(d, l), e) static inline unsigned long user_access_save(void) { return 0UL; } static inline void user_access_restore(unsigned long flags) { } #endif /* !user_access_begin */ diff --git a/kernel/signal.c b/kernel/signal.c index 2d102e025883..2c5eb741fe8c 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -3493,11 +3493,6 @@ enum siginfo_layout siginfo_layout(unsigned sig, int= si_code) return layout; } =20 -static inline char __user *si_expansion(const siginfo_t __user *info) -{ - return ((char __user *)info) + sizeof(struct kernel_siginfo); -} - int copy_siginfo_to_user(siginfo_t __user *to, const kernel_siginfo_t *fro= m) { char __user *expansion =3D si_expansion(to); --=20 2.54.0 From nobody Sun May 24 19:33:05 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 109FD3C8197 for ; Fri, 22 May 2026 09:56:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779443817; cv=none; b=nmVnfNN78JlORsAKWYUks+hKBSW6kGbJyVZefYOcw95p3Yfur4cHZwSHkFj9W+MJtOwbdWaS8v+RVKfLx58Ma12qtphObuOU/S21TyMcABhxrPyc0JvPTY7NJMMM2rKo13n9a+JUcHMpb1mNO6QUcBbmmpC/NzDeSnD/2fjc3wo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779443817; c=relaxed/simple; bh=XuOAOSYDASIkE8k1DcwiObr6/h55lx5h+RiNNYy8aAY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=NVE74bLAO0Mls5F0s8k0pbEM8fAV4HAesK2uCLfTTv+Qz4HuJJGHwpBTFIlQw99zQAeU++wFArZ7nhfBSxBgx+cyLNWn7/jjJ9cmMHGFgwZX3mKMUnuXRFfxWGEwuwBLPFU01/49wLNpsk7v83cmRii8gUG4QXmW68msLU17taU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=FPWVhxS6; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="FPWVhxS6" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4A0141F000E9; Fri, 22 May 2026 09:56:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779443815; bh=KetQGnpihDD2vxXf7LRusXJw3y8BnoktxOIVo1JkiuE=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=FPWVhxS6abEj6Wk6gFOxmmr6UOrr890+s7heZe8/fOUS5UVOBRFX97dsWRpgb7YaK rnMYA0kQylA8upBWX0FZvF1tdr8ONj8sJ+ginfH1TRkAfkmnYc2X4wnlMLpcf07R1f 3DTfbM24AXKjQ6FoYLsxFPLlgzyyzgQ1Pt+wJv+CO1agEntrgLhgfHwDouGe/pwk6G /E5S7iUP/VXGkGAE1/4m72Yhps6wh+PYkLpHm6Y6FeLniPes3Zesk0K5OatPEX70Io iZkKfq6ylDva5sT2HLA2em2ubKAOcESOa6S/VeKXS8PhvqWTQF+4F4XGgrOJ1DZwfy uLzHNsBIsiruw== From: "Christophe Leroy (CS GROUP)" To: Michael Ellerman , Nicholas Piggin , Madhavan Srinivasan Cc: "Christophe Leroy (CS GROUP)" , linux-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org Subject: [PATCH v1 7/8] powerpc/uaccess: Add unsafe_clear_user() Date: Fri, 22 May 2026 11:56:07 +0200 Message-ID: X-Mailer: git-send-email 2.54.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=1532; i=chleroy@kernel.org; h=from:subject:message-id; bh=XuOAOSYDASIkE8k1DcwiObr6/h55lx5h+RiNNYy8aAY=; b=owGbwMvMwCV2d0KB2p7V54MZT6slMWQJaNjvkJjaz3Dv4lZeb6npj7TCjacndbLNDT2ltjlL2 8MsYGN7RykLgxgXg6yYIsvx/9y7ZnR9Sc2fuksfZg4rE8gQBi5OAZjIWmZGhjPiVwo4Nm99mie/ o+5Dz9dm27sMs17pzNPbkvIq+/mWviJGhoblz8xW5Zs5Ke1ZOD97ysaP1tob1d7/TulLC+ovrPt hyQ4A X-Developer-Key: i=chleroy@kernel.org; a=openpgp; fpr=10FFE6F8B390DE17ACC2632368A92FEB01B8DD78 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Implement unsafe_clear_user() for powerpc. It's a copy/paste of unsafe_copy_to_user() with value 0 as source. It may be improved in a later patch by using 'dcbz' instruction to zeroize full cache lines at once. Signed-off-by: Christophe Leroy (CS GROUP) --- arch/powerpc/include/asm/uaccess.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/= uaccess.h index e98c628e3899..ef6711d1278b 100644 --- a/arch/powerpc/include/asm/uaccess.h +++ b/arch/powerpc/include/asm/uaccess.h @@ -588,6 +588,26 @@ do { \ unsafe_put_user(*(u8*)(_src + _i), (u8 __user *)(_dst + _i), e); \ } while (0) =20 +#define unsafe_clear_user(d, l, e) \ +do { \ + u8 __user *_dst =3D (u8 __user *)(d); \ + size_t _len =3D (l); \ + int _i; \ + \ + for (_i =3D 0; _i < (_len & ~(sizeof(u64) - 1)); _i +=3D sizeof(u64)) \ + unsafe_put_user(0, (u64 __user *)(_dst + _i), e); \ + if (_len & 4) { \ + unsafe_put_user(0, (u32 __user *)(_dst + _i), e); \ + _i +=3D 4; \ + } \ + if (_len & 2) { \ + unsafe_put_user(0, (u16 __user *)(_dst + _i), e); \ + _i +=3D 2; \ + } \ + if (_len & 1) \ + unsafe_put_user(0, (u8 __user *)(_dst + _i), e); \ +} while (0) + #define arch_get_kernel_nofault(dst, src, type, err_label) \ __get_user_size_goto(*((type *)(dst)), \ (__force type __user *)(src), sizeof(type), err_label) --=20 2.54.0 From nobody Sun May 24 19:33:05 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 71AD23C65FD for ; Fri, 22 May 2026 09:56:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779443819; cv=none; b=BuKUVDGDu7uuKwKRgNm2zBS9bA8PrLk6tMFkQozkBy/v7MmYc982eXtnrVMJuN7yMhlpkk9MV5RndxovQWb7YtBQcWcxvBHgDOWGpJ91+Ei/t7AxIiPiaLhUwsZg/5cfWfQHfGl+FQNq2Z5Q+NAW2WnS+Ecnh8gb3j7Ii48O9bU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779443819; c=relaxed/simple; bh=rIbxm+X12keZqdi4mG1S8vXGOqwRa/TOAViAMLqxvMw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DU9lVRoCyEhSs2P29+oxxb4lPM7NQM0Bns9UItRRAMGc7iYyXNgorK7AMrLv9tm/1CKzTe95OOmwae/PP7klV/lJIQfWqEJPiKNwMWnovmGFAUNG3PCWmiROWevx+aMXcTn9EEkCpvXBFS4ZuHJ2u/mUv5Phul4yfP3TwqKPtBY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=blaxcWEp; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="blaxcWEp" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 793971F00A3D; Fri, 22 May 2026 09:56:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779443818; bh=/rlRShe3uK6rrgQZ4IrnyUDRenTqFqb/izOjWLnR3G0=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=blaxcWEp8Alstxd06rVmlKQUcUEfXjfOvS3jgXpwpaE4e9xfGXyFa5HJ+dTS0Ftai G9Kp9lqTiCbGeSfL0R7ILUI8TW0PTHpuiFpADsTx3Xp2sf9smT+Z0rVEQReYIO/J0W DpcZbplzYDHfL1LKKtOyzbPYzCJNLrgJc0vD70XT6hapkiETHNzgeWeaK/iuMfn0qO gILQ6ErbVRhVG887QcuGdHF1IziYJ/N9KLRY8vP/FeqbLMIEPX+PDoduF7vDWbnIaK Pa0OT3OgqxRKL9Rz9vS61i5q+YCErQ2pd1OTg/V9rZcsUPhEXvyb8XAEG9bXJ8jlhV gFyLAN9bIPMYA== From: "Christophe Leroy (CS GROUP)" To: Michael Ellerman , Nicholas Piggin , Madhavan Srinivasan Cc: "Christophe Leroy (CS GROUP)" , linux-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org Subject: [PATCH v1 8/8] powerpc/signal: Use unsafe_copy_siginfo_to_user() Date: Fri, 22 May 2026 11:56:08 +0200 Message-ID: <4a8b361c988655ab008ee2b205bfb0b246e16cc2.1779441786.git.chleroy@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=3199; i=chleroy@kernel.org; h=from:subject:message-id; bh=rIbxm+X12keZqdi4mG1S8vXGOqwRa/TOAViAMLqxvMw=; b=owGbwMvMwCV2d0KB2p7V54MZT6slMWQJaNi3dT5aZGE+kZFFcu+dtINx/070nHmlf5Yx+cut1 pqWbQvjO0pZGMS4GGTFFFmO/+feNaPrS2r+1F36MHNYmUCGMHBxCsBExOwY/kffWfFwtX6Xa2lY ekV9cO1DG+k/K1suyjquKdHOXenf842R4ZJV6af7ydvNOU8mnVfM6trX513zx3qKxh2LaXtzMuX m8wAA X-Developer-Key: i=chleroy@kernel.org; a=openpgp; fpr=10FFE6F8B390DE17ACC2632368A92FEB01B8DD78 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Use unsafe_copy_siginfo_to_user() in order to do the copy within the user access block. On an mpc 8321 (book3s/32) the improvment is about 5% on a process sending a signal to itself. Signed-off-by: Christophe Leroy (CS GROUP) --- arch/powerpc/kernel/signal_32.c | 18 +++++++++--------- arch/powerpc/kernel/signal_64.c | 5 +---- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_3= 2.c index 6b1fbd95b07d..99a3efa874eb 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c @@ -716,12 +716,6 @@ static long restore_tm_user_regs(struct pt_regs *regs,= struct mcontext __user *s } #endif =20 -#ifdef CONFIG_PPC64 - -#define copy_siginfo_to_user copy_siginfo_to_user32 - -#endif /* CONFIG_PPC64 */ - /* * Set up a signal frame for a "real-time" signal handler * (one which gets siginfo). @@ -735,6 +729,7 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t *= oldset, struct pt_regs *regs =3D tsk->thread.regs; /* Save the thread's msr before get_tm_stackpointer() changes it */ unsigned long msr =3D regs->msr; + compat_siginfo_t uinfo; =20 /* Set up Signal Frame */ frame =3D get_sigframe(ksig, tsk, sizeof(*frame), 1); @@ -744,6 +739,9 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t *= oldset, else prepare_save_user_regs(1); =20 + if (IS_ENABLED(CONFIG_COMPAT)) + copy_siginfo_to_external32(&uinfo, &ksig->info); + scoped_user_rw_access_size(newsp, __SIGNAL_FRAMESIZE + 16 + sizeof(*frame= ), badframe) { struct mcontext __user *mctx; struct mcontext __user *tm_mctx =3D NULL; @@ -785,14 +783,16 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t= *oldset, asm("dcbst %y0; sync; icbi %y0; sync" :: "Z" (mctx->mc_pad[0])); } unsafe_put_sigset_t(&frame->uc.uc_sigmask, oldset, badframe); + if (IS_ENABLED(CONFIG_COMPAT)) + unsafe_copy_to_user(&frame->info, &uinfo, sizeof(frame->info), badframe= ); + else + unsafe_copy_siginfo_to_user((void __user *)&frame->info, &ksig->info, + badframe); =20 /* create a stack frame for the caller of the handler */ unsafe_put_user(regs->gpr[1], newsp, badframe); } =20 - if (copy_siginfo_to_user(&frame->info, &ksig->info)) - goto badframe; - regs->link =3D tramp; =20 #ifdef CONFIG_PPC_FPU_REGS diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_6= 4.c index 67de29cf581a..fa18ac43eb2a 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c @@ -893,14 +893,11 @@ int handle_rt_signal64(struct ksignal *ksig, sigset_t= *set, } =20 unsafe_copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set), badframe); + unsafe_copy_siginfo_to_user(&frame->info, &ksig->info, badframe); /* Allocate a dummy caller frame for the signal handler. */ unsafe_put_user(regs->gpr[1], newsp, badframe); } =20 - /* Save the siginfo outside of the unsafe block. */ - if (copy_siginfo_to_user(&frame->info, &ksig->info)) - goto badframe; - /* Make sure signal handler doesn't get spurious FP exceptions */ tsk->thread.fp_state.fpscr =3D 0; =20 --=20 2.54.0