aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm64/kernel/signal32.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-02-23 21:50:11 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-23 21:50:11 -0500
commit9e2d59ad580d590134285f361a0e80f0e98c0207 (patch)
treef3232be75781484193413f32ec82c21f6d8eb76e /arch/arm64/kernel/signal32.c
parent5ce1a70e2f00f0bce0cab57f798ca354b9496169 (diff)
parent235b80226b986dabcbba844968f7807866bd0bfe (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal
Pull signal handling cleanups from Al Viro: "This is the first pile; another one will come a bit later and will contain SYSCALL_DEFINE-related patches. - a bunch of signal-related syscalls (both native and compat) unified. - a bunch of compat syscalls switched to COMPAT_SYSCALL_DEFINE (fixing several potential problems with missing argument validation, while we are at it) - a lot of now-pointless wrappers killed - a couple of architectures (cris and hexagon) forgot to save altstack settings into sigframe, even though they used the (uninitialized) values in sigreturn; fixed. - microblaze fixes for delivery of multiple signals arriving at once - saner set of helpers for signal delivery introduced, several architectures switched to using those." * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal: (143 commits) x86: convert to ksignal sparc: convert to ksignal arm: switch to struct ksignal * passing alpha: pass k_sigaction and siginfo_t using ksignal pointer burying unused conditionals make do_sigaltstack() static arm64: switch to generic old sigaction() (compat-only) arm64: switch to generic compat rt_sigaction() arm64: switch compat to generic old sigsuspend arm64: switch to generic compat rt_sigqueueinfo() arm64: switch to generic compat rt_sigpending() arm64: switch to generic compat rt_sigprocmask() arm64: switch to generic sigaltstack sparc: switch to generic old sigsuspend sparc: COMPAT_SYSCALL_DEFINE does all sign-extension as well as SYSCALL_DEFINE sparc: kill sign-extending wrappers for native syscalls kill sparc32_open() sparc: switch to use of generic old sigaction sparc: switch sys_compat_rt_sigaction() to COMPAT_SYSCALL_DEFINE mips: switch to generic sys_fork() and sys_clone() ...
Diffstat (limited to 'arch/arm64/kernel/signal32.c')
-rw-r--r--arch/arm64/kernel/signal32.c220
1 files changed, 2 insertions, 218 deletions
diff --git a/arch/arm64/kernel/signal32.c b/arch/arm64/kernel/signal32.c
index 41db148a7eb9..7f4f3673f2bc 100644
--- a/arch/arm64/kernel/signal32.c
+++ b/arch/arm64/kernel/signal32.c
@@ -28,26 +28,6 @@
28#include <asm/uaccess.h> 28#include <asm/uaccess.h>
29#include <asm/unistd32.h> 29#include <asm/unistd32.h>
30 30
31struct compat_sigaction {
32 compat_uptr_t sa_handler;
33 compat_ulong_t sa_flags;
34 compat_uptr_t sa_restorer;
35 compat_sigset_t sa_mask;
36};
37
38struct compat_old_sigaction {
39 compat_uptr_t sa_handler;
40 compat_old_sigset_t sa_mask;
41 compat_ulong_t sa_flags;
42 compat_uptr_t sa_restorer;
43};
44
45typedef struct compat_sigaltstack {
46 compat_uptr_t ss_sp;
47 int ss_flags;
48 compat_size_t ss_size;
49} compat_stack_t;
50
51struct compat_sigcontext { 31struct compat_sigcontext {
52 /* We always set these two fields to 0 */ 32 /* We always set these two fields to 0 */
53 compat_ulong_t trap_no; 33 compat_ulong_t trap_no;
@@ -339,127 +319,6 @@ static int compat_restore_vfp_context(struct compat_vfp_sigframe __user *frame)
339 return err ? -EFAULT : 0; 319 return err ? -EFAULT : 0;
340} 320}
341 321
342/*
343 * atomically swap in the new signal mask, and wait for a signal.
344 */
345asmlinkage int compat_sys_sigsuspend(int restart, compat_ulong_t oldmask,
346 compat_old_sigset_t mask)
347{
348 sigset_t blocked;
349
350 siginitset(&current->blocked, mask);
351 return sigsuspend(&blocked);
352}
353
354asmlinkage int compat_sys_sigaction(int sig,
355 const struct compat_old_sigaction __user *act,
356 struct compat_old_sigaction __user *oact)
357{
358 struct k_sigaction new_ka, old_ka;
359 int ret;
360 compat_old_sigset_t mask;
361 compat_uptr_t handler, restorer;
362
363 if (act) {
364 if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
365 __get_user(handler, &act->sa_handler) ||
366 __get_user(restorer, &act->sa_restorer) ||
367 __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
368 __get_user(mask, &act->sa_mask))
369 return -EFAULT;
370
371 new_ka.sa.sa_handler = compat_ptr(handler);
372 new_ka.sa.sa_restorer = compat_ptr(restorer);
373 siginitset(&new_ka.sa.sa_mask, mask);
374 }
375
376 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
377
378 if (!ret && oact) {
379 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
380 __put_user(ptr_to_compat(old_ka.sa.sa_handler),
381 &oact->sa_handler) ||
382 __put_user(ptr_to_compat(old_ka.sa.sa_restorer),
383 &oact->sa_restorer) ||
384 __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
385 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
386 return -EFAULT;
387 }
388
389 return ret;
390}
391
392asmlinkage int compat_sys_rt_sigaction(int sig,
393 const struct compat_sigaction __user *act,
394 struct compat_sigaction __user *oact,
395 compat_size_t sigsetsize)
396{
397 struct k_sigaction new_ka, old_ka;
398 int ret;
399
400 /* XXX: Don't preclude handling different sized sigset_t's. */
401 if (sigsetsize != sizeof(compat_sigset_t))
402 return -EINVAL;
403
404 if (act) {
405 compat_uptr_t handler, restorer;
406
407 ret = get_user(handler, &act->sa_handler);
408 new_ka.sa.sa_handler = compat_ptr(handler);
409 ret |= get_user(restorer, &act->sa_restorer);
410 new_ka.sa.sa_restorer = compat_ptr(restorer);
411 ret |= get_sigset_t(&new_ka.sa.sa_mask, &act->sa_mask);
412 ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
413 if (ret)
414 return -EFAULT;
415 }
416
417 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
418 if (!ret && oact) {
419 ret = put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler);
420 ret |= put_sigset_t(&oact->sa_mask, &old_ka.sa.sa_mask);
421 ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
422 }
423 return ret;
424}
425
426int compat_do_sigaltstack(compat_uptr_t compat_uss, compat_uptr_t compat_uoss,
427 compat_ulong_t sp)
428{
429 compat_stack_t __user *newstack = compat_ptr(compat_uss);
430 compat_stack_t __user *oldstack = compat_ptr(compat_uoss);
431 compat_uptr_t ss_sp;
432 int ret;
433 mm_segment_t old_fs;
434 stack_t uss, uoss;
435
436 /* Marshall the compat new stack into a stack_t */
437 if (newstack) {
438 if (get_user(ss_sp, &newstack->ss_sp) ||
439 __get_user(uss.ss_flags, &newstack->ss_flags) ||
440 __get_user(uss.ss_size, &newstack->ss_size))
441 return -EFAULT;
442 uss.ss_sp = compat_ptr(ss_sp);
443 }
444
445 old_fs = get_fs();
446 set_fs(KERNEL_DS);
447 /* The __user pointer casts are valid because of the set_fs() */
448 ret = do_sigaltstack(
449 newstack ? (stack_t __user *) &uss : NULL,
450 oldstack ? (stack_t __user *) &uoss : NULL,
451 (unsigned long)sp);
452 set_fs(old_fs);
453
454 /* Convert the old stack_t into a compat stack. */
455 if (!ret && oldstack &&
456 (put_user(ptr_to_compat(uoss.ss_sp), &oldstack->ss_sp) ||
457 __put_user(uoss.ss_flags, &oldstack->ss_flags) ||
458 __put_user(uoss.ss_size, &oldstack->ss_size)))
459 return -EFAULT;
460 return ret;
461}
462
463static int compat_restore_sigframe(struct pt_regs *regs, 322static int compat_restore_sigframe(struct pt_regs *regs,
464 struct compat_sigframe __user *sf) 323 struct compat_sigframe __user *sf)
465{ 324{
@@ -562,9 +421,7 @@ asmlinkage int compat_sys_rt_sigreturn(struct pt_regs *regs)
562 if (compat_restore_sigframe(regs, &frame->sig)) 421 if (compat_restore_sigframe(regs, &frame->sig))
563 goto badframe; 422 goto badframe;
564 423
565 if (compat_do_sigaltstack(ptr_to_compat(&frame->sig.uc.uc_stack), 424 if (compat_restore_altstack(&frame->sig.uc.uc_stack))
566 ptr_to_compat((void __user *)NULL),
567 regs->compat_sp) == -EFAULT)
568 goto badframe; 425 goto badframe;
569 426
570 return regs->regs[0]; 427 return regs->regs[0];
@@ -705,11 +562,7 @@ int compat_setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
705 __put_user_error(0, &frame->sig.uc.uc_flags, err); 562 __put_user_error(0, &frame->sig.uc.uc_flags, err);
706 __put_user_error(0, &frame->sig.uc.uc_link, err); 563 __put_user_error(0, &frame->sig.uc.uc_link, err);
707 564
708 memset(&stack, 0, sizeof(stack)); 565 err |= __compat_save_altstack(&frame->sig.uc.uc_stack, regs->compat_sp);
709 stack.ss_sp = (compat_uptr_t)current->sas_ss_sp;
710 stack.ss_flags = sas_ss_flags(regs->compat_sp);
711 stack.ss_size = current->sas_ss_size;
712 err |= __copy_to_user(&frame->sig.uc.uc_stack, &stack, sizeof(stack));
713 566
714 err |= compat_setup_sigframe(&frame->sig, regs, set); 567 err |= compat_setup_sigframe(&frame->sig, regs, set);
715 568
@@ -742,75 +595,6 @@ int compat_setup_frame(int usig, struct k_sigaction *ka, sigset_t *set,
742 return err; 595 return err;
743} 596}
744 597
745/*
746 * RT signals don't have generic compat wrappers.
747 * See arch/powerpc/kernel/signal_32.c
748 */
749asmlinkage int compat_sys_rt_sigprocmask(int how, compat_sigset_t __user *set,
750 compat_sigset_t __user *oset,
751 compat_size_t sigsetsize)
752{
753 sigset_t s;
754 sigset_t __user *up;
755 int ret;
756 mm_segment_t old_fs = get_fs();
757
758 if (set) {
759 if (get_sigset_t(&s, set))
760 return -EFAULT;
761 }
762
763 set_fs(KERNEL_DS);
764 /* This is valid because of the set_fs() */
765 up = (sigset_t __user *) &s;
766 ret = sys_rt_sigprocmask(how, set ? up : NULL, oset ? up : NULL,
767 sigsetsize);
768 set_fs(old_fs);
769 if (ret)
770 return ret;
771 if (oset) {
772 if (put_sigset_t(oset, &s))
773 return -EFAULT;
774 }
775 return 0;
776}
777
778asmlinkage int compat_sys_rt_sigpending(compat_sigset_t __user *set,
779 compat_size_t sigsetsize)
780{
781 sigset_t s;
782 int ret;
783 mm_segment_t old_fs = get_fs();
784
785 set_fs(KERNEL_DS);
786 /* The __user pointer cast is valid because of the set_fs() */
787 ret = sys_rt_sigpending((sigset_t __user *) &s, sigsetsize);
788 set_fs(old_fs);
789 if (!ret) {
790 if (put_sigset_t(set, &s))
791 return -EFAULT;
792 }
793 return ret;
794}
795
796asmlinkage int compat_sys_rt_sigqueueinfo(int pid, int sig,
797 compat_siginfo_t __user *uinfo)
798{
799 siginfo_t info;
800 int ret;
801 mm_segment_t old_fs = get_fs();
802
803 ret = copy_siginfo_from_user32(&info, uinfo);
804 if (unlikely(ret))
805 return ret;
806
807 set_fs (KERNEL_DS);
808 /* The __user pointer cast is valid because of the set_fs() */
809 ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *) &info);
810 set_fs (old_fs);
811 return ret;
812}
813
814void compat_setup_restart_syscall(struct pt_regs *regs) 598void compat_setup_restart_syscall(struct pt_regs *regs)
815{ 599{
816 regs->regs[7] = __NR_compat_restart_syscall; 600 regs->regs[7] = __NR_compat_restart_syscall;