From: Al Viro Date: Sun, 23 Dec 2012 08:13:40 +0000 (-0500) Subject: mips: switch to generic sigaltstack X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=ea536ad4f231a0055792d9b144715605cbd670c1;p=linux-beck.git mips: switch to generic sigaltstack Signed-off-by: Al Viro --- diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 2ac626ab9d43..a8a41e091d04 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -41,6 +41,7 @@ config MIPS select HAVE_MOD_ARCH_SPECIFIC select MODULES_USE_ELF_REL if MODULES select MODULES_USE_ELF_RELA if MODULES && 64BIT + select GENERIC_SIGALTSTACK menu "Machine selection" diff --git a/arch/mips/include/asm/compat.h b/arch/mips/include/asm/compat.h index 3c5d1464b7bd..ebaae9649f8a 100644 --- a/arch/mips/include/asm/compat.h +++ b/arch/mips/include/asm/compat.h @@ -288,6 +288,14 @@ struct compat_shmid64_ds { compat_ulong_t __unused2; }; +/* MIPS has unusual order of fields in stack_t */ +typedef struct compat_sigaltstack { + compat_uptr_t ss_sp; + compat_size_t ss_size; + int ss_flags; +} compat_stack_t; +#define compat_sigaltstack compat_sigaltstack + static inline int is_compat_task(void) { return test_thread_flag(TIF_32BIT_ADDR); diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index c29ac197f446..7388e25984b2 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S @@ -233,7 +233,7 @@ EXPORT(sysn32_call_table) PTR compat_sys_rt_sigtimedwait PTR sys_32_rt_sigqueueinfo PTR sysn32_rt_sigsuspend - PTR sys32_sigaltstack + PTR compat_sys_sigaltstack PTR compat_sys_utime /* 6130 */ PTR sys_mknod PTR sys_32_personality diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index cf3e75e46650..07fcd818ad3a 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S @@ -398,7 +398,7 @@ sys_call_table: PTR sys_getcwd PTR sys_capget PTR sys_capset /* 4205 */ - PTR sys32_sigaltstack + PTR compat_sys_sigaltstack PTR sys_32_sendfile PTR sys_ni_syscall PTR sys_ni_syscall diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index 4d790d1f03d6..eab30865b2bd 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c @@ -313,15 +313,6 @@ SYSCALL_DEFINE3(sigaction, int, sig, const struct sigaction __user *, act, } #endif -asmlinkage int sys_sigaltstack(nabi_no_regargs struct pt_regs regs) -{ - const stack_t __user *uss = (const stack_t __user *) regs.regs[4]; - stack_t __user *uoss = (stack_t __user *) regs.regs[5]; - unsigned long usp = regs.regs[29]; - - return do_sigaltstack(uss, uoss, usp); -} - #ifdef CONFIG_TRAD_SIGNALS asmlinkage void sys_sigreturn(nabi_no_regargs struct pt_regs regs) { @@ -378,9 +369,8 @@ asmlinkage void sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs) else if (sig) force_sig(sig, current); - /* It is more difficult to avoid calling this function than to - call it and ignore errors. */ - do_sigaltstack(&frame->rs_uc.uc_stack, NULL, regs.regs[29]); + if (restore_altstack(&frame->rs_uc.uc_stack)) + goto badframe; /* * Don't let your children do this ... @@ -457,12 +447,7 @@ static int setup_rt_frame(void *sig_return, struct k_sigaction *ka, /* Create the ucontext. */ err |= __put_user(0, &frame->rs_uc.uc_flags); err |= __put_user(NULL, &frame->rs_uc.uc_link); - err |= __put_user((void __user *)current->sas_ss_sp, - &frame->rs_uc.uc_stack.ss_sp); - err |= __put_user(sas_ss_flags(regs->regs[29]), - &frame->rs_uc.uc_stack.ss_flags); - err |= __put_user(current->sas_ss_size, - &frame->rs_uc.uc_stack.ss_size); + err |= __save_altstack(&frame->rs_uc.uc_stack, regs->regs[29]); err |= setup_sigcontext(regs, &frame->rs_uc.uc_mcontext); err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set)); diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c index da1b56a39ac7..c51e5df4297b 100644 --- a/arch/mips/kernel/signal32.c +++ b/arch/mips/kernel/signal32.c @@ -61,17 +61,10 @@ struct sigaction32 { compat_sigset_t sa_mask; }; -/* IRIX compatible stack_t */ -typedef struct sigaltstack32 { - s32 ss_sp; - compat_size_t ss_size; - int ss_flags; -} stack32_t; - struct ucontext32 { u32 uc_flags; s32 uc_link; - stack32_t uc_stack; + compat_stack_t uc_stack; struct sigcontext32 uc_mcontext; compat_sigset_t uc_sigmask; /* mask last for extensibility */ }; @@ -350,45 +343,6 @@ SYSCALL_DEFINE3(32_sigaction, long, sig, const struct sigaction32 __user *, act, return ret; } -asmlinkage int sys32_sigaltstack(nabi_no_regargs struct pt_regs regs) -{ - const stack32_t __user *uss = (const stack32_t __user *) regs.regs[4]; - stack32_t __user *uoss = (stack32_t __user *) regs.regs[5]; - unsigned long usp = regs.regs[29]; - stack_t kss, koss; - int ret, err = 0; - mm_segment_t old_fs = get_fs(); - s32 sp; - - if (uss) { - if (!access_ok(VERIFY_READ, uss, sizeof(*uss))) - return -EFAULT; - err |= __get_user(sp, &uss->ss_sp); - kss.ss_sp = (void __user *) (long) sp; - err |= __get_user(kss.ss_size, &uss->ss_size); - err |= __get_user(kss.ss_flags, &uss->ss_flags); - if (err) - return -EFAULT; - } - - set_fs(KERNEL_DS); - ret = do_sigaltstack(uss ? (stack_t __user *)&kss : NULL, - uoss ? (stack_t __user *)&koss : NULL, usp); - set_fs(old_fs); - - if (!ret && uoss) { - if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss))) - return -EFAULT; - sp = (int) (unsigned long) koss.ss_sp; - err |= __put_user(sp, &uoss->ss_sp); - err |= __put_user(koss.ss_size, &uoss->ss_size); - err |= __put_user(koss.ss_flags, &uoss->ss_flags); - if (err) - return -EFAULT; - } - return ret; -} - int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) { int err; @@ -490,10 +444,7 @@ badframe: asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) { struct rt_sigframe32 __user *frame; - mm_segment_t old_fs; sigset_t set; - stack_t st; - s32 sp; int sig; frame = (struct rt_sigframe32 __user *) regs.regs[29]; @@ -510,22 +461,9 @@ asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) else if (sig) force_sig(sig, current); - /* The ucontext contains a stack32_t, so we must convert! */ - if (__get_user(sp, &frame->rs_uc.uc_stack.ss_sp)) - goto badframe; - st.ss_sp = (void __user *)(long) sp; - if (__get_user(st.ss_size, &frame->rs_uc.uc_stack.ss_size)) - goto badframe; - if (__get_user(st.ss_flags, &frame->rs_uc.uc_stack.ss_flags)) + if (compat_restore_altstack(&frame->rs_uc.uc_stack)) goto badframe; - /* 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, regs.regs[29]); - set_fs(old_fs); - /* * Don't let your children do this ... */ @@ -590,7 +528,6 @@ static int setup_rt_frame_32(void *sig_return, struct k_sigaction *ka, { struct rt_sigframe32 __user *frame; int err = 0; - s32 sp; frame = get_sigframe(ka, regs, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) @@ -602,13 +539,7 @@ static int setup_rt_frame_32(void *sig_return, struct k_sigaction *ka, /* Create the ucontext. */ err |= __put_user(0, &frame->rs_uc.uc_flags); err |= __put_user(0, &frame->rs_uc.uc_link); - sp = (int) (long) current->sas_ss_sp; - err |= __put_user(sp, - &frame->rs_uc.uc_stack.ss_sp); - err |= __put_user(sas_ss_flags(regs->regs[29]), - &frame->rs_uc.uc_stack.ss_flags); - err |= __put_user(current->sas_ss_size, - &frame->rs_uc.uc_stack.ss_size); + err |= __compat_save_altstack(&frame->rs_uc.uc_stack, regs->regs[29]); err |= setup_sigcontext32(regs, &frame->rs_uc.uc_mcontext); err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set); diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c index 3574c145511b..e62e2bc63a81 100644 --- a/arch/mips/kernel/signal_n32.c +++ b/arch/mips/kernel/signal_n32.c @@ -50,18 +50,10 @@ extern int setup_sigcontext(struct pt_regs *, struct sigcontext __user *); extern int restore_sigcontext(struct pt_regs *, struct sigcontext __user *); - -/* IRIX compatible stack_t */ -typedef struct sigaltstack32 { - s32 ss_sp; - compat_size_t ss_size; - int ss_flags; -} stack32_t; - struct ucontextn32 { u32 uc_flags; s32 uc_link; - stack32_t uc_stack; + compat_stack_t uc_stack; struct sigcontext uc_mcontext; compat_sigset_t uc_sigmask; /* mask last for extensibility */ }; @@ -97,10 +89,7 @@ asmlinkage int sysn32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) { struct rt_sigframe_n32 __user *frame; - mm_segment_t old_fs; sigset_t set; - stack_t st; - s32 sp; int sig; frame = (struct rt_sigframe_n32 __user *) regs.regs[29]; @@ -117,22 +106,8 @@ asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) else if (sig) force_sig(sig, current); - /* The ucontext contains a stack32_t, so we must convert! */ - if (__get_user(sp, &frame->rs_uc.uc_stack.ss_sp)) - goto badframe; - st.ss_sp = (void __user *)(long) sp; - if (__get_user(st.ss_size, &frame->rs_uc.uc_stack.ss_size)) + if (compat_restore_altstack(&frame->rs_uc.uc_stack)) goto badframe; - if (__get_user(st.ss_flags, &frame->rs_uc.uc_stack.ss_flags)) - goto badframe; - - /* 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, regs.regs[29]); - set_fs(old_fs); - /* * Don't let your children do this ... @@ -153,7 +128,6 @@ static int setup_rt_frame_n32(void *sig_return, struct k_sigaction *ka, { struct rt_sigframe_n32 __user *frame; int err = 0; - s32 sp; frame = get_sigframe(ka, regs, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) @@ -165,13 +139,7 @@ static int setup_rt_frame_n32(void *sig_return, struct k_sigaction *ka, /* Create the ucontext. */ err |= __put_user(0, &frame->rs_uc.uc_flags); err |= __put_user(0, &frame->rs_uc.uc_link); - sp = (int) (long) current->sas_ss_sp; - err |= __put_user(sp, - &frame->rs_uc.uc_stack.ss_sp); - err |= __put_user(sas_ss_flags(regs->regs[29]), - &frame->rs_uc.uc_stack.ss_flags); - err |= __put_user(current->sas_ss_size, - &frame->rs_uc.uc_stack.ss_size); + err |= __compat_save_altstack(&frame->rs_uc.uc_stack, regs->regs[29]); err |= setup_sigcontext(regs, &frame->rs_uc.uc_mcontext); err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set);