From 52907f0e4765cba370ef07d536cf4e4ecea8c0ba Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 20 Oct 2026 10:05:11 -1000 Subject: [PATCH] powerpc/signal64: use scoped user access in setup_trampoline() setup_trampoline() writes the seven words of the on-stack sigreturn trampoline with __put_user(), relying on the frame having been checked when the frame setup opened its user write access. It is called after that access has been closed again, so each of the seven writes opens and closes user access on its own. Write them inside one scoped_user_write_access_size() covering the whole trampoline instead. Everything in it is a store, so a write-only window is enough, and the instruction cache flush stays outside it. This is part of getting rid of __get_user() and __put_user() entirely. Signed-off-by: Linus Torvalds --- arch/powerpc/kernel/signal_64.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index 0610573cfcd5..b2003a10b369 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c @@ -624,24 +624,27 @@ static long restore_tm_sigcontexts(struct task_struct *tsk, struct sigcontext __ static long setup_trampoline(unsigned int syscall, unsigned int __user *tramp) { int i; - long err = 0; - /* Call the handler and pop the dummy stackframe*/ - err |= __put_user(PPC_RAW_BCTRL(), &tramp[0]); - err |= __put_user(PPC_RAW_ADDI(_R1, _R1, __SIGNAL_FRAMESIZE), &tramp[1]); + scoped_user_write_access_size(tramp, TRAMP_SIZE * sizeof(*tramp), efault) { + /* Call the handler and pop the dummy stackframe*/ + unsafe_put_user(PPC_RAW_BCTRL(), &tramp[0], efault); + unsafe_put_user(PPC_RAW_ADDI(_R1, _R1, __SIGNAL_FRAMESIZE), &tramp[1], efault); - err |= __put_user(PPC_RAW_LI(_R0, syscall), &tramp[2]); - err |= __put_user(PPC_RAW_SC(), &tramp[3]); + unsafe_put_user(PPC_RAW_LI(_R0, syscall), &tramp[2], efault); + unsafe_put_user(PPC_RAW_SC(), &tramp[3], efault); - /* Minimal traceback info */ - for (i=TRAMP_TRACEBACK; i < TRAMP_SIZE ;i++) - err |= __put_user(0, &tramp[i]); + /* Minimal traceback info */ + for (i=TRAMP_TRACEBACK; i < TRAMP_SIZE ;i++) + unsafe_put_user(0, &tramp[i], efault); + } - if (!err) - flush_icache_range((unsigned long) &tramp[0], + flush_icache_range((unsigned long) &tramp[0], (unsigned long) &tramp[TRAMP_SIZE]); - return err; + return 0; + +efault: + return -EFAULT; } /*