[Bug 234722] [patch] [linux] getsockopt(SOL_SOCKET, SO_PEERCRED) on a Unix socket fails silently

bugzilla-noreply at freebsd.org bugzilla-noreply at freebsd.org
Mon Jan 7 23:16:50 UTC 2019


https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=234722

            Bug ID: 234722
           Summary: [patch] [linux] getsockopt(SOL_SOCKET, SO_PEERCRED) on
                    a Unix socket fails silently
           Product: Base System
           Version: 12.0-RELEASE
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Some People
          Priority: ---
         Component: kern
          Assignee: bugs at FreeBSD.org
          Reporter: bakaidl at gmail.com

Created attachment 200893
  --> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=200893&action=edit
Source for reproduction and patch

When using the SO_PEERCRED getsockopt for a Unix socket from a Linux program
with the Linux compatibility layer, it returns with no error, but the resulting
struct ucred contains garbage.

To reproduce, compile the attached linux_peercred_test.c for Linux, set up a
listening Unix socket named test.sock on FreeBSD (nc -l -U test.sock or socat
UNIX-LISTEN:test.sock -) and run linux_peercred_test.
It will return something along the line of this:
[bakaid at freebsd ~]$ ./linux_peercred_test
uid: 4294965248, gid: 6, pid: 0

The cause seem to be the following:
The Linux compat layer translates the Linux getsockopt for level SOL_SOCKET
(1), optname SO_PEERCRED (17) to level SOL_SOCKET (0xffff), optname
LOCAL_PEERCRED (1), and calls kern_getsockopt (sys/kern/uipc_syscalls.c) with
these parameters (sys/compat/linux/linux_socket.c).

However, LOCAL_PEERCRED should be called with level 0, not level SOL_SOCKET, as
demonstrated (among others) by the getpeereid implementation
(lib/libc/gen/getpeereid.c).

Even worse, calling it with SOL_SOCKET will cause the getsockopt being served
as a SOL_SOCKET request (kern_getsockopt -> sogetopt (sys/kern/uipc_socket.c))
and interpreted as SO_DEBUG (1), which will return successfully, causing the
failure to be silent.

I've only tried this on FreeBSD 12.0-RELEASE r341666 GENERIC  amd64, but
looking through the relevant git history I don't see positive evidence that
this function ever worked properly.

The attached patch (compat_linux_so_peercred_fix.patch) fixes the issue, which
can be verified by running linux_peercred_test again:
[bakaid at freebsd ~]$ ./linux_peercred_test 
uid: 1001, gid: 1001, pid: 0

-- 
You are receiving this mail because:
You are the assignee for the bug.


More information about the freebsd-bugs mailing list