.. | .. |
---|
47 | 47 | |
---|
48 | 48 | #include <asm/setup.h> |
---|
49 | 49 | #include <linux/uaccess.h> |
---|
50 | | -#include <asm/pgtable.h> |
---|
51 | 50 | #include <asm/traps.h> |
---|
52 | 51 | #include <asm/ucontext.h> |
---|
53 | 52 | #include <asm/cacheflush.h> |
---|
.. | .. |
---|
62 | 61 | #define FMT4SIZE 0 |
---|
63 | 62 | #else |
---|
64 | 63 | #define FORMAT 0 |
---|
65 | | -#define FMT4SIZE sizeof(((struct frame *)0)->un.fmt4) |
---|
| 64 | +#define FMT4SIZE sizeof_field(struct frame, un.fmt4) |
---|
66 | 65 | #endif |
---|
67 | 66 | |
---|
68 | 67 | static const int frame_size_change[16] = { |
---|
69 | | - [1] = -1, /* sizeof(((struct frame *)0)->un.fmt1), */ |
---|
70 | | - [2] = sizeof(((struct frame *)0)->un.fmt2), |
---|
71 | | - [3] = sizeof(((struct frame *)0)->un.fmt3), |
---|
| 68 | + [1] = -1, /* sizeof_field(struct frame, un.fmt1), */ |
---|
| 69 | + [2] = sizeof_field(struct frame, un.fmt2), |
---|
| 70 | + [3] = sizeof_field(struct frame, un.fmt3), |
---|
72 | 71 | [4] = FMT4SIZE, |
---|
73 | | - [5] = -1, /* sizeof(((struct frame *)0)->un.fmt5), */ |
---|
74 | | - [6] = -1, /* sizeof(((struct frame *)0)->un.fmt6), */ |
---|
75 | | - [7] = sizeof(((struct frame *)0)->un.fmt7), |
---|
76 | | - [8] = -1, /* sizeof(((struct frame *)0)->un.fmt8), */ |
---|
77 | | - [9] = sizeof(((struct frame *)0)->un.fmt9), |
---|
78 | | - [10] = sizeof(((struct frame *)0)->un.fmta), |
---|
79 | | - [11] = sizeof(((struct frame *)0)->un.fmtb), |
---|
80 | | - [12] = -1, /* sizeof(((struct frame *)0)->un.fmtc), */ |
---|
81 | | - [13] = -1, /* sizeof(((struct frame *)0)->un.fmtd), */ |
---|
82 | | - [14] = -1, /* sizeof(((struct frame *)0)->un.fmte), */ |
---|
83 | | - [15] = -1, /* sizeof(((struct frame *)0)->un.fmtf), */ |
---|
| 72 | + [5] = -1, /* sizeof_field(struct frame, un.fmt5), */ |
---|
| 73 | + [6] = -1, /* sizeof_field(struct frame, un.fmt6), */ |
---|
| 74 | + [7] = sizeof_field(struct frame, un.fmt7), |
---|
| 75 | + [8] = -1, /* sizeof_field(struct frame, un.fmt8), */ |
---|
| 76 | + [9] = sizeof_field(struct frame, un.fmt9), |
---|
| 77 | + [10] = sizeof_field(struct frame, un.fmta), |
---|
| 78 | + [11] = sizeof_field(struct frame, un.fmtb), |
---|
| 79 | + [12] = -1, /* sizeof_field(struct frame, un.fmtc), */ |
---|
| 80 | + [13] = -1, /* sizeof_field(struct frame, un.fmtd), */ |
---|
| 81 | + [14] = -1, /* sizeof_field(struct frame, un.fmte), */ |
---|
| 82 | + [15] = -1, /* sizeof_field(struct frame, un.fmtf), */ |
---|
84 | 83 | }; |
---|
85 | 84 | |
---|
86 | 85 | static inline int frame_extra_sizes(int f) |
---|
.. | .. |
---|
651 | 650 | regs->vector = formatvec & 0xfff; |
---|
652 | 651 | } else { |
---|
653 | 652 | struct switch_stack *sw = (struct switch_stack *)regs - 1; |
---|
654 | | - unsigned long buf[fsize / 2]; /* yes, twice as much */ |
---|
| 653 | + /* yes, twice as much as max(sizeof(frame.un.fmt<x>)) */ |
---|
| 654 | + unsigned long buf[sizeof_field(struct frame, un) / 2]; |
---|
655 | 655 | |
---|
656 | 656 | /* that'll make sure that expansion won't crap over data */ |
---|
657 | 657 | if (copy_from_user(buf + fsize / 4, fp, fsize)) |
---|
.. | .. |
---|
787 | 787 | struct sigframe __user *frame = (struct sigframe __user *)(usp - 4); |
---|
788 | 788 | sigset_t set; |
---|
789 | 789 | |
---|
790 | | - if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
---|
| 790 | + if (!access_ok(frame, sizeof(*frame))) |
---|
791 | 791 | goto badframe; |
---|
792 | 792 | if (__get_user(set.sig[0], &frame->sc.sc_mask) || |
---|
793 | 793 | (_NSIG_WORDS > 1 && |
---|
.. | .. |
---|
802 | 802 | return regs->d0; |
---|
803 | 803 | |
---|
804 | 804 | badframe: |
---|
805 | | - force_sig(SIGSEGV, current); |
---|
| 805 | + force_sig(SIGSEGV); |
---|
806 | 806 | return 0; |
---|
807 | 807 | } |
---|
808 | 808 | |
---|
.. | .. |
---|
812 | 812 | struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(usp - 4); |
---|
813 | 813 | sigset_t set; |
---|
814 | 814 | |
---|
815 | | - if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
---|
| 815 | + if (!access_ok(frame, sizeof(*frame))) |
---|
816 | 816 | goto badframe; |
---|
817 | 817 | if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) |
---|
818 | 818 | goto badframe; |
---|
.. | .. |
---|
824 | 824 | return regs->d0; |
---|
825 | 825 | |
---|
826 | 826 | badframe: |
---|
827 | | - force_sig(SIGSEGV, current); |
---|
| 827 | + force_sig(SIGSEGV); |
---|
828 | 828 | return 0; |
---|
829 | 829 | } |
---|
830 | 830 | |
---|
.. | .. |
---|
882 | 882 | } |
---|
883 | 883 | |
---|
884 | 884 | static inline void __user * |
---|
885 | | -get_sigframe(struct ksignal *ksig, size_t frame_size) |
---|
| 885 | +get_sigframe(struct ksignal *ksig, struct pt_regs *tregs, size_t frame_size) |
---|
886 | 886 | { |
---|
887 | 887 | unsigned long usp = sigsp(rdusp(), ksig); |
---|
| 888 | + unsigned long gap = 0; |
---|
888 | 889 | |
---|
889 | | - return (void __user *)((usp - frame_size) & -8UL); |
---|
| 890 | + if (CPU_IS_020_OR_030 && tregs->format == 0xb) { |
---|
| 891 | + /* USP is unreliable so use worst-case value */ |
---|
| 892 | + gap = 256; |
---|
| 893 | + } |
---|
| 894 | + |
---|
| 895 | + return (void __user *)((usp - gap - frame_size) & -8UL); |
---|
890 | 896 | } |
---|
891 | 897 | |
---|
892 | 898 | static int setup_frame(struct ksignal *ksig, sigset_t *set, |
---|
.. | .. |
---|
904 | 910 | return -EFAULT; |
---|
905 | 911 | } |
---|
906 | 912 | |
---|
907 | | - frame = get_sigframe(ksig, sizeof(*frame) + fsize); |
---|
| 913 | + frame = get_sigframe(ksig, tregs, sizeof(*frame) + fsize); |
---|
908 | 914 | |
---|
909 | 915 | if (fsize) |
---|
910 | 916 | err |= copy_to_user (frame + 1, regs + 1, fsize); |
---|
.. | .. |
---|
928 | 934 | err |= __put_user(0x70004e40 + (__NR_sigreturn << 16), |
---|
929 | 935 | (long __user *)(frame->retcode)); |
---|
930 | 936 | #else |
---|
931 | | - err |= __put_user((void *) ret_from_user_signal, &frame->pretcode); |
---|
| 937 | + err |= __put_user((long) ret_from_user_signal, |
---|
| 938 | + (long __user *) &frame->pretcode); |
---|
932 | 939 | #endif |
---|
933 | 940 | |
---|
934 | 941 | if (err) |
---|
.. | .. |
---|
975 | 982 | return -EFAULT; |
---|
976 | 983 | } |
---|
977 | 984 | |
---|
978 | | - frame = get_sigframe(ksig, sizeof(*frame)); |
---|
| 985 | + frame = get_sigframe(ksig, tregs, sizeof(*frame)); |
---|
979 | 986 | |
---|
980 | 987 | if (fsize) |
---|
981 | 988 | err |= copy_to_user (&frame->uc.uc_extra, regs + 1, fsize); |
---|
.. | .. |
---|
1007 | 1014 | err |= __put_user(0x4e40, (short __user *)(frame->retcode + 4)); |
---|
1008 | 1015 | #endif |
---|
1009 | 1016 | #else |
---|
1010 | | - err |= __put_user((void *) ret_from_user_rt_signal, &frame->pretcode); |
---|
| 1017 | + err |= __put_user((long) ret_from_user_rt_signal, |
---|
| 1018 | + (long __user *) &frame->pretcode); |
---|
1011 | 1019 | #endif /* CONFIG_MMU */ |
---|
1012 | 1020 | |
---|
1013 | 1021 | if (err) |
---|
.. | .. |
---|
1063 | 1071 | regs->d0 = -EINTR; |
---|
1064 | 1072 | break; |
---|
1065 | 1073 | } |
---|
1066 | | - /* fallthrough */ |
---|
| 1074 | + fallthrough; |
---|
1067 | 1075 | case -ERESTARTNOINTR: |
---|
1068 | 1076 | do_restart: |
---|
1069 | 1077 | regs->d0 = regs->orig_d0; |
---|
.. | .. |
---|
1127 | 1135 | |
---|
1128 | 1136 | void do_notify_resume(struct pt_regs *regs) |
---|
1129 | 1137 | { |
---|
1130 | | - if (test_thread_flag(TIF_SIGPENDING)) |
---|
| 1138 | + if (test_thread_flag(TIF_NOTIFY_SIGNAL) || |
---|
| 1139 | + test_thread_flag(TIF_SIGPENDING)) |
---|
1131 | 1140 | do_signal(regs); |
---|
1132 | 1141 | |
---|
1133 | | - if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) |
---|
| 1142 | + if (test_thread_flag(TIF_NOTIFY_RESUME)) |
---|
1134 | 1143 | tracehook_notify_resume(regs); |
---|
1135 | 1144 | } |
---|