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 |