[lkml]   [2012]   [Aug]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
Messages in this thread
    Patch in this message
    Subject[PATCH] 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:
    struct sock_fprog {
    unsigned short len;
    struct sock_filter __user *filter;

    ret = -EINVAL;
    if (optlen == sizeof(struct sock_fprog)) {
    struct sock_fprog fprog;

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

    ret = sk_attach_filter(&fprog, sk);

    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:

    Reported-by: Mads <>
    Signed-off-by: Mike Frysinger <>
    arch/x86/syscalls/syscall_64.tbl | 6 ++++--
    1 file changed, 4 insertions(+), 2 deletions(-)

    diff --git a/arch/x86/syscalls/syscall_64.tbl b/arch/x86/syscalls/syscall_64.tbl
    index 29aed7a..a582bfe 100644
    --- a/arch/x86/syscalls/syscall_64.tbl
    +++ b/arch/x86/syscalls/syscall_64.tbl
    @@ -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

     \ /
      Last update: 2012-08-18 23:01    [W:0.038 / U:48.892 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site