Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 118272
b: refs/heads/master
c: 16c29d1
h: refs/heads/master
v: v3
  • Loading branch information
Michael Neuling authored and Paul Mackerras committed Oct 31, 2008
1 parent 6035509 commit 2f900f5
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 40 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: b160544cccb403310cf38ddb3ebc156ea454848a
refs/heads/master: 16c29d180becc5bdf92fd0fc7314a44a671b5f4e
36 changes: 15 additions & 21 deletions trunk/arch/powerpc/kernel/signal_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ inline unsigned long copy_fpr_from_user(struct task_struct *task,
* altivec/spe instructions at some point.
*/
static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame,
int sigret)
int sigret, int ctx_has_vsx_region)
{
unsigned long msr = regs->msr;

Expand Down Expand Up @@ -451,7 +451,7 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame,
* the saved MSR value to indicate that frame->mc_vregs
* contains valid data
*/
if (current->thread.used_vsr) {
if (current->thread.used_vsr && ctx_has_vsx_region) {
__giveup_vsx(current);
if (copy_vsx_to_user(&frame->mc_vsregs, current))
return 1;
Expand Down Expand Up @@ -858,11 +858,11 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
frame = &rt_sf->uc.uc_mcontext;
addr = frame;
if (vdso32_rt_sigtramp && current->mm->context.vdso_base) {
if (save_user_regs(regs, frame, 0))
if (save_user_regs(regs, frame, 0, 1))
goto badframe;
regs->link = current->mm->context.vdso_base + vdso32_rt_sigtramp;
} else {
if (save_user_regs(regs, frame, __NR_rt_sigreturn))
if (save_user_regs(regs, frame, __NR_rt_sigreturn, 1))
goto badframe;
regs->link = (unsigned long) frame->tramp;
}
Expand Down Expand Up @@ -936,12 +936,13 @@ long sys_swapcontext(struct ucontext __user *old_ctx,
int ctx_size, int r6, int r7, int r8, struct pt_regs *regs)
{
unsigned char tmp;
int ctx_has_vsx_region = 0;

#ifdef CONFIG_PPC64
unsigned long new_msr = 0;

if (new_ctx &&
__get_user(new_msr, &new_ctx->uc_mcontext.mc_gregs[PT_MSR]))
get_user(new_msr, &new_ctx->uc_mcontext.mc_gregs[PT_MSR]))
return -EFAULT;
/*
* Check that the context is not smaller than the original
Expand All @@ -956,16 +957,9 @@ long sys_swapcontext(struct ucontext __user *old_ctx,
if ((ctx_size < sizeof(struct ucontext)) &&
(new_msr & MSR_VSX))
return -EINVAL;
#ifdef CONFIG_VSX
/*
* If userspace doesn't provide enough room for VSX data,
* but current thread has used VSX, we don't have anywhere
* to store the full context back into.
*/
if ((ctx_size < sizeof(struct ucontext)) &&
(current->thread.used_vsr && old_ctx))
return -EINVAL;
#endif
/* Does the context have enough room to store VSX data? */
if (ctx_size >= sizeof(struct ucontext))
ctx_has_vsx_region = 1;
#else
/* Context size is for future use. Right now, we only make sure
* we are passed something we understand
Expand All @@ -985,17 +979,17 @@ long sys_swapcontext(struct ucontext __user *old_ctx,
*/
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, mctx, 0)
if (!access_ok(VERIFY_WRITE, old_ctx, ctx_size)
|| save_user_regs(regs, mctx, 0, ctx_has_vsx_region)
|| put_sigset_t(&old_ctx->uc_sigmask, &current->blocked)
|| __put_user(to_user_ptr(mctx), &old_ctx->uc_regs))
return -EFAULT;
}
if (new_ctx == NULL)
return 0;
if (!access_ok(VERIFY_READ, new_ctx, sizeof(*new_ctx))
if (!access_ok(VERIFY_READ, new_ctx, ctx_size)
|| __get_user(tmp, (u8 __user *) new_ctx)
|| __get_user(tmp, (u8 __user *) (new_ctx + 1) - 1))
|| __get_user(tmp, (u8 __user *) new_ctx + ctx_size - 1))
return -EFAULT;

/*
Expand Down Expand Up @@ -1196,11 +1190,11 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,
goto badframe;

if (vdso32_sigtramp && current->mm->context.vdso_base) {
if (save_user_regs(regs, &frame->mctx, 0))
if (save_user_regs(regs, &frame->mctx, 0, 1))
goto badframe;
regs->link = current->mm->context.vdso_base + vdso32_sigtramp;
} else {
if (save_user_regs(regs, &frame->mctx, __NR_sigreturn))
if (save_user_regs(regs, &frame->mctx, __NR_sigreturn, 1))
goto badframe;
regs->link = (unsigned long) frame->mctx.tramp;
}
Expand Down
33 changes: 15 additions & 18 deletions trunk/arch/powerpc/kernel/signal_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ static const char fmt64[] = KERN_INFO \
*/

static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
int signr, sigset_t *set, unsigned long handler)
int signr, sigset_t *set, unsigned long handler,
int ctx_has_vsx_region)
{
/* When CONFIG_ALTIVEC is set, we _always_ setup v_regs even if the
* process never used altivec yet (MSR_VEC is zero in pt_regs of
Expand Down Expand Up @@ -121,7 +122,7 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
* then out to userspace. Update v_regs to point after the
* VMX data.
*/
if (current->thread.used_vsr) {
if (current->thread.used_vsr && ctx_has_vsx_region) {
__giveup_vsx(current);
v_regs += ELF_NVRREG;
err |= copy_vsx_to_user(v_regs, current);
Expand Down Expand Up @@ -282,9 +283,10 @@ int sys_swapcontext(struct ucontext __user *old_ctx,
unsigned char tmp;
sigset_t set;
unsigned long new_msr = 0;
int ctx_has_vsx_region = 0;

if (new_ctx &&
__get_user(new_msr, &new_ctx->uc_mcontext.gp_regs[PT_MSR]))
get_user(new_msr, &new_ctx->uc_mcontext.gp_regs[PT_MSR]))
return -EFAULT;
/*
* Check that the context is not smaller than the original
Expand All @@ -299,28 +301,23 @@ int sys_swapcontext(struct ucontext __user *old_ctx,
if ((ctx_size < sizeof(struct ucontext)) &&
(new_msr & MSR_VSX))
return -EINVAL;
#ifdef CONFIG_VSX
/*
* If userspace doesn't provide enough room for VSX data,
* but current thread has used VSX, we don't have anywhere
* to store the full context back into.
*/
if ((ctx_size < sizeof(struct ucontext)) &&
(current->thread.used_vsr && old_ctx))
return -EINVAL;
#endif
/* Does the context have enough room to store VSX data? */
if (ctx_size >= sizeof(struct ucontext))
ctx_has_vsx_region = 1;

if (old_ctx != NULL) {
if (!access_ok(VERIFY_WRITE, old_ctx, sizeof(*old_ctx))
|| setup_sigcontext(&old_ctx->uc_mcontext, regs, 0, NULL, 0)
if (!access_ok(VERIFY_WRITE, old_ctx, ctx_size)
|| setup_sigcontext(&old_ctx->uc_mcontext, regs, 0, NULL, 0,
ctx_has_vsx_region)
|| __copy_to_user(&old_ctx->uc_sigmask,
&current->blocked, sizeof(sigset_t)))
return -EFAULT;
}
if (new_ctx == NULL)
return 0;
if (!access_ok(VERIFY_READ, new_ctx, sizeof(*new_ctx))
if (!access_ok(VERIFY_READ, new_ctx, ctx_size)
|| __get_user(tmp, (u8 __user *) new_ctx)
|| __get_user(tmp, (u8 __user *) (new_ctx + 1) - 1))
|| __get_user(tmp, (u8 __user *) new_ctx + ctx_size - 1))
return -EFAULT;

/*
Expand Down Expand Up @@ -423,7 +420,7 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
&frame->uc.uc_stack.ss_flags);
err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, signr, NULL,
(unsigned long)ka->sa.sa_handler);
(unsigned long)ka->sa.sa_handler, 1);
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
if (err)
goto badframe;
Expand Down

0 comments on commit 2f900f5

Please sign in to comment.