aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/signal.c
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2012-05-29 17:13:55 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2012-05-29 17:13:55 -0400
commite94c805f0c234ef54609f23695b60add6b25ad40 (patch)
tree09e116c62b065316eb93070e78a1843d9055373a /arch/arm/kernel/signal.c
parentef0c14842e6e04b860d0309c5d5a3c1ead344e35 (diff)
parent70b58d896b1b30e4b89d369fbeb244c0e952cf9f (diff)
Merge branch 'for-arm' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal.git into for-linus
Conflicts: arch/arm/kernel/ptrace.c
Diffstat (limited to 'arch/arm/kernel/signal.c')
-rw-r--r--arch/arm/kernel/signal.c85
1 files changed, 18 insertions, 67 deletions
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index 73d9a420850d..b7ffda1ad8f2 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -29,7 +29,6 @@
29 */ 29 */
30#define SWI_SYS_SIGRETURN (0xef000000|(__NR_sigreturn)|(__NR_OABI_SYSCALL_BASE)) 30#define SWI_SYS_SIGRETURN (0xef000000|(__NR_sigreturn)|(__NR_OABI_SYSCALL_BASE))
31#define SWI_SYS_RT_SIGRETURN (0xef000000|(__NR_rt_sigreturn)|(__NR_OABI_SYSCALL_BASE)) 31#define SWI_SYS_RT_SIGRETURN (0xef000000|(__NR_rt_sigreturn)|(__NR_OABI_SYSCALL_BASE))
32#define SWI_SYS_RESTART (0xef000000|__NR_restart_syscall|__NR_OABI_SYSCALL_BASE)
33 32
34/* 33/*
35 * With EABI, the syscall number has to be loaded into r7. 34 * With EABI, the syscall number has to be loaded into r7.
@@ -50,18 +49,6 @@ const unsigned long sigreturn_codes[7] = {
50}; 49};
51 50
52/* 51/*
53 * Either we support OABI only, or we have EABI with the OABI
54 * compat layer enabled. In the later case we don't know if
55 * user space is EABI or not, and if not we must not clobber r7.
56 * Always using the OABI syscall solves that issue and works for
57 * all those cases.
58 */
59const unsigned long syscall_restart_code[2] = {
60 SWI_SYS_RESTART, /* swi __NR_restart_syscall */
61 0xe49df004, /* ldr pc, [sp], #4 */
62};
63
64/*
65 * atomically swap in the new signal mask, and wait for a signal. 52 * atomically swap in the new signal mask, and wait for a signal.
66 */ 53 */
67asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask) 54asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask)
@@ -91,10 +78,10 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
91 old_sigset_t mask; 78 old_sigset_t mask;
92 if (!access_ok(VERIFY_READ, act, sizeof(*act)) || 79 if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
93 __get_user(new_ka.sa.sa_handler, &act->sa_handler) || 80 __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
94 __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) 81 __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) ||
82 __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
83 __get_user(mask, &act->sa_mask))
95 return -EFAULT; 84 return -EFAULT;
96 __get_user(new_ka.sa.sa_flags, &act->sa_flags);
97 __get_user(mask, &act->sa_mask);
98 siginitset(&new_ka.sa.sa_mask, mask); 85 siginitset(&new_ka.sa.sa_mask, mask);
99 } 86 }
100 87
@@ -103,10 +90,10 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
103 if (!ret && oact) { 90 if (!ret && oact) {
104 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || 91 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
105 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || 92 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
106 __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) 93 __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) ||
94 __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
95 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
107 return -EFAULT; 96 return -EFAULT;
108 __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
109 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
110 } 97 }
111 98
112 return ret; 99 return ret;
@@ -611,15 +598,6 @@ static void do_signal(struct pt_regs *regs, int syscall)
611 int signr; 598 int signr;
612 599
613 /* 600 /*
614 * We want the common case to go fast, which
615 * is why we may in certain cases get here from
616 * kernel mode. Just return without doing anything
617 * if so.
618 */
619 if (!user_mode(regs))
620 return;
621
622 /*
623 * If we were from a system call, check for system call restarting... 601 * If we were from a system call, check for system call restarting...
624 */ 602 */
625 if (syscall) { 603 if (syscall) {
@@ -635,18 +613,13 @@ static void do_signal(struct pt_regs *regs, int syscall)
635 case -ERESTARTNOHAND: 613 case -ERESTARTNOHAND:
636 case -ERESTARTSYS: 614 case -ERESTARTSYS:
637 case -ERESTARTNOINTR: 615 case -ERESTARTNOINTR:
616 case -ERESTART_RESTARTBLOCK:
638 regs->ARM_r0 = regs->ARM_ORIG_r0; 617 regs->ARM_r0 = regs->ARM_ORIG_r0;
639 regs->ARM_pc = restart_addr; 618 regs->ARM_pc = restart_addr;
640 break; 619 break;
641 case -ERESTART_RESTARTBLOCK:
642 regs->ARM_r0 = -EINTR;
643 break;
644 } 620 }
645 } 621 }
646 622
647 if (try_to_freeze())
648 goto no_signal;
649
650 /* 623 /*
651 * Get the signal to deliver. When running under ptrace, at this 624 * Get the signal to deliver. When running under ptrace, at this
652 * point the debugger may change all our registers ... 625 * point the debugger may change all our registers ...
@@ -661,12 +634,14 @@ static void do_signal(struct pt_regs *regs, int syscall)
661 * debugger has chosen to restart at a different PC. 634 * debugger has chosen to restart at a different PC.
662 */ 635 */
663 if (regs->ARM_pc == restart_addr) { 636 if (regs->ARM_pc == restart_addr) {
664 if (retval == -ERESTARTNOHAND 637 if (retval == -ERESTARTNOHAND ||
638 retval == -ERESTART_RESTARTBLOCK
665 || (retval == -ERESTARTSYS 639 || (retval == -ERESTARTSYS
666 && !(ka.sa.sa_flags & SA_RESTART))) { 640 && !(ka.sa.sa_flags & SA_RESTART))) {
667 regs->ARM_r0 = -EINTR; 641 regs->ARM_r0 = -EINTR;
668 regs->ARM_pc = continue_addr; 642 regs->ARM_pc = continue_addr;
669 } 643 }
644 clear_thread_flag(TIF_SYSCALL_RESTARTSYS);
670 } 645 }
671 646
672 if (test_thread_flag(TIF_RESTORE_SIGMASK)) 647 if (test_thread_flag(TIF_RESTORE_SIGMASK))
@@ -686,7 +661,6 @@ static void do_signal(struct pt_regs *regs, int syscall)
686 return; 661 return;
687 } 662 }
688 663
689 no_signal:
690 if (syscall) { 664 if (syscall) {
691 /* 665 /*
692 * Handle restarting a different system call. As above, 666 * Handle restarting a different system call. As above,
@@ -694,38 +668,15 @@ static void do_signal(struct pt_regs *regs, int syscall)
694 * ignore the restart. 668 * ignore the restart.
695 */ 669 */
696 if (retval == -ERESTART_RESTARTBLOCK 670 if (retval == -ERESTART_RESTARTBLOCK
697 && regs->ARM_pc == continue_addr) { 671 && regs->ARM_pc == restart_addr)
698 if (thumb_mode(regs)) { 672 set_thread_flag(TIF_SYSCALL_RESTARTSYS);
699 regs->ARM_r7 = __NR_restart_syscall - __NR_SYSCALL_BASE;
700 regs->ARM_pc -= 2;
701 } else {
702#if defined(CONFIG_AEABI) && !defined(CONFIG_OABI_COMPAT)
703 regs->ARM_r7 = __NR_restart_syscall;
704 regs->ARM_pc -= 4;
705#else
706 u32 __user *usp;
707
708 regs->ARM_sp -= 4;
709 usp = (u32 __user *)regs->ARM_sp;
710
711 if (put_user(regs->ARM_pc, usp) == 0) {
712 regs->ARM_pc = KERN_RESTART_CODE;
713 } else {
714 regs->ARM_sp += 4;
715 force_sigsegv(0, current);
716 }
717#endif
718 }
719 }
720
721 /* If there's no signal to deliver, we just put the saved sigmask
722 * back.
723 */
724 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
725 clear_thread_flag(TIF_RESTORE_SIGMASK);
726 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
727 }
728 } 673 }
674
675 /* If there's no signal to deliver, we just put the saved sigmask
676 * back.
677 */
678 if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK))
679 set_current_blocked(&current->saved_sigmask);
729} 680}
730 681
731asmlinkage void 682asmlinkage void