file descriptor passing in D-Bus: how much is actually used?

Simon McVittie simon.mcvittie at collabora.co.uk
Tue Oct 7 05:56:29 PDT 2014


D-Bus has recently had several vulnerabilities involving file descriptor
passing (typical APIs for this feature include DBUS_TYPE_UNIX_FD,
G_VARIANT_TYPE_HANDLE or QDBusUnixFileDescriptor).

File descriptors imply allocation of kernel memory, so the kernel has to
be careful how many fds it allows. This is fine when fds are passed
directly between processes, but in D-Bus they are passed through an
intermediary (dbus-daemon) and the kernel can't know that dbus-daemon is
not the one to "blame" for those fds, meaning that dbus-daemon has to go
to some lengths to limit abuse by its clients.

To try to avoid or mitigate any other vulnerabilities that might exist
in this area, I think we should consider locking down fd-passing
further. Here are some specific restrictions we could consider applying
- I would like to know about any examples of real-world applications
that would be broken by these.

* kdbus does not allow fds to be attached to a broadcast message, and
  the kdbus developers have suggested that dbus-daemon should apply the
  same restriction so malicious processes can't use it for
  amplification. Does anything actually send fds in broadcasts, either
  on the system bus or session bus? I haven't found any examples.

* It is harder for an abusive process to be a problem if it is only
  allowed to send a few fds per message, which is why 1.8.8 dropped
  the default per-message limit from 1024 to 16. Can this limit drop
  further? Does anything send more than one fd per message on the
  system bus? I haven't found any examples on the system bus, but
  there *are* applications that send more than one at a time on the
  session bus.

* The denial of service risk is primarily on the system bus.
  Would it be feasible to lock down the system bus configuration
  so only specific uids are allowed to send/receive fds, or so only
  specific well-known names are allowed to send/receive fds, or
  something similar, requiring system services that use fds to
  declare that they do so? All the examples I've found are a
  trusted system process at either the sending or receiving end.

Here are the concrete users of fd-passing that I am aware of, based on
some searches on codesearch.debian.net:

system (privileged)
===================

Here, "unprivileged" only refers to the ability to send the message
containing the fd in the first place: even if the service is just going
to reject the method call or check with polkit first, that's still
sending and receiving a fd.

* Several systemd-logind methods return one fd
  from the service to the client
  (root service -> unprivileged client)

* Some BlueZ methods return one fd from the service to the client
  (root service -> at_console or semi-privileged client)

* The colord service can receive a colour profile from its clients
  (unprivileged client -> root service)

* The udisks2 service receives fds for loopback mounting from its
  clients
  (unprivileged client -> root service)

* The udisks2 service sends block device fds to authorized clients
  (root service -> administratively privileged client)

* The ofono service sends fds to its clients
  (root service -> at_console client)

* The connman service sends fds to its clients
  (root service -> at_console client)

Other privileged buses
======================

* The cgmanager service receives fds from its clients
  (root client -> root service) on a private DBusServer

session/user/tests (unprivileged)
=================================

* Qt's regression tests use an array of two fds
* GLib's regression tests pass one fd
* GApplication passes its standard input to the main service process
  (without using an item of type DBUS_TYPE_UNIX_FD)
* The gvfs service returns one fd when a file is opened for read or
  write
* gnome-terminal can forward arbitrary fds to the main service process
* The Tracker service receives one fd from its client
* Chromium has some sort of API for external services which seems
  to use one fd

unclear
=======

* EFL and Emacs have some sort of support for fd-passing,
  I'm not sure what they do with it or whether it's just there
  for completeness


More information about the dbus mailing list