Date: Thu, 21 Feb 2013 14:00:47 +0000 From: Nicholas Wilson <nicholas@nicholaswilson.me.uk> To: freebsd-hackers@freebsd.org Subject: LOCAL_PEERCRED with socketpair Message-ID: <CAN%2BZGEkVFqLbRMkquR3NAh3Qdv=d8Bvhqqme1JdTL70BHQ8suw@mail.gmail.com>
next in thread | raw e-mail | index | archive | help
Hello, I've noticed that getpeereid/LOCAL_PEERCRED doesn't work with sockets created through socketpair, but only through actual listen/connect calls. I notice that in unp_connect, we stash the peercred of the thread, then call on to unp_connect2. In kern_socketpair, we call straight through to unp_connect2 (through pr_usrreqs->pru_connect2), so this makes sense from the code. I'd like to suggest we support peercred for socketpair-created sockets. Motivation: 1. All unix-domain STREAM sockets should be created equal. We can support it, so why shouldn't we? 2. getpeerucred on Solaris, SO_PEERCRED on Linux, and of most relevance MacOS's implementation of LOCAL_PEERCRED all work fine on socketpair sockets. (A point against is that AIX's getpeereid follows the BSD behaviour of requiring a connect/listen call.) Programmers are therefore more likely to expect it to work than not. Apart from AIX, we're the only people not providing this capability. 3. Real-world uses. I was actually trying to sandbox a daemon with capsicum when I ran into this, which requires a certain amount of mucking around with file descriptor passing. Being able to establish a channel with a socketpair, hand it to a secure daemon, and be able to check the peer's credentials in the daemon, is a reasonable use-case. 4. Compatibility. It's not going to break old applications to make the change. Patch: --- sys/kern/uipc_syscalls.c.RELEASE-9.1-243808 2013-02-21 13:37:31.778270145 +0000 +++ sys/kern/uipc_syscalls.c 2013-02-21 13:45:58.747896673 +0000 @@ -642,6 +642,19 @@ error =3D soconnect2(so2, so1); if (error) goto free4; + } else if (type =3D=3D SOCK_STREAM) { + struct unpcb *unp, *unp2; + unp =3D sotounpcb(so1); + unp2 =3D sotounpcb(so2); + UNP_PCB_LOCK(unp); + UNP_PCB_LOCK(unp2); + cru2x(td->td_ucred, &unp->unp_peercred); + memcpy(&unp2->unp_peercred, &unp->unp_peercred, + sizeof(unp2->unp_peercred)); + unp->unp_flags |=3D UNP_HAVEPC; + unp2->unp_flags |=3D UNP_HAVEPC; + UNP_PCB_UNLOCK(unp); + UNP_PCB_UNLOCK(unp2); } finit(fp1, FREAD | FWRITE, DTYPE_SOCKET, fp1->f_data, &socketops); finit(fp2, FREAD | FWRITE, DTYPE_SOCKET, fp2->f_data, &socketops); I've not looked into the FreeBSD kernel before, so the patch may be useless! I think conceptually it's the right place to put it though. unix.4.man and getpeereid.3.man would have to be updated also. Best wishes, Nicholas ----- Nicholas Wilson: nicholas@nicholaswilson.me.uk Site and blog: www.nicholaswilson.me.uk 6 Tribune Court, CB4 2TU 07845=E2=80=AF182898
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAN%2BZGEkVFqLbRMkquR3NAh3Qdv=d8Bvhqqme1JdTL70BHQ8suw>