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,7 +109,8 @@ static inline int target_to_host_signal(int sig) | ||
| 109 | return target_to_host_signal_table[sig]; | 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 | int i; | 115 | int i; |
| 115 | unsigned long sigmask; | 116 | unsigned long sigmask; |
| @@ -122,25 +123,35 @@ void host_to_target_sigset(target_sigset_t *d, const sigset_t *s) | @@ -122,25 +123,35 @@ void host_to_target_sigset(target_sigset_t *d, const sigset_t *s) | ||
| 122 | target_sigmask |= 1 << (host_to_target_signal(i + 1) - 1); | 123 | target_sigmask |= 1 << (host_to_target_signal(i + 1) - 1); |
| 123 | } | 124 | } |
| 124 | #if TARGET_LONG_BITS == 32 && HOST_LONG_BITS == 32 | 125 | #if TARGET_LONG_BITS == 32 && HOST_LONG_BITS == 32 |
| 125 | - d->sig[0] = tswapl(target_sigmask); | 126 | + d->sig[0] = target_sigmask; |
| 126 | for(i = 1;i < TARGET_NSIG_WORDS; i++) { | 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 | #elif TARGET_LONG_BITS == 32 && HOST_LONG_BITS == 64 && TARGET_NSIG_WORDS == 2 | 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 | #else | 133 | #else |
| 133 | #error host_to_target_sigset | 134 | #error host_to_target_sigset |
| 134 | #endif | 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 | int i; | 150 | int i; |
| 140 | unsigned long sigmask; | 151 | unsigned long sigmask; |
| 141 | target_ulong target_sigmask; | 152 | target_ulong target_sigmask; |
| 142 | 153 | ||
| 143 | - target_sigmask = tswapl(s->sig[0]); | 154 | + target_sigmask = s->sig[0]; |
| 144 | sigmask = 0; | 155 | sigmask = 0; |
| 145 | for(i = 0; i < 32; i++) { | 156 | for(i = 0; i < 32; i++) { |
| 146 | if (target_sigmask & (1 << i)) | 157 | if (target_sigmask & (1 << i)) |
| @@ -149,15 +160,25 @@ void target_to_host_sigset(sigset_t *d, const target_sigset_t *s) | @@ -149,15 +160,25 @@ void target_to_host_sigset(sigset_t *d, const target_sigset_t *s) | ||
| 149 | #if TARGET_LONG_BITS == 32 && HOST_LONG_BITS == 32 | 160 | #if TARGET_LONG_BITS == 32 && HOST_LONG_BITS == 32 |
| 150 | ((unsigned long *)d)[0] = sigmask; | 161 | ((unsigned long *)d)[0] = sigmask; |
| 151 | for(i = 1;i < TARGET_NSIG_WORDS; i++) { | 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 | #elif TARGET_LONG_BITS == 32 && HOST_LONG_BITS == 64 && TARGET_NSIG_WORDS == 2 | 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 | #else | 167 | #else |
| 157 | #error target_to_host_sigset | 168 | #error target_to_host_sigset |
| 158 | #endif /* TARGET_LONG_BITS */ | 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 | void host_to_target_old_sigset(target_ulong *old_sigset, | 182 | void host_to_target_old_sigset(target_ulong *old_sigset, |
| 162 | const sigset_t *sigset) | 183 | const sigset_t *sigset) |
| 163 | { | 184 | { |
| @@ -640,7 +661,7 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, | @@ -640,7 +661,7 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, | ||
| 640 | target_sigset_t *set, CPUX86State *env) | 661 | target_sigset_t *set, CPUX86State *env) |
| 641 | { | 662 | { |
| 642 | struct sigframe *frame; | 663 | struct sigframe *frame; |
| 643 | - int err = 0; | 664 | + int i, err = 0; |
| 644 | 665 | ||
| 645 | frame = get_sigframe(ka, env, sizeof(*frame)); | 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,12 +680,10 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, | ||
| 659 | if (err) | 680 | if (err) |
| 660 | goto give_sigsegv; | 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 | /* Set up to return from userspace. If provided, use a stub | 688 | /* Set up to return from userspace. If provided, use a stub |
| 670 | already in userspace. */ | 689 | already in userspace. */ |
| @@ -704,7 +723,7 @@ static void setup_rt_frame(int sig, struct emulated_sigaction *ka, | @@ -704,7 +723,7 @@ static void setup_rt_frame(int sig, struct emulated_sigaction *ka, | ||
| 704 | target_sigset_t *set, CPUX86State *env) | 723 | target_sigset_t *set, CPUX86State *env) |
| 705 | { | 724 | { |
| 706 | struct rt_sigframe *frame; | 725 | struct rt_sigframe *frame; |
| 707 | - int err = 0; | 726 | + int i, err = 0; |
| 708 | 727 | ||
| 709 | frame = get_sigframe(ka, env, sizeof(*frame)); | 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,9 +751,10 @@ static void setup_rt_frame(int sig, struct emulated_sigaction *ka, | ||
| 732 | err |= __put_user(/* current->sas_ss_size */ 0, &frame->uc.uc_stack.ss_size); | 751 | err |= __put_user(/* current->sas_ss_size */ 0, &frame->uc.uc_stack.ss_size); |
| 733 | err |= setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate, | 752 | err |= setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate, |
| 734 | env, set->sig[0]); | 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 | /* Set up to return from userspace. If provided, use a stub | 759 | /* Set up to return from userspace. If provided, use a stub |
| 740 | already in userspace. */ | 760 | already in userspace. */ |
| @@ -829,11 +849,14 @@ long do_sigreturn(CPUX86State *env) | @@ -829,11 +849,14 @@ long do_sigreturn(CPUX86State *env) | ||
| 829 | fprintf(stderr, "do_sigreturn\n"); | 849 | fprintf(stderr, "do_sigreturn\n"); |
| 830 | #endif | 850 | #endif |
| 831 | /* set blocked signals */ | 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 | sigprocmask(SIG_SETMASK, &set, NULL); | 860 | sigprocmask(SIG_SETMASK, &set, NULL); |
| 838 | 861 | ||
| 839 | /* restore registers */ | 862 | /* restore registers */ |
| @@ -849,7 +872,6 @@ badframe: | @@ -849,7 +872,6 @@ badframe: | ||
| 849 | long do_rt_sigreturn(CPUX86State *env) | 872 | long do_rt_sigreturn(CPUX86State *env) |
| 850 | { | 873 | { |
| 851 | struct rt_sigframe *frame = (struct rt_sigframe *)(env->regs[R_ESP] - 4); | 874 | struct rt_sigframe *frame = (struct rt_sigframe *)(env->regs[R_ESP] - 4); |
| 852 | - target_sigset_t target_set; | ||
| 853 | sigset_t set; | 875 | sigset_t set; |
| 854 | // stack_t st; | 876 | // stack_t st; |
| 855 | int eax; | 877 | int eax; |
| @@ -858,9 +880,7 @@ long do_rt_sigreturn(CPUX86State *env) | @@ -858,9 +880,7 @@ long do_rt_sigreturn(CPUX86State *env) | ||
| 858 | if (verify_area(VERIFY_READ, frame, sizeof(*frame))) | 880 | if (verify_area(VERIFY_READ, frame, sizeof(*frame))) |
| 859 | goto badframe; | 881 | goto badframe; |
| 860 | #endif | 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 | sigprocmask(SIG_SETMASK, &set, NULL); | 884 | sigprocmask(SIG_SETMASK, &set, NULL); |
| 865 | 885 | ||
| 866 | if (restore_sigcontext(env, &frame->uc.uc_mcontext, &eax)) | 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,13 +1104,13 @@ static void setup_frame(int usig, struct emulated_sigaction *ka, | ||
| 1084 | target_sigset_t *set, CPUState *regs) | 1104 | target_sigset_t *set, CPUState *regs) |
| 1085 | { | 1105 | { |
| 1086 | struct sigframe *frame = get_sigframe(ka, regs, sizeof(*frame)); | 1106 | struct sigframe *frame = get_sigframe(ka, regs, sizeof(*frame)); |
| 1087 | - int err = 0; | 1107 | + int i, err = 0; |
| 1088 | 1108 | ||
| 1089 | err |= setup_sigcontext(&frame->sc, /*&frame->fpstate,*/ regs, set->sig[0]); | 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 | if (err == 0) | 1116 | if (err == 0) |
| @@ -1103,7 +1123,7 @@ static void setup_rt_frame(int usig, struct emulated_sigaction *ka, | @@ -1103,7 +1123,7 @@ static void setup_rt_frame(int usig, struct emulated_sigaction *ka, | ||
| 1103 | target_sigset_t *set, CPUState *env) | 1123 | target_sigset_t *set, CPUState *env) |
| 1104 | { | 1124 | { |
| 1105 | struct rt_sigframe *frame = get_sigframe(ka, env, sizeof(*frame)); | 1125 | struct rt_sigframe *frame = get_sigframe(ka, env, sizeof(*frame)); |
| 1106 | - int err = 0; | 1126 | + int i, err = 0; |
| 1107 | 1127 | ||
| 1108 | if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) | 1128 | if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) |
| 1109 | return /* 1 */; | 1129 | return /* 1 */; |
| @@ -1117,7 +1137,10 @@ static void setup_rt_frame(int usig, struct emulated_sigaction *ka, | @@ -1117,7 +1137,10 @@ static void setup_rt_frame(int usig, struct emulated_sigaction *ka, | ||
| 1117 | 1137 | ||
| 1118 | err |= setup_sigcontext(&frame->uc.uc_mcontext, /*&frame->fpstate,*/ | 1138 | err |= setup_sigcontext(&frame->uc.uc_mcontext, /*&frame->fpstate,*/ |
| 1119 | env, set->sig[0]); | 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 | if (err == 0) | 1145 | if (err == 0) |
| 1123 | err = setup_return(env, ka, &frame->retcode, frame, usig); | 1146 | err = setup_return(env, ka, &frame->retcode, frame, usig); |
| @@ -1170,6 +1193,7 @@ long do_sigreturn(CPUState *env) | @@ -1170,6 +1193,7 @@ long do_sigreturn(CPUState *env) | ||
| 1170 | struct sigframe *frame; | 1193 | struct sigframe *frame; |
| 1171 | target_sigset_t set; | 1194 | target_sigset_t set; |
| 1172 | sigset_t host_set; | 1195 | sigset_t host_set; |
| 1196 | + int i; | ||
| 1173 | 1197 | ||
| 1174 | /* | 1198 | /* |
| 1175 | * Since we stacked the signal on a 64-bit boundary, | 1199 | * Since we stacked the signal on a 64-bit boundary, |
| @@ -1185,13 +1209,14 @@ long do_sigreturn(CPUState *env) | @@ -1185,13 +1209,14 @@ long do_sigreturn(CPUState *env) | ||
| 1185 | if (verify_area(VERIFY_READ, frame, sizeof (*frame))) | 1209 | if (verify_area(VERIFY_READ, frame, sizeof (*frame))) |
| 1186 | goto badframe; | 1210 | goto badframe; |
| 1187 | #endif | 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 | sigprocmask(SIG_SETMASK, &host_set, NULL); | 1220 | sigprocmask(SIG_SETMASK, &host_set, NULL); |
| 1196 | 1221 | ||
| 1197 | if (restore_sigcontext(env, &frame->sc)) | 1222 | if (restore_sigcontext(env, &frame->sc)) |
| @@ -1212,7 +1237,6 @@ badframe: | @@ -1212,7 +1237,6 @@ badframe: | ||
| 1212 | long do_rt_sigreturn(CPUState *env) | 1237 | long do_rt_sigreturn(CPUState *env) |
| 1213 | { | 1238 | { |
| 1214 | struct rt_sigframe *frame; | 1239 | struct rt_sigframe *frame; |
| 1215 | - target_sigset_t set; | ||
| 1216 | sigset_t host_set; | 1240 | sigset_t host_set; |
| 1217 | 1241 | ||
| 1218 | /* | 1242 | /* |
| @@ -1229,10 +1253,7 @@ long do_rt_sigreturn(CPUState *env) | @@ -1229,10 +1253,7 @@ long do_rt_sigreturn(CPUState *env) | ||
| 1229 | if (verify_area(VERIFY_READ, frame, sizeof (*frame))) | 1253 | if (verify_area(VERIFY_READ, frame, sizeof (*frame))) |
| 1230 | goto badframe; | 1254 | goto badframe; |
| 1231 | #endif | 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 | sigprocmask(SIG_SETMASK, &host_set, NULL); | 1257 | sigprocmask(SIG_SETMASK, &host_set, NULL); |
| 1237 | 1258 | ||
| 1238 | if (restore_sigcontext(env, &frame->uc.uc_mcontext)) | 1259 | if (restore_sigcontext(env, &frame->uc.uc_mcontext)) |
| @@ -1335,7 +1356,7 @@ void process_pending_signals(void *cpu_env) | @@ -1335,7 +1356,7 @@ void process_pending_signals(void *cpu_env) | ||
| 1335 | sigprocmask(SIG_BLOCK, &set, &old_set); | 1356 | sigprocmask(SIG_BLOCK, &set, &old_set); |
| 1336 | /* save the previous blocked signal state to restore it at the | 1357 | /* save the previous blocked signal state to restore it at the |
| 1337 | end of the signal execution (see do_sigreturn) */ | 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 | /* if the CPU is in VM86 mode, we restore the 32 bit values */ | 1361 | /* if the CPU is in VM86 mode, we restore the 32 bit values */ |
| 1341 | #ifdef TARGET_I386 | 1362 | #ifdef TARGET_I386 |