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