diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-11-11 14:26:47 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-11-11 14:26:47 +0000 |
commit | 579a97f7ff4c0f958a5d8adcba717a205bb58567 (patch) | |
tree | 845f187afdd4a15f4625d2156f0fd967beb50c5d /linux-user/signal.c | |
parent | 44f8625d23f9807c0853556ffe1c44540bd453f9 (diff) | |
download | qemu-579a97f7ff4c0f958a5d8adcba717a205bb58567.zip qemu-579a97f7ff4c0f958a5d8adcba717a205bb58567.tar.gz qemu-579a97f7ff4c0f958a5d8adcba717a205bb58567.tar.bz2 |
Linux user memory access API change (initial patch by Thayne Harbaugh)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3583 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'linux-user/signal.c')
-rw-r--r-- | linux-user/signal.c | 244 |
1 files changed, 138 insertions, 106 deletions
diff --git a/linux-user/signal.c b/linux-user/signal.c index a0f1511..e9da097 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -435,31 +435,32 @@ static void host_signal_handler(int host_signum, siginfo_t *info, } /* do_sigaltstack() returns target values and errnos. */ -int do_sigaltstack(const struct target_sigaltstack *uss, - struct target_sigaltstack *uoss, - abi_ulong sp) +/* compare linux/kernel/signal.c:do_sigaltstack() */ +abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp) { int ret; struct target_sigaltstack oss; /* XXX: test errors */ - if(uoss) + if(uoss_addr) { __put_user(target_sigaltstack_used.ss_sp, &oss.ss_sp); __put_user(target_sigaltstack_used.ss_size, &oss.ss_size); __put_user(sas_ss_flags(sp), &oss.ss_flags); } - if(uss) + if(uss_addr) { - struct target_sigaltstack ss; + struct target_sigaltstack *uss; + struct target_sigaltstack ss; ret = -TARGET_EFAULT; - if (!access_ok(VERIFY_READ, uss, sizeof(*uss)) + if (!lock_user_struct(VERIFY_READ, uss, uss_addr, 1) || __get_user(ss.ss_sp, &uss->ss_sp) || __get_user(ss.ss_size, &uss->ss_size) || __get_user(ss.ss_flags, &uss->ss_flags)) goto out; + unlock_user_struct(uss, uss_addr, 0); ret = -TARGET_EPERM; if (on_sig_stack(sp)) @@ -484,11 +485,10 @@ int do_sigaltstack(const struct target_sigaltstack *uss, target_sigaltstack_used.ss_size = ss.ss_size; } - if (uoss) { + if (uoss_addr) { ret = -TARGET_EFAULT; - if (!access_ok(VERIFY_WRITE, uoss, sizeof(oss))) + if (copy_to_user(uoss_addr, &oss, sizeof(oss))) goto out; - memcpy(uoss, &oss, sizeof(oss)); } ret = 0; @@ -671,6 +671,7 @@ setup_sigcontext(struct target_sigcontext *sc, struct target_fpstate *fpstate, { int err = 0; + /* already locked in setup_frame() */ err |= __put_user(env->segs[R_GS].selector, (unsigned int *)&sc->gs); err |= __put_user(env->segs[R_FS].selector, (unsigned int *)&sc->fs); err |= __put_user(env->segs[R_ES].selector, (unsigned int *)&sc->es); @@ -706,7 +707,7 @@ setup_sigcontext(struct target_sigcontext *sc, struct target_fpstate *fpstate, * Determine which stack to use.. */ -static inline void * +static inline abi_ulong get_sigframe(struct emulated_sigaction *ka, CPUX86State *env, size_t frame_size) { unsigned long esp; @@ -726,19 +727,22 @@ get_sigframe(struct emulated_sigaction *ka, CPUX86State *env, size_t frame_size) ka->sa.sa_restorer) { esp = (unsigned long) ka->sa.sa_restorer; } - return g2h((esp - frame_size) & -8ul); + return (esp - frame_size) & -8ul; } +/* compare linux/arch/i386/kernel/signal.c:setup_frame() */ static void setup_frame(int sig, struct emulated_sigaction *ka, target_sigset_t *set, CPUX86State *env) { + abi_ulong frame_addr; struct sigframe *frame; int i, err = 0; - frame = get_sigframe(ka, env, sizeof(*frame)); + frame_addr = get_sigframe(ka, env, sizeof(*frame)); - if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) + if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) goto give_sigsegv; + err |= __put_user((/*current->exec_domain && current->exec_domain->signal_invmap && sig < 32 @@ -786,24 +790,29 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, cpu_x86_load_seg(env, R_CS, __USER_CS); env->eflags &= ~TF_MASK; + unlock_user_struct(frame, frame_addr, 1); + return; give_sigsegv: + unlock_user_struct(frame, frame_addr, 1); if (sig == TARGET_SIGSEGV) ka->sa._sa_handler = TARGET_SIG_DFL; force_sig(TARGET_SIGSEGV /* , current */); } +/* compare linux/arch/i386/kernel/signal.c:setup_rt_frame() */ static void setup_rt_frame(int sig, struct emulated_sigaction *ka, target_siginfo_t *info, target_sigset_t *set, CPUX86State *env) { + abi_ulong frame_addr; struct rt_sigframe *frame; int i, err = 0; - frame = get_sigframe(ka, env, sizeof(*frame)); + frame_addr = get_sigframe(ka, env, sizeof(*frame)); - if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) + if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) goto give_sigsegv; err |= __put_user((/*current->exec_domain @@ -859,9 +868,12 @@ static void setup_rt_frame(int sig, struct emulated_sigaction *ka, cpu_x86_load_seg(env, R_CS, __USER_CS); env->eflags &= ~TF_MASK; + unlock_user_struct(frame, frame_addr, 1); + return; give_sigsegv: + unlock_user_struct(frame, frame_addr, 1); if (sig == TARGET_SIGSEGV) ka->sa._sa_handler = TARGET_SIG_DFL; force_sig(TARGET_SIGSEGV /* , current */); @@ -918,7 +930,8 @@ badframe: long do_sigreturn(CPUX86State *env) { - struct sigframe *frame = (struct sigframe *)g2h(env->regs[R_ESP] - 8); + struct sigframe *frame; + abi_ulong frame_addr = env->regs[R_ESP] - 8; target_sigset_t target_set; sigset_t set; int eax, i; @@ -926,6 +939,8 @@ long do_sigreturn(CPUX86State *env) #if defined(DEBUG_SIGNAL) fprintf(stderr, "do_sigreturn\n"); #endif + if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) + goto badframe; /* set blocked signals */ if (__get_user(target_set.sig[0], &frame->sc.oldmask)) goto badframe; @@ -940,9 +955,11 @@ long do_sigreturn(CPUX86State *env) /* restore registers */ if (restore_sigcontext(env, &frame->sc, &eax)) goto badframe; + unlock_user_struct(frame, frame_addr, 0); return eax; badframe: + unlock_user_struct(frame, frame_addr, 0); force_sig(TARGET_SIGSEGV); return 0; } @@ -963,7 +980,7 @@ long do_rt_sigreturn(CPUX86State *env) if (restore_sigcontext(env, &frame->uc.tuc_mcontext, &eax)) goto badframe; - if (do_sigaltstack(&frame->uc.tuc_stack, NULL, get_sp_from_cpustate(env)) == -EFAULT) + if (do_sigaltstack(h2g(&frame->uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT) goto badframe; return eax; @@ -1086,7 +1103,7 @@ setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/ return err; } -static inline void * +static inline abi_ulong get_sigframe(struct emulated_sigaction *ka, CPUState *regs, int framesize) { unsigned long sp = regs->regs[13]; @@ -1099,7 +1116,7 @@ get_sigframe(struct emulated_sigaction *ka, CPUState *regs, int framesize) /* * ATPCS B01 mandates 8-byte alignment */ - return g2h((sp - framesize) & ~7); + return (sp - framesize) & ~7; } static int @@ -1167,33 +1184,43 @@ setup_return(CPUState *env, struct emulated_sigaction *ka, return 0; } +/* compare linux/arch/arm/kernel/signal.c:setup_frame() */ static void setup_frame(int usig, struct emulated_sigaction *ka, target_sigset_t *set, CPUState *regs) { - struct sigframe *frame = get_sigframe(ka, regs, sizeof(*frame)); + struct sigframe *frame; + abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame)); int i, err = 0; + if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) + return; + err |= setup_sigcontext(&frame->sc, /*&frame->fpstate,*/ regs, set->sig[0]); for(i = 1; i < TARGET_NSIG_WORDS; i++) { if (__put_user(set->sig[i], &frame->extramask[i - 1])) - return; + goto end; } if (err == 0) err = setup_return(regs, ka, &frame->retcode, frame, usig); + +end: + unlock_user_struct(frame, frame_addr, 1); // return err; } +/* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */ static void setup_rt_frame(int usig, struct emulated_sigaction *ka, target_siginfo_t *info, target_sigset_t *set, CPUState *env) { - struct rt_sigframe *frame = get_sigframe(ka, env, sizeof(*frame)); + struct rt_sigframe *frame; + abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame)); struct target_sigaltstack stack; int i, err = 0; - if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) + if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) return /* 1 */; __put_user_error(&frame->info, (abi_ulong *)&frame->pinfo, err); @@ -1207,16 +1234,13 @@ static void setup_rt_frame(int usig, struct emulated_sigaction *ka, __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp); __put_user(target_sigaltstack_used.ss_size, &stack.ss_size); __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags); - if (!access_ok(VERIFY_WRITE, &frame->uc.tuc_stack, sizeof(stack))) - err = 1; - else - memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack)); + err |= copy_to_user(&frame->uc.tuc_stack, &stack, sizeof(stack)); err |= setup_sigcontext(&frame->uc.tuc_mcontext, /*&frame->fpstate,*/ env, set->sig[0]); for(i = 0; i < TARGET_NSIG_WORDS; i++) { if (__put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i])) - return; + goto end; } if (err == 0) @@ -1232,6 +1256,9 @@ static void setup_rt_frame(int usig, struct emulated_sigaction *ka, env->regs[2] = (abi_ulong)frame->puc; } +end: + unlock_user_struct(frame, frame_addr, 1); + // return err; } @@ -1338,7 +1365,7 @@ long do_rt_sigreturn(CPUState *env) if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) goto badframe; - if (do_sigaltstack(&frame->uc.tuc_stack, NULL, get_sp_from_cpustate(env)) == -EFAULT) + if (do_sigaltstack(h2g(&frame->uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT) goto badframe; #if 0 @@ -1788,8 +1815,8 @@ void sparc64_set_context(CPUSPARCState *env) abi_ulong *src, *dst; grp = &ucp->uc_mcontext.mc_gregs; - err = get_user(pc, &((*grp)[MC_PC])); - err |= get_user(npc, &((*grp)[MC_NPC])); + err = __get_user(pc, &((*grp)[MC_PC])); + err |= __get_user(npc, &((*grp)[MC_NPC])); if (err || ((pc | npc) & 3)) goto do_sigsegv; if (env->regwptr[UREG_I1]) { @@ -1797,14 +1824,14 @@ void sparc64_set_context(CPUSPARCState *env) sigset_t set; if (TARGET_NSIG_WORDS == 1) { - if (get_user(target_set.sig[0], &ucp->uc_sigmask.sig[0])) + if (__get_user(target_set.sig[0], &ucp->uc_sigmask.sig[0])) goto do_sigsegv; } else { src = &ucp->uc_sigmask; dst = &target_set; for (i = 0; i < sizeof(target_sigset_t) / sizeof(abi_ulong); i++, dst++, src++) - err |= get_user(dst, src); + err |= __get_user(dst, src); if (err) goto do_sigsegv; } @@ -1813,44 +1840,44 @@ void sparc64_set_context(CPUSPARCState *env) } env->pc = pc; env->npc = npc; - err |= get_user(env->y, &((*grp)[MC_Y])); - err |= get_user(tstate, &((*grp)[MC_TSTATE])); + err |= __get_user(env->y, &((*grp)[MC_Y])); + err |= __get_user(tstate, &((*grp)[MC_TSTATE])); env->asi = (tstate >> 24) & 0xff; PUT_CCR(env, tstate >> 32); PUT_CWP64(env, tstate & 0x1f); - err |= get_user(env->gregs[1], (&(*grp)[MC_G1])); - err |= get_user(env->gregs[2], (&(*grp)[MC_G2])); - err |= get_user(env->gregs[3], (&(*grp)[MC_G3])); - err |= get_user(env->gregs[4], (&(*grp)[MC_G4])); - err |= get_user(env->gregs[5], (&(*grp)[MC_G5])); - err |= get_user(env->gregs[6], (&(*grp)[MC_G6])); - err |= get_user(env->gregs[7], (&(*grp)[MC_G7])); - err |= get_user(env->regwptr[UREG_I0], (&(*grp)[MC_O0])); - err |= get_user(env->regwptr[UREG_I1], (&(*grp)[MC_O1])); - err |= get_user(env->regwptr[UREG_I2], (&(*grp)[MC_O2])); - err |= get_user(env->regwptr[UREG_I3], (&(*grp)[MC_O3])); - err |= get_user(env->regwptr[UREG_I4], (&(*grp)[MC_O4])); - err |= get_user(env->regwptr[UREG_I5], (&(*grp)[MC_O5])); - err |= get_user(env->regwptr[UREG_I6], (&(*grp)[MC_O6])); - err |= get_user(env->regwptr[UREG_I7], (&(*grp)[MC_O7])); - - err |= get_user(fp, &(ucp->uc_mcontext.mc_fp)); - err |= get_user(i7, &(ucp->uc_mcontext.mc_i7)); - err |= put_user(fp, - (&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[6]))); - err |= put_user(i7, - (&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[7]))); - - err |= get_user(fenab, &(ucp->uc_mcontext.mc_fpregs.mcfpu_enab)); - err |= get_user(env->fprs, &(ucp->uc_mcontext.mc_fpregs.mcfpu_fprs)); + err |= __get_user(env->gregs[1], (&(*grp)[MC_G1])); + err |= __get_user(env->gregs[2], (&(*grp)[MC_G2])); + err |= __get_user(env->gregs[3], (&(*grp)[MC_G3])); + err |= __get_user(env->gregs[4], (&(*grp)[MC_G4])); + err |= __get_user(env->gregs[5], (&(*grp)[MC_G5])); + err |= __get_user(env->gregs[6], (&(*grp)[MC_G6])); + err |= __get_user(env->gregs[7], (&(*grp)[MC_G7])); + err |= __get_user(env->regwptr[UREG_I0], (&(*grp)[MC_O0])); + err |= __get_user(env->regwptr[UREG_I1], (&(*grp)[MC_O1])); + err |= __get_user(env->regwptr[UREG_I2], (&(*grp)[MC_O2])); + err |= __get_user(env->regwptr[UREG_I3], (&(*grp)[MC_O3])); + err |= __get_user(env->regwptr[UREG_I4], (&(*grp)[MC_O4])); + err |= __get_user(env->regwptr[UREG_I5], (&(*grp)[MC_O5])); + err |= __get_user(env->regwptr[UREG_I6], (&(*grp)[MC_O6])); + err |= __get_user(env->regwptr[UREG_I7], (&(*grp)[MC_O7])); + + err |= __get_user(fp, &(ucp->uc_mcontext.mc_fp)); + err |= __get_user(i7, &(ucp->uc_mcontext.mc_i7)); + err |= __put_user(fp, + (&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[6]))); + err |= __put_user(i7, + (&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[7]))); + + err |= __get_user(fenab, &(ucp->uc_mcontext.mc_fpregs.mcfpu_enab)); + err |= __get_user(env->fprs, &(ucp->uc_mcontext.mc_fpregs.mcfpu_fprs)); src = &(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs); dst = &env->fpr; for (i = 0; i < 64; i++, dst++, src++) - err |= get_user(dst, src); - err |= get_user(env->fsr, - &(ucp->uc_mcontext.mc_fpregs.mcfpu_fsr)); - err |= get_user(env->gsr, - &(ucp->uc_mcontext.mc_fpregs.mcfpu_gsr)); + err |= __get_user(dst, src); + err |= __get_user(env->fsr, + &(ucp->uc_mcontext.mc_fpregs.mcfpu_fsr)); + err |= __get_user(env->gsr, + &(ucp->uc_mcontext.mc_fpregs.mcfpu_gsr)); if (err) goto do_sigsegv; @@ -1884,52 +1911,52 @@ void sparc64_get_context(CPUSPARCState *env) sigprocmask(0, NULL, &set); host_to_target_sigset_internal(&target_set, &set); if (TARGET_NSIG_WORDS == 1) - err |= put_user(target_set.sig[0], - (abi_ulong *)&ucp->uc_sigmask); + err |= __put_user(target_set.sig[0], + (abi_ulong *)&ucp->uc_sigmask); else { src = &target_set; dst = &ucp->uc_sigmask; for (i = 0; i < sizeof(target_sigset_t) / sizeof(abi_ulong); i++, dst++, src++) - err |= put_user(src, dst); + err |= __put_user(src, dst); if (err) goto do_sigsegv; } - err |= put_user(env->tstate, &((*grp)[MC_TSTATE])); - err |= put_user(env->pc, &((*grp)[MC_PC])); - err |= put_user(env->npc, &((*grp)[MC_NPC])); - err |= put_user(env->y, &((*grp)[MC_Y])); - err |= put_user(env->gregs[1], &((*grp)[MC_G1])); - err |= put_user(env->gregs[2], &((*grp)[MC_G2])); - err |= put_user(env->gregs[3], &((*grp)[MC_G3])); - err |= put_user(env->gregs[4], &((*grp)[MC_G4])); - err |= put_user(env->gregs[5], &((*grp)[MC_G5])); - err |= put_user(env->gregs[6], &((*grp)[MC_G6])); - err |= put_user(env->gregs[7], &((*grp)[MC_G7])); - err |= put_user(env->regwptr[UREG_I0], &((*grp)[MC_O0])); - err |= put_user(env->regwptr[UREG_I1], &((*grp)[MC_O1])); - err |= put_user(env->regwptr[UREG_I2], &((*grp)[MC_O2])); - err |= put_user(env->regwptr[UREG_I3], &((*grp)[MC_O3])); - err |= put_user(env->regwptr[UREG_I4], &((*grp)[MC_O4])); - err |= put_user(env->regwptr[UREG_I5], &((*grp)[MC_O5])); - err |= put_user(env->regwptr[UREG_I6], &((*grp)[MC_O6])); - err |= put_user(env->regwptr[UREG_I7], &((*grp)[MC_O7])); - - err |= get_user(fp, - (&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[6]))); - err |= get_user(i7, - (&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[7]))); - err |= put_user(fp, &(mcp->mc_fp)); - err |= put_user(i7, &(mcp->mc_i7)); + err |= __put_user(env->tstate, &((*grp)[MC_TSTATE])); + err |= __put_user(env->pc, &((*grp)[MC_PC])); + err |= __put_user(env->npc, &((*grp)[MC_NPC])); + err |= __put_user(env->y, &((*grp)[MC_Y])); + err |= __put_user(env->gregs[1], &((*grp)[MC_G1])); + err |= __put_user(env->gregs[2], &((*grp)[MC_G2])); + err |= __put_user(env->gregs[3], &((*grp)[MC_G3])); + err |= __put_user(env->gregs[4], &((*grp)[MC_G4])); + err |= __put_user(env->gregs[5], &((*grp)[MC_G5])); + err |= __put_user(env->gregs[6], &((*grp)[MC_G6])); + err |= __put_user(env->gregs[7], &((*grp)[MC_G7])); + err |= __put_user(env->regwptr[UREG_I0], &((*grp)[MC_O0])); + err |= __put_user(env->regwptr[UREG_I1], &((*grp)[MC_O1])); + err |= __put_user(env->regwptr[UREG_I2], &((*grp)[MC_O2])); + err |= __put_user(env->regwptr[UREG_I3], &((*grp)[MC_O3])); + err |= __put_user(env->regwptr[UREG_I4], &((*grp)[MC_O4])); + err |= __put_user(env->regwptr[UREG_I5], &((*grp)[MC_O5])); + err |= __put_user(env->regwptr[UREG_I6], &((*grp)[MC_O6])); + err |= __put_user(env->regwptr[UREG_I7], &((*grp)[MC_O7])); + + err |= __get_user(fp, + (&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[6]))); + err |= __get_user(i7, + (&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[7]))); + err |= __put_user(fp, &(mcp->mc_fp)); + err |= __put_user(i7, &(mcp->mc_i7)); src = &env->fpr; dst = &(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs); for (i = 0; i < 64; i++, dst++, src++) - err |= put_user(src, dst); - err |= put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr)); - err |= put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr)); - err |= put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs)); + err |= __put_user(src, dst); + err |= __put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr)); + err |= __put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr)); + err |= __put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs)); if (err) goto do_sigsegv; @@ -2191,7 +2218,7 @@ restore_sigcontext(CPUState *regs, struct target_sigcontext *sc) /* * Determine which stack to use.. */ -static inline void * +static inline abi_ulong get_sigframe(struct emulated_sigaction *ka, CPUState *regs, size_t frame_size) { unsigned long sp; @@ -2211,17 +2238,19 @@ get_sigframe(struct emulated_sigaction *ka, CPUState *regs, size_t frame_size) sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size; } - return g2h((sp - frame_size) & ~7); + return (sp - frame_size) & ~7; } +/* compare linux/arch/mips/kernel/signal.c:setup_frame() */ static void setup_frame(int sig, struct emulated_sigaction * ka, - target_sigset_t *set, CPUState *regs) + target_sigset_t *set, CPUState *regs) { struct sigframe *frame; + abi_ulong frame_addr; int i; - frame = get_sigframe(ka, regs, sizeof(*frame)); - if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) + frame_addr = get_sigframe(ka, regs, sizeof(*frame)); + if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) goto give_sigsegv; install_sigtramp(frame->sf_code, TARGET_NR_sigreturn); @@ -2253,9 +2282,11 @@ static void setup_frame(int sig, struct emulated_sigaction * ka, * since it returns to userland using eret * we cannot do this here, and we must set PC directly */ regs->PC[regs->current_tc] = regs->gpr[25][regs->current_tc] = ka->sa._sa_handler; + unlock_user_struct(frame, frame_addr, 1); return; give_sigsegv: + unlock_user_struct(frame, frame_addr, 1); force_sig(TARGET_SIGSEGV/*, current*/); return; } @@ -2263,6 +2294,7 @@ give_sigsegv: long do_sigreturn(CPUState *regs) { struct sigframe *frame; + abi_ulong frame_addr; sigset_t blocked; target_sigset_t target_set; int i; @@ -2270,8 +2302,8 @@ long do_sigreturn(CPUState *regs) #if defined(DEBUG_SIGNAL) fprintf(stderr, "do_sigreturn\n"); #endif - frame = (struct sigframe *) regs->gpr[29][regs->current_tc]; - if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) + frame_addr = regs->gpr[29][regs->current_tc]; + if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) goto badframe; for(i = 0; i < TARGET_NSIG_WORDS; i++) { |