linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* powerpc: fix swapcontext backwards compatibility due to VSX ucontext changes
@ 2008-07-04  8:25 Michael Neuling
  2008-07-04 11:08 ` Paul Mackerras
  0 siblings, 1 reply; 4+ messages in thread
From: Michael Neuling @ 2008-07-04  8:25 UTC (permalink / raw)
  To: benh; +Cc: linuxppc-dev, paulus

When the ucontext changed to add the VSX context, this broke backwards
compatibly on swapcontext.  swapcontext only compares the ucontext
size passed in from the user to the new kernel ucontext size.

This adds a check against the old ucontext size (with VMX but without
VSX).  It also adds some sanity check for ucontexts without VSX, but
where VSX is used according the MSR.  Fixes for both 32 and 64bit
processes on 64bit kernels

Kudos to Paulus for noticing.

Signed-off-by: Michael Neuling <mikey@neuling.org>
---
Benh: please apply to your 2.6.27 tree.

PS "I for one welcome our new powerpc linux maintainer overload" :-)

 arch/powerpc/kernel/signal_32.c |   36 +++++++++++++++++++++++++++++++++++-
 arch/powerpc/kernel/signal_64.c |   35 +++++++++++++++++++++++++++++++----
 2 files changed, 66 insertions(+), 5 deletions(-)

Index: linux-2.6-ozlabs/arch/powerpc/kernel/signal_32.c
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/kernel/signal_32.c
+++ linux-2.6-ozlabs/arch/powerpc/kernel/signal_32.c
@@ -68,6 +68,13 @@
 #define ucontext	ucontext32
 
 /*
+ * Userspace code may pass a ucontext which doesn't include VSX added
+ * at the end.  We need to check for this case.
+ */
+#define UCONTEXTSIZEWITHOUTVSX \
+		(sizeof(struct ucontext) - sizeof(elf_vsrreghalf_t32))
+
+/*
  * Returning 0 means we return to userspace via
  * ret_from_except and thus restore all user
  * registers from *regs.  This is what we need
@@ -930,12 +937,39 @@ long sys_swapcontext(struct ucontext __u
 {
 	unsigned char tmp;
 
+#ifdef CONFIG_PPC64
+	unsigned long new_msr = 0;
+
+	if (new_ctx &&
+	    __get_user(new_msr, &new_ctx->uc_mcontext.mc_gregs[PT_MSR]))
+		return -EFAULT;
+	if (/*
+	     * Check that the context is not smaller than the original
+	     * size (with VMX but without VSX)
+	     */
+		(ctx_size < UCONTEXTSIZEWITHOUTVSX) ||
+	    /*
+	     * 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.
+	     */
+		((ctx_size < sizeof(struct ucontext)) &&
+		 (regs->msr & MSR_VSX) && old_ctx) ||
+	    /*
+	     * If the new context state sets the MSR VSX bits but
+	     * it doesn't provide VSX state.
+	     */
+		((ctx_size < sizeof(struct ucontext)) &&
+		 (new_msr & MSR_VSX)))
+		/* ... computer says "noooo" */
+		return -EINVAL;
+#else
 	/* Context size is for future use. Right now, we only make sure
 	 * we are passed something we understand
 	 */
 	if (ctx_size < sizeof(struct ucontext))
 		return -EINVAL;
-
+#endif
 	if (old_ctx != NULL) {
 		struct mcontext __user *mctx;
 
Index: linux-2.6-ozlabs/arch/powerpc/kernel/signal_64.c
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/kernel/signal_64.c
+++ linux-2.6-ozlabs/arch/powerpc/kernel/signal_64.c
@@ -268,6 +268,13 @@ static long setup_trampoline(unsigned in
 }
 
 /*
+ * Userspace code may pass a ucontext which doesn't include VSX added
+ * at the end.  We need to check for this case.
+ */
+#define UCONTEXTSIZEWITHOUTVSX \
+		(sizeof(struct ucontext) - 32*sizeof(long))
+
+/*
  * Handle {get,set,swap}_context operations
  */
 int sys_swapcontext(struct ucontext __user *old_ctx,
@@ -277,10 +284,30 @@ int sys_swapcontext(struct ucontext __us
 	unsigned char tmp;
 	sigset_t set;
 
-	/* Context size is for future use. Right now, we only make sure
-	 * we are passed something we understand
-	 */
-	if (ctx_size < sizeof(struct ucontext))
+	unsigned long new_msr = 0;
+
+	if (new_ctx &&
+	    __get_user(new_msr, &new_ctx->uc_mcontext.gp_regs[PT_MSR]))
+		return -EFAULT;
+	if (/*
+	     * Check that the context is not smaller than the original
+	     * size (with VMX but without VSX)
+	     */
+		(ctx_size < UCONTEXTSIZEWITHOUTVSX) ||
+	    /*
+	     * 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.
+	     */
+		((ctx_size < sizeof(struct ucontext)) &&
+		 (regs->msr & MSR_VSX) && old_ctx) ||
+	    /*
+	     * If the new context state sets the MSR VSX bits but
+	     * it doesn't provide VSX state.
+	     */
+		((ctx_size < sizeof(struct ucontext)) &&
+		 (new_msr & MSR_VSX)))
+		/* ... computer says "No" */
 		return -EINVAL;
 
 	if (old_ctx != NULL) {

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: powerpc: fix swapcontext backwards compatibility due to VSX ucontext changes
  2008-07-04  8:25 powerpc: fix swapcontext backwards compatibility due to VSX ucontext changes Michael Neuling
@ 2008-07-04 11:08 ` Paul Mackerras
  2008-07-06  8:37   ` Michael Neuling
  0 siblings, 1 reply; 4+ messages in thread
From: Paul Mackerras @ 2008-07-04 11:08 UTC (permalink / raw)
  To: Michael Neuling; +Cc: linuxppc-dev

Michael Neuling writes:

> +	    /*
> +	     * 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.
> +	     */
> +		((ctx_size < sizeof(struct ucontext)) &&
> +		 (regs->msr & MSR_VSX) && old_ctx) ||

I think we need to check current->thread.used_vsr rather than
regs->msr here (in both instances of this code).

Paul.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* powerpc: fix swapcontext backwards compatibility due to VSX ucontext changes
  2008-07-04 11:08 ` Paul Mackerras
@ 2008-07-06  8:37   ` Michael Neuling
  2008-07-08  8:43     ` [PATCH] " Michael Neuling
  0 siblings, 1 reply; 4+ messages in thread
From: Michael Neuling @ 2008-07-06  8:37 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev

When the ucontext changed to add the VSX context, this broke backwards
compatibly on swapcontext.  swapcontext only compares the ucontext
size passed in from the user to the new kernel ucontext size.

This adds a check against the old ucontext size (with VMX but without
VSX).  It also adds some sanity check for ucontexts without VSX, but
where VSX is used according the MSR.  Fixes for both 32 and 64bit
processes on 64bit kernels

Kudos to Paulus for noticing.

Signed-off-by: Michael Neuling <mikey@neuling.org>
---
> > +	    /*
> > +	     * 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.
> > +	     */
> > +		((ctx_size < sizeof(struct ucontext)) &&
> > +		 (regs->msr & MSR_VSX) && old_ctx) ||
> 
> I think we need to check current->thread.used_vsr rather than
> regs->msr here (in both instances of this code).

Yep I agree.  Thanks

 arch/powerpc/kernel/signal_32.c |   36 +++++++++++++++++++++++++++++++++++-
 arch/powerpc/kernel/signal_64.c |   35 +++++++++++++++++++++++++++++++----
 2 files changed, 66 insertions(+), 5 deletions(-)

Index: linux-2.6-ozlabs/arch/powerpc/kernel/signal_32.c
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/kernel/signal_32.c
+++ linux-2.6-ozlabs/arch/powerpc/kernel/signal_32.c
@@ -68,6 +68,13 @@
 #define ucontext	ucontext32
 
 /*
+ * Userspace code may pass a ucontext which doesn't include VSX added
+ * at the end.  We need to check for this case.
+ */
+#define UCONTEXTSIZEWITHOUTVSX \
+		(sizeof(struct ucontext) - sizeof(elf_vsrreghalf_t32))
+
+/*
  * Returning 0 means we return to userspace via
  * ret_from_except and thus restore all user
  * registers from *regs.  This is what we need
@@ -930,12 +937,39 @@ long sys_swapcontext(struct ucontext __u
 {
 	unsigned char tmp;
 
+#ifdef CONFIG_PPC64
+	unsigned long new_msr = 0;
+
+	if (new_ctx &&
+	    __get_user(new_msr, &new_ctx->uc_mcontext.mc_gregs[PT_MSR]))
+		return -EFAULT;
+	if (/*
+	     * Check that the context is not smaller than the original
+	     * size (with VMX but without VSX)
+	     */
+		(ctx_size < UCONTEXTSIZEWITHOUTVSX) ||
+	    /*
+	     * 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.
+	     */
+		((ctx_size < sizeof(struct ucontext)) &&
+		 current->thread.used_vsr && old_ctx) ||
+	    /*
+	     * If the new context state sets the MSR VSX bits but
+	     * it doesn't provide VSX state.
+	     */
+		((ctx_size < sizeof(struct ucontext)) &&
+		 (new_msr & MSR_VSX)))
+		/* ... computer says "noooo" */
+		return -EINVAL;
+#else
 	/* Context size is for future use. Right now, we only make sure
 	 * we are passed something we understand
 	 */
 	if (ctx_size < sizeof(struct ucontext))
 		return -EINVAL;
-
+#endif
 	if (old_ctx != NULL) {
 		struct mcontext __user *mctx;
 
Index: linux-2.6-ozlabs/arch/powerpc/kernel/signal_64.c
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/kernel/signal_64.c
+++ linux-2.6-ozlabs/arch/powerpc/kernel/signal_64.c
@@ -268,6 +268,13 @@ static long setup_trampoline(unsigned in
 }
 
 /*
+ * Userspace code may pass a ucontext which doesn't include VSX added
+ * at the end.  We need to check for this case.
+ */
+#define UCONTEXTSIZEWITHOUTVSX \
+		(sizeof(struct ucontext) - 32*sizeof(long))
+
+/*
  * Handle {get,set,swap}_context operations
  */
 int sys_swapcontext(struct ucontext __user *old_ctx,
@@ -277,10 +284,30 @@ int sys_swapcontext(struct ucontext __us
 	unsigned char tmp;
 	sigset_t set;
 
-	/* Context size is for future use. Right now, we only make sure
-	 * we are passed something we understand
-	 */
-	if (ctx_size < sizeof(struct ucontext))
+	unsigned long new_msr = 0;
+
+	if (new_ctx &&
+	    __get_user(new_msr, &new_ctx->uc_mcontext.gp_regs[PT_MSR]))
+		return -EFAULT;
+	if (/*
+	     * Check that the context is not smaller than the original
+	     * size (with VMX but without VSX)
+	     */
+		(ctx_size < UCONTEXTSIZEWITHOUTVSX) ||
+	    /*
+	     * 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.
+	     */
+		((ctx_size < sizeof(struct ucontext)) &&
+		 current->thread.used_vsr && old_ctx) ||
+	    /*
+	     * If the new context state sets the MSR VSX bits but
+	     * it doesn't provide VSX state.
+	     */
+		((ctx_size < sizeof(struct ucontext)) &&
+		 (new_msr & MSR_VSX)))
+		/* ... computer says "No" */
 		return -EINVAL;
 
 	if (old_ctx != NULL) {

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH] powerpc: fix swapcontext backwards compatibility due to VSX ucontext changes
  2008-07-06  8:37   ` Michael Neuling
@ 2008-07-08  8:43     ` Michael Neuling
  0 siblings, 0 replies; 4+ messages in thread
From: Michael Neuling @ 2008-07-08  8:43 UTC (permalink / raw)
  To: benh; +Cc: linuxppc-dev, paulus

When the ucontext changed to add the VSX context, this broke backwards
compatibly on swapcontext.  swapcontext only compares the ucontext size
passed in from the user to the new kernel ucontext size.

This adds a check against the old ucontext size (with VMX but without
VSX).  It also adds some sanity check for ucontexts without VSX, but
where VSX is used according the MSR.  Fixes for both 32 and 64bit
processes on 64bit kernels

Kudos to Paulus for noticing.

Signed-off-by: Michael Neuling <mikey@neuling.org>
---
Fix compile error without CONFIG_VSX

 arch/powerpc/kernel/signal_32.c |   39 ++++++++++++++++++++++++++++++++++++++-
 arch/powerpc/kernel/signal_64.c |   36 ++++++++++++++++++++++++++++++++----
 2 files changed, 70 insertions(+), 5 deletions(-)

Index: linux-2.6-ozlabs/arch/powerpc/kernel/signal_32.c
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/kernel/signal_32.c
+++ linux-2.6-ozlabs/arch/powerpc/kernel/signal_32.c
@@ -68,6 +68,13 @@
 #define ucontext	ucontext32
 
 /*
+ * Userspace code may pass a ucontext which doesn't include VSX added
+ * at the end.  We need to check for this case.
+ */
+#define UCONTEXTSIZEWITHOUTVSX \
+		(sizeof(struct ucontext) - sizeof(elf_vsrreghalf_t32))
+
+/*
  * Returning 0 means we return to userspace via
  * ret_from_except and thus restore all user
  * registers from *regs.  This is what we need
@@ -930,12 +937,42 @@ long sys_swapcontext(struct ucontext __u
 {
 	unsigned char tmp;
 
+#ifdef CONFIG_PPC64
+	unsigned long new_msr = 0;
+
+	if (new_ctx &&
+	    __get_user(new_msr, &new_ctx->uc_mcontext.mc_gregs[PT_MSR]))
+		return -EFAULT;
+	/*
+	 * Check that the context is not smaller than the original
+	 * size (with VMX but without VSX)
+	 */
+	if (ctx_size < UCONTEXTSIZEWITHOUTVSX)
+		return -EINVAL;
+	/*
+	 * If the new context state sets the MSR VSX bits but
+	 * it doesn't provide VSX state.
+	 */
+	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
+#else
 	/* Context size is for future use. Right now, we only make sure
 	 * we are passed something we understand
 	 */
 	if (ctx_size < sizeof(struct ucontext))
 		return -EINVAL;
-
+#endif
 	if (old_ctx != NULL) {
 		struct mcontext __user *mctx;
 
Index: linux-2.6-ozlabs/arch/powerpc/kernel/signal_64.c
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/kernel/signal_64.c
+++ linux-2.6-ozlabs/arch/powerpc/kernel/signal_64.c
@@ -268,6 +268,13 @@ static long setup_trampoline(unsigned in
 }
 
 /*
+ * Userspace code may pass a ucontext which doesn't include VSX added
+ * at the end.  We need to check for this case.
+ */
+#define UCONTEXTSIZEWITHOUTVSX \
+		(sizeof(struct ucontext) - 32*sizeof(long))
+
+/*
  * Handle {get,set,swap}_context operations
  */
 int sys_swapcontext(struct ucontext __user *old_ctx,
@@ -276,13 +283,34 @@ int sys_swapcontext(struct ucontext __us
 {
 	unsigned char tmp;
 	sigset_t set;
+	unsigned long new_msr = 0;
 
-	/* Context size is for future use. Right now, we only make sure
-	 * we are passed something we understand
+	if (new_ctx &&
+	    __get_user(new_msr, &new_ctx->uc_mcontext.gp_regs[PT_MSR]))
+		return -EFAULT;
+	/*
+	 * Check that the context is not smaller than the original
+	 * size (with VMX but without VSX)
 	 */
-	if (ctx_size < sizeof(struct ucontext))
+	if (ctx_size < UCONTEXTSIZEWITHOUTVSX)
 		return -EINVAL;
-
+	/*
+	 * If the new context state sets the MSR VSX bits but
+	 * it doesn't provide VSX state.
+	 */
+	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
 	if (old_ctx != NULL) {
 		if (!access_ok(VERIFY_WRITE, old_ctx, sizeof(*old_ctx))
 		    || setup_sigcontext(&old_ctx->uc_mcontext, regs, 0, NULL, 0)

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2008-07-08  8:43 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-07-04  8:25 powerpc: fix swapcontext backwards compatibility due to VSX ucontext changes Michael Neuling
2008-07-04 11:08 ` Paul Mackerras
2008-07-06  8:37   ` Michael Neuling
2008-07-08  8:43     ` [PATCH] " Michael Neuling

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).