X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=arch%2Fpowerpc%2Fkernel%2Fsignal_32.c;h=6b405a3f43f943b67c5b3cd2cabaeed43847aa00;hb=812fd1fd63caf2d72906603ebb9c6049a19ef4d2;hp=e4ebe1a6228e5e9a9ad32da2dd7f601f5f6afc61;hpb=bef986502fa398b1785a3979b1aa17cd902d3527;p=powerpc.git diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index e4ebe1a622..6b405a3f43 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c @@ -835,11 +835,21 @@ long sys_swapcontext(struct ucontext __user *old_ctx, return -EINVAL; if (old_ctx != NULL) { + struct mcontext __user *mctx; + + /* + * old_ctx might not be 16-byte aligned, in which + * case old_ctx->uc_mcontext won't be either. + * Because we have the old_ctx->uc_pad2 field + * before old_ctx->uc_mcontext, we need to round down + * from &old_ctx->uc_mcontext to a 16-byte boundary. + */ + mctx = (struct mcontext __user *) + ((unsigned long) &old_ctx->uc_mcontext & ~0xfUL); if (!access_ok(VERIFY_WRITE, old_ctx, sizeof(*old_ctx)) - || save_user_regs(regs, &old_ctx->uc_mcontext, 0) + || save_user_regs(regs, mctx, 0) || put_sigset_t(&old_ctx->uc_sigmask, ¤t->blocked) - || __put_user(to_user_ptr(&old_ctx->uc_mcontext), - &old_ctx->uc_regs)) + || __put_user(to_user_ptr(mctx), &old_ctx->uc_regs)) return -EFAULT; } if (new_ctx == NULL)