Commit 9231944d9669595cecee8dda969546216470d6ad
1 parent
d69d1fa0
sigset_t endianness fix in signal context
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@929 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
67 additions
and
46 deletions
linux-user/signal.c
| ... | ... | @@ -109,7 +109,8 @@ static inline int target_to_host_signal(int sig) |
| 109 | 109 | return target_to_host_signal_table[sig]; |
| 110 | 110 | } |
| 111 | 111 | |
| 112 | -void host_to_target_sigset(target_sigset_t *d, const sigset_t *s) | |
| 112 | +static void host_to_target_sigset_internal(target_sigset_t *d, | |
| 113 | + const sigset_t *s) | |
| 113 | 114 | { |
| 114 | 115 | int i; |
| 115 | 116 | unsigned long sigmask; |
| ... | ... | @@ -122,25 +123,35 @@ void host_to_target_sigset(target_sigset_t *d, const sigset_t *s) |
| 122 | 123 | target_sigmask |= 1 << (host_to_target_signal(i + 1) - 1); |
| 123 | 124 | } |
| 124 | 125 | #if TARGET_LONG_BITS == 32 && HOST_LONG_BITS == 32 |
| 125 | - d->sig[0] = tswapl(target_sigmask); | |
| 126 | + d->sig[0] = target_sigmask; | |
| 126 | 127 | for(i = 1;i < TARGET_NSIG_WORDS; i++) { |
| 127 | - d->sig[i] = tswapl(((unsigned long *)s)[i]); | |
| 128 | + d->sig[i] = ((unsigned long *)s)[i]; | |
| 128 | 129 | } |
| 129 | 130 | #elif TARGET_LONG_BITS == 32 && HOST_LONG_BITS == 64 && TARGET_NSIG_WORDS == 2 |
| 130 | - d->sig[0] = tswapl(target_sigmask); | |
| 131 | - d->sig[1] = tswapl(sigmask >> 32); | |
| 131 | + d->sig[0] = target_sigmask; | |
| 132 | + d->sig[1] = sigmask >> 32; | |
| 132 | 133 | #else |
| 133 | 134 | #error host_to_target_sigset |
| 134 | 135 | #endif |
| 135 | 136 | } |
| 136 | 137 | |
| 137 | -void target_to_host_sigset(sigset_t *d, const target_sigset_t *s) | |
| 138 | +void host_to_target_sigset(target_sigset_t *d, const sigset_t *s) | |
| 139 | +{ | |
| 140 | + target_sigset_t d1; | |
| 141 | + int i; | |
| 142 | + | |
| 143 | + host_to_target_sigset_internal(&d1, s); | |
| 144 | + for(i = 0;i < TARGET_NSIG_WORDS; i++) | |
| 145 | + __put_user(d1.sig[i], &d->sig[i]); | |
| 146 | +} | |
| 147 | + | |
| 148 | +void target_to_host_sigset_internal(sigset_t *d, const target_sigset_t *s) | |
| 138 | 149 | { |
| 139 | 150 | int i; |
| 140 | 151 | unsigned long sigmask; |
| 141 | 152 | target_ulong target_sigmask; |
| 142 | 153 | |
| 143 | - target_sigmask = tswapl(s->sig[0]); | |
| 154 | + target_sigmask = s->sig[0]; | |
| 144 | 155 | sigmask = 0; |
| 145 | 156 | for(i = 0; i < 32; i++) { |
| 146 | 157 | if (target_sigmask & (1 << i)) |
| ... | ... | @@ -149,15 +160,25 @@ void target_to_host_sigset(sigset_t *d, const target_sigset_t *s) |
| 149 | 160 | #if TARGET_LONG_BITS == 32 && HOST_LONG_BITS == 32 |
| 150 | 161 | ((unsigned long *)d)[0] = sigmask; |
| 151 | 162 | for(i = 1;i < TARGET_NSIG_WORDS; i++) { |
| 152 | - ((unsigned long *)d)[i] = tswapl(s->sig[i]); | |
| 163 | + ((unsigned long *)d)[i] = s->sig[i]; | |
| 153 | 164 | } |
| 154 | 165 | #elif TARGET_LONG_BITS == 32 && HOST_LONG_BITS == 64 && TARGET_NSIG_WORDS == 2 |
| 155 | - ((unsigned long *)d)[0] = sigmask | ((unsigned long)tswapl(s->sig[1]) << 32); | |
| 166 | + ((unsigned long *)d)[0] = sigmask | ((unsigned long)(s->sig[1]) << 32); | |
| 156 | 167 | #else |
| 157 | 168 | #error target_to_host_sigset |
| 158 | 169 | #endif /* TARGET_LONG_BITS */ |
| 159 | 170 | } |
| 160 | 171 | |
| 172 | +void target_to_host_sigset(sigset_t *d, const target_sigset_t *s) | |
| 173 | +{ | |
| 174 | + target_sigset_t s1; | |
| 175 | + int i; | |
| 176 | + | |
| 177 | + for(i = 0;i < TARGET_NSIG_WORDS; i++) | |
| 178 | + __get_user(s1.sig[i], &s->sig[i]); | |
| 179 | + target_to_host_sigset_internal(d, &s1); | |
| 180 | +} | |
| 181 | + | |
| 161 | 182 | void host_to_target_old_sigset(target_ulong *old_sigset, |
| 162 | 183 | const sigset_t *sigset) |
| 163 | 184 | { |
| ... | ... | @@ -640,7 +661,7 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, |
| 640 | 661 | target_sigset_t *set, CPUX86State *env) |
| 641 | 662 | { |
| 642 | 663 | struct sigframe *frame; |
| 643 | - int err = 0; | |
| 664 | + int i, err = 0; | |
| 644 | 665 | |
| 645 | 666 | frame = get_sigframe(ka, env, sizeof(*frame)); |
| 646 | 667 | |
| ... | ... | @@ -659,12 +680,10 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, |
| 659 | 680 | if (err) |
| 660 | 681 | goto give_sigsegv; |
| 661 | 682 | |
| 662 | - if (TARGET_NSIG_WORDS > 1) { | |
| 663 | - err |= __copy_to_user(frame->extramask, &set->sig[1], | |
| 664 | - sizeof(frame->extramask)); | |
| 665 | - } | |
| 666 | - if (err) | |
| 667 | - goto give_sigsegv; | |
| 683 | + for(i = 1; i < TARGET_NSIG_WORDS; i++) { | |
| 684 | + if (__put_user(set->sig[i], &frame->extramask[i - 1])) | |
| 685 | + goto give_sigsegv; | |
| 686 | + } | |
| 668 | 687 | |
| 669 | 688 | /* Set up to return from userspace. If provided, use a stub |
| 670 | 689 | already in userspace. */ |
| ... | ... | @@ -704,7 +723,7 @@ static void setup_rt_frame(int sig, struct emulated_sigaction *ka, |
| 704 | 723 | target_sigset_t *set, CPUX86State *env) |
| 705 | 724 | { |
| 706 | 725 | struct rt_sigframe *frame; |
| 707 | - int err = 0; | |
| 726 | + int i, err = 0; | |
| 708 | 727 | |
| 709 | 728 | frame = get_sigframe(ka, env, sizeof(*frame)); |
| 710 | 729 | |
| ... | ... | @@ -732,9 +751,10 @@ static void setup_rt_frame(int sig, struct emulated_sigaction *ka, |
| 732 | 751 | err |= __put_user(/* current->sas_ss_size */ 0, &frame->uc.uc_stack.ss_size); |
| 733 | 752 | err |= setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate, |
| 734 | 753 | env, set->sig[0]); |
| 735 | - err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | |
| 736 | - if (err) | |
| 737 | - goto give_sigsegv; | |
| 754 | + for(i = 0; i < TARGET_NSIG_WORDS; i++) { | |
| 755 | + if (__put_user(set->sig[i], &frame->uc.uc_sigmask.sig[i])) | |
| 756 | + goto give_sigsegv; | |
| 757 | + } | |
| 738 | 758 | |
| 739 | 759 | /* Set up to return from userspace. If provided, use a stub |
| 740 | 760 | already in userspace. */ |
| ... | ... | @@ -829,11 +849,14 @@ long do_sigreturn(CPUX86State *env) |
| 829 | 849 | fprintf(stderr, "do_sigreturn\n"); |
| 830 | 850 | #endif |
| 831 | 851 | /* set blocked signals */ |
| 832 | - target_set.sig[0] = frame->sc.oldmask; | |
| 833 | - for(i = 1; i < TARGET_NSIG_WORDS; i++) | |
| 834 | - target_set.sig[i] = frame->extramask[i - 1]; | |
| 852 | + if (__get_user(target_set.sig[0], &frame->sc.oldmask)) | |
| 853 | + goto badframe; | |
| 854 | + for(i = 1; i < TARGET_NSIG_WORDS; i++) { | |
| 855 | + if (__get_user(target_set.sig[i], &frame->extramask[i - 1])) | |
| 856 | + goto badframe; | |
| 857 | + } | |
| 835 | 858 | |
| 836 | - target_to_host_sigset(&set, &target_set); | |
| 859 | + target_to_host_sigset_internal(&set, &target_set); | |
| 837 | 860 | sigprocmask(SIG_SETMASK, &set, NULL); |
| 838 | 861 | |
| 839 | 862 | /* restore registers */ |
| ... | ... | @@ -849,7 +872,6 @@ badframe: |
| 849 | 872 | long do_rt_sigreturn(CPUX86State *env) |
| 850 | 873 | { |
| 851 | 874 | struct rt_sigframe *frame = (struct rt_sigframe *)(env->regs[R_ESP] - 4); |
| 852 | - target_sigset_t target_set; | |
| 853 | 875 | sigset_t set; |
| 854 | 876 | // stack_t st; |
| 855 | 877 | int eax; |
| ... | ... | @@ -858,9 +880,7 @@ long do_rt_sigreturn(CPUX86State *env) |
| 858 | 880 | if (verify_area(VERIFY_READ, frame, sizeof(*frame))) |
| 859 | 881 | goto badframe; |
| 860 | 882 | #endif |
| 861 | - memcpy(&target_set, &frame->uc.uc_sigmask, sizeof(target_sigset_t)); | |
| 862 | - | |
| 863 | - target_to_host_sigset(&set, &target_set); | |
| 883 | + target_to_host_sigset(&set, &frame->uc.uc_sigmask); | |
| 864 | 884 | sigprocmask(SIG_SETMASK, &set, NULL); |
| 865 | 885 | |
| 866 | 886 | if (restore_sigcontext(env, &frame->uc.uc_mcontext, &eax)) |
| ... | ... | @@ -1084,13 +1104,13 @@ static void setup_frame(int usig, struct emulated_sigaction *ka, |
| 1084 | 1104 | target_sigset_t *set, CPUState *regs) |
| 1085 | 1105 | { |
| 1086 | 1106 | struct sigframe *frame = get_sigframe(ka, regs, sizeof(*frame)); |
| 1087 | - int err = 0; | |
| 1107 | + int i, err = 0; | |
| 1088 | 1108 | |
| 1089 | 1109 | err |= setup_sigcontext(&frame->sc, /*&frame->fpstate,*/ regs, set->sig[0]); |
| 1090 | 1110 | |
| 1091 | - if (TARGET_NSIG_WORDS > 1) { | |
| 1092 | - err |= __copy_to_user(frame->extramask, &set->sig[1], | |
| 1093 | - sizeof(frame->extramask)); | |
| 1111 | + for(i = 1; i < TARGET_NSIG_WORDS; i++) { | |
| 1112 | + if (__put_user(set->sig[i], &frame->extramask[i - 1])) | |
| 1113 | + return; | |
| 1094 | 1114 | } |
| 1095 | 1115 | |
| 1096 | 1116 | if (err == 0) |
| ... | ... | @@ -1103,7 +1123,7 @@ static void setup_rt_frame(int usig, struct emulated_sigaction *ka, |
| 1103 | 1123 | target_sigset_t *set, CPUState *env) |
| 1104 | 1124 | { |
| 1105 | 1125 | struct rt_sigframe *frame = get_sigframe(ka, env, sizeof(*frame)); |
| 1106 | - int err = 0; | |
| 1126 | + int i, err = 0; | |
| 1107 | 1127 | |
| 1108 | 1128 | if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) |
| 1109 | 1129 | return /* 1 */; |
| ... | ... | @@ -1117,7 +1137,10 @@ static void setup_rt_frame(int usig, struct emulated_sigaction *ka, |
| 1117 | 1137 | |
| 1118 | 1138 | err |= setup_sigcontext(&frame->uc.uc_mcontext, /*&frame->fpstate,*/ |
| 1119 | 1139 | env, set->sig[0]); |
| 1120 | - err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | |
| 1140 | + for(i = 0; i < TARGET_NSIG_WORDS; i++) { | |
| 1141 | + if (__put_user(set->sig[i], &frame->uc.uc_sigmask.sig[i])) | |
| 1142 | + return; | |
| 1143 | + } | |
| 1121 | 1144 | |
| 1122 | 1145 | if (err == 0) |
| 1123 | 1146 | err = setup_return(env, ka, &frame->retcode, frame, usig); |
| ... | ... | @@ -1170,6 +1193,7 @@ long do_sigreturn(CPUState *env) |
| 1170 | 1193 | struct sigframe *frame; |
| 1171 | 1194 | target_sigset_t set; |
| 1172 | 1195 | sigset_t host_set; |
| 1196 | + int i; | |
| 1173 | 1197 | |
| 1174 | 1198 | /* |
| 1175 | 1199 | * Since we stacked the signal on a 64-bit boundary, |
| ... | ... | @@ -1185,13 +1209,14 @@ long do_sigreturn(CPUState *env) |
| 1185 | 1209 | if (verify_area(VERIFY_READ, frame, sizeof (*frame))) |
| 1186 | 1210 | goto badframe; |
| 1187 | 1211 | #endif |
| 1188 | - if (__get_user(set.sig[0], &frame->sc.oldmask) | |
| 1189 | - || (TARGET_NSIG_WORDS > 1 | |
| 1190 | - && __copy_from_user(&set.sig[1], &frame->extramask, | |
| 1191 | - sizeof(frame->extramask)))) | |
| 1192 | - goto badframe; | |
| 1212 | + if (__get_user(set.sig[0], &frame->sc.oldmask)) | |
| 1213 | + goto badframe; | |
| 1214 | + for(i = 1; i < TARGET_NSIG_WORDS; i++) { | |
| 1215 | + if (__get_user(set.sig[i], &frame->extramask[i - 1])) | |
| 1216 | + goto badframe; | |
| 1217 | + } | |
| 1193 | 1218 | |
| 1194 | - target_to_host_sigset(&host_set, &set); | |
| 1219 | + target_to_host_sigset_internal(&host_set, &set); | |
| 1195 | 1220 | sigprocmask(SIG_SETMASK, &host_set, NULL); |
| 1196 | 1221 | |
| 1197 | 1222 | if (restore_sigcontext(env, &frame->sc)) |
| ... | ... | @@ -1212,7 +1237,6 @@ badframe: |
| 1212 | 1237 | long do_rt_sigreturn(CPUState *env) |
| 1213 | 1238 | { |
| 1214 | 1239 | struct rt_sigframe *frame; |
| 1215 | - target_sigset_t set; | |
| 1216 | 1240 | sigset_t host_set; |
| 1217 | 1241 | |
| 1218 | 1242 | /* |
| ... | ... | @@ -1229,10 +1253,7 @@ long do_rt_sigreturn(CPUState *env) |
| 1229 | 1253 | if (verify_area(VERIFY_READ, frame, sizeof (*frame))) |
| 1230 | 1254 | goto badframe; |
| 1231 | 1255 | #endif |
| 1232 | - if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) | |
| 1233 | - goto badframe; | |
| 1234 | - | |
| 1235 | - target_to_host_sigset(&host_set, &set); | |
| 1256 | + target_to_host_sigset(&host_set, &frame->uc.uc_sigmask); | |
| 1236 | 1257 | sigprocmask(SIG_SETMASK, &host_set, NULL); |
| 1237 | 1258 | |
| 1238 | 1259 | if (restore_sigcontext(env, &frame->uc.uc_mcontext)) |
| ... | ... | @@ -1335,7 +1356,7 @@ void process_pending_signals(void *cpu_env) |
| 1335 | 1356 | sigprocmask(SIG_BLOCK, &set, &old_set); |
| 1336 | 1357 | /* save the previous blocked signal state to restore it at the |
| 1337 | 1358 | end of the signal execution (see do_sigreturn) */ |
| 1338 | - host_to_target_sigset(&target_old_set, &old_set); | |
| 1359 | + host_to_target_sigset_internal(&target_old_set, &old_set); | |
| 1339 | 1360 | |
| 1340 | 1361 | /* if the CPU is in VM86 mode, we restore the 32 bit values */ |
| 1341 | 1362 | #ifdef TARGET_I386 | ... | ... |