stable.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 3.18 v2 0/5] MIPS: NT_PRFPREG regset handling fixes
@ 2018-01-11 16:53 Maciej W. Rozycki
  2018-01-11 16:54 ` [PATCH 3.18 v2 1/5] MIPS: Factor out NT_PRFPREG regset access helpers Maciej W. Rozycki
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Maciej W. Rozycki @ 2018-01-11 16:53 UTC (permalink / raw)
  To: stable; +Cc: Ralf Baechle

Hi,

 This is a repost of my recent 3.18 backports of NT_PRFPREG regset 
handling fixes, sent as a series for patch ordering clarity.  I've added 
`v2' annotation for patch management purposes, retaining original 
headings.  The patches themselves are unchanged.

  Maciej

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

* [PATCH 3.18 v2 1/5] MIPS: Factor out NT_PRFPREG regset access helpers
  2018-01-11 16:53 [PATCH 3.18 v2 0/5] MIPS: NT_PRFPREG regset handling fixes Maciej W. Rozycki
@ 2018-01-11 16:54 ` Maciej W. Rozycki
  2018-01-11 16:55 ` [PATCH 3.18 v2 2/5] MIPS: Guard against any partial write attempt with PTRACE_SETREGSET Maciej W. Rozycki
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Maciej W. Rozycki @ 2018-01-11 16:54 UTC (permalink / raw)
  To: stable; +Cc: Ralf Baechle

In preparation to fix a commit 72b22bbad1e7 ("MIPS: Don't assume 64-bit
FP registers for FP regset") FCSR access regression factor out
NT_PRFPREG regset access helpers for the non-MSA and the MSA variants
respectively, to avoid having to deal with excessive indentation in the
actual fix.

No functional change, however use `target->thread.fpu.fpr[0]' rather
than `target->thread.fpu.fpr[i]' for FGR holding type size determination
as there's no `i' variable to refer to anymore, and for the factored out
`i' variable declaration use `unsigned int' rather than `unsigned' as
its type, following the common style.

Signed-off-by: Maciej W. Rozycki <macro@mips.com>
Fixes: 72b22bbad1e7 ("MIPS: Don't assume 64-bit FP registers for FP regset")
Cc: James Hogan <james.hogan@mips.com>
Cc: Paul Burton <Paul.Burton@mips.com>
Cc: Alex Smith <alex@alex-smith.me.uk>
Cc: Dave Martin <Dave.Martin@arm.com>
Cc: linux-mips@linux-mips.org
Cc: linux-kernel@vger.kernel.org
Cc: stable@vger.kernel.org # v3.15+
Patchwork: https://patchwork.linux-mips.org/patch/17925/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
---
Hi,

 This is a (mechanically regenerated) version of commit a03fe72572c1 for
3.18-stable and before.  No functional changes.  Please apply.

  Maciej

---
 arch/mips/kernel/ptrace.c |  106 +++++++++++++++++++++++++++++++++++-----------
 1 file changed, 82 insertions(+), 24 deletions(-)

linux-mips-nt-prfpreg-factor-out.diff
Index: linux-stable-el/arch/mips/kernel/ptrace.c
===================================================================
--- linux-stable-el.orig/arch/mips/kernel/ptrace.c	2018-01-10 18:16:16.000000000 +0000
+++ linux-stable-el/arch/mips/kernel/ptrace.c	2018-01-10 20:00:49.092601000 +0000
@@ -400,25 +400,36 @@ static int gpr64_set(struct task_struct 
 
 #endif /* CONFIG_64BIT */
 
-static int fpr_get(struct task_struct *target,
-		   const struct user_regset *regset,
-		   unsigned int pos, unsigned int count,
-		   void *kbuf, void __user *ubuf)
+/*
+ * Copy the floating-point context to the supplied NT_PRFPREG buffer,
+ * !CONFIG_CPU_HAS_MSA variant.  FP context's general register slots
+ * correspond 1:1 to buffer slots.
+ */
+static int fpr_get_fpa(struct task_struct *target,
+		       unsigned int *pos, unsigned int *count,
+		       void **kbuf, void __user **ubuf)
 {
-	unsigned i;
-	int err;
-	u64 fpr_val;
-
-	/* XXX fcr31  */
+	return user_regset_copyout(pos, count, kbuf, ubuf,
+				   &target->thread.fpu,
+				   0, sizeof(elf_fpregset_t));
+}
 
-	if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t))
-		return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
-					   &target->thread.fpu,
-					   0, sizeof(elf_fpregset_t));
+/*
+ * Copy the floating-point context to the supplied NT_PRFPREG buffer,
+ * CONFIG_CPU_HAS_MSA variant.  Only lower 64 bits of FP context's
+ * general register slots are copied to buffer slots.
+ */
+static int fpr_get_msa(struct task_struct *target,
+		       unsigned int *pos, unsigned int *count,
+		       void **kbuf, void __user **ubuf)
+{
+	unsigned int i;
+	u64 fpr_val;
+	int err;
 
 	for (i = 0; i < NUM_FPU_REGS; i++) {
 		fpr_val = get_fpr64(&target->thread.fpu.fpr[i], 0);
-		err = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+		err = user_regset_copyout(pos, count, kbuf, ubuf,
 					  &fpr_val, i * sizeof(elf_fpreg_t),
 					  (i + 1) * sizeof(elf_fpreg_t));
 		if (err)
@@ -428,25 +439,54 @@ static int fpr_get(struct task_struct *t
 	return 0;
 }
 
-static int fpr_set(struct task_struct *target,
+/* Copy the floating-point context to the supplied NT_PRFPREG buffer.  */
+static int fpr_get(struct task_struct *target,
 		   const struct user_regset *regset,
 		   unsigned int pos, unsigned int count,
-		   const void *kbuf, const void __user *ubuf)
+		   void *kbuf, void __user *ubuf)
 {
-	unsigned i;
 	int err;
-	u64 fpr_val;
 
 	/* XXX fcr31  */
 
-	if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t))
-		return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
-					  &target->thread.fpu,
-					  0, sizeof(elf_fpregset_t));
+	if (sizeof(target->thread.fpu.fpr[0]) == sizeof(elf_fpreg_t))
+		err = fpr_get_fpa(target, &pos, &count, &kbuf, &ubuf);
+	else
+		err = fpr_get_msa(target, &pos, &count, &kbuf, &ubuf);
+
+	return err;
+}
+
+/*
+ * Copy the supplied NT_PRFPREG buffer to the floating-point context,
+ * !CONFIG_CPU_HAS_MSA variant.   Buffer slots correspond 1:1 to FP
+ * context's general register slots.
+ */
+static int fpr_set_fpa(struct task_struct *target,
+		       unsigned int *pos, unsigned int *count,
+		       const void **kbuf, const void __user **ubuf)
+{
+	return user_regset_copyin(pos, count, kbuf, ubuf,
+				  &target->thread.fpu,
+				  0, sizeof(elf_fpregset_t));
+}
+
+/*
+ * Copy the supplied NT_PRFPREG buffer to the floating-point context,
+ * CONFIG_CPU_HAS_MSA variant.  Buffer slots are copied to lower 64
+ * bits only of FP context's general register slots.
+ */
+static int fpr_set_msa(struct task_struct *target,
+		       unsigned int *pos, unsigned int *count,
+		       const void **kbuf, const void __user **ubuf)
+{
+	unsigned int i;
+	u64 fpr_val;
+	int err;
 
 	BUILD_BUG_ON(sizeof(fpr_val) != sizeof(elf_fpreg_t));
-	for (i = 0; i < NUM_FPU_REGS && count >= sizeof(elf_fpreg_t); i++) {
-		err = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+	for (i = 0; i < NUM_FPU_REGS && *count >= sizeof(elf_fpreg_t); i++) {
+		err = user_regset_copyin(pos, count, kbuf, ubuf,
 					 &fpr_val, i * sizeof(elf_fpreg_t),
 					 (i + 1) * sizeof(elf_fpreg_t));
 		if (err)
@@ -457,6 +497,24 @@ static int fpr_set(struct task_struct *t
 	return 0;
 }
 
+/* Copy the supplied NT_PRFPREG buffer to the floating-point context.  */
+static int fpr_set(struct task_struct *target,
+		   const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   const void *kbuf, const void __user *ubuf)
+{
+	int err;
+
+	/* XXX fcr31  */
+
+	if (sizeof(target->thread.fpu.fpr[0]) == sizeof(elf_fpreg_t))
+		err = fpr_set_fpa(target, &pos, &count, &kbuf, &ubuf);
+	else
+		err = fpr_set_msa(target, &pos, &count, &kbuf, &ubuf);
+
+	return err;
+}
+
 enum mips_regset {
 	REGSET_GPR,
 	REGSET_FPR,

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

* [PATCH 3.18 v2 2/5] MIPS: Guard against any partial write attempt with PTRACE_SETREGSET
  2018-01-11 16:53 [PATCH 3.18 v2 0/5] MIPS: NT_PRFPREG regset handling fixes Maciej W. Rozycki
  2018-01-11 16:54 ` [PATCH 3.18 v2 1/5] MIPS: Factor out NT_PRFPREG regset access helpers Maciej W. Rozycki
@ 2018-01-11 16:55 ` Maciej W. Rozycki
  2018-01-11 16:55 ` [PATCH 3.18 v2 3/5] MIPS: Consistently handle buffer counter " Maciej W. Rozycki
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Maciej W. Rozycki @ 2018-01-11 16:55 UTC (permalink / raw)
  To: stable; +Cc: Ralf Baechle

Complement commit d614fd58a283 ("mips/ptrace: Preserve previous
registers for short regset write") and ensure that no partial register
write attempt is made with PTRACE_SETREGSET, as we do not preinitialize
any temporaries used to hold incoming register data and consequently
random data could be written.

It is the responsibility of the caller, such as `ptrace_regset', to
arrange for writes to span whole registers only, so here we only assert
that it has indeed happened.

Signed-off-by: Maciej W. Rozycki <macro@mips.com>
Fixes: 72b22bbad1e7 ("MIPS: Don't assume 64-bit FP registers for FP regset")
Cc: James Hogan <james.hogan@mips.com>
Cc: Paul Burton <Paul.Burton@mips.com>
Cc: Alex Smith <alex@alex-smith.me.uk>
Cc: Dave Martin <Dave.Martin@arm.com>
Cc: linux-mips@linux-mips.org
Cc: linux-kernel@vger.kernel.org
Cc: stable@vger.kernel.org # v3.15+
Patchwork: https://patchwork.linux-mips.org/patch/17926/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
---
Hi,

 This is a (mechanically regenerated) version of commit dc24d0edf33c for
3.18-stable and before.  No functional changes.  Please apply.

  Maciej

---
 arch/mips/kernel/ptrace.c |   12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

linux-mips-nt-prfpreg-size-bug.diff
Index: linux-stable-el/arch/mips/kernel/ptrace.c
===================================================================
--- linux-stable-el.orig/arch/mips/kernel/ptrace.c	2018-01-10 20:13:31.900045000 +0000
+++ linux-stable-el/arch/mips/kernel/ptrace.c	2018-01-10 20:13:33.337064000 +0000
@@ -497,7 +497,15 @@ static int fpr_set_msa(struct task_struc
 	return 0;
 }
 
-/* Copy the supplied NT_PRFPREG buffer to the floating-point context.  */
+/*
+ * Copy the supplied NT_PRFPREG buffer to the floating-point context.
+ *
+ * We optimize for the case where `count % sizeof(elf_fpreg_t) == 0',
+ * which is supposed to have been guaranteed by the kernel before
+ * calling us, e.g. in `ptrace_regset'.  We enforce that requirement,
+ * so that we can safely avoid preinitializing temporaries for
+ * partial register writes.
+ */
 static int fpr_set(struct task_struct *target,
 		   const struct user_regset *regset,
 		   unsigned int pos, unsigned int count,
@@ -505,6 +513,8 @@ static int fpr_set(struct task_struct *t
 {
 	int err;
 
+	BUG_ON(count % sizeof(elf_fpreg_t));
+
 	/* XXX fcr31  */
 
 	if (sizeof(target->thread.fpu.fpr[0]) == sizeof(elf_fpreg_t))

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

* [PATCH 3.18 v2 3/5] MIPS: Consistently handle buffer counter with PTRACE_SETREGSET
  2018-01-11 16:53 [PATCH 3.18 v2 0/5] MIPS: NT_PRFPREG regset handling fixes Maciej W. Rozycki
  2018-01-11 16:54 ` [PATCH 3.18 v2 1/5] MIPS: Factor out NT_PRFPREG regset access helpers Maciej W. Rozycki
  2018-01-11 16:55 ` [PATCH 3.18 v2 2/5] MIPS: Guard against any partial write attempt with PTRACE_SETREGSET Maciej W. Rozycki
@ 2018-01-11 16:55 ` Maciej W. Rozycki
  2018-01-11 16:56 ` [PATCH 3.18 v2 4/5] MIPS: Fix an FCSR access API regression with NT_PRFPREG and MSA Maciej W. Rozycki
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Maciej W. Rozycki @ 2018-01-11 16:55 UTC (permalink / raw)
  To: stable; +Cc: Ralf Baechle

Update commit d614fd58a283 ("mips/ptrace: Preserve previous registers
for short regset write") bug and consistently consume all data supplied
to `fpr_set_msa' with the ptrace(2) PTRACE_SETREGSET request, such that
a zero data buffer counter is returned where insufficient data has been
given to fill a whole number of FP general registers.

In reality this is not going to happen, as the caller is supposed to
only supply data covering a whole number of registers and it is verified
in `ptrace_regset' and again asserted in `fpr_set', however structuring
code such that the presence of trailing partial FP general register data
causes `fpr_set_msa' to return with a non-zero data buffer counter makes
it appear that this trailing data will be used if there are subsequent
writes made to FP registers, which is going to be the case with the FCSR
once the missing write to that register has been fixed.

Fixes: d614fd58a283 ("mips/ptrace: Preserve previous registers for short regset write")
Signed-off-by: Maciej W. Rozycki <macro@mips.com>
Cc: James Hogan <james.hogan@mips.com>
Cc: Paul Burton <Paul.Burton@mips.com>
Cc: Alex Smith <alex@alex-smith.me.uk>
Cc: Dave Martin <Dave.Martin@arm.com>
Cc: linux-mips@linux-mips.org
Cc: linux-kernel@vger.kernel.org
Cc: stable@vger.kernel.org # v4.11+
Patchwork: https://patchwork.linux-mips.org/patch/17927/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
---
Hi,

 This is a (mechanically regenerated) version of commit 80b3ffce0196 for
3.18-stable and before.  No functional changes.  Please apply.

  Maciej

---
 arch/mips/kernel/ptrace.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

linux-mips-nt-prfpreg-count.diff
Index: linux-stable-el/arch/mips/kernel/ptrace.c
===================================================================
--- linux-stable-el.orig/arch/mips/kernel/ptrace.c	2018-01-10 20:27:12.485956000 +0000
+++ linux-stable-el/arch/mips/kernel/ptrace.c	2018-01-10 20:27:13.744971000 +0000
@@ -485,7 +485,7 @@ static int fpr_set_msa(struct task_struc
 	int err;
 
 	BUILD_BUG_ON(sizeof(fpr_val) != sizeof(elf_fpreg_t));
-	for (i = 0; i < NUM_FPU_REGS && *count >= sizeof(elf_fpreg_t); i++) {
+	for (i = 0; i < NUM_FPU_REGS && *count > 0; i++) {
 		err = user_regset_copyin(pos, count, kbuf, ubuf,
 					 &fpr_val, i * sizeof(elf_fpreg_t),
 					 (i + 1) * sizeof(elf_fpreg_t));

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

* [PATCH 3.18 v2 4/5] MIPS: Fix an FCSR access API regression with NT_PRFPREG and MSA
  2018-01-11 16:53 [PATCH 3.18 v2 0/5] MIPS: NT_PRFPREG regset handling fixes Maciej W. Rozycki
                   ` (2 preceding siblings ...)
  2018-01-11 16:55 ` [PATCH 3.18 v2 3/5] MIPS: Consistently handle buffer counter " Maciej W. Rozycki
@ 2018-01-11 16:56 ` Maciej W. Rozycki
  2018-01-11 16:57 ` [PATCH 3.18 v2 5/5] MIPS: Disallow outsized PTRACE_SETREGSET NT_PRFPREG regset accesses Maciej W. Rozycki
  2018-01-13 17:41 ` [PATCH 3.18 v2 0/5] MIPS: NT_PRFPREG regset handling fixes Greg KH
  5 siblings, 0 replies; 7+ messages in thread
From: Maciej W. Rozycki @ 2018-01-11 16:56 UTC (permalink / raw)
  To: stable; +Cc: Ralf Baechle

Fix a commit 72b22bbad1e7 ("MIPS: Don't assume 64-bit FP registers for
FP regset") public API regression, then activated by commit 1db1af84d6df
("MIPS: Basic MSA context switching support"), that caused the FCSR
register not to be read or written for CONFIG_CPU_HAS_MSA kernel
configurations (regardless of actual presence or absence of the MSA
feature in a given processor) with ptrace(2) PTRACE_GETREGSET and
PTRACE_SETREGSET requests nor recorded in core dumps.

This is because with !CONFIG_CPU_HAS_MSA configurations the whole of
`elf_fpregset_t' array is bulk-copied as it is, which includes the FCSR
in one half of the last, 33rd slot, whereas with CONFIG_CPU_HAS_MSA
configurations array elements are copied individually, and then only the
leading 32 FGR slots while the remaining slot is ignored.

Correct the code then such that only FGR slots are copied in the
respective !MSA and MSA helpers an then the FCSR slot is handled
separately in common code.  Use `ptrace_setfcr31' to update the FCSR
too, so that the read-only mask is respected.

Retrieving a correct value of FCSR is important in debugging not only
for the human to be able to get the right interpretation of the
situation, but for correct operation of GDB as well.  This is because
the condition code bits in FSCR are used by GDB to determine the
location to place a breakpoint at when single-stepping through an FPU
branch instruction.  If such a breakpoint is placed incorrectly (i.e.
with the condition reversed), then it will be missed, likely causing the
debuggee to run away from the control of GDB and consequently breaking
the process of investigation.

Fortunately GDB continues using the older PTRACE_GETFPREGS ptrace(2)
request which is unaffected, so the regression only really hits with
post-mortem debug sessions using a core dump file, in which case
execution, and consequently single-stepping through branches is not
possible.  Of course core files created by buggy kernels out there will
have the value of FCSR recorded clobbered, but such core files cannot be
corrected and the person using them simply will have to be aware that
the value of FCSR retrieved is not reliable.

Which also means we can likely get away without defining a replacement
API which would ensure a correct value of FSCR to be retrieved, or none
at all.

This is based on previous work by Alex Smith, extensively rewritten.

Signed-off-by: Alex Smith <alex@alex-smith.me.uk>
Signed-off-by: James Hogan <james.hogan@mips.com>
Signed-off-by: Maciej W. Rozycki <macro@mips.com>
Fixes: 72b22bbad1e7 ("MIPS: Don't assume 64-bit FP registers for FP regset")
Cc: Paul Burton <Paul.Burton@mips.com>
Cc: Dave Martin <Dave.Martin@arm.com>
Cc: linux-mips@linux-mips.org
Cc: linux-kernel@vger.kernel.org
Cc: stable@vger.kernel.org # v3.15+
Patchwork: https://patchwork.linux-mips.org/patch/17928/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
---
Hi,

 This is a version of commit be07a6a11883 for 3.18-stable and before.  It 
updates code added like this:

-		ptrace_setfcr31(target, fcr31);
+		target->thread.fpu.fcr31 = fcr31 & ~FPU_CSR_ALL_X;

because there is no `ptrace_setfcr31' helper in 3.18.  This is equivalent 
to the original commit in terms of functionality as at version 3.18.  
Please apply.

  Maciej

---
 arch/mips/kernel/ptrace.c |   47 +++++++++++++++++++++++++++++++++++-----------
 1 file changed, 36 insertions(+), 11 deletions(-)

linux-mips-nt-prfpreg-fcsr.diff
Index: linux-stable-el/arch/mips/kernel/ptrace.c
===================================================================
--- linux-stable-el.orig/arch/mips/kernel/ptrace.c	2018-01-10 20:03:43.000000000 +0000
+++ linux-stable-el/arch/mips/kernel/ptrace.c	2018-01-10 20:11:52.407204000 +0000
@@ -403,7 +403,7 @@ static int gpr64_set(struct task_struct 
 /*
  * Copy the floating-point context to the supplied NT_PRFPREG buffer,
  * !CONFIG_CPU_HAS_MSA variant.  FP context's general register slots
- * correspond 1:1 to buffer slots.
+ * correspond 1:1 to buffer slots.  Only general registers are copied.
  */
 static int fpr_get_fpa(struct task_struct *target,
 		       unsigned int *pos, unsigned int *count,
@@ -411,13 +411,14 @@ static int fpr_get_fpa(struct task_struc
 {
 	return user_regset_copyout(pos, count, kbuf, ubuf,
 				   &target->thread.fpu,
-				   0, sizeof(elf_fpregset_t));
+				   0, NUM_FPU_REGS * sizeof(elf_fpreg_t));
 }
 
 /*
  * Copy the floating-point context to the supplied NT_PRFPREG buffer,
  * CONFIG_CPU_HAS_MSA variant.  Only lower 64 bits of FP context's
- * general register slots are copied to buffer slots.
+ * general register slots are copied to buffer slots.  Only general
+ * registers are copied.
  */
 static int fpr_get_msa(struct task_struct *target,
 		       unsigned int *pos, unsigned int *count,
@@ -439,20 +440,29 @@ static int fpr_get_msa(struct task_struc
 	return 0;
 }
 
-/* Copy the floating-point context to the supplied NT_PRFPREG buffer.  */
+/*
+ * Copy the floating-point context to the supplied NT_PRFPREG buffer.
+ * Choose the appropriate helper for general registers, and then copy
+ * the FCSR register separately.
+ */
 static int fpr_get(struct task_struct *target,
 		   const struct user_regset *regset,
 		   unsigned int pos, unsigned int count,
 		   void *kbuf, void __user *ubuf)
 {
+	const int fcr31_pos = NUM_FPU_REGS * sizeof(elf_fpreg_t);
 	int err;
 
-	/* XXX fcr31  */
-
 	if (sizeof(target->thread.fpu.fpr[0]) == sizeof(elf_fpreg_t))
 		err = fpr_get_fpa(target, &pos, &count, &kbuf, &ubuf);
 	else
 		err = fpr_get_msa(target, &pos, &count, &kbuf, &ubuf);
+	if (err)
+		return err;
+
+	err = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				  &target->thread.fpu.fcr31,
+				  fcr31_pos, fcr31_pos + sizeof(u32));
 
 	return err;
 }
@@ -460,7 +470,7 @@ static int fpr_get(struct task_struct *t
 /*
  * Copy the supplied NT_PRFPREG buffer to the floating-point context,
  * !CONFIG_CPU_HAS_MSA variant.   Buffer slots correspond 1:1 to FP
- * context's general register slots.
+ * context's general register slots.  Only general registers are copied.
  */
 static int fpr_set_fpa(struct task_struct *target,
 		       unsigned int *pos, unsigned int *count,
@@ -468,13 +478,14 @@ static int fpr_set_fpa(struct task_struc
 {
 	return user_regset_copyin(pos, count, kbuf, ubuf,
 				  &target->thread.fpu,
-				  0, sizeof(elf_fpregset_t));
+				  0, NUM_FPU_REGS * sizeof(elf_fpreg_t));
 }
 
 /*
  * Copy the supplied NT_PRFPREG buffer to the floating-point context,
  * CONFIG_CPU_HAS_MSA variant.  Buffer slots are copied to lower 64
- * bits only of FP context's general register slots.
+ * bits only of FP context's general register slots.  Only general
+ * registers are copied.
  */
 static int fpr_set_msa(struct task_struct *target,
 		       unsigned int *pos, unsigned int *count,
@@ -499,6 +510,8 @@ static int fpr_set_msa(struct task_struc
 
 /*
  * Copy the supplied NT_PRFPREG buffer to the floating-point context.
+ * Choose the appropriate helper for general registers, and then copy
+ * the FCSR register separately.
  *
  * We optimize for the case where `count % sizeof(elf_fpreg_t) == 0',
  * which is supposed to have been guaranteed by the kernel before
@@ -511,16 +524,28 @@ static int fpr_set(struct task_struct *t
 		   unsigned int pos, unsigned int count,
 		   const void *kbuf, const void __user *ubuf)
 {
+	const int fcr31_pos = NUM_FPU_REGS * sizeof(elf_fpreg_t);
+	u32 fcr31;
 	int err;
 
 	BUG_ON(count % sizeof(elf_fpreg_t));
 
-	/* XXX fcr31  */
-
 	if (sizeof(target->thread.fpu.fpr[0]) == sizeof(elf_fpreg_t))
 		err = fpr_set_fpa(target, &pos, &count, &kbuf, &ubuf);
 	else
 		err = fpr_set_msa(target, &pos, &count, &kbuf, &ubuf);
+	if (err)
+		return err;
+
+	if (count > 0) {
+		err = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+					 &fcr31,
+					 fcr31_pos, fcr31_pos + sizeof(u32));
+		if (err)
+			return err;
+
+		target->thread.fpu.fcr31 = fcr31 & ~FPU_CSR_ALL_X;
+	}
 
 	return err;
 }

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

* [PATCH 3.18 v2 5/5] MIPS: Disallow outsized PTRACE_SETREGSET NT_PRFPREG regset accesses
  2018-01-11 16:53 [PATCH 3.18 v2 0/5] MIPS: NT_PRFPREG regset handling fixes Maciej W. Rozycki
                   ` (3 preceding siblings ...)
  2018-01-11 16:56 ` [PATCH 3.18 v2 4/5] MIPS: Fix an FCSR access API regression with NT_PRFPREG and MSA Maciej W. Rozycki
@ 2018-01-11 16:57 ` Maciej W. Rozycki
  2018-01-13 17:41 ` [PATCH 3.18 v2 0/5] MIPS: NT_PRFPREG regset handling fixes Greg KH
  5 siblings, 0 replies; 7+ messages in thread
From: Maciej W. Rozycki @ 2018-01-11 16:57 UTC (permalink / raw)
  To: stable; +Cc: Ralf Baechle

Complement commit c23b3d1a5311 ("MIPS: ptrace: Change GP regset to use
correct core dump register layout") and also reject outsized
PTRACE_SETREGSET requests to the NT_PRFPREG regset, like with the
NT_PRSTATUS regset.

Signed-off-by: Maciej W. Rozycki <macro@mips.com>
Fixes: c23b3d1a5311 ("MIPS: ptrace: Change GP regset to use correct core dump register layout")
Cc: James Hogan <james.hogan@mips.com>
Cc: Paul Burton <Paul.Burton@mips.com>
Cc: Alex Smith <alex@alex-smith.me.uk>
Cc: Dave Martin <Dave.Martin@arm.com>
Cc: linux-mips@linux-mips.org
Cc: linux-kernel@vger.kernel.org
Cc: stable@vger.kernel.org # v3.17+
Patchwork: https://patchwork.linux-mips.org/patch/17930/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
---
Hi,

 This is a (mechanically regenerated) version of commit c8c5a3a24d39 for 
3.18-stable and before.  No functional changes.  Please apply.

  Maciej

---
 arch/mips/kernel/ptrace.c |    3 +++
 1 file changed, 3 insertions(+)

linux-mips-nt-prfpreg-size.diff
Index: linux-stable-el/arch/mips/kernel/ptrace.c
===================================================================
--- linux-stable-el.orig/arch/mips/kernel/ptrace.c	2018-01-10 20:11:52.000000000 +0000
+++ linux-stable-el/arch/mips/kernel/ptrace.c	2018-01-10 20:13:16.212944000 +0000
@@ -530,6 +530,9 @@ static int fpr_set(struct task_struct *t
 
 	BUG_ON(count % sizeof(elf_fpreg_t));
 
+	if (pos + count > sizeof(elf_fpregset_t))
+		return -EIO;
+
 	if (sizeof(target->thread.fpu.fpr[0]) == sizeof(elf_fpreg_t))
 		err = fpr_set_fpa(target, &pos, &count, &kbuf, &ubuf);
 	else

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

* Re: [PATCH 3.18 v2 0/5] MIPS: NT_PRFPREG regset handling fixes
  2018-01-11 16:53 [PATCH 3.18 v2 0/5] MIPS: NT_PRFPREG regset handling fixes Maciej W. Rozycki
                   ` (4 preceding siblings ...)
  2018-01-11 16:57 ` [PATCH 3.18 v2 5/5] MIPS: Disallow outsized PTRACE_SETREGSET NT_PRFPREG regset accesses Maciej W. Rozycki
@ 2018-01-13 17:41 ` Greg KH
  5 siblings, 0 replies; 7+ messages in thread
From: Greg KH @ 2018-01-13 17:41 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: stable, Ralf Baechle

On Thu, Jan 11, 2018 at 04:53:41PM +0000, Maciej W. Rozycki wrote:
> Hi,
> 
>  This is a repost of my recent 3.18 backports of NT_PRFPREG regset 
> handling fixes, sent as a series for patch ordering clarity.  I've added 
> `v2' annotation for patch management purposes, retaining original 
> headings.  The patches themselves are unchanged.

Thanks for the series, all now applied.

greg k-h

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

end of thread, other threads:[~2018-01-13 17:41 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-11 16:53 [PATCH 3.18 v2 0/5] MIPS: NT_PRFPREG regset handling fixes Maciej W. Rozycki
2018-01-11 16:54 ` [PATCH 3.18 v2 1/5] MIPS: Factor out NT_PRFPREG regset access helpers Maciej W. Rozycki
2018-01-11 16:55 ` [PATCH 3.18 v2 2/5] MIPS: Guard against any partial write attempt with PTRACE_SETREGSET Maciej W. Rozycki
2018-01-11 16:55 ` [PATCH 3.18 v2 3/5] MIPS: Consistently handle buffer counter " Maciej W. Rozycki
2018-01-11 16:56 ` [PATCH 3.18 v2 4/5] MIPS: Fix an FCSR access API regression with NT_PRFPREG and MSA Maciej W. Rozycki
2018-01-11 16:57 ` [PATCH 3.18 v2 5/5] MIPS: Disallow outsized PTRACE_SETREGSET NT_PRFPREG regset accesses Maciej W. Rozycki
2018-01-13 17:41 ` [PATCH 3.18 v2 0/5] MIPS: NT_PRFPREG regset handling fixes Greg KH

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).