Commit e807f957 authored by Vlad Malov's avatar Vlad Malov Committed by Ralf Baechle
Browse files

MIPS: Fix potential DOS by untrusted user app.



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.  Both 32 and 64 bit versions are use the same code now.

Signed-off-by: default avatarVlad Malov <Vlad.Malov@caviumnetworks.com>
Signed-off-by: default avatarDavid Daney <ddaney@caviumnetworks.com>
Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent feaf3848
Loading
Loading
Loading
Loading
+1 −4
Original line number Diff line number Diff line
@@ -262,14 +262,11 @@ bad_alignment:
	LEAF(sys_syscall)
	subu	t0, a0, __NR_O32_Linux	# check syscall number
	sltiu	v0, t0, __NR_O32_Linux_syscalls + 1
	beqz	t0, einval		# do not recurse
	sll	t1, t0, 3
	beqz	v0, einval

	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.
+5 −7
Original line number Diff line number Diff line
@@ -174,14 +174,12 @@ not_o32_scall:
	END(handle_sys)

LEAF(sys32_syscall)
	sltu	v0, a0, __NR_O32_Linux + __NR_O32_Linux_syscalls + 1
	subu	t0, a0, __NR_O32_Linux	# check syscall number
	sltiu	v0, t0, __NR_O32_Linux_syscalls + 1
	beqz	t0, einval		# do not recurse
	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
	ld	t2, sys_call_table(t1)		# syscall routine

	move	a0, a1			# shift argument registers
	move	a1, a2