diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2012-05-29 17:13:55 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2012-05-29 17:13:55 -0400 |
commit | e94c805f0c234ef54609f23695b60add6b25ad40 (patch) | |
tree | 09e116c62b065316eb93070e78a1843d9055373a /arch/arm/kernel | |
parent | ef0c14842e6e04b860d0309c5d5a3c1ead344e35 (diff) | |
parent | 70b58d896b1b30e4b89d369fbeb244c0e952cf9f (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')
-rw-r--r-- | arch/arm/kernel/entry-common.S | 8 | ||||
-rw-r--r-- | arch/arm/kernel/ptrace.c | 3 | ||||
-rw-r--r-- | arch/arm/kernel/signal.c | 85 | ||||
-rw-r--r-- | arch/arm/kernel/signal.h | 2 | ||||
-rw-r--r-- | arch/arm/kernel/traps.c | 2 |
5 files changed, 27 insertions, 73 deletions
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 7bd2d3cb8957..4afed88d250a 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S | |||
@@ -53,9 +53,13 @@ fast_work_pending: | |||
53 | work_pending: | 53 | work_pending: |
54 | tst r1, #_TIF_NEED_RESCHED | 54 | tst r1, #_TIF_NEED_RESCHED |
55 | bne work_resched | 55 | bne work_resched |
56 | tst r1, #_TIF_SIGPENDING|_TIF_NOTIFY_RESUME | 56 | /* |
57 | beq no_work_pending | 57 | * TIF_SIGPENDING or TIF_NOTIFY_RESUME must've been set if we got here |
58 | */ | ||
59 | ldr r2, [sp, #S_PSR] | ||
58 | mov r0, sp @ 'regs' | 60 | mov r0, sp @ 'regs' |
61 | tst r2, #15 @ are we returning to user mode? | ||
62 | bne no_work_pending @ no? just leave, then... | ||
59 | mov r2, why @ 'syscall' | 63 | mov r2, why @ 'syscall' |
60 | tst r1, #_TIF_SIGPENDING @ delivering a signal? | 64 | tst r1, #_TIF_SIGPENDING @ delivering a signal? |
61 | movne why, #0 @ prevent further restarts | 65 | movne why, #0 @ prevent further restarts |
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index 14e38261cd31..5700a7ae7f0b 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/regset.h> | 25 | #include <linux/regset.h> |
26 | #include <linux/audit.h> | 26 | #include <linux/audit.h> |
27 | #include <linux/tracehook.h> | 27 | #include <linux/tracehook.h> |
28 | #include <linux/unistd.h> | ||
28 | 29 | ||
29 | #include <asm/pgtable.h> | 30 | #include <asm/pgtable.h> |
30 | #include <asm/traps.h> | 31 | #include <asm/traps.h> |
@@ -917,6 +918,8 @@ asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno) | |||
917 | audit_syscall_entry(AUDIT_ARCH_ARM, scno, regs->ARM_r0, | 918 | audit_syscall_entry(AUDIT_ARCH_ARM, scno, regs->ARM_r0, |
918 | regs->ARM_r1, regs->ARM_r2, regs->ARM_r3); | 919 | regs->ARM_r1, regs->ARM_r2, regs->ARM_r3); |
919 | 920 | ||
921 | if (why == 0 && test_and_clear_thread_flag(TIF_SYSCALL_RESTARTSYS)) | ||
922 | scno = __NR_restart_syscall - __NR_SYSCALL_BASE; | ||
920 | if (!test_thread_flag(TIF_SYSCALL_TRACE)) | 923 | if (!test_thread_flag(TIF_SYSCALL_TRACE)) |
921 | return scno; | 924 | return scno; |
922 | 925 | ||
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 | */ | ||
59 | const 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 | */ |
67 | asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask) | 54 | asmlinkage 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, ¤t->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(¤t->saved_sigmask); | ||
729 | } | 680 | } |
730 | 681 | ||
731 | asmlinkage void | 682 | asmlinkage void |
diff --git a/arch/arm/kernel/signal.h b/arch/arm/kernel/signal.h index 6fcfe8398aa4..5ff067b7c752 100644 --- a/arch/arm/kernel/signal.h +++ b/arch/arm/kernel/signal.h | |||
@@ -8,7 +8,5 @@ | |||
8 | * published by the Free Software Foundation. | 8 | * published by the Free Software Foundation. |
9 | */ | 9 | */ |
10 | #define KERN_SIGRETURN_CODE (CONFIG_VECTORS_BASE + 0x00000500) | 10 | #define KERN_SIGRETURN_CODE (CONFIG_VECTORS_BASE + 0x00000500) |
11 | #define KERN_RESTART_CODE (KERN_SIGRETURN_CODE + sizeof(sigreturn_codes)) | ||
12 | 11 | ||
13 | extern const unsigned long sigreturn_codes[7]; | 12 | extern const unsigned long sigreturn_codes[7]; |
14 | extern const unsigned long syscall_restart_code[2]; | ||
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 3647170e9a16..4928d89758f4 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c | |||
@@ -820,8 +820,6 @@ void __init early_trap_init(void *vectors_base) | |||
820 | */ | 820 | */ |
821 | memcpy((void *)(vectors + KERN_SIGRETURN_CODE - CONFIG_VECTORS_BASE), | 821 | memcpy((void *)(vectors + KERN_SIGRETURN_CODE - CONFIG_VECTORS_BASE), |
822 | sigreturn_codes, sizeof(sigreturn_codes)); | 822 | sigreturn_codes, sizeof(sigreturn_codes)); |
823 | memcpy((void *)(vectors + KERN_RESTART_CODE - CONFIG_VECTORS_BASE), | ||
824 | syscall_restart_code, sizeof(syscall_restart_code)); | ||
825 | 823 | ||
826 | flush_icache_range(vectors, vectors + PAGE_SIZE); | 824 | flush_icache_range(vectors, vectors + PAGE_SIZE); |
827 | modify_domain(DOMAIN_USER, DOMAIN_CLIENT); | 825 | modify_domain(DOMAIN_USER, DOMAIN_CLIENT); |