diff --git a/[refs] b/[refs] index e9df7291dbb3..e53d018ebf6f 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 51682036d006b175022d0cd010672d3fff041278 +refs/heads/master: 47880695011964be808d3151f0f47bd6626f6f2f diff --git a/trunk/arch/arm64/Kconfig b/trunk/arch/arm64/Kconfig index 1f27c58f44ad..f8f362aafee9 100644 --- a/trunk/arch/arm64/Kconfig +++ b/trunk/arch/arm64/Kconfig @@ -6,15 +6,10 @@ config ARM64 select CLONE_BACKWARDS select COMMON_CLK select GENERIC_CLOCKEVENTS - select GENERIC_COMPAT_RT_SIGACTION - select GENERIC_COMPAT_RT_SIGPENDING - select GENERIC_COMPAT_RT_SIGPROCMASK - select GENERIC_COMPAT_RT_SIGQUEUEINFO select GENERIC_HARDIRQS_NO_DEPRECATED select GENERIC_IOMAP select GENERIC_IRQ_PROBE select GENERIC_IRQ_SHOW - select GENERIC_SIGALTSTACK select GENERIC_SMP_IDLE_THREAD select GENERIC_TIME_VSYSCALL select HARDIRQS_SW_RESEND @@ -209,8 +204,6 @@ config COMPAT depends on !ARM64_64K_PAGES select COMPAT_BINFMT_ELF select HAVE_UID16 - select OLD_SIGSUSPEND3 - select COMPAT_OLD_SIGACTION help This option enables support for a 32-bit EL0 running under a 64-bit kernel at EL1. AArch32-specific components such as system calls, diff --git a/trunk/arch/arm64/include/asm/syscalls.h b/trunk/arch/arm64/include/asm/syscalls.h index 48fe7c600e98..20d63b290665 100644 --- a/trunk/arch/arm64/include/asm/syscalls.h +++ b/trunk/arch/arm64/include/asm/syscalls.h @@ -24,6 +24,8 @@ * System call wrappers implemented in kernel/entry.S. */ asmlinkage long sys_rt_sigreturn_wrapper(void); +asmlinkage long sys_sigaltstack_wrapper(const stack_t __user *uss, + stack_t __user *uoss); #include diff --git a/trunk/arch/arm64/include/asm/unistd32.h b/trunk/arch/arm64/include/asm/unistd32.h index e60e386178d1..5ef47ba3ed45 100644 --- a/trunk/arch/arm64/include/asm/unistd32.h +++ b/trunk/arch/arm64/include/asm/unistd32.h @@ -93,7 +93,7 @@ __SYSCALL(68, sys_ni_syscall) /* 68 was sys_sgetmask */ __SYSCALL(69, sys_ni_syscall) /* 69 was sys_ssetmask */ __SYSCALL(70, sys_setreuid16) __SYSCALL(71, sys_setregid16) -__SYSCALL(72, sys_sigsuspend) +__SYSCALL(72, compat_sys_sigsuspend) __SYSCALL(73, compat_sys_sigpending) __SYSCALL(74, sys_sethostname) __SYSCALL(75, compat_sys_setrlimit) @@ -207,7 +207,7 @@ __SYSCALL(182, sys_chown16) __SYSCALL(183, sys_getcwd) __SYSCALL(184, sys_capget) __SYSCALL(185, sys_capset) -__SYSCALL(186, compat_sys_sigaltstack) +__SYSCALL(186, compat_sys_sigaltstack_wrapper) __SYSCALL(187, compat_sys_sendfile) __SYSCALL(188, sys_ni_syscall) /* 188 reserved */ __SYSCALL(189, sys_ni_syscall) /* 189 reserved */ diff --git a/trunk/arch/arm64/kernel/entry.S b/trunk/arch/arm64/kernel/entry.S index 514d6098dbee..9c94f404ded6 100644 --- a/trunk/arch/arm64/kernel/entry.S +++ b/trunk/arch/arm64/kernel/entry.S @@ -677,5 +677,10 @@ ENTRY(sys_rt_sigreturn_wrapper) b sys_rt_sigreturn ENDPROC(sys_rt_sigreturn_wrapper) +ENTRY(sys_sigaltstack_wrapper) + ldr x2, [sp, #S_SP] + b sys_sigaltstack +ENDPROC(sys_sigaltstack_wrapper) + ENTRY(handle_arch_irq) .quad 0 diff --git a/trunk/arch/arm64/kernel/signal.c b/trunk/arch/arm64/kernel/signal.c index 890a591f75dd..abd756315cb5 100644 --- a/trunk/arch/arm64/kernel/signal.c +++ b/trunk/arch/arm64/kernel/signal.c @@ -149,7 +149,8 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) if (restore_sigframe(regs, frame)) goto badframe; - if (restore_altstack(&frame->uc.uc_stack)) + if (do_sigaltstack(&frame->uc.uc_stack, + NULL, regs->sp) == -EFAULT) goto badframe; return regs->regs[0]; @@ -163,6 +164,12 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) return 0; } +asmlinkage long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, + unsigned long sp) +{ + return do_sigaltstack(uss, uoss, sp); +} + static int setup_sigframe(struct rt_sigframe __user *sf, struct pt_regs *regs, sigset_t *set) { @@ -243,6 +250,7 @@ static int setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { struct rt_sigframe __user *frame; + stack_t stack; int err = 0; frame = get_sigframe(ka, regs); @@ -252,7 +260,12 @@ static int setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, __put_user_error(0, &frame->uc.uc_flags, err); __put_user_error(NULL, &frame->uc.uc_link, err); - err |= __save_altstack(&frame->uc.uc_stack, regs->sp); + memset(&stack, 0, sizeof(stack)); + stack.ss_sp = (void __user *)current->sas_ss_sp; + stack.ss_flags = sas_ss_flags(regs->sp); + stack.ss_size = current->sas_ss_size; + err |= __copy_to_user(&frame->uc.uc_stack, &stack, sizeof(stack)); + err |= setup_sigframe(frame, regs, set); if (err == 0) { setup_return(regs, ka, frame, usig); diff --git a/trunk/arch/arm64/kernel/signal32.c b/trunk/arch/arm64/kernel/signal32.c index 92ada01f4cd8..a4db3d22aac4 100644 --- a/trunk/arch/arm64/kernel/signal32.c +++ b/trunk/arch/arm64/kernel/signal32.c @@ -28,6 +28,26 @@ #include #include +struct compat_sigaction { + compat_uptr_t sa_handler; + compat_ulong_t sa_flags; + compat_uptr_t sa_restorer; + compat_sigset_t sa_mask; +}; + +struct compat_old_sigaction { + compat_uptr_t sa_handler; + compat_old_sigset_t sa_mask; + compat_ulong_t sa_flags; + compat_uptr_t sa_restorer; +}; + +typedef struct compat_sigaltstack { + compat_uptr_t ss_sp; + int ss_flags; + compat_size_t ss_size; +} compat_stack_t; + struct compat_sigcontext { /* We always set these two fields to 0 */ compat_ulong_t trap_no; @@ -319,6 +339,127 @@ static int compat_restore_vfp_context(struct compat_vfp_sigframe __user *frame) return err ? -EFAULT : 0; } +/* + * atomically swap in the new signal mask, and wait for a signal. + */ +asmlinkage int compat_sys_sigsuspend(int restart, compat_ulong_t oldmask, + compat_old_sigset_t mask) +{ + sigset_t blocked; + + siginitset(¤t->blocked, mask); + return sigsuspend(&blocked); +} + +asmlinkage int compat_sys_sigaction(int sig, + const struct compat_old_sigaction __user *act, + struct compat_old_sigaction __user *oact) +{ + struct k_sigaction new_ka, old_ka; + int ret; + compat_old_sigset_t mask; + compat_uptr_t handler, restorer; + + if (act) { + if (!access_ok(VERIFY_READ, act, sizeof(*act)) || + __get_user(handler, &act->sa_handler) || + __get_user(restorer, &act->sa_restorer) || + __get_user(new_ka.sa.sa_flags, &act->sa_flags) || + __get_user(mask, &act->sa_mask)) + return -EFAULT; + + new_ka.sa.sa_handler = compat_ptr(handler); + new_ka.sa.sa_restorer = compat_ptr(restorer); + 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(ptr_to_compat(old_ka.sa.sa_handler), + &oact->sa_handler) || + __put_user(ptr_to_compat(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 compat_sys_rt_sigaction(int sig, + const struct compat_sigaction __user *act, + struct compat_sigaction __user *oact, + compat_size_t sigsetsize) +{ + struct k_sigaction new_ka, old_ka; + int ret; + + /* XXX: Don't preclude handling different sized sigset_t's. */ + if (sigsetsize != sizeof(compat_sigset_t)) + return -EINVAL; + + if (act) { + compat_uptr_t handler, restorer; + + ret = get_user(handler, &act->sa_handler); + new_ka.sa.sa_handler = compat_ptr(handler); + ret |= get_user(restorer, &act->sa_restorer); + new_ka.sa.sa_restorer = compat_ptr(restorer); + ret |= get_sigset_t(&new_ka.sa.sa_mask, &act->sa_mask); + ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags); + if (ret) + return -EFAULT; + } + + ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); + if (!ret && oact) { + ret = put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler); + ret |= put_sigset_t(&oact->sa_mask, &old_ka.sa.sa_mask); + ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags); + } + return ret; +} + +int compat_do_sigaltstack(compat_uptr_t compat_uss, compat_uptr_t compat_uoss, + compat_ulong_t sp) +{ + compat_stack_t __user *newstack = compat_ptr(compat_uss); + compat_stack_t __user *oldstack = compat_ptr(compat_uoss); + compat_uptr_t ss_sp; + int ret; + mm_segment_t old_fs; + stack_t uss, uoss; + + /* Marshall the compat new stack into a stack_t */ + if (newstack) { + if (get_user(ss_sp, &newstack->ss_sp) || + __get_user(uss.ss_flags, &newstack->ss_flags) || + __get_user(uss.ss_size, &newstack->ss_size)) + return -EFAULT; + uss.ss_sp = compat_ptr(ss_sp); + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + /* The __user pointer casts are valid because of the set_fs() */ + ret = do_sigaltstack( + newstack ? (stack_t __user *) &uss : NULL, + oldstack ? (stack_t __user *) &uoss : NULL, + (unsigned long)sp); + set_fs(old_fs); + + /* Convert the old stack_t into a compat stack. */ + if (!ret && oldstack && + (put_user(ptr_to_compat(uoss.ss_sp), &oldstack->ss_sp) || + __put_user(uoss.ss_flags, &oldstack->ss_flags) || + __put_user(uoss.ss_size, &oldstack->ss_size))) + return -EFAULT; + return ret; +} + static int compat_restore_sigframe(struct pt_regs *regs, struct compat_sigframe __user *sf) { @@ -421,7 +562,9 @@ asmlinkage int compat_sys_rt_sigreturn(struct pt_regs *regs) if (compat_restore_sigframe(regs, &frame->sig)) goto badframe; - if (compat_restore_altstack(&frame->sig.uc.uc_stack)) + if (compat_do_sigaltstack(ptr_to_compat(&frame->sig.uc.uc_stack), + ptr_to_compat((void __user *)NULL), + regs->compat_sp) == -EFAULT) goto badframe; return regs->regs[0]; @@ -562,7 +705,11 @@ int compat_setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, __put_user_error(0, &frame->sig.uc.uc_flags, err); __put_user_error(NULL, &frame->sig.uc.uc_link, err); - err |= __compat_save_altstack(&frame->sig.uc.uc_stack, regs->compat_sp); + memset(&stack, 0, sizeof(stack)); + stack.ss_sp = (compat_uptr_t)current->sas_ss_sp; + stack.ss_flags = sas_ss_flags(regs->compat_sp); + stack.ss_size = current->sas_ss_size; + err |= __copy_to_user(&frame->sig.uc.uc_stack, &stack, sizeof(stack)); err |= compat_setup_sigframe(&frame->sig, regs, set); @@ -595,6 +742,75 @@ int compat_setup_frame(int usig, struct k_sigaction *ka, sigset_t *set, return err; } +/* + * RT signals don't have generic compat wrappers. + * See arch/powerpc/kernel/signal_32.c + */ +asmlinkage int compat_sys_rt_sigprocmask(int how, compat_sigset_t __user *set, + compat_sigset_t __user *oset, + compat_size_t sigsetsize) +{ + sigset_t s; + sigset_t __user *up; + int ret; + mm_segment_t old_fs = get_fs(); + + if (set) { + if (get_sigset_t(&s, set)) + return -EFAULT; + } + + set_fs(KERNEL_DS); + /* This is valid because of the set_fs() */ + up = (sigset_t __user *) &s; + ret = sys_rt_sigprocmask(how, set ? up : NULL, oset ? up : NULL, + sigsetsize); + set_fs(old_fs); + if (ret) + return ret; + if (oset) { + if (put_sigset_t(oset, &s)) + return -EFAULT; + } + return 0; +} + +asmlinkage int compat_sys_rt_sigpending(compat_sigset_t __user *set, + compat_size_t sigsetsize) +{ + sigset_t s; + int ret; + mm_segment_t old_fs = get_fs(); + + set_fs(KERNEL_DS); + /* The __user pointer cast is valid because of the set_fs() */ + ret = sys_rt_sigpending((sigset_t __user *) &s, sigsetsize); + set_fs(old_fs); + if (!ret) { + if (put_sigset_t(set, &s)) + return -EFAULT; + } + return ret; +} + +asmlinkage int compat_sys_rt_sigqueueinfo(int pid, int sig, + compat_siginfo_t __user *uinfo) +{ + siginfo_t info; + int ret; + mm_segment_t old_fs = get_fs(); + + ret = copy_siginfo_from_user32(&info, uinfo); + if (unlikely(ret)) + return ret; + + set_fs (KERNEL_DS); + /* The __user pointer cast is valid because of the set_fs() */ + ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *) &info); + set_fs (old_fs); + return ret; +} + void compat_setup_restart_syscall(struct pt_regs *regs) { regs->regs[7] = __NR_compat_restart_syscall; diff --git a/trunk/arch/arm64/kernel/sys.c b/trunk/arch/arm64/kernel/sys.c index 3fa98ff14f0e..8292a9b090f8 100644 --- a/trunk/arch/arm64/kernel/sys.c +++ b/trunk/arch/arm64/kernel/sys.c @@ -40,6 +40,7 @@ asmlinkage long sys_mmap(unsigned long addr, unsigned long len, * Wrappers to pass the pt_regs argument. */ #define sys_rt_sigreturn sys_rt_sigreturn_wrapper +#define sys_sigaltstack sys_sigaltstack_wrapper #include diff --git a/trunk/arch/arm64/kernel/sys32.S b/trunk/arch/arm64/kernel/sys32.S index 6abb05721614..7ef59e9245ef 100644 --- a/trunk/arch/arm64/kernel/sys32.S +++ b/trunk/arch/arm64/kernel/sys32.S @@ -39,6 +39,11 @@ compat_sys_rt_sigreturn_wrapper: b compat_sys_rt_sigreturn ENDPROC(compat_sys_rt_sigreturn_wrapper) +compat_sys_sigaltstack_wrapper: + ldr x2, [sp, #S_COMPAT_SP] + b compat_do_sigaltstack +ENDPROC(compat_sys_sigaltstack_wrapper) + compat_sys_statfs64_wrapper: mov w3, #84 cmp w1, #88 diff --git a/trunk/arch/avr32/Kconfig b/trunk/arch/avr32/Kconfig index 2ae6591b3a55..e888b72b6e10 100644 --- a/trunk/arch/avr32/Kconfig +++ b/trunk/arch/avr32/Kconfig @@ -17,6 +17,7 @@ config AVR32 select GENERIC_CLOCKEVENTS select HAVE_MOD_ARCH_SPECIFIC select MODULES_USE_ELF_RELA + select GENERIC_SIGALTSTACK help AVR32 is a high-performance 32-bit RISC microprocessor core, designed for cost-sensitive embedded applications, with particular diff --git a/trunk/arch/avr32/kernel/signal.c b/trunk/arch/avr32/kernel/signal.c index 5e01c3a40ced..b80c0b3d2bab 100644 --- a/trunk/arch/avr32/kernel/signal.c +++ b/trunk/arch/avr32/kernel/signal.c @@ -21,12 +21,6 @@ #include #include -asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, - struct pt_regs *regs) -{ - return do_sigaltstack(uss, uoss, regs->sp); -} - struct rt_sigframe { struct siginfo info; @@ -91,7 +85,7 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) goto badframe; - if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT) + if (restore_altstack(&frame->uc.uc_stack)) goto badframe; pr_debug("Context restored: pc = %08lx, lr = %08lx, sp = %08lx\n", @@ -175,12 +169,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, /* Set up the ucontext */ err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(NULL, &frame->uc.uc_link); - err |= __put_user((void __user *)current->sas_ss_sp, - &frame->uc.uc_stack.ss_sp); - err |= __put_user(sas_ss_flags(regs->sp), - &frame->uc.uc_stack.ss_flags); - err |= __put_user(current->sas_ss_size, - &frame->uc.uc_stack.ss_size); + err |= __save_altstack(&frame->uc.uc_stack, regs->sp); err |= setup_sigcontext(&frame->uc.uc_mcontext, regs); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); diff --git a/trunk/arch/avr32/kernel/syscall-stubs.S b/trunk/arch/avr32/kernel/syscall-stubs.S index 275aab9731fd..b5fc927cd398 100644 --- a/trunk/arch/avr32/kernel/syscall-stubs.S +++ b/trunk/arch/avr32/kernel/syscall-stubs.S @@ -20,12 +20,6 @@ __sys_rt_sigsuspend: mov r10, sp rjmp sys_rt_sigsuspend - .global __sys_sigaltstack - .type __sys_sigaltstack,@function -__sys_sigaltstack: - mov r10, sp - rjmp sys_sigaltstack - .global __sys_rt_sigreturn .type __sys_rt_sigreturn,@function __sys_rt_sigreturn: diff --git a/trunk/arch/avr32/kernel/syscall_table.S b/trunk/arch/avr32/kernel/syscall_table.S index f27bb878da6b..017a904180c8 100644 --- a/trunk/arch/avr32/kernel/syscall_table.S +++ b/trunk/arch/avr32/kernel/syscall_table.S @@ -115,7 +115,7 @@ sys_call_table: .long sys_statfs .long sys_fstatfs /* 100 */ .long sys_vhangup - .long __sys_sigaltstack + .long sys_sigaltstack .long sys_syslog .long sys_setitimer .long sys_getitimer /* 105 */