parisc: Check user signal stack trampoline is inside TASK_SIZE
authorHelge Deller <deller@gmx.de>
Sun, 5 Sep 2021 09:53:32 +0000 (11:53 +0200)
committerHelge Deller <deller@gmx.de>
Thu, 9 Sep 2021 10:44:31 +0000 (12:44 +0200)
Add some additional checks to ensure the signal stack is inside
userspace bounds.

Signed-off-by: Helge Deller <deller@gmx.de>
arch/parisc/kernel/signal.c

index 77db707..46b1050 100644 (file)
@@ -237,18 +237,22 @@ setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs,
 #endif
        
        usp = (regs->gr[30] & ~(0x01UL));
+       sigframe_size = PARISC_RT_SIGFRAME_SIZE;
 #ifdef CONFIG_64BIT
        if (is_compat_task()) {
                /* The gcc alloca implementation leaves garbage in the upper 32 bits of sp */
                usp = (compat_uint_t)usp;
+               sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
        }
 #endif
-       /*FIXME: frame_size parameter is unused, remove it. */
-       frame = get_sigframe(&ksig->ka, usp, sizeof(*frame));
+       frame = get_sigframe(&ksig->ka, usp, sigframe_size);
 
        DBG(1,"SETUP_RT_FRAME: START\n");
        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
 
@@ -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.
         */
-       sigframe_size = PARISC_RT_SIGFRAME_SIZE;
-#ifdef CONFIG_64BIT
-       if (is_compat_task())
-               sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
-#endif
        if (in_syscall) {
                regs->gr[31] = haddr;
 #ifdef CONFIG_64BIT
@@ -518,6 +517,10 @@ insert_restart_trampoline(struct pt_regs *regs)
                unsigned long end  = (unsigned long) &usp[5];
                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
                 * with __NR_restart_syscall
                 *