parisc: Check user signal stack trampoline is inside TASK_SIZE

Add some additional checks to ensure the signal stack is inside
userspace bounds.

Signed-off-by: Helge Deller <deller@gmx.de>
This commit is contained in:
Helge Deller 2021-09-05 11:53:32 +02:00
parent ea4b3fca18
commit 3e4a1aff2a
1 changed files with 10 additions and 7 deletions

View File

@ -237,18 +237,22 @@ setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs,
#endif #endif
usp = (regs->gr[30] & ~(0x01UL)); usp = (regs->gr[30] & ~(0x01UL));
sigframe_size = PARISC_RT_SIGFRAME_SIZE;
#ifdef CONFIG_64BIT #ifdef CONFIG_64BIT
if (is_compat_task()) { if (is_compat_task()) {
/* The gcc alloca implementation leaves garbage in the upper 32 bits of sp */ /* The gcc alloca implementation leaves garbage in the upper 32 bits of sp */
usp = (compat_uint_t)usp; usp = (compat_uint_t)usp;
sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
} }
#endif #endif
/*FIXME: frame_size parameter is unused, remove it. */ frame = get_sigframe(&ksig->ka, usp, sigframe_size);
frame = get_sigframe(&ksig->ka, usp, sizeof(*frame));
DBG(1,"SETUP_RT_FRAME: START\n"); DBG(1,"SETUP_RT_FRAME: START\n");
DBG(1,"setup_rt_frame: frame %p info %p\n", frame, ksig->info); DBG(1,"setup_rt_frame: frame %p info %p\n", frame, ksig->info);
start = (unsigned long) frame;
if (start >= user_addr_max() - sigframe_size)
return -EFAULT;
#ifdef CONFIG_64BIT #ifdef CONFIG_64BIT
@ -343,11 +347,6 @@ setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs,
/* The syscall return path will create IAOQ values from r31. /* The syscall return path will create IAOQ values from r31.
*/ */
sigframe_size = PARISC_RT_SIGFRAME_SIZE;
#ifdef CONFIG_64BIT
if (is_compat_task())
sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
#endif
if (in_syscall) { if (in_syscall) {
regs->gr[31] = haddr; regs->gr[31] = haddr;
#ifdef CONFIG_64BIT #ifdef CONFIG_64BIT
@ -518,6 +517,10 @@ insert_restart_trampoline(struct pt_regs *regs)
unsigned long end = (unsigned long) &usp[5]; unsigned long end = (unsigned long) &usp[5];
long err = 0; long err = 0;
/* check that we don't exceed the stack */
if (A(&usp[0]) >= user_addr_max() - 5 * sizeof(int))
return;
/* Setup a trampoline to restart the syscall /* Setup a trampoline to restart the syscall
* with __NR_restart_syscall * with __NR_restart_syscall
* *