Commit 1c9bb1a0 authored by Paul Mackerras's avatar Paul Mackerras

[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: default avatarPaul Mackerras <paulus@samba.org>
parent bb63ab13
...@@ -835,11 +835,21 @@ long sys_swapcontext(struct ucontext __user *old_ctx, ...@@ -835,11 +835,21 @@ long sys_swapcontext(struct ucontext __user *old_ctx,
return -EINVAL; return -EINVAL;
if (old_ctx != NULL) { 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)) 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_sigset_t(&old_ctx->uc_sigmask, &current->blocked)
|| __put_user(to_user_ptr(&old_ctx->uc_mcontext), || __put_user(to_user_ptr(mctx), &old_ctx->uc_regs))
&old_ctx->uc_regs))
return -EFAULT; return -EFAULT;
} }
if (new_ctx == NULL) if (new_ctx == NULL)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment