diff options
author | Helge Deller <deller@gmx.de> | 2021-09-05 11:53:32 +0200 |
---|---|---|
committer | Helge Deller <deller@gmx.de> | 2021-09-09 12:44:31 +0200 |
commit | 3e4a1aff2a97cb4fd7f0268e4b69e8c9d3641277 (patch) | |
tree | f6ce820b7ad357598ac07a950e1dc38959ac4e72 /arch | |
parent | ea4b3fca18adc81e6a965b2ad0668f38d5d3485b (diff) | |
download | lwn-3e4a1aff2a97cb4fd7f0268e4b69e8c9d3641277.tar.gz lwn-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.c | 17 |
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 * |