diff options
| author | Al Viro <viro@zeniv.linux.org.uk> | 2012-12-23 03:26:46 -0500 |
|---|---|---|
| committer | Al Viro <viro@zeniv.linux.org.uk> | 2013-02-03 18:16:08 -0500 |
| commit | 7cce246557bf379ea271d91f257ce248362cc12d (patch) | |
| tree | a3c6c9c6f590990cbb1b3b6671b8c5e3fd1ff55a | |
| parent | 0aa0203fb43f04714004b2c4ad33b858e240555d (diff) | |
powerpc: switch to generic sigaltstack
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
| -rw-r--r-- | arch/powerpc/Kconfig | 1 | ||||
| -rw-r--r-- | arch/powerpc/include/asm/syscalls.h | 4 | ||||
| -rw-r--r-- | arch/powerpc/kernel/ppc32.h | 8 | ||||
| -rw-r--r-- | arch/powerpc/kernel/signal.c | 7 | ||||
| -rw-r--r-- | arch/powerpc/kernel/signal_32.c | 69 | ||||
| -rw-r--r-- | arch/powerpc/kernel/signal_64.c | 11 |
6 files changed, 13 insertions, 87 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 17903f1f356b..dd52babec7d7 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
| @@ -144,6 +144,7 @@ config PPC | |||
| 144 | select HAVE_MOD_ARCH_SPECIFIC | 144 | select HAVE_MOD_ARCH_SPECIFIC |
| 145 | select MODULES_USE_ELF_RELA | 145 | select MODULES_USE_ELF_RELA |
| 146 | select CLONE_BACKWARDS | 146 | select CLONE_BACKWARDS |
| 147 | select GENERIC_SIGALTSTACK | ||
| 147 | 148 | ||
| 148 | config EARLY_PRINTK | 149 | config EARLY_PRINTK |
| 149 | bool | 150 | bool |
diff --git a/arch/powerpc/include/asm/syscalls.h b/arch/powerpc/include/asm/syscalls.h index 6949c42ffac2..01d240ded0d5 100644 --- a/arch/powerpc/include/asm/syscalls.h +++ b/arch/powerpc/include/asm/syscalls.h | |||
| @@ -22,9 +22,5 @@ asmlinkage long ppc64_personality(unsigned long personality); | |||
| 22 | asmlinkage int ppc_rtas(struct rtas_args __user *uargs); | 22 | asmlinkage int ppc_rtas(struct rtas_args __user *uargs); |
| 23 | asmlinkage time_t sys64_time(time_t __user * tloc); | 23 | asmlinkage time_t sys64_time(time_t __user * tloc); |
| 24 | 24 | ||
| 25 | asmlinkage long sys_sigaltstack(const stack_t __user *uss, | ||
| 26 | stack_t __user *uoss, unsigned long r5, unsigned long r6, | ||
| 27 | unsigned long r7, unsigned long r8, struct pt_regs *regs); | ||
| 28 | |||
| 29 | #endif /* __KERNEL__ */ | 25 | #endif /* __KERNEL__ */ |
| 30 | #endif /* __ASM_POWERPC_SYSCALLS_H */ | 26 | #endif /* __ASM_POWERPC_SYSCALLS_H */ |
diff --git a/arch/powerpc/kernel/ppc32.h b/arch/powerpc/kernel/ppc32.h index 02fb0ee26093..f6bee3e6f438 100644 --- a/arch/powerpc/kernel/ppc32.h +++ b/arch/powerpc/kernel/ppc32.h | |||
| @@ -34,12 +34,6 @@ struct sigaction32 { | |||
| 34 | compat_sigset_t sa_mask; /* A 32 bit mask */ | 34 | compat_sigset_t sa_mask; /* A 32 bit mask */ |
| 35 | }; | 35 | }; |
| 36 | 36 | ||
| 37 | typedef struct sigaltstack_32 { | ||
| 38 | unsigned int ss_sp; | ||
| 39 | int ss_flags; | ||
| 40 | compat_size_t ss_size; | ||
| 41 | } stack_32_t; | ||
| 42 | |||
| 43 | struct pt_regs32 { | 37 | struct pt_regs32 { |
| 44 | unsigned int gpr[32]; | 38 | unsigned int gpr[32]; |
| 45 | unsigned int nip; | 39 | unsigned int nip; |
| @@ -75,7 +69,7 @@ struct mcontext32 { | |||
| 75 | struct ucontext32 { | 69 | struct ucontext32 { |
| 76 | unsigned int uc_flags; | 70 | unsigned int uc_flags; |
| 77 | unsigned int uc_link; | 71 | unsigned int uc_link; |
| 78 | stack_32_t uc_stack; | 72 | compat_stack_t uc_stack; |
| 79 | int uc_pad[7]; | 73 | int uc_pad[7]; |
| 80 | compat_uptr_t uc_regs; /* points to uc_mcontext field */ | 74 | compat_uptr_t uc_regs; /* points to uc_mcontext field */ |
| 81 | compat_sigset_t uc_sigmask; /* mask last for extensibility */ | 75 | compat_sigset_t uc_sigmask; /* mask last for extensibility */ |
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c index 3b997118df50..fa99dc54965c 100644 --- a/arch/powerpc/kernel/signal.c +++ b/arch/powerpc/kernel/signal.c | |||
| @@ -169,10 +169,3 @@ void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) | |||
| 169 | tracehook_notify_resume(regs); | 169 | tracehook_notify_resume(regs); |
| 170 | } | 170 | } |
| 171 | } | 171 | } |
| 172 | |||
| 173 | long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, | ||
| 174 | unsigned long r5, unsigned long r6, unsigned long r7, | ||
| 175 | unsigned long r8, struct pt_regs *regs) | ||
| 176 | { | ||
| 177 | return do_sigaltstack(uss, uoss, regs->gpr[1]); | ||
| 178 | } | ||
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index 9ec3fed3caac..0ea248c893cb 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c | |||
| @@ -67,6 +67,8 @@ | |||
| 67 | #define mcontext mcontext32 | 67 | #define mcontext mcontext32 |
| 68 | #define ucontext ucontext32 | 68 | #define ucontext ucontext32 |
| 69 | 69 | ||
| 70 | #define __save_altstack __compat_save_altstack | ||
| 71 | |||
| 70 | /* | 72 | /* |
| 71 | * Userspace code may pass a ucontext which doesn't include VSX added | 73 | * Userspace code may pass a ucontext which doesn't include VSX added |
| 72 | * at the end. We need to check for this case. | 74 | * at the end. We need to check for this case. |
| @@ -763,55 +765,6 @@ long compat_sys_rt_sigqueueinfo(u32 pid, u32 sig, compat_siginfo_t __user *uinfo | |||
| 763 | set_fs (old_fs); | 765 | set_fs (old_fs); |
| 764 | return ret; | 766 | return ret; |
| 765 | } | 767 | } |
| 766 | /* | ||
| 767 | * Start Alternate signal stack support | ||
| 768 | * | ||
| 769 | * System Calls | ||
| 770 | * sigaltatck compat_sys_sigaltstack | ||
| 771 | */ | ||
| 772 | |||
| 773 | int compat_sys_sigaltstack(u32 __new, u32 __old, int r5, | ||
| 774 | int r6, int r7, int r8, struct pt_regs *regs) | ||
| 775 | { | ||
| 776 | stack_32_t __user * newstack = compat_ptr(__new); | ||
| 777 | stack_32_t __user * oldstack = compat_ptr(__old); | ||
| 778 | stack_t uss, uoss; | ||
| 779 | int ret; | ||
| 780 | mm_segment_t old_fs; | ||
| 781 | unsigned long sp; | ||
| 782 | compat_uptr_t ss_sp; | ||
| 783 | |||
| 784 | /* | ||
| 785 | * set sp to the user stack on entry to the system call | ||
| 786 | * the system call router sets R9 to the saved registers | ||
| 787 | */ | ||
| 788 | sp = regs->gpr[1]; | ||
| 789 | |||
| 790 | /* Put new stack info in local 64 bit stack struct */ | ||
| 791 | if (newstack) { | ||
| 792 | if (get_user(ss_sp, &newstack->ss_sp) || | ||
| 793 | __get_user(uss.ss_flags, &newstack->ss_flags) || | ||
| 794 | __get_user(uss.ss_size, &newstack->ss_size)) | ||
| 795 | return -EFAULT; | ||
| 796 | uss.ss_sp = compat_ptr(ss_sp); | ||
| 797 | } | ||
| 798 | |||
| 799 | old_fs = get_fs(); | ||
| 800 | set_fs(KERNEL_DS); | ||
| 801 | /* The __user pointer casts are valid because of the set_fs() */ | ||
| 802 | ret = do_sigaltstack( | ||
| 803 | newstack ? (stack_t __user *) &uss : NULL, | ||
| 804 | oldstack ? (stack_t __user *) &uoss : NULL, | ||
| 805 | sp); | ||
| 806 | set_fs(old_fs); | ||
| 807 | /* Copy the stack information to the user output buffer */ | ||
| 808 | if (!ret && oldstack && | ||
| 809 | (put_user(ptr_to_compat(uoss.ss_sp), &oldstack->ss_sp) || | ||
| 810 | __put_user(uoss.ss_flags, &oldstack->ss_flags) || | ||
| 811 | __put_user(uoss.ss_size, &oldstack->ss_size))) | ||
| 812 | return -EFAULT; | ||
| 813 | return ret; | ||
| 814 | } | ||
| 815 | #endif /* CONFIG_PPC64 */ | 768 | #endif /* CONFIG_PPC64 */ |
| 816 | 769 | ||
| 817 | /* | 770 | /* |
| @@ -838,10 +791,7 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, | |||
| 838 | if (copy_siginfo_to_user(&rt_sf->info, info) | 791 | if (copy_siginfo_to_user(&rt_sf->info, info) |
| 839 | || __put_user(0, &rt_sf->uc.uc_flags) | 792 | || __put_user(0, &rt_sf->uc.uc_flags) |
| 840 | || __put_user(0, &rt_sf->uc.uc_link) | 793 | || __put_user(0, &rt_sf->uc.uc_link) |
| 841 | || __put_user(current->sas_ss_sp, &rt_sf->uc.uc_stack.ss_sp) | 794 | || __save_altstack(&rt_sf->uc.uc_stack, regs->gpr[1]) |
| 842 | || __put_user(sas_ss_flags(regs->gpr[1]), | ||
| 843 | &rt_sf->uc.uc_stack.ss_flags) | ||
| 844 | || __put_user(current->sas_ss_size, &rt_sf->uc.uc_stack.ss_size) | ||
| 845 | || __put_user(to_user_ptr(&rt_sf->uc.uc_mcontext), | 795 | || __put_user(to_user_ptr(&rt_sf->uc.uc_mcontext), |
| 846 | &rt_sf->uc.uc_regs) | 796 | &rt_sf->uc.uc_regs) |
| 847 | || put_sigset_t(&rt_sf->uc.uc_sigmask, oldset)) | 797 | || put_sigset_t(&rt_sf->uc.uc_sigmask, oldset)) |
| @@ -1038,14 +988,11 @@ long sys_rt_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8, | |||
| 1038 | * change it. -- paulus | 988 | * change it. -- paulus |
| 1039 | */ | 989 | */ |
| 1040 | #ifdef CONFIG_PPC64 | 990 | #ifdef CONFIG_PPC64 |
| 1041 | /* | 991 | if (compat_restore_altstack(&rt_sf->uc.uc_stack)) |
| 1042 | * We use the compat_sys_ version that does the 32/64 bits conversion | 992 | goto bad; |
| 1043 | * and takes userland pointer directly. What about error checking ? | ||
| 1044 | * nobody does any... | ||
| 1045 | */ | ||
| 1046 | compat_sys_sigaltstack((u32)(u64)&rt_sf->uc.uc_stack, 0, 0, 0, 0, 0, regs); | ||
| 1047 | #else | 993 | #else |
| 1048 | do_sigaltstack(&rt_sf->uc.uc_stack, NULL, regs->gpr[1]); | 994 | if (restore_altstack(&rt_sf->uc.uc_stack)) |
| 995 | goto bad; | ||
| 1049 | #endif | 996 | #endif |
| 1050 | set_thread_flag(TIF_RESTOREALL); | 997 | set_thread_flag(TIF_RESTOREALL); |
| 1051 | return 0; | 998 | return 0; |
| @@ -1161,7 +1108,7 @@ int sys_debug_setcontext(struct ucontext __user *ctx, | |||
| 1161 | * always done it up until now so it is probably better not to | 1108 | * always done it up until now so it is probably better not to |
| 1162 | * change it. -- paulus | 1109 | * change it. -- paulus |
| 1163 | */ | 1110 | */ |
| 1164 | do_sigaltstack(&ctx->uc_stack, NULL, regs->gpr[1]); | 1111 | restore_altstack(&ctx->uc_stack); |
| 1165 | 1112 | ||
| 1166 | set_thread_flag(TIF_RESTOREALL); | 1113 | set_thread_flag(TIF_RESTOREALL); |
| 1167 | out: | 1114 | out: |
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index 1ca045d44324..807b5b1535e9 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c | |||
| @@ -368,10 +368,8 @@ int sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, | |||
| 368 | if (restore_sigcontext(regs, NULL, 1, &uc->uc_mcontext)) | 368 | if (restore_sigcontext(regs, NULL, 1, &uc->uc_mcontext)) |
| 369 | goto badframe; | 369 | goto badframe; |
| 370 | 370 | ||
| 371 | /* do_sigaltstack expects a __user pointer and won't modify | 371 | if (restore_altstack(&uc->uc_stack)) |
| 372 | * what's in there anyway | 372 | goto badframe; |
| 373 | */ | ||
| 374 | do_sigaltstack(&uc->uc_stack, NULL, regs->gpr[1]); | ||
| 375 | 373 | ||
| 376 | set_thread_flag(TIF_RESTOREALL); | 374 | set_thread_flag(TIF_RESTOREALL); |
| 377 | return 0; | 375 | return 0; |
| @@ -416,10 +414,7 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info, | |||
| 416 | /* Create the ucontext. */ | 414 | /* Create the ucontext. */ |
| 417 | err |= __put_user(0, &frame->uc.uc_flags); | 415 | err |= __put_user(0, &frame->uc.uc_flags); |
| 418 | err |= __put_user(0, &frame->uc.uc_link); | 416 | err |= __put_user(0, &frame->uc.uc_link); |
| 419 | err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); | 417 | err |= __save_altstack(&frame->uc.uc_stack, regs->gpr[1]); |
| 420 | err |= __put_user(sas_ss_flags(regs->gpr[1]), | ||
| 421 | &frame->uc.uc_stack.ss_flags); | ||
| 422 | err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); | ||
| 423 | err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, signr, NULL, | 418 | err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, signr, NULL, |
| 424 | (unsigned long)ka->sa.sa_handler, 1); | 419 | (unsigned long)ka->sa.sa_handler, 1); |
| 425 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | 420 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); |
