aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Cowgill <James.Cowgill@imgtec.com>2017-03-31 12:09:59 -0400
committerRalf Baechle <ralf@linux-mips.org>2017-08-29 09:48:34 -0400
commit5af2ed36697e2a48cd7d36232212caa6240fe9bb (patch)
tree0d696a9c3f6d55392847992d38bcc60a6f88c57f
parent3d729deaf287c43e415c5d791c9ac8414dbeff70 (diff)
MIPS: Remove pt_regs adjustments in indirect syscall handler
If a restartable syscall is called using the indirect o32 syscall handler - eg: syscall(__NR_waitid, ...), then it is possible for the incorrect arguments to be passed to the syscall after it has been restarted. This is because the syscall handler tries to shift all the registers down one place in pt_regs so that when the syscall is restarted, the "real" syscall is called instead. Unfortunately it only shifts the arguments passed in registers, not the arguments on the user stack. This causes the 4th argument to be duplicated when the syscall is restarted. Fix by removing all the pt_regs shifting so that the indirect syscall handler is called again when the syscall is restarted. The comment "some syscalls like execve get their arguments from struct pt_regs" is long out of date so this should now be safe. Signed-off-by: James Cowgill <James.Cowgill@imgtec.com> Reviewed-by: James Hogan <james.hogan@imgtec.com> Tested-by: James Hogan <james.hogan@imgtec.com> Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/15856/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r--arch/mips/kernel/scall32-o32.S11
-rw-r--r--arch/mips/kernel/scall64-o32.S6
2 files changed, 0 insertions, 17 deletions
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index 27c2f90eeb21..a9a7d78803cd 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -190,12 +190,6 @@ illegal_syscall:
190 sll t1, t0, 2 190 sll t1, t0, 2
191 beqz v0, einval 191 beqz v0, einval
192 lw t2, sys_call_table(t1) # syscall routine 192 lw t2, sys_call_table(t1) # syscall routine
193 sw a0, PT_R2(sp) # call routine directly on restart
194
195 /* Some syscalls like execve get their arguments from struct pt_regs
196 and claim zero arguments in the syscall table. Thus we have to
197 assume the worst case and shuffle around all potential arguments.
198 If you want performance, don't use indirect syscalls. */
199 193
200 move a0, a1 # shift argument registers 194 move a0, a1 # shift argument registers
201 move a1, a2 195 move a1, a2
@@ -207,11 +201,6 @@ illegal_syscall:
207 sw t4, 16(sp) 201 sw t4, 16(sp)
208 sw t5, 20(sp) 202 sw t5, 20(sp)
209 sw t6, 24(sp) 203 sw t6, 24(sp)
210 sw a0, PT_R4(sp) # .. and push back a0 - a3, some
211 sw a1, PT_R5(sp) # syscalls expect them there
212 sw a2, PT_R6(sp)
213 sw a3, PT_R7(sp)
214 sw a3, PT_R26(sp) # update a3 for syscall restarting
215 jr t2 204 jr t2
216 /* Unreached */ 205 /* Unreached */
217 206
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index c30bc520885f..9ebe3e2403b1 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -198,7 +198,6 @@ LEAF(sys32_syscall)
198 dsll t1, t0, 3 198 dsll t1, t0, 3
199 beqz v0, einval 199 beqz v0, einval
200 ld t2, sys32_call_table(t1) # syscall routine 200 ld t2, sys32_call_table(t1) # syscall routine
201 sd a0, PT_R2(sp) # call routine directly on restart
202 201
203 move a0, a1 # shift argument registers 202 move a0, a1 # shift argument registers
204 move a1, a2 203 move a1, a2
@@ -207,11 +206,6 @@ LEAF(sys32_syscall)
207 move a4, a5 206 move a4, a5
208 move a5, a6 207 move a5, a6
209 move a6, a7 208 move a6, a7
210 sd a0, PT_R4(sp) # ... and push back a0 - a3, some
211 sd a1, PT_R5(sp) # syscalls expect them there
212 sd a2, PT_R6(sp)
213 sd a3, PT_R7(sp)
214 sd a3, PT_R26(sp) # update a3 for syscall restarting
215 jr t2 209 jr t2
216 /* Unreached */ 210 /* Unreached */
217 211