Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=1c9bb1a01ac1bc92a0d98cf3e40a7922ee684dc0
Commit:     1c9bb1a01ac1bc92a0d98cf3e40a7922ee684dc0
Parent:     bb63ab13515951f4d09b16c9e8bd6e50b0f20d1e
Author:     Paul Mackerras <[EMAIL PROTECTED]>
AuthorDate: Wed Dec 20 13:57:06 2006 +1100
Committer:  Paul Mackerras <[EMAIL PROTECTED]>
CommitDate: Wed Dec 20 16:37:49 2006 +1100

    [POWERPC] Fix register save area alignment for swapcontext syscall
    
    For 32-bit processes, the getcontext side of the swapcontext system
    call (i.e. the saving of the context when the first argument is
    non-NULL) has to set the ctx->uc_mcontext.uc_regs pointer to the place
    where it saves the registers.  Which it does, but it doesn't ensure
    that the pointer is 16-byte aligned.  16-byte alignment is needed
    because the Altivec/VMX registers are saved in there, and they need to
    be on a 16-byte boundary.
    
    This fixes it by ensuring the appropriate alignment of the pointer.
    This issue was pointed out by Jakub Jelinek.
    
    Signed-off-by: Paul Mackerras <[EMAIL PROTECTED]>
---
 arch/powerpc/kernel/signal_32.c |   16 +++++++++++++---
 1 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index e4ebe1a..6b405a3 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, &current->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)
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to