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