From: Vlad Malov <Vlad.Malov@xxxxxxxxxxxxxxxxxx> On a 64 bit kernel if an o32 syscall was made with a syscall number less than 4000, we would read the function from outside of the bounds of the syscall table. This led to non-deterministic behavior including system crashes. While we were at it we reworked the 32 bit version as well to use fewer instructions. Signed-off-by: Vlad Malov <Vlad.Malov@xxxxxxxxxxxxxxxxxx> Signed-off-by: David Daney <ddaney@xxxxxxxxxxxxxxxxxx> --- arch/mips/kernel/scall32-o32.S | 9 ++++----- arch/mips/kernel/scall64-o32.S | 14 +++++++------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S index 759f680..e638363 100644 --- a/arch/mips/kernel/scall32-o32.S +++ b/arch/mips/kernel/scall32-o32.S @@ -260,16 +260,15 @@ bad_alignment: END(sys_sysmips) LEAF(sys_syscall) + .set noreorder subu t0, a0, __NR_O32_Linux # check syscall number - sltiu v0, t0, __NR_O32_Linux_syscalls + 1 + beqz t0, einval # do not recurse + sltu v0, t0, __NR_O32_Linux_syscalls + 1 sll t1, t0, 3 beqz v0, einval - + .set reorder lw t2, sys_call_table(t1) # syscall routine - li v1, 4000 - __NR_O32_Linux # index of sys_syscall - beq t0, v1, einval # do not recurse - /* Some syscalls like execve get their arguments from struct pt_regs and claim zero arguments in the syscall table. Thus we have to assume the worst case and shuffle around all potential arguments. diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index 6c7ef83..d8b3cb1 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S @@ -174,14 +174,14 @@ not_o32_scall: END(handle_sys) LEAF(sys32_syscall) - sltu v0, a0, __NR_O32_Linux + __NR_O32_Linux_syscalls + 1 + .set noreorder + subu t0, a0, __NR_O32_Linux # check syscall number + beqz t0, einval # do not recurse + sltu v0, t0, __NR_O32_Linux_syscalls + 1 + dsll t1, t0, 3 beqz v0, einval - - dsll v0, a0, 3 - ld t2, (sys_call_table - (__NR_O32_Linux * 8))(v0) - - li v1, 4000 # indirect syscall number - beq a0, v1, einval # do not recurse + .set reorder + lw t2, sys_call_table(t1) # syscall routine move a0, a1 # shift argument registers move a1, a2