projects/linux·commit 52907f0e

powerpc/signal64: use scoped user access in setup_trampoline()

52907f0e · Linus Torvalds <[email protected]> · 2026-10-20 10:05:11 -10:00

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 <[email protected]>
Commit
52907f0e4765cba370ef07d536cf4e4ecea8c0ba
Parents
2f0bb47c

Changes

1 files changed · +15 −12

FileStatusAddDelContent
arch/powerpc/kernel/signal_64.cmodified+15−12View file

arch/powerpc/kernel/signal_64.c

View file
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index 0610573..b2003a1 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;
}
/*