Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 515c7af8 authored by Mike Frysinger's avatar Mike Frysinger Committed by H. Peter Anvin
Browse files

x32: Use compat shims for {g,s}etsockopt

Some of the arguments to {g,s}etsockopt are passed in userland pointers.
If we try to use the 64bit entry point, we end up sometimes failing.

For example, dhcpcd doesn't run in x32:
	# dhcpcd eth0
	dhcpcd[1979]: version 5.5.6 starting
	dhcpcd[1979]: eth0: broadcasting for a lease
	dhcpcd[1979]: eth0: open_socket: Invalid argument
	dhcpcd[1979]: eth0: send_raw_packet: Bad file descriptor

The code in particular is getting back EINVAL when doing:
	struct sock_fprog pf;
	setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &pf, sizeof(pf));

Diving into the kernel code, we can see:
include/linux/filter.h:
	struct sock_fprog {
		unsigned short len;
		struct sock_filter __user *filter;
	};

net/core/sock.c:
	case SO_ATTACH_FILTER:
		ret = -EINVAL;
		if (optlen == sizeof(struct sock_fprog)) {
			struct sock_fprog fprog;

			ret = -EFAULT;
			if (copy_from_user(&fprog, optval, sizeof(fprog)))
				break;

			ret = sk_attach_filter(&fprog, sk);
		}
		break;

arch/x86/syscalls/syscall_64.tbl:
	54 common setsockopt sys_setsockopt
	55 common getsockopt sys_getsockopt

So for x64, sizeof(sock_fprog) is 16 bytes.  For x86/x32, it's 8 bytes.
This comes down to the pointer being 32bit for x32, which means we need
to do structure size translation.  But since x32 comes in directly to
sys_setsockopt, it doesn't get translated like x86.

After changing the syscall table and rebuilding glibc with the new kernel
headers, dhcp runs fine in an x32 userland.

Oddly, it seems like Linus noted the same thing during the initial port,
but I guess that was missed/lost along the way:
	https://lkml.org/lkml/2011/8/26/452

[ hpa: tagging for -stable since this is an ABI fix. ]

Bugzilla: https://bugs.gentoo.org/423649


Reported-by: default avatarMads <mads@ab3.no>
Signed-off-by: default avatarMike Frysinger <vapier@gentoo.org>
Link: http://lkml.kernel.org/r/1345320697-15713-1-git-send-email-vapier@gentoo.org


Cc: H. J. Lu <hjl.tools@gmail.com>
Cc: <stable@vger.kernel.org> v3.4..v3.5
Signed-off-by: default avatarH. Peter Anvin <hpa@zytor.com>
parent f026cfa8
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -60,8 +60,8 @@
51	common	getsockname		sys_getsockname
52	common	getpeername		sys_getpeername
53	common	socketpair		sys_socketpair
54	common	setsockopt		sys_setsockopt
55	common	getsockopt		sys_getsockopt
54	64	setsockopt		sys_setsockopt
55	64	getsockopt		sys_getsockopt
56	common	clone			stub_clone
57	common	fork			stub_fork
58	common	vfork			stub_vfork
@@ -353,3 +353,5 @@
538	x32	sendmmsg		compat_sys_sendmmsg
539	x32	process_vm_readv	compat_sys_process_vm_readv
540	x32	process_vm_writev	compat_sys_process_vm_writev
541	x32	setsockopt		compat_sys_setsockopt
542	x32	getsockopt		compat_sys_getsockopt