Bug 100291

Summary: sys_getsockopt -> compat_sys_getsockopt for O32 subsystem
Product: Platform Specific/Hardware Reporter: Alexey (l-aurora)
Component: MIPSAssignee: ralf
Status: CLOSED CODE_FIX    
Severity: normal    
Priority: P1    
Hardware: All   
OS: Linux   
Kernel Version: 3.7.10 Subsystem:
Regression: No Bisected commit-id:

Description Alexey 2015-06-22 04:43:26 UTC
Hello.

There is a wrong system call used for compatibility between native kernel and O32 userspace:
/arch/mips/kernel/scall64-o32.S

PTR sys_getsockopt
but:
PTR compat_sys_setsockopt

This false symmetry in system calls leads to erroneous behavior when any data structure (which differs in size for 32-bit and 64-bit subsystems) is passed from O32 into kernel via setsockopt(), got back via getsockopt() and finally sent again via setsockopt().
First compat_sys_setsockopt will bloat it correctly for kernel space usage, then sys_getsockopt will send it to userspace without backward conversion, and even if userspace does nothing with this data, second compat_sys_setsockopt will bloat it again.

One of the easier ways to reproduce the consequences of the bug is to use iptables compiled for O32 with ULOG target. We will get the error on the second try:

First call
>iptables -I INPUT -j ULOG
(OK)
Second call
>iptables -I INPUT -j ULOG
x_tables: ip_tables: ULOG.0 target: invalid size 56 (kernel) != (user) 64

The second call does not matter a bit here, as it is the first rule that gets bloated twice in kernel, so we'll get the error as long as the first ULOG rule succeeds.

Also, there was a patch fixing this bug, but only concerning N32:
https://patchwork.linux-mips.org/patch/7115/

To fix the bug, it is needed to reapply the patch above for O32 (scall64-o32.S)
-	PTR	sys_getsockopt
+	PTR	compat_sys_getsockopt
Comment 1 ralf 2015-07-09 17:33:45 UTC
Thanks.  Fix will go upstream as commit c73a4f70457c43633ee906310811a4479b1413a8 (MIPS: O32: Use compat_sys_getsockopt.)