62 lines
2.4 KiB
Diff
62 lines
2.4 KiB
Diff
From: Alex Smith <alex.smith@imgtec.com>
|
|
Date: Wed, 23 Jul 2014 14:40:11 +0100
|
|
Subject: MIPS: O32/32-bit: Fix bug which can cause incorrect system
|
|
call restarts
|
|
Origin: https://git.kernel.org/linus/e90e6fddc57055c4c6b57f92787fea1c065d440b
|
|
|
|
On 32-bit/O32, pt_regs has a padding area at the beginning into which the
|
|
syscall arguments passed via the user stack are copied. 4 arguments
|
|
totalling 16 bytes are copied to offset 16 bytes into this area, however
|
|
the area is only 24 bytes long. This means the last 2 arguments overwrite
|
|
pt_regs->regs[{0,1}].
|
|
|
|
If a syscall function returns an error, handle_sys stores the original
|
|
syscall number in pt_regs->regs[0] for syscall restart. signal.c checks
|
|
whether regs[0] is non-zero, if it is it will check whether the syscall
|
|
return value is one of the ERESTART* codes to see if it must be
|
|
restarted.
|
|
|
|
Should a syscall be made that results in a non-zero value being copied
|
|
off the user stack into regs[0], and then returns a positive (non-error)
|
|
value that matches one of the ERESTART* error codes, this can be mistaken
|
|
for requiring a syscall restart.
|
|
|
|
While the possibility for this to occur has always existed, it is made
|
|
much more likely to occur by commit 46e12c07b3b9 ("MIPS: O32 / 32-bit:
|
|
Always copy 4 stack arguments."), since now every syscall will copy 4
|
|
arguments and overwrite regs[0], rather than just those with 7 or 8
|
|
arguments.
|
|
|
|
Since that commit, booting Debian under a 32-bit MIPS kernel almost
|
|
always results in a hang early in boot, due to a wait4 syscall returning
|
|
a PID that matches one of the ERESTART* codes, which then causes an
|
|
incorrect restart of the syscall.
|
|
|
|
The problem is fixed by increasing the size of the padding area so that
|
|
arguments copied off the stack will not overwrite pt_regs->regs[{0,1}].
|
|
|
|
Signed-off-by: Alex Smith <alex.smith@imgtec.com>
|
|
Cc: <stable@vger.kernel.org> # v3.13+
|
|
Tested-by: Aurelien Jarno <aurelien@aurel32.net>
|
|
Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
|
|
---
|
|
arch/mips/include/asm/ptrace.h | 2 +-
|
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
|
diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h
|
|
index 7e6e682..c301fa9 100644
|
|
--- a/arch/mips/include/asm/ptrace.h
|
|
+++ b/arch/mips/include/asm/ptrace.h
|
|
@@ -23,7 +23,7 @@
|
|
struct pt_regs {
|
|
#ifdef CONFIG_32BIT
|
|
/* Pad bytes for argument save space on the stack. */
|
|
- unsigned long pad0[6];
|
|
+ unsigned long pad0[8];
|
|
#endif
|
|
|
|
/* Saved main processor registers. */
|
|
--
|
|
1.7.10.4
|
|
|