diff options
| author | Al Viro <viro@zeniv.linux.org.uk> | 2010-10-03 01:36:58 -0400 |
|---|---|---|
| committer | Geert Uytterhoeven <geert@linux-m68k.org> | 2011-01-07 08:01:34 -0500 |
| commit | 90731d7537317ad5d9672187f7a1dff90b29bb12 (patch) | |
| tree | 8d089b54e65358190f47011a122779d996b9ae90 | |
| parent | f85741eb5fb2653fd9138b4bef68396615c720f7 (diff) | |
m68k: If we fail to set sigframe up, just leave regs alone...
Same principle as with the previous patch - do not destroy the
state if sigframe setup fails. Incidentally, it's actually
_less_ work - we don't need to go through adjust_stack dance
on failure if we don't touch regs->stkadj until we know we'd
written sigframe out.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
| -rw-r--r-- | arch/m68k/kernel/signal.c | 44 |
1 files changed, 30 insertions, 14 deletions
diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c index a6dd61418e76..16ea319d1ed5 100644 --- a/arch/m68k/kernel/signal.c +++ b/arch/m68k/kernel/signal.c | |||
| @@ -761,10 +761,8 @@ static int setup_frame (int sig, struct k_sigaction *ka, | |||
| 761 | 761 | ||
| 762 | frame = get_sigframe(ka, regs, sizeof(*frame) + fsize); | 762 | frame = get_sigframe(ka, regs, sizeof(*frame) + fsize); |
| 763 | 763 | ||
| 764 | if (fsize) { | 764 | if (fsize) |
| 765 | err |= copy_to_user (frame + 1, regs + 1, fsize); | 765 | err |= copy_to_user (frame + 1, regs + 1, fsize); |
| 766 | regs->stkadj = fsize; | ||
| 767 | } | ||
| 768 | 766 | ||
| 769 | err |= __put_user((current_thread_info()->exec_domain | 767 | err |= __put_user((current_thread_info()->exec_domain |
| 770 | && current_thread_info()->exec_domain->signal_invmap | 768 | && current_thread_info()->exec_domain->signal_invmap |
| @@ -794,11 +792,21 @@ static int setup_frame (int sig, struct k_sigaction *ka, | |||
| 794 | 792 | ||
| 795 | push_cache ((unsigned long) &frame->retcode); | 793 | push_cache ((unsigned long) &frame->retcode); |
| 796 | 794 | ||
| 797 | /* Set up registers for signal handler */ | 795 | /* |
| 796 | * Set up registers for signal handler. All the state we are about | ||
| 797 | * to destroy is successfully copied to sigframe. | ||
| 798 | */ | ||
| 798 | wrusp ((unsigned long) frame); | 799 | wrusp ((unsigned long) frame); |
| 799 | regs->pc = (unsigned long) ka->sa.sa_handler; | 800 | regs->pc = (unsigned long) ka->sa.sa_handler; |
| 800 | 801 | ||
| 801 | adjust_stack: | 802 | /* |
| 803 | * This is subtle; if we build more than one sigframe, all but the | ||
| 804 | * first one will see frame format 0 and have fsize == 0, so we won't | ||
| 805 | * screw stkadj. | ||
| 806 | */ | ||
| 807 | if (fsize) | ||
| 808 | regs->stkadj = fsize; | ||
| 809 | |||
| 802 | /* Prepare to skip over the extra stuff in the exception frame. */ | 810 | /* Prepare to skip over the extra stuff in the exception frame. */ |
| 803 | if (regs->stkadj) { | 811 | if (regs->stkadj) { |
| 804 | struct pt_regs *tregs = | 812 | struct pt_regs *tregs = |
| @@ -813,11 +821,11 @@ adjust_stack: | |||
| 813 | tregs->pc = regs->pc; | 821 | tregs->pc = regs->pc; |
| 814 | tregs->sr = regs->sr; | 822 | tregs->sr = regs->sr; |
| 815 | } | 823 | } |
| 816 | return err; | 824 | return 0; |
| 817 | 825 | ||
| 818 | give_sigsegv: | 826 | give_sigsegv: |
| 819 | force_sigsegv(sig, current); | 827 | force_sigsegv(sig, current); |
| 820 | goto adjust_stack; | 828 | return err; |
| 821 | } | 829 | } |
| 822 | 830 | ||
| 823 | static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, | 831 | static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, |
| @@ -837,10 +845,8 @@ static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, | |||
| 837 | 845 | ||
| 838 | frame = get_sigframe(ka, regs, sizeof(*frame)); | 846 | frame = get_sigframe(ka, regs, sizeof(*frame)); |
| 839 | 847 | ||
| 840 | if (fsize) { | 848 | if (fsize) |
| 841 | err |= copy_to_user (&frame->uc.uc_extra, regs + 1, fsize); | 849 | err |= copy_to_user (&frame->uc.uc_extra, regs + 1, fsize); |
| 842 | regs->stkadj = fsize; | ||
| 843 | } | ||
| 844 | 850 | ||
| 845 | err |= __put_user((current_thread_info()->exec_domain | 851 | err |= __put_user((current_thread_info()->exec_domain |
| 846 | && current_thread_info()->exec_domain->signal_invmap | 852 | && current_thread_info()->exec_domain->signal_invmap |
| @@ -882,11 +888,21 @@ static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, | |||
| 882 | 888 | ||
| 883 | push_cache ((unsigned long) &frame->retcode); | 889 | push_cache ((unsigned long) &frame->retcode); |
| 884 | 890 | ||
| 885 | /* Set up registers for signal handler */ | 891 | /* |
| 892 | * Set up registers for signal handler. All the state we are about | ||
| 893 | * to destroy is successfully copied to sigframe. | ||
| 894 | */ | ||
| 886 | wrusp ((unsigned long) frame); | 895 | wrusp ((unsigned long) frame); |
| 887 | regs->pc = (unsigned long) ka->sa.sa_handler; | 896 | regs->pc = (unsigned long) ka->sa.sa_handler; |
| 888 | 897 | ||
| 889 | adjust_stack: | 898 | /* |
| 899 | * This is subtle; if we build more than one sigframe, all but the | ||
| 900 | * first one will see frame format 0 and have fsize == 0, so we won't | ||
| 901 | * screw stkadj. | ||
| 902 | */ | ||
| 903 | if (fsize) | ||
| 904 | regs->stkadj = fsize; | ||
| 905 | |||
| 890 | /* Prepare to skip over the extra stuff in the exception frame. */ | 906 | /* Prepare to skip over the extra stuff in the exception frame. */ |
| 891 | if (regs->stkadj) { | 907 | if (regs->stkadj) { |
| 892 | struct pt_regs *tregs = | 908 | struct pt_regs *tregs = |
| @@ -901,11 +917,11 @@ adjust_stack: | |||
| 901 | tregs->pc = regs->pc; | 917 | tregs->pc = regs->pc; |
| 902 | tregs->sr = regs->sr; | 918 | tregs->sr = regs->sr; |
| 903 | } | 919 | } |
| 904 | return err; | 920 | return 0; |
| 905 | 921 | ||
| 906 | give_sigsegv: | 922 | give_sigsegv: |
| 907 | force_sigsegv(sig, current); | 923 | force_sigsegv(sig, current); |
| 908 | goto adjust_stack; | 924 | return err; |
| 909 | } | 925 | } |
| 910 | 926 | ||
| 911 | static inline void | 927 | static inline void |
