Commit 9231944d9669595cecee8dda969546216470d6ad

Authored by bellard
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