Re: [RFC PATCH] m68k: Handle put_user faults more carefully

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Finn,

Am 15.04.2024 um 22:18 schrieb Finn Thain:
Running 'stress-ng --sysbadaddr -1' on my MC68040 system immediately
produces an oops:
[...]

The cause is a deliberately misaligned access in the 'bad_end_addr' test
case in the 'sysbadaddr' stressor. The location being accessed here,
0xc043dfff, was contrived to span the boundary between a r/w anonymous page
and an unmapped page. The address was then passed to the getcwd syscall
which faulted in copy_to_user().

The fault for the mapped page appears to be handled okay -- up until
do_040writeback1() called put_user() which produced a second fault due to
the unmapped page.

Michael Schmitz helpfully deciphered the oops and explained the exception
processing leading up to it.

    "regs->pc does point to the PC in the format 7 frame which is the PC
    the fault was detected at, but not (in case of a writeback fault)
    the PC of the faulting instruction [that is, MOVES.L].

    "The writeback would still cross the page boundary, and fault if the
    unmapped page still isn't present. We would not see the PC of the
    movesl in that case, and fail to find the PC in the exception
    table."

One solution is to add a NOP instruction after the MOVES.L to flush the
pipeline and take the fault. That way, the PC value in the exception frame
becomes dependable so the exception table works.

Theoretically, there seems to be another bug in the existing code. If
the instruction following the MOVES faulted, then after the fixup,
execution would resume at the instruction which caused the fault. This
appears to be a loop. After this patch, that cannot happen.

[...]
---
 arch/m68k/include/asm/uaccess.h | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/arch/m68k/include/asm/uaccess.h b/arch/m68k/include/asm/uaccess.h
index 64914872a5c9..44e52d8323e5 100644
--- a/arch/m68k/include/asm/uaccess.h
+++ b/arch/m68k/include/asm/uaccess.h
@@ -31,11 +31,12 @@
 #define __put_user_asm(inst, res, x, ptr, bwl, reg, err) \
 asm volatile ("\n"					\
 	"1:	"inst"."#bwl"	%2,%1\n"		\
-	"2:\n"						\
+	"2:	nop\n"					\
+	"3:\n"						\
 	"	.section .fixup,\"ax\"\n"		\
 	"	.even\n"				\
 	"10:	moveq.l	%3,%0\n"			\
-	"	jra 2b\n"				\
+	"	jra 3b\n"				\
 	"	.previous\n"				\
 	"\n"						\
 	"	.section __ex_table,\"a\"\n"		\
@@ -53,11 +54,12 @@ do {								\
 	asm volatile ("\n"					\
 		"1:	"inst".l %2,(%1)+\n"			\
 		"2:	"inst".l %R2,(%1)\n"			\
-		"3:\n"						\
+		"3:	nop\n"					\
+		"4:\n"						\
 		"	.section .fixup,\"ax\"\n"		\
 		"	.even\n"				\
 		"10:	movel %3,%0\n"				\
-		"	jra 3b\n"				\
+		"	jra 4b\n"				\
 		"	.previous\n"				\
 		"\n"						\
 		"	.section __ex_table,\"a\"\n"		\


Extensively tested on 68030, too (where there isn't a writeback but put_user can still fault in the same context), and after some review and testing I'm satisfed adding NOPs is the only solution, so:

Tested-by: Michael Schmitz <schmitzmic@xxxxxxxxx>
Reviewed-by: Michael Schmitz <schmitzmic@xxxxxxxxx>




[Index of Archives]     [Video for Linux]     [Yosemite News]     [Linux S/390]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux