From 894ca05f4add52809834b79f0e9399e44f81cea7 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 23 Dec 2012 03:41:17 -0500 Subject: [PATCH] --- yaml --- r: 356746 b: refs/heads/master c: 99b06feb0f7c99f171cb962d0e6a17f81625abd3 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/arch/sh/Kconfig | 3 - trunk/arch/sh/include/asm/syscalls_32.h | 6 ++ trunk/arch/sh/include/uapi/asm/signal.h | 2 - trunk/arch/sh/kernel/signal_32.c | 63 +++++++++++++++++++- trunk/arch/sh/kernel/signal_64.c | 62 ++++++++++++++++++- trunk/arch/sparc/Kconfig | 1 + trunk/arch/sparc/include/asm/compat_signal.h | 6 -- trunk/arch/sparc/kernel/entry.S | 8 --- trunk/arch/sparc/kernel/signal32.c | 48 ++------------- trunk/arch/sparc/kernel/signal_32.c | 17 +----- trunk/arch/sparc/kernel/signal_64.c | 7 +-- trunk/arch/sparc/kernel/syscalls.S | 6 -- trunk/arch/sparc/kernel/systbls_64.S | 2 +- 14 files changed, 139 insertions(+), 94 deletions(-) diff --git a/[refs] b/[refs] index f0355befbb73..7dbad5dbfabb 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 0679a858c5439bf4bc05fd211d3690f82fefa5b6 +refs/heads/master: 99b06feb0f7c99f171cb962d0e6a17f81625abd3 diff --git a/trunk/arch/sh/Kconfig b/trunk/arch/sh/Kconfig index b5fd9f3c9925..babc2b826c5c 100644 --- a/trunk/arch/sh/Kconfig +++ b/trunk/arch/sh/Kconfig @@ -40,9 +40,6 @@ config SUPERH select GENERIC_STRNLEN_USER select HAVE_MOD_ARCH_SPECIFIC if DWARF_UNWINDER select MODULES_USE_ELF_RELA - select GENERIC_SIGALTSTACK - select OLD_SIGSUSPEND - select OLD_SIGACTION help The SuperH is a RISC processor targeted for use in embedded systems and consumer electronics; it was also used in the Sega Dreamcast diff --git a/trunk/arch/sh/include/asm/syscalls_32.h b/trunk/arch/sh/include/asm/syscalls_32.h index 4f97df87d7d5..cc25485996bb 100644 --- a/trunk/arch/sh/include/asm/syscalls_32.h +++ b/trunk/arch/sh/include/asm/syscalls_32.h @@ -9,6 +9,12 @@ struct pt_regs; +asmlinkage int sys_sigsuspend(old_sigset_t mask); +asmlinkage int sys_sigaction(int sig, const struct old_sigaction __user *act, + struct old_sigaction __user *oact); +asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, + unsigned long r6, unsigned long r7, + struct pt_regs __regs); asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, struct pt_regs __regs); diff --git a/trunk/arch/sh/include/uapi/asm/signal.h b/trunk/arch/sh/include/uapi/asm/signal.h index cb96d02f55a4..9ac530a90bce 100644 --- a/trunk/arch/sh/include/uapi/asm/signal.h +++ b/trunk/arch/sh/include/uapi/asm/signal.h @@ -5,13 +5,11 @@ #include -#ifndef __KERNEL__ struct old_sigaction { __sighandler_t sa_handler; old_sigset_t sa_mask; unsigned long sa_flags; void (*sa_restorer)(void); }; -#endif #endif /* __ASM_SH_SIGNAL_H */ diff --git a/trunk/arch/sh/kernel/signal_32.c b/trunk/arch/sh/kernel/signal_32.c index 6af6e7c5cac8..2f1f65356c0c 100644 --- a/trunk/arch/sh/kernel/signal_32.c +++ b/trunk/arch/sh/kernel/signal_32.c @@ -46,6 +46,60 @@ struct fdpic_func_descriptor { */ #define UNWINDGUARD 64 +/* + * Atomically swap in the new signal mask, and wait for a signal. + */ +asmlinkage int +sys_sigsuspend(old_sigset_t mask) +{ + sigset_t blocked; + siginitset(&blocked, mask); + return sigsuspend(&blocked); +} + +asmlinkage int +sys_sigaction(int sig, const struct old_sigaction __user *act, + struct old_sigaction __user *oact) +{ + struct k_sigaction new_ka, old_ka; + int ret; + + if (act) { + old_sigset_t mask; + if (!access_ok(VERIFY_READ, act, sizeof(*act)) || + __get_user(new_ka.sa.sa_handler, &act->sa_handler) || + __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) || + __get_user(new_ka.sa.sa_flags, &act->sa_flags) || + __get_user(mask, &act->sa_mask)) + return -EFAULT; + siginitset(&new_ka.sa.sa_mask, mask); + } + + ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); + + if (!ret && oact) { + if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || + __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || + __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) || + __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || + __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask)) + return -EFAULT; + } + + return ret; +} + +asmlinkage int +sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, + unsigned long r6, unsigned long r7, + struct pt_regs __regs) +{ + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); + + return do_sigaltstack(uss, uoss, regs->regs[15]); +} + + /* * Do a signal return; undo the signal stack. */ @@ -203,7 +257,8 @@ asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5, if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0)) goto badframe; - if (restore_altstack(&frame->uc.uc_stack)) + if (do_sigaltstack(&frame->uc.uc_stack, NULL, + regs->regs[15]) == -EFAULT) goto badframe; return r0; @@ -368,7 +423,11 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(NULL, &frame->uc.uc_link); - err |= __save_altstack(&frame->uc.uc_stack, regs->regs[15]); + err |= __put_user((void *)current->sas_ss_sp, + &frame->uc.uc_stack.ss_sp); + err |= __put_user(sas_ss_flags(regs->regs[15]), + &frame->uc.uc_stack.ss_flags); + err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); diff --git a/trunk/arch/sh/kernel/signal_64.c b/trunk/arch/sh/kernel/signal_64.c index 23d4c71c91af..d867cd95a622 100644 --- a/trunk/arch/sh/kernel/signal_64.c +++ b/trunk/arch/sh/kernel/signal_64.c @@ -127,6 +127,58 @@ static void do_signal(struct pt_regs *regs) restore_saved_sigmask(); } +/* + * Atomically swap in the new signal mask, and wait for a signal. + */ +asmlinkage int +sys_sigsuspend(old_sigset_t mask) +{ + sigset_t blocked; + siginitset(&blocked, mask); + return sigsuspend(&blocked); +} + +asmlinkage int +sys_sigaction(int sig, const struct old_sigaction __user *act, + struct old_sigaction __user *oact) +{ + struct k_sigaction new_ka, old_ka; + int ret; + + if (act) { + old_sigset_t mask; + if (!access_ok(VERIFY_READ, act, sizeof(*act)) || + __get_user(new_ka.sa.sa_handler, &act->sa_handler) || + __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) || + __get_user(new_ka.sa.sa_flags, &act->sa_flags) || + __get_user(mask, &act->sa_mask)) + return -EFAULT; + siginitset(&new_ka.sa.sa_mask, mask); + } + + ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); + + if (!ret && oact) { + if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || + __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || + __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) || + __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || + __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask)) + return -EFAULT; + } + + return ret; +} + +asmlinkage int +sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, + unsigned long r4, unsigned long r5, unsigned long r6, + unsigned long r7, + struct pt_regs * regs) +{ + return do_sigaltstack(uss, uoss, REF_REG_SP); +} + /* * Do a signal return; undo the signal stack. */ @@ -312,7 +364,9 @@ asmlinkage int sys_rt_sigreturn(unsigned long r2, unsigned long r3, goto badframe; regs->pc -= 4; - if (restore_altstack(&frame->uc.uc_stack)) + /* It is more difficult to avoid calling this function than to + call it and ignore errors. */ + if (do_sigaltstack(&frame->uc.uc_stack, NULL, REF_REG_SP) == -EFAULT) goto badframe; return (int) ret; @@ -506,7 +560,11 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(0, &frame->uc.uc_link); - err |= __save_altstack(&frame->uc.uc_stack, regs->regs[REG_SP]); + err |= __put_user((void *)current->sas_ss_sp, + &frame->uc.uc_stack.ss_sp); + err |= __put_user(sas_ss_flags(regs->regs[REG_SP]), + &frame->uc.uc_stack.ss_flags); + err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); diff --git a/trunk/arch/sparc/Kconfig b/trunk/arch/sparc/Kconfig index 89dde2f0653a..3274f5dc8deb 100644 --- a/trunk/arch/sparc/Kconfig +++ b/trunk/arch/sparc/Kconfig @@ -42,6 +42,7 @@ config SPARC select GENERIC_STRNLEN_USER select MODULES_USE_ELF_RELA select ODD_RT_SIGACTION + select GENERIC_SIGALTSTACK config SPARC32 def_bool !64BIT diff --git a/trunk/arch/sparc/include/asm/compat_signal.h b/trunk/arch/sparc/include/asm/compat_signal.h index b759eab9b51c..9ed1f128b4d1 100644 --- a/trunk/arch/sparc/include/asm/compat_signal.h +++ b/trunk/arch/sparc/include/asm/compat_signal.h @@ -18,12 +18,6 @@ struct __old_sigaction32 { unsigned int sa_flags; unsigned sa_restorer; /* not used by Linux/SPARC yet */ }; - -typedef struct sigaltstack32 { - u32 ss_sp; - int ss_flags; - compat_size_t ss_size; -} stack_t32; #endif #endif /* !(_COMPAT_SIGNAL_H) */ diff --git a/trunk/arch/sparc/kernel/entry.S b/trunk/arch/sparc/kernel/entry.S index 21fd1a8f47d2..e2a030045089 100644 --- a/trunk/arch/sparc/kernel/entry.S +++ b/trunk/arch/sparc/kernel/entry.S @@ -819,14 +819,6 @@ sys_sparc_pipe: call sparc_pipe mov %l5, %o7 - .align 4 - .globl sys_sigaltstack -sys_sigaltstack: - mov %o7, %l5 - mov %fp, %o2 - call do_sigaltstack - mov %l5, %o7 - .align 4 .globl sys_sigstack sys_sigstack: diff --git a/trunk/arch/sparc/kernel/signal32.c b/trunk/arch/sparc/kernel/signal32.c index 53e48f721ce3..9d9eb91d0de1 100644 --- a/trunk/arch/sparc/kernel/signal32.c +++ b/trunk/arch/sparc/kernel/signal32.c @@ -61,7 +61,7 @@ struct rt_signal_frame32 { compat_sigset_t mask; /* __siginfo_fpu_t * */ u32 fpu_save; unsigned int insns[2]; - stack_t32 stack; + compat_stack_t stack; unsigned int extra_size; /* Should be sizeof(siginfo_extra_v8plus_t) */ /* Only valid if (regs.psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS */ siginfo_extra_v8plus_t v8plus; @@ -230,13 +230,11 @@ void do_sigreturn32(struct pt_regs *regs) asmlinkage void do_rt_sigreturn32(struct pt_regs *regs) { struct rt_signal_frame32 __user *sf; - unsigned int psr, pc, npc, u_ss_sp; + unsigned int psr, pc, npc; compat_uptr_t fpu_save; compat_uptr_t rwin_save; - mm_segment_t old_fs; sigset_t set; compat_sigset_t seta; - stack_t st; int err, i; /* Always make any pending restarted system calls return -EINTR */ @@ -295,20 +293,10 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs) if (!err && fpu_save) err |= restore_fpu_state(regs, compat_ptr(fpu_save)); err |= copy_from_user(&seta, &sf->mask, sizeof(compat_sigset_t)); - err |= __get_user(u_ss_sp, &sf->stack.ss_sp); - st.ss_sp = compat_ptr(u_ss_sp); - err |= __get_user(st.ss_flags, &sf->stack.ss_flags); - err |= __get_user(st.ss_size, &sf->stack.ss_size); + err |= compat_restore_altstack(&sf->stack); if (err) goto segv; - /* It is more difficult to avoid calling this function than to - call it and ignore errors. */ - old_fs = get_fs(); - set_fs(KERNEL_DS); - do_sigaltstack((stack_t __user *) &st, NULL, (unsigned long)sf); - set_fs(old_fs); - err |= __get_user(rwin_save, &sf->rwin_save); if (!err && rwin_save) { if (restore_rwin_state(compat_ptr(rwin_save))) @@ -642,9 +630,7 @@ static int setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs, err |= copy_siginfo_to_user32(&sf->info, info); /* Setup sigaltstack */ - err |= __put_user(current->sas_ss_sp, &sf->stack.ss_sp); - err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &sf->stack.ss_flags); - err |= __put_user(current->sas_ss_size, &sf->stack.ss_size); + err |= __compat_save_altstack(&sf->stack, regs->u_regs[UREG_FP]); switch (_NSIG_WORDS) { case 4: seta.sig[7] = (oldset->sig[3] >> 32); @@ -856,29 +842,3 @@ asmlinkage int do_sys32_sigstack(u32 u_ssptr, u32 u_ossptr, unsigned long sp) out: return ret; } - -asmlinkage long do_sys32_sigaltstack(u32 ussa, u32 uossa, unsigned long sp) -{ - stack_t uss, uoss; - u32 u_ss_sp = 0; - int ret; - mm_segment_t old_fs; - stack_t32 __user *uss32 = compat_ptr(ussa); - stack_t32 __user *uoss32 = compat_ptr(uossa); - - if (ussa && (get_user(u_ss_sp, &uss32->ss_sp) || - __get_user(uss.ss_flags, &uss32->ss_flags) || - __get_user(uss.ss_size, &uss32->ss_size))) - return -EFAULT; - uss.ss_sp = compat_ptr(u_ss_sp); - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = do_sigaltstack(ussa ? (stack_t __user *) &uss : NULL, - uossa ? (stack_t __user *) &uoss : NULL, sp); - set_fs(old_fs); - if (!ret && uossa && (put_user(ptr_to_compat(uoss.ss_sp), &uoss32->ss_sp) || - __put_user(uoss.ss_flags, &uoss32->ss_flags) || - __put_user(uoss.ss_size, &uoss32->ss_size))) - return -EFAULT; - return ret; -} diff --git a/trunk/arch/sparc/kernel/signal_32.c b/trunk/arch/sparc/kernel/signal_32.c index 68f9c8650af4..7391fa89651f 100644 --- a/trunk/arch/sparc/kernel/signal_32.c +++ b/trunk/arch/sparc/kernel/signal_32.c @@ -141,9 +141,7 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs) unsigned int psr, pc, npc; __siginfo_fpu_t __user *fpu_save; __siginfo_rwin_t __user *rwin_save; - mm_segment_t old_fs; sigset_t set; - stack_t st; int err; synchronize_user_stack(); @@ -171,8 +169,7 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs) if (!err && fpu_save) err |= restore_fpu_state(regs, fpu_save); err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t)); - - err |= __copy_from_user(&st, &sf->stack, sizeof(stack_t)); + err |= restore_altstack(&sf->stack); if (err) goto segv; @@ -180,14 +177,6 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs) regs->pc = pc; regs->npc = npc; - /* It is more difficult to avoid calling this function than to - * call it and ignore errors. - */ - old_fs = get_fs(); - set_fs(KERNEL_DS); - do_sigaltstack((const stack_t __user *) &st, NULL, (unsigned long)sf); - set_fs(old_fs); - err |= __get_user(rwin_save, &sf->rwin_save); if (!err && rwin_save) { if (restore_rwin_state(rwin_save)) @@ -391,9 +380,7 @@ static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, err |= __copy_to_user(&sf->mask, &oldset->sig[0], sizeof(sigset_t)); /* Setup sigaltstack */ - err |= __put_user(current->sas_ss_sp, &sf->stack.ss_sp); - err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &sf->stack.ss_flags); - err |= __put_user(current->sas_ss_size, &sf->stack.ss_size); + err |= __save_altstack(&sf->stack, regs->u_regs[UREG_FP]); if (!wsaved) { err |= __copy_to_user(sf, (char *) regs->u_regs[UREG_FP], diff --git a/trunk/arch/sparc/kernel/signal_64.c b/trunk/arch/sparc/kernel/signal_64.c index 689e1ba62809..176e0e7b8f60 100644 --- a/trunk/arch/sparc/kernel/signal_64.c +++ b/trunk/arch/sparc/kernel/signal_64.c @@ -295,7 +295,8 @@ void do_rt_sigreturn(struct pt_regs *regs) err |= restore_fpu_state(regs, fpu_save); err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t)); - if (err || do_sigaltstack(&sf->stack, NULL, (unsigned long)sf) == -EFAULT) + err |= restore_altstack(&sf->stack); + if (err) goto segv; err |= __get_user(rwin_save, &sf->rwin_save); @@ -403,9 +404,7 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, } /* Setup sigaltstack */ - err |= __put_user(current->sas_ss_sp, &sf->stack.ss_sp); - err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &sf->stack.ss_flags); - err |= __put_user(current->sas_ss_size, &sf->stack.ss_size); + err |= __save_altstack(&sf->stack, regs->u_regs[UREG_FP]); err |= copy_to_user(&sf->mask, oldset, sizeof(sigset_t)); diff --git a/trunk/arch/sparc/kernel/syscalls.S b/trunk/arch/sparc/kernel/syscalls.S index e0fed7711a94..22a1098961f5 100644 --- a/trunk/arch/sparc/kernel/syscalls.S +++ b/trunk/arch/sparc/kernel/syscalls.S @@ -25,16 +25,10 @@ sys_nis_syscall: sys_memory_ordering: ba,pt %xcc, sparc_memory_ordering add %sp, PTREGS_OFF, %o1 -sys_sigaltstack: - ba,pt %xcc, do_sigaltstack - add %i6, STACK_BIAS, %o2 #ifdef CONFIG_COMPAT sys32_sigstack: ba,pt %xcc, do_sys32_sigstack mov %i6, %o2 -sys32_sigaltstack: - ba,pt %xcc, do_sys32_sigaltstack - mov %i6, %o2 #endif .align 32 #ifdef CONFIG_COMPAT diff --git a/trunk/arch/sparc/kernel/systbls_64.S b/trunk/arch/sparc/kernel/systbls_64.S index 1009ecb92678..83ec8d467083 100644 --- a/trunk/arch/sparc/kernel/systbls_64.S +++ b/trunk/arch/sparc/kernel/systbls_64.S @@ -23,7 +23,7 @@ sys_call_table32: /*10*/ .word sys_unlink, sunos_execv, sys_chdir, sys_chown16, sys32_mknod /*15*/ .word sys_chmod, sys_lchown16, sys_brk, sys_nis_syscall, sys32_lseek /*20*/ .word sys_getpid, sys_capget, sys_capset, sys_setuid16, sys_getuid16 -/*25*/ .word sys32_vmsplice, compat_sys_ptrace, sys_alarm, sys32_sigaltstack, sys_pause +/*25*/ .word sys32_vmsplice, compat_sys_ptrace, sys_alarm, compat_sys_sigaltstack, sys_pause /*30*/ .word compat_sys_utime, sys_lchown, sys_fchown, sys32_access, sys32_nice .word sys_chown, sys_sync, sys32_kill, compat_sys_newstat, sys32_sendfile /*40*/ .word compat_sys_newlstat, sys_dup, sys_sparc_pipe, compat_sys_times, sys_getuid