sigset_t endianness fix in signal context

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@929 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
bellard 2004-06-19 16:58:13 +00:00
parent d69d1fa01a
commit 9231944d96

View File

@ -109,7 +109,8 @@ static inline int target_to_host_signal(int sig)
return target_to_host_signal_table[sig]; return target_to_host_signal_table[sig];
} }
void host_to_target_sigset(target_sigset_t *d, const sigset_t *s) static void host_to_target_sigset_internal(target_sigset_t *d,
const sigset_t *s)
{ {
int i; int i;
unsigned long sigmask; unsigned long sigmask;
@ -122,25 +123,35 @@ void host_to_target_sigset(target_sigset_t *d, const sigset_t *s)
target_sigmask |= 1 << (host_to_target_signal(i + 1) - 1); target_sigmask |= 1 << (host_to_target_signal(i + 1) - 1);
} }
#if TARGET_LONG_BITS == 32 && HOST_LONG_BITS == 32 #if TARGET_LONG_BITS == 32 && HOST_LONG_BITS == 32
d->sig[0] = tswapl(target_sigmask); d->sig[0] = target_sigmask;
for(i = 1;i < TARGET_NSIG_WORDS; i++) { for(i = 1;i < TARGET_NSIG_WORDS; i++) {
d->sig[i] = tswapl(((unsigned long *)s)[i]); d->sig[i] = ((unsigned long *)s)[i];
} }
#elif TARGET_LONG_BITS == 32 && HOST_LONG_BITS == 64 && TARGET_NSIG_WORDS == 2 #elif TARGET_LONG_BITS == 32 && HOST_LONG_BITS == 64 && TARGET_NSIG_WORDS == 2
d->sig[0] = tswapl(target_sigmask); d->sig[0] = target_sigmask;
d->sig[1] = tswapl(sigmask >> 32); d->sig[1] = sigmask >> 32;
#else #else
#error host_to_target_sigset #error host_to_target_sigset
#endif #endif
} }
void target_to_host_sigset(sigset_t *d, const target_sigset_t *s) void host_to_target_sigset(target_sigset_t *d, const sigset_t *s)
{
target_sigset_t d1;
int i;
host_to_target_sigset_internal(&d1, s);
for(i = 0;i < TARGET_NSIG_WORDS; i++)
__put_user(d1.sig[i], &d->sig[i]);
}
void target_to_host_sigset_internal(sigset_t *d, const target_sigset_t *s)
{ {
int i; int i;
unsigned long sigmask; unsigned long sigmask;
target_ulong target_sigmask; target_ulong target_sigmask;
target_sigmask = tswapl(s->sig[0]); target_sigmask = s->sig[0];
sigmask = 0; sigmask = 0;
for(i = 0; i < 32; i++) { for(i = 0; i < 32; i++) {
if (target_sigmask & (1 << i)) if (target_sigmask & (1 << i))
@ -149,15 +160,25 @@ void target_to_host_sigset(sigset_t *d, const target_sigset_t *s)
#if TARGET_LONG_BITS == 32 && HOST_LONG_BITS == 32 #if TARGET_LONG_BITS == 32 && HOST_LONG_BITS == 32
((unsigned long *)d)[0] = sigmask; ((unsigned long *)d)[0] = sigmask;
for(i = 1;i < TARGET_NSIG_WORDS; i++) { for(i = 1;i < TARGET_NSIG_WORDS; i++) {
((unsigned long *)d)[i] = tswapl(s->sig[i]); ((unsigned long *)d)[i] = s->sig[i];
} }
#elif TARGET_LONG_BITS == 32 && HOST_LONG_BITS == 64 && TARGET_NSIG_WORDS == 2 #elif TARGET_LONG_BITS == 32 && HOST_LONG_BITS == 64 && TARGET_NSIG_WORDS == 2
((unsigned long *)d)[0] = sigmask | ((unsigned long)tswapl(s->sig[1]) << 32); ((unsigned long *)d)[0] = sigmask | ((unsigned long)(s->sig[1]) << 32);
#else #else
#error target_to_host_sigset #error target_to_host_sigset
#endif /* TARGET_LONG_BITS */ #endif /* TARGET_LONG_BITS */
} }
void target_to_host_sigset(sigset_t *d, const target_sigset_t *s)
{
target_sigset_t s1;
int i;
for(i = 0;i < TARGET_NSIG_WORDS; i++)
__get_user(s1.sig[i], &s->sig[i]);
target_to_host_sigset_internal(d, &s1);
}
void host_to_target_old_sigset(target_ulong *old_sigset, void host_to_target_old_sigset(target_ulong *old_sigset,
const sigset_t *sigset) const sigset_t *sigset)
{ {
@ -640,7 +661,7 @@ static void setup_frame(int sig, struct emulated_sigaction *ka,
target_sigset_t *set, CPUX86State *env) target_sigset_t *set, CPUX86State *env)
{ {
struct sigframe *frame; struct sigframe *frame;
int err = 0; int i, err = 0;
frame = get_sigframe(ka, env, sizeof(*frame)); frame = get_sigframe(ka, env, sizeof(*frame));
@ -659,12 +680,10 @@ static void setup_frame(int sig, struct emulated_sigaction *ka,
if (err) if (err)
goto give_sigsegv; goto give_sigsegv;
if (TARGET_NSIG_WORDS > 1) { for(i = 1; i < TARGET_NSIG_WORDS; i++) {
err |= __copy_to_user(frame->extramask, &set->sig[1], if (__put_user(set->sig[i], &frame->extramask[i - 1]))
sizeof(frame->extramask)); goto give_sigsegv;
} }
if (err)
goto give_sigsegv;
/* Set up to return from userspace. If provided, use a stub /* Set up to return from userspace. If provided, use a stub
already in userspace. */ already in userspace. */
@ -704,7 +723,7 @@ static void setup_rt_frame(int sig, struct emulated_sigaction *ka,
target_sigset_t *set, CPUX86State *env) target_sigset_t *set, CPUX86State *env)
{ {
struct rt_sigframe *frame; struct rt_sigframe *frame;
int err = 0; int i, err = 0;
frame = get_sigframe(ka, env, sizeof(*frame)); frame = get_sigframe(ka, env, sizeof(*frame));
@ -732,9 +751,10 @@ static void setup_rt_frame(int sig, struct emulated_sigaction *ka,
err |= __put_user(/* current->sas_ss_size */ 0, &frame->uc.uc_stack.ss_size); err |= __put_user(/* current->sas_ss_size */ 0, &frame->uc.uc_stack.ss_size);
err |= setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate, err |= setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate,
env, set->sig[0]); env, set->sig[0]);
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); for(i = 0; i < TARGET_NSIG_WORDS; i++) {
if (err) if (__put_user(set->sig[i], &frame->uc.uc_sigmask.sig[i]))
goto give_sigsegv; goto give_sigsegv;
}
/* Set up to return from userspace. If provided, use a stub /* Set up to return from userspace. If provided, use a stub
already in userspace. */ already in userspace. */
@ -829,11 +849,14 @@ long do_sigreturn(CPUX86State *env)
fprintf(stderr, "do_sigreturn\n"); fprintf(stderr, "do_sigreturn\n");
#endif #endif
/* set blocked signals */ /* set blocked signals */
target_set.sig[0] = frame->sc.oldmask; if (__get_user(target_set.sig[0], &frame->sc.oldmask))
for(i = 1; i < TARGET_NSIG_WORDS; i++) goto badframe;
target_set.sig[i] = frame->extramask[i - 1]; for(i = 1; i < TARGET_NSIG_WORDS; i++) {
if (__get_user(target_set.sig[i], &frame->extramask[i - 1]))
goto badframe;
}
target_to_host_sigset(&set, &target_set); target_to_host_sigset_internal(&set, &target_set);
sigprocmask(SIG_SETMASK, &set, NULL); sigprocmask(SIG_SETMASK, &set, NULL);
/* restore registers */ /* restore registers */
@ -849,7 +872,6 @@ badframe:
long do_rt_sigreturn(CPUX86State *env) long do_rt_sigreturn(CPUX86State *env)
{ {
struct rt_sigframe *frame = (struct rt_sigframe *)(env->regs[R_ESP] - 4); struct rt_sigframe *frame = (struct rt_sigframe *)(env->regs[R_ESP] - 4);
target_sigset_t target_set;
sigset_t set; sigset_t set;
// stack_t st; // stack_t st;
int eax; int eax;
@ -858,9 +880,7 @@ long do_rt_sigreturn(CPUX86State *env)
if (verify_area(VERIFY_READ, frame, sizeof(*frame))) if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
goto badframe; goto badframe;
#endif #endif
memcpy(&target_set, &frame->uc.uc_sigmask, sizeof(target_sigset_t)); target_to_host_sigset(&set, &frame->uc.uc_sigmask);
target_to_host_sigset(&set, &target_set);
sigprocmask(SIG_SETMASK, &set, NULL); sigprocmask(SIG_SETMASK, &set, NULL);
if (restore_sigcontext(env, &frame->uc.uc_mcontext, &eax)) if (restore_sigcontext(env, &frame->uc.uc_mcontext, &eax))
@ -1084,13 +1104,13 @@ static void setup_frame(int usig, struct emulated_sigaction *ka,
target_sigset_t *set, CPUState *regs) target_sigset_t *set, CPUState *regs)
{ {
struct sigframe *frame = get_sigframe(ka, regs, sizeof(*frame)); struct sigframe *frame = get_sigframe(ka, regs, sizeof(*frame));
int err = 0; int i, err = 0;
err |= setup_sigcontext(&frame->sc, /*&frame->fpstate,*/ regs, set->sig[0]); err |= setup_sigcontext(&frame->sc, /*&frame->fpstate,*/ regs, set->sig[0]);
if (TARGET_NSIG_WORDS > 1) { for(i = 1; i < TARGET_NSIG_WORDS; i++) {
err |= __copy_to_user(frame->extramask, &set->sig[1], if (__put_user(set->sig[i], &frame->extramask[i - 1]))
sizeof(frame->extramask)); return;
} }
if (err == 0) if (err == 0)
@ -1103,7 +1123,7 @@ static void setup_rt_frame(int usig, struct emulated_sigaction *ka,
target_sigset_t *set, CPUState *env) target_sigset_t *set, CPUState *env)
{ {
struct rt_sigframe *frame = get_sigframe(ka, env, sizeof(*frame)); struct rt_sigframe *frame = get_sigframe(ka, env, sizeof(*frame));
int err = 0; int i, err = 0;
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
return /* 1 */; return /* 1 */;
@ -1117,7 +1137,10 @@ static void setup_rt_frame(int usig, struct emulated_sigaction *ka,
err |= setup_sigcontext(&frame->uc.uc_mcontext, /*&frame->fpstate,*/ err |= setup_sigcontext(&frame->uc.uc_mcontext, /*&frame->fpstate,*/
env, set->sig[0]); env, set->sig[0]);
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); for(i = 0; i < TARGET_NSIG_WORDS; i++) {
if (__put_user(set->sig[i], &frame->uc.uc_sigmask.sig[i]))
return;
}
if (err == 0) if (err == 0)
err = setup_return(env, ka, &frame->retcode, frame, usig); err = setup_return(env, ka, &frame->retcode, frame, usig);
@ -1170,6 +1193,7 @@ long do_sigreturn(CPUState *env)
struct sigframe *frame; struct sigframe *frame;
target_sigset_t set; target_sigset_t set;
sigset_t host_set; sigset_t host_set;
int i;
/* /*
* Since we stacked the signal on a 64-bit boundary, * Since we stacked the signal on a 64-bit boundary,
@ -1185,13 +1209,14 @@ long do_sigreturn(CPUState *env)
if (verify_area(VERIFY_READ, frame, sizeof (*frame))) if (verify_area(VERIFY_READ, frame, sizeof (*frame)))
goto badframe; goto badframe;
#endif #endif
if (__get_user(set.sig[0], &frame->sc.oldmask) if (__get_user(set.sig[0], &frame->sc.oldmask))
|| (TARGET_NSIG_WORDS > 1 goto badframe;
&& __copy_from_user(&set.sig[1], &frame->extramask, for(i = 1; i < TARGET_NSIG_WORDS; i++) {
sizeof(frame->extramask)))) if (__get_user(set.sig[i], &frame->extramask[i - 1]))
goto badframe; goto badframe;
}
target_to_host_sigset(&host_set, &set); target_to_host_sigset_internal(&host_set, &set);
sigprocmask(SIG_SETMASK, &host_set, NULL); sigprocmask(SIG_SETMASK, &host_set, NULL);
if (restore_sigcontext(env, &frame->sc)) if (restore_sigcontext(env, &frame->sc))
@ -1212,7 +1237,6 @@ badframe:
long do_rt_sigreturn(CPUState *env) long do_rt_sigreturn(CPUState *env)
{ {
struct rt_sigframe *frame; struct rt_sigframe *frame;
target_sigset_t set;
sigset_t host_set; sigset_t host_set;
/* /*
@ -1229,10 +1253,7 @@ long do_rt_sigreturn(CPUState *env)
if (verify_area(VERIFY_READ, frame, sizeof (*frame))) if (verify_area(VERIFY_READ, frame, sizeof (*frame)))
goto badframe; goto badframe;
#endif #endif
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) target_to_host_sigset(&host_set, &frame->uc.uc_sigmask);
goto badframe;
target_to_host_sigset(&host_set, &set);
sigprocmask(SIG_SETMASK, &host_set, NULL); sigprocmask(SIG_SETMASK, &host_set, NULL);
if (restore_sigcontext(env, &frame->uc.uc_mcontext)) if (restore_sigcontext(env, &frame->uc.uc_mcontext))
@ -1335,7 +1356,7 @@ void process_pending_signals(void *cpu_env)
sigprocmask(SIG_BLOCK, &set, &old_set); sigprocmask(SIG_BLOCK, &set, &old_set);
/* save the previous blocked signal state to restore it at the /* save the previous blocked signal state to restore it at the
end of the signal execution (see do_sigreturn) */ end of the signal execution (see do_sigreturn) */
host_to_target_sigset(&target_old_set, &old_set); host_to_target_sigset_internal(&target_old_set, &old_set);
/* if the CPU is in VM86 mode, we restore the 32 bit values */ /* if the CPU is in VM86 mode, we restore the 32 bit values */
#ifdef TARGET_I386 #ifdef TARGET_I386