X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fppc64%2Fkernel%2Fsignal32.c;h=3c2fa5c284c04ef223c468c2df53f6c7676dc20a;hb=f7f1b0f1e2fbadeab12d24236000e778aa9b1ead;hp=145eac7ef8f4afe9c72395d4bce43ee765eb4b9b;hpb=e3f6fb6212a7102bdb56ba38fa1e98fe72950475;p=linux-2.6.git diff --git a/arch/ppc64/kernel/signal32.c b/arch/ppc64/kernel/signal32.c index 145eac7ef..3c2fa5c28 100644 --- a/arch/ppc64/kernel/signal32.c +++ b/arch/ppc64/kernel/signal32.c @@ -31,6 +31,7 @@ #include #include #include +#include #define DEBUG_SIG 0 @@ -637,7 +638,7 @@ static int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, /* create a stack frame for the caller of the handler */ newsp -= __SIGNAL_FRAMESIZE32 + 16; - if (verify_area(VERIFY_WRITE, (void __user *)newsp, origsp - newsp)) + if (!access_ok(VERIFY_WRITE, (void __user *)newsp, origsp - newsp)) goto badframe; compat_from_sigset(&c_oldset, oldset); @@ -656,18 +657,24 @@ static int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, /* Save user registers on the stack */ frame = &rt_sf->uc.uc_mcontext; - if (save_user_regs(regs, frame, __NR_rt_sigreturn)) + if (put_user(regs->gpr[1], (u32 __user *)newsp)) goto badframe; - if (put_user(regs->gpr[1], (unsigned long __user *)newsp)) - goto badframe; + if (vdso32_rt_sigtramp && current->thread.vdso_base) { + if (save_user_regs(regs, frame, 0)) + goto badframe; + regs->link = current->thread.vdso_base + vdso32_rt_sigtramp; + } else { + if (save_user_regs(regs, frame, __NR_rt_sigreturn)) + goto badframe; + regs->link = (unsigned long) frame->tramp; + } regs->gpr[1] = (unsigned long) newsp; regs->gpr[3] = sig; regs->gpr[4] = (unsigned long) &rt_sf->info; regs->gpr[5] = (unsigned long) &rt_sf->uc; regs->gpr[6] = (unsigned long) rt_sf; regs->nip = (unsigned long) ka->sa.sa_handler; - regs->link = (unsigned long) frame->tramp; regs->trap = 0; regs->result = 0; @@ -721,7 +728,7 @@ long sys32_swapcontext(struct ucontext32 __user *old_ctx, if (old_ctx != NULL) { compat_from_sigset(&c_set, ¤t->blocked); - if (verify_area(VERIFY_WRITE, old_ctx, sizeof(*old_ctx)) + if (!access_ok(VERIFY_WRITE, old_ctx, sizeof(*old_ctx)) || save_user_regs(regs, &old_ctx->uc_mcontext, 0) || __copy_to_user(&old_ctx->uc_sigmask, &c_set, sizeof(c_set)) || __put_user((u32)(u64)&old_ctx->uc_mcontext, &old_ctx->uc_regs)) @@ -729,7 +736,7 @@ long sys32_swapcontext(struct ucontext32 __user *old_ctx, } if (new_ctx == NULL) return 0; - if (verify_area(VERIFY_READ, new_ctx, sizeof(*new_ctx)) + if (!access_ok(VERIFY_READ, new_ctx, sizeof(*new_ctx)) || __get_user(tmp, (u8 __user *) new_ctx) || __get_user(tmp, (u8 __user *) (new_ctx + 1) - 1)) return -EFAULT; @@ -739,7 +746,7 @@ long sys32_swapcontext(struct ucontext32 __user *old_ctx, * image of the user's registers, we can't just return -EFAULT * because the user's registers will be corrupted. For instance * the NIP value may have been updated but not some of the - * other registers. Given that we have done the verify_area + * other registers. Given that we have done the access_ok * and successfully read the first and last bytes of the region * above, this should only happen in an out-of-memory situation * or if another thread unmaps the region containing the context. @@ -763,7 +770,7 @@ long sys32_rt_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8, rt_sf = (struct rt_sigframe32 __user *) (regs->gpr[1] + __SIGNAL_FRAMESIZE32 + 16); - if (verify_area(VERIFY_READ, rt_sf, sizeof(*rt_sf))) + if (!access_ok(VERIFY_READ, rt_sf, sizeof(*rt_sf))) goto bad; if (do_setcontext32(&rt_sf->uc, regs, 1)) goto bad; @@ -812,7 +819,7 @@ static int handle_signal32(unsigned long sig, struct k_sigaction *ka, /* create a stack frame for the caller of the handler */ newsp -= __SIGNAL_FRAMESIZE32; - if (verify_area(VERIFY_WRITE, (void __user *) newsp, origsp - newsp)) + if (!access_ok(VERIFY_WRITE, (void __user *) newsp, origsp - newsp)) goto badframe; #if _NSIG != 64 @@ -825,16 +832,22 @@ static int handle_signal32(unsigned long sig, struct k_sigaction *ka, || __put_user(sig, &sc->signal)) goto badframe; - if (save_user_regs(regs, &frame->mctx, __NR_sigreturn)) - goto badframe; + if (vdso32_sigtramp && current->thread.vdso_base) { + if (save_user_regs(regs, &frame->mctx, 0)) + goto badframe; + regs->link = current->thread.vdso_base + vdso32_sigtramp; + } else { + if (save_user_regs(regs, &frame->mctx, __NR_sigreturn)) + goto badframe; + regs->link = (unsigned long) frame->mctx.tramp; + } - if (put_user(regs->gpr[1], (unsigned long __user *)newsp)) + if (put_user(regs->gpr[1], (u32 __user *)newsp)) goto badframe; regs->gpr[1] = (unsigned long) newsp; regs->gpr[3] = sig; regs->gpr[4] = (unsigned long) sc; regs->nip = (unsigned long) ka->sa.sa_handler; - regs->link = (unsigned long) frame->mctx.tramp; regs->trap = 0; regs->result = 0; @@ -879,7 +892,7 @@ long sys32_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8, restore_sigmask(&set); sr = (struct mcontext32 __user *)(u64)sigctx.regs; - if (verify_area(VERIFY_READ, sr, sizeof(*sr)) + if (!access_ok(VERIFY_READ, sr, sizeof(*sr)) || restore_user_regs(regs, sr, 1)) goto badframe;