summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorHelge Deller <deller@gmx.de>2021-09-05 11:53:32 +0200
committerHelge Deller <deller@gmx.de>2021-09-09 12:44:31 +0200
commit3e4a1aff2a97cb4fd7f0268e4b69e8c9d3641277 (patch)
treef6ce820b7ad357598ac07a950e1dc38959ac4e72 /arch
parentparisc: Drop useless debug info and comments from signal.c (diff)
downloadlinux-3e4a1aff2a97cb4fd7f0268e4b69e8c9d3641277.tar.xz
linux-3e4a1aff2a97cb4fd7f0268e4b69e8c9d3641277.zip
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>
Diffstat (limited to 'arch')
-rw-r--r--arch/parisc/kernel/signal.c17
1 files changed, 10 insertions, 7 deletions
diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c
index 77db707ce391..46b1050640b8 100644
--- a/arch/parisc/kernel/signal.c
+++ b/arch/parisc/kernel/signal.c
@@ -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
*