Hello! I came across this glibc patch [0] from Svante Signell that is apparently not upstream, but shipped in Debian. I have also seen this wiki page [1]. So here is a braindump of how that patch is broken and why we cannot easily fix it.
[0]: https://salsa.debian.org/glibc-team/glibc/-/blob/sid/debian/patches/hurd-i386/tg-sendmsg-SCM_CREDS.diff [1]: https://www.gnu.org/software/hurd/open_issues/sendmsg_scm_creds.html I understand that implementing these APIs is important for D-Bus and Wayland (and X.Org, maybe? I don't know), but I can also see why the patch can not be upstreamed. For one thing, the patch uses auth_server_authenticate (newport = MACH_PORT_NULL), and you know what that means, right? Man-in-the-middle attacks! Just get root to authenticate to you (could be from root sending these same SCM_CREDS to you, or from something else entirely like io_reauth), and forward its rendezvous port to your peer. Boom, the peer thinks you're root. I'm posting this publicly because it doesn't look like there is anything sensitive on D-Bus right now. I've checked on my Debian GNU/Hurd box, and there's only org.freedesktop.DBus itself, while on darnassus there does not seem to be a D-Bus socket at all, despite the daemon running and the socket path being specified in its config as one would expect. But if we had systemd or Polkit or something listening on D-Bus and providing privileged services (such as: spawn this command as root), it'd be trivial to trick them into believing you're root and getting them to run a program of your choosing as root. And I don't think it's possible to fix this, at least not easily. Fixing this would require making use of the newport mechanism for sure. Ideally, that'd require us to somehow replace the socket port in the first peer with a new "reauthenticated" socket port (not actually reauthenticated as in io_reauth). This leaves the question of what to do with already queued data unclear -- we can neither trust it (since it was queued on the old socket port), nor ignore it (that would surely mess with the peer's expectations) The alternative to replacing the socket port is some awkward "confirm that you're actually trying to reauth this socket port" dance, a la what we did with proc_reauthenticate_complete (), but more complicated (you'd have to pass the sockaddr as a Mach port). But that would not work either, because... it's important that both send() and recv() on the socket remain asynchronous, i.e. the two calls on the two sides must not need to actually rendezvous with each other. The first peer must be able to queue some data (and creds) with a non-blocking send() and go on its merry way, without waiting for the second peer to recv(). In particular this means that the first peer cannot synchronously wait for auth_user_authenticate () to return, since that waits until the second peer calls recv(). Similarly, once the second peer does get to recv() the data & creds, it must be able to so without blocking, so even if we do manage to send some newport to the first peer, we cannot e.g. wait until it calls some sort of "socket_scm_creds_ack ()" RPC on it. ------- What D-Bus and Wayland would really prefer is getsockopt (SO_PEERCRED) rather than SCM_CREDS. The former gives you the peer's creds without the peer having to do anything special at all. Importantly, it should return peer's credentials *at the time of socket creation*, otherwise there's the possibility of a race-based attack: you create the socket and queue (send) your request, then you quickly exec ("su"). By the time dbus-daemon sees the request and checks your credentials, the process belongs to root. Since [2], pflocal already caches creator's primary [UG]ID, so I guess that could be used to implement getsockopt (SO_PEERCRED) without any client involvement. (Except that it seems to set them to 0 if unknown, which is not going to work for obvious reasons...) [2]: https://git.savannah.gnu.org/cgit/hurd/hurd.git/commit/?id=594cfb7586089dfefab60574495baf6ed4048c1d But the issue with *that* is also the usual one when transferring [UG]IDs as data (and not finding out the [UG]IDs using the auth protocol); namely the two peers can be in different "UID namespaces", that is, use different auth servers (think fakeauth). Specifically for SO_PEERCRED and fakeauth, imagine the two peers both run with the same fakeauth server, but pflocal does not. So the peer who calls getsockopt (SO_PEERCRED) will get UID=1000 from pflocal, even though its peer's UID is 0 as far as it's concerned. But note that: * fakeauth [currently] doesn't support this -- it always forwards authenticate() RPCs to the upstream auth server, and only itself acts on auth_getids () & friends. So even if a client and a server are both using the same fakeauth, the server will still see the 'outer' credentials of the client (i.e. UID=1000). IMO this should be fixed independently. * Linux _does_ support using SO_PEERCRED across PID and UID namespaces, and converts the IDs as appropriate. Sergey