diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-23 21:50:11 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-23 21:50:11 -0500 |
commit | 9e2d59ad580d590134285f361a0e80f0e98c0207 (patch) | |
tree | f3232be75781484193413f32ec82c21f6d8eb76e /arch/arm64/kernel/signal32.c | |
parent | 5ce1a70e2f00f0bce0cab57f798ca354b9496169 (diff) | |
parent | 235b80226b986dabcbba844968f7807866bd0bfe (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.c | 220 |
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 | ||
31 | struct 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 | |||
38 | struct 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 | |||
45 | typedef struct compat_sigaltstack { | ||
46 | compat_uptr_t ss_sp; | ||
47 | int ss_flags; | ||
48 | compat_size_t ss_size; | ||
49 | } compat_stack_t; | ||
50 | |||
51 | struct compat_sigcontext { | 31 | struct 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 | */ | ||
345 | asmlinkage int compat_sys_sigsuspend(int restart, compat_ulong_t oldmask, | ||
346 | compat_old_sigset_t mask) | ||
347 | { | ||
348 | sigset_t blocked; | ||
349 | |||
350 | siginitset(¤t->blocked, mask); | ||
351 | return sigsuspend(&blocked); | ||
352 | } | ||
353 | |||
354 | asmlinkage 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 | |||
392 | asmlinkage 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 | |||
426 | int 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 | |||
463 | static int compat_restore_sigframe(struct pt_regs *regs, | 322 | static 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 | */ | ||
749 | asmlinkage 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 | |||
778 | asmlinkage 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 | |||
796 | asmlinkage 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 | |||
814 | void compat_setup_restart_syscall(struct pt_regs *regs) | 598 | void 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; |