]>
Commit | Line | Data |
---|---|---|
c8fb49aa GKH |
1 | From e90e6fddc57055c4c6b57f92787fea1c065d440b Mon Sep 17 00:00:00 2001 |
2 | From: Alex Smith <alex.smith@imgtec.com> | |
3 | Date: Wed, 23 Jul 2014 14:40:11 +0100 | |
4 | Subject: MIPS: O32/32-bit: Fix bug which can cause incorrect system call restarts | |
5 | ||
6 | From: Alex Smith <alex.smith@imgtec.com> | |
7 | ||
8 | commit e90e6fddc57055c4c6b57f92787fea1c065d440b upstream. | |
9 | ||
10 | On 32-bit/O32, pt_regs has a padding area at the beginning into which the | |
11 | syscall arguments passed via the user stack are copied. 4 arguments | |
12 | totalling 16 bytes are copied to offset 16 bytes into this area, however | |
13 | the area is only 24 bytes long. This means the last 2 arguments overwrite | |
14 | pt_regs->regs[{0,1}]. | |
15 | ||
16 | If a syscall function returns an error, handle_sys stores the original | |
17 | syscall number in pt_regs->regs[0] for syscall restart. signal.c checks | |
18 | whether regs[0] is non-zero, if it is it will check whether the syscall | |
19 | return value is one of the ERESTART* codes to see if it must be | |
20 | restarted. | |
21 | ||
22 | Should a syscall be made that results in a non-zero value being copied | |
23 | off the user stack into regs[0], and then returns a positive (non-error) | |
24 | value that matches one of the ERESTART* error codes, this can be mistaken | |
25 | for requiring a syscall restart. | |
26 | ||
27 | While the possibility for this to occur has always existed, it is made | |
28 | much more likely to occur by commit 46e12c07b3b9 ("MIPS: O32 / 32-bit: | |
29 | Always copy 4 stack arguments."), since now every syscall will copy 4 | |
30 | arguments and overwrite regs[0], rather than just those with 7 or 8 | |
31 | arguments. | |
32 | ||
33 | Since that commit, booting Debian under a 32-bit MIPS kernel almost | |
34 | always results in a hang early in boot, due to a wait4 syscall returning | |
35 | a PID that matches one of the ERESTART* codes, which then causes an | |
36 | incorrect restart of the syscall. | |
37 | ||
38 | The problem is fixed by increasing the size of the padding area so that | |
39 | arguments copied off the stack will not overwrite pt_regs->regs[{0,1}]. | |
40 | ||
41 | Signed-off-by: Alex Smith <alex.smith@imgtec.com> | |
42 | Reviewed-by: Aurelien Jarno <aurelien@aurel32.net> | |
43 | Tested-by: Aurelien Jarno <aurelien@aurel32.net> | |
44 | Cc: linux-mips@linux-mips.org | |
45 | Patchwork: https://patchwork.linux-mips.org/patch/7454/ | |
46 | Signed-off-by: Ralf Baechle <ralf@linux-mips.org> | |
47 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
48 | ||
49 | --- | |
50 | arch/mips/include/asm/ptrace.h | 2 +- | |
51 | 1 file changed, 1 insertion(+), 1 deletion(-) | |
52 | ||
53 | --- a/arch/mips/include/asm/ptrace.h | |
54 | +++ b/arch/mips/include/asm/ptrace.h | |
55 | @@ -23,7 +23,7 @@ | |
56 | struct pt_regs { | |
57 | #ifdef CONFIG_32BIT | |
58 | /* Pad bytes for argument save space on the stack. */ | |
59 | - unsigned long pad0[6]; | |
60 | + unsigned long pad0[8]; | |
61 | #endif | |
62 | ||
63 | /* Saved main processor registers. */ |