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 /arch/m68k | |
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>
Diffstat (limited to 'arch/m68k')
-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 |