| .. | .. |
|---|
| 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 | } |
|---|