83

dbus is supposed to provide "a simple way for applications to talk to one another".

But I am still not sure what it is useful for, practically. I have never seen a situation where dbus is useful, I only see warnings that some dbus component has experienced errors, such as when I start terminator from commandline (so that I can see errors):

Error retrieving accessibility bus address: org.freedesktop.DBus.Error.ServiceUnknown: The name org.a11y.Bus was not provided by any .service files

I got rid of the above error by adding NO_AT_BRIDGE=1 to /etc/environment. I have no idea what that does.

Almost all gui applications seem to be linked with dbus. Some allow to be started without dbus, ie:

terminator --no-dbus

I see no difference in behavior. What is supposed to stop working, when terminator is started without dbus?

Also, I have tried disabling various dbus components to see what stops working:

I have deleted /etc/X11/Xsession.d/95dbus_update-activation-env just to see what happens. It contained the following code:

if [ -n "$DBUS_SESSION_BUS_ADDRESS" ] && [ -x "/usr/bin/dbus-update-activation-environment" ]; then
  # subshell so we can unset environment variables
  (
    # unset login-session-specifics
    unset XDG_SEAT
    unset XDG_SESSION_ID
    unset XDG_VTNR

    # tell dbus-daemon --session to put the Xsession's environment in activated services' environments
    dbus-update-activation-environment --verbose --all
  )
fi

Everything works the same, as far as I can tell. What was the purpose of the above script?

In what situation would it be useful for my applications to talk to each other via dbus?

Are there applications that don't work without dbus?

My system is Debian Buster, and I am using plain openbox environment (without any desktop environment such as Gnome or KDE)

1
  • 7
    +1 For humility/humor: "I got rid of the above error by adding....I have no idea what that does."
    – dtmland
    Commented Aug 10, 2022 at 4:45

5 Answers 5

61

dbus does exactly what you said: it allows two-way communication between applications.


For your specific example you mentioned terminator. From terminator's man page, we see:

--new-tab
    If this is specified and Terminator is already running, DBus 
    will be used to spawn a new tab in the first Terminator window.

So if you do this from another terminal (konsole, xterm, gnome-terminal):

$ terminator &
$ terminator --new-tab &

You'll see that the first command opens a new window. The second command opens a new tab in the first window. That's done by the second process using dbus to find the first process, asking it to open a new tab, then quitting.

If you do this from another terminal:

$ terminator --no-dbus &
$ terminator --new-tab &

You'll see that the first command opens a new window. The second command fails to find the first window's dbus, so it launches a new window. I installed terminator to test this, and it's true.

In addition, I suspect polkit would be affected. Polkit uses dbus to elevate privileges for GUI applications. It's like the sudo of the GUI world. If you are in gnome, and see the whole screen get covered while you are asked for the administrator's password, that's polkit in action. I suspect you won't get that prompt in any GUI application you start from terminator if you have --no-dbus. It'll either fail to authenticate, or fallback to some terminal authentication. From terminator try pkexec ls. That will run ls with elevated privileges. See if it's different with and without the --no-dbus option. I don't have a polkit agent in my window manager (i3) so I can't test this one out.


I mostly know about dbus in terms of systemd, so that's where the rest of my answer will come from.

Are there applications that don't work without dbus?

Yes. Take systemctl. systemctl status will issue a query to "org.freedesktop.systemd1", and will present that to you. systemctl start will call a dbus method and pass the unit as an argument to that method. systemd recieves the call and performs the action.

If you want to take action in response to a systemd unit (i.e. foo.service) changing states, you can get a file descriptor for interface org.freedesktop.DBus.Properties with path /org/freedesktop/systemd1/unit/foo_2eservice and member PropertiesChanged. Setup an inotify on that FD and you suddenly have a way to react to a service starting, stopping, failing, etc.

If you want to take a look at what's available on the systemd dbus for a specific unit (i.e. ssh.service) try this command:

busctl introspect \
    org.freedesktop.systemd1 \
    /org/freedesktop/systemd1/unit/ssh_2eservice
NAME                                TYPE      SIGNATURE       RESULT/VALUE                             FLAGS
org.freedesktop.DBus.Introspectable interface -               -                                        -
.Introspect                         method    -               s                                        -
org.freedesktop.DBus.Peer           interface -               -                                        -
.GetMachineId                       method    -               s                                        -
.Ping                               method    -               -                                        -
org.freedesktop.DBus.Properties     interface -               -                                        -
.Get                                method    ss              v                                        -
.GetAll                             method    s               a{sv}                                    -
.Set                                method    ssv             -                                        -
.PropertiesChanged                  signal    sa{sv}as        -                                        -
org.freedesktop.systemd1.Service    interface -               -                                        -
.AttachProcesses                    method    sau             -                                        -
.GetProcesses                       method    -               a(sus)                                   -
.AllowedCPUs                        property  ay              0                                        -
.AllowedMemoryNodes                 property  ay              0                                        -
.AmbientCapabilities                property  t               0                                        const
.AppArmorProfile                    property  (bs)            false ""                                 const
.BindPaths                          property  a(ssbt)         0                                        const
.BindReadOnlyPaths                  property  a(ssbt)         0                                        const
.BlockIOAccounting                  property  b               false                                    -
.BlockIODeviceWeight                property  a(st)           0                                        -
.BlockIOReadBandwidth               property  a(st)           0                                        -
.BlockIOWeight                      property  t               18446744073709551615                     -
.BlockIOWriteBandwidth              property  a(st)           0                                        -
.BusName                            property  s               ""                                       const
.CPUAccounting                      property  b               false                                    -
.CPUAffinity                        property  ay              0                                        const
.CPUAffinityFromNUMA                property  b               false                                    const
.CPUQuotaPerSecUSec                 property  t               18446744073709551615                     -
.CPUQuotaPeriodUSec                 property  t               18446744073709551615                     -
.CPUSchedulingPolicy                property  i               0                                        const
.CPUSchedulingPriority              property  i               0                                        const
.CPUSchedulingResetOnFork           property  b               false                                    const
.CPUShares                          property  t               18446744073709551615                     -
.CPUUsageNSec                       property  t               18446744073709551615                     -
.CPUWeight                          property  t               18446744073709551615                     -
.CacheDirectory                     property  as              0                                        const
.CacheDirectoryMode                 property  u               493                                      const
.CapabilityBoundingSet              property  t               18446744073709551615                     const
.CleanResult                        property  s               "success"                                emits-change
.ConfigurationDirectory             property  as              0                                        const
.ConfigurationDirectoryMode         property  u               493                                      const
.ControlGroup                       property  s               "/system.slice/ssh.service"              -
.ControlPID                         property  u               0                                        emits-change
.CoredumpFilter                     property  t               51                                       const
.DefaultMemoryLow                   property  t               0                                        -
.DefaultMemoryMin                   property  t               0                                        -
.Delegate                           property  b               false                                    -
.DelegateControllers                property  as              0                                        -
.DeviceAllow                        property  a(ss)           0                                        -
.DevicePolicy                       property  s               "auto"                                   -
.DisableControllers                 property  as              0                                        -
.DynamicUser                        property  b               false                                    const
.EffectiveCPUs                      property  ay              0                                        -
.EffectiveMemoryNodes               property  ay              0                                        -
.Environment                        property  as              0                                        const
.EnvironmentFiles                   property  a(sb)           1 "/etc/default/ssh" true                const
.ExecCondition                      property  a(sasbttttuii)  0                                        emits-invalidation
.ExecConditionEx                    property  a(sasasttttuii) 0                                        emits-invalidation
.ExecMainCode                       property  i               0                                        emits-change
.ExecMainExitTimestamp              property  t               0                                        emits-change
.ExecMainExitTimestampMonotonic     property  t               0                                        emits-change
.ExecMainPID                        property  u               835                                      emits-change
.ExecMainStartTimestamp             property  t               1597235861087584                         emits-change
.ExecMainStartTimestampMonotonic    property  t               5386565                                  emits-change
.ExecMainStatus                     property  i               0                                        emits-change
.ExecReload                         property  a(sasbttttuii)  2 "/usr/sbin/sshd" 2 "/usr/sbin/sshd" "… emits-invalidation
.ExecReloadEx                       property  a(sasasttttuii) 2 "/usr/sbin/sshd" 2 "/usr/sbin/sshd" "… emits-invalidation
.ExecStart                          property  a(sasbttttuii)  1 "/usr/sbin/sshd" 3 "/usr/sbin/sshd" "… emits-invalidation
.ExecStartEx                        property  a(sasasttttuii) 1 "/usr/sbin/sshd" 3 "/usr/sbin/sshd" "… emits-invalidation
.ExecStartPost                      property  a(sasbttttuii)  0                                        emits-invalidation
.ExecStartPostEx                    property  a(sasasttttuii) 0                                        emits-invalidation
.ExecStartPre                       property  a(sasbttttuii)  1 "/usr/sbin/sshd" 2 "/usr/sbin/sshd" "… emits-invalidation
.ExecStartPreEx                     property  a(sasasttttuii) 1 "/usr/sbin/sshd" 2 "/usr/sbin/sshd" "… emits-invalidation
.ExecStop                           property  a(sasbttttuii)  0                                        emits-invalidation
.ExecStopEx                         property  a(sasasttttuii) 0                                        emits-invalidation
.ExecStopPost                       property  a(sasbttttuii)  0                                        emits-invalidation
.ExecStopPostEx                     property  a(sasasttttuii) 0                                        emits-invalidation
.FileDescriptorStoreMax             property  u               0                                        const
.FinalKillSignal                    property  i               9                                        const
.GID                                property  u               4294967295                               emits-change
.Group                              property  s               ""                                       const
.GuessMainPID                       property  b               true                                     const
.IOAccounting                       property  b               false                                    -
.IODeviceLatencyTargetUSec          property  a(st)           0                                        -
.IODeviceWeight                     property  a(st)           0                                        -
.IOReadBandwidthMax                 property  a(st)           0                                        -
.IOReadBytes                        property  t               18446744073709551615                     -
.IOReadIOPSMax                      property  a(st)           0                                        -
.IOReadOperations                   property  t               18446744073709551615                     -
.IOSchedulingClass                  property  i               0                                        const
.IOSchedulingPriority               property  i               0                                        const
.IOWeight                           property  t               18446744073709551615                     -
.IOWriteBandwidthMax                property  a(st)           0                                        -
.IOWriteBytes                       property  t               18446744073709551615                     -
.IOWriteIOPSMax                     property  a(st)           0                                        -
.IOWriteOperations                  property  t               18446744073709551615                     -
.IPAccounting                       property  b               false                                    -
.IPAddressAllow                     property  a(iayu)         0                                        -
.IPAddressDeny                      property  a(iayu)         0                                        -
.IPEgressBytes                      property  t               18446744073709551615                     -
.IPEgressFilterPath                 property  as              0                                        -
.IPEgressPackets                    property  t               18446744073709551615                     -
.IPIngressBytes                     property  t               18446744073709551615                     -
.IPIngressFilterPath                property  as              0                                        -
.IPIngressPackets                   property  t               18446744073709551615                     -
.IgnoreSIGPIPE                      property  b               true                                     const
.InaccessiblePaths                  property  as              0                                        const
...skipping...
.CollectMode                        property  s               "inactive"                               const
.ConditionResult                    property  b               true                                     emits-change
.ConditionTimestamp                 property  t               1597235861034899                         emits-change
.ConditionTimestampMonotonic        property  t               5333881                                  emits-change
.Conditions                         property  a(sbbsi)        1 "ConditionPathExists" false true "/et… emits-invalidation
.ConflictedBy                       property  as              0                                        const
.Conflicts                          property  as              1 "shutdown.target"                      const
.ConsistsOf                         property  as              0                                        const
.DefaultDependencies                property  b               true                                     const
.Description                        property  s               "OpenBSD Secure Shell server"            const
.Documentation                      property  as              2 "man:sshd(8)" "man:sshd_config(5)"     const
.DropInPaths                        property  as              0                                        const
.FailureAction                      property  s               "none"                                   const
.FailureActionExitStatus            property  i               -1                                       const
.Following                          property  s               ""                                       -
.FragmentPath                       property  s               "/lib/systemd/system/ssh.service"        const
.FreezerState                       property  s               "running"                                emits-change
.Id                                 property  s               "ssh.service"                            const
.IgnoreOnIsolate                    property  b               false                                    const
.InactiveEnterTimestamp             property  t               0                                        emits-change
.InactiveEnterTimestampMonotonic    property  t               0                                        emits-change
.InactiveExitTimestamp              property  t               1597235861039525                         emits-change
.InactiveExitTimestampMonotonic     property  t               5338505                                  emits-change
.InvocationID                       property  ay              16 90 215 118 165 228 162 72 57 179 144… emits-change
.Job                                property  (uo)            0 "/"                                    emits-change
.JobRunningTimeoutUSec              property  t               18446744073709551615                     const
.JobTimeoutAction                   property  s               "none"                                   const
.JobTimeoutRebootArgument           property  s               ""                                       const
.JobTimeoutUSec                     property  t               18446744073709551615                     const
.JoinsNamespaceOf                   property  as              0                                        const
.LoadError                          property  (ss)            "" ""                                    const
.LoadState                          property  s               "loaded"                                 const
.Names                              property  as              2 "ssh.service" "sshd.service"           const
.NeedDaemonReload                   property  b               false                                    const
.OnFailure                          property  as              0                                        const
.OnFailureJobMode                   property  s               "replace"                                const
.PartOf                             property  as              0                                        const
.Perpetual                          property  b               false                                    const
.PropagatesReloadTo                 property  as              0                                        const
.RebootArgument                     property  s               ""                                       const
.Refs                               property  as              0                                        -
.RefuseManualStart                  property  b               false                                    const
.RefuseManualStop                   property  b               false                                    const
.ReloadPropagatedFrom               property  as              0                                        const
.RequiredBy                         property  as              0                                        const
.Requires                           property  as              3 "system.slice" "-.mount" "sysinit.tar… const
.RequiresMountsFor                  property  as              1 "/run/sshd"                            const
.Requisite                          property  as              0                                        const
.RequisiteOf                        property  as              0                                        const
.SourcePath                         property  s               ""                                       const
.StartLimitAction                   property  s               "none"                                   const
.StartLimitBurst                    property  u               5                                        const
.StartLimitIntervalUSec             property  t               10000000                                 const
.StateChangeTimestamp               property  t               1597235861208937                         emits-change
.StateChangeTimestampMonotonic      property  t               5507917                                  emits-change
.StopWhenUnneeded                   property  b               false                                    const
.SubState                           property  s               "running"                                emits-change
.SuccessAction                      property  s               "none"                                   const
.SuccessActionExitStatus            property  i               -1                                       const
.Transient                          property  b               false                                    const
.TriggeredBy                        property  as              0                                        const
.Triggers                           property  as              0                                        const
.UnitFilePreset                     property  s               "enabled"                                -
.UnitFileState                      property  s               "enabled"                                -
.WantedBy                           property  as              1 "multi-user.target"                    const
.Wants                              property  as              0                                        const

You can see from this that the dbus interface is pretty powerful.

You might ask: Why don't these applications just communicate via sockets or files?

DBus provides a common interface. You don't need different logic to call methods or check properties based on the application you are talking to. You just need to know the name of the path.

I've used systemd as an example because that's what I understand best, but there are tons of uses of dbus on most desktops. Everything from authentication, to display settings are available on dbus.

13
  • 6
    I'm not sure if your explanation makes much sense. TCP sockets do take up ports, but for local IPC most software wouldn't use them anyway -- it would use local "Unix" sockets which only take up a path name. (You'll find many daemons having local sockets under /run, and even your systemctl example will actually use a dedicated socket for communicating with systemd in case the system D-Bus bus is unavailable.) Commented Aug 13, 2020 at 14:42
  • 23
    The programs DO “just communicate via sockets”, because DBus is implemented on top of them. But when you “just communicate via sockets”, you have to say which sockets and what protocol. DBus is there to answer those questions – let you find the peer that implements what you want to do and specify the general format.
    – Jan Hudec
    Commented Aug 13, 2020 at 19:34
  • 5
    @BenPen Service discovery for local processes is something mostly driven by desktop/GUI use. While Linux does have some companies behind it pushing it in that direction, I'm not aware of desktop UNIX companies. You can have D-Bus on BSD but most setups only use a bare bones D-Bus to make GNOME/KDE run as Jörg said. There's quite some scepticism regarding D-Bus and the bigger picture of logind/systemd/... as it transforms the system from a primarily shell-driven power-user centric system to a "modern" desktop. Those features are thus often deemed to be bloat.
    – ljrk
    Commented Aug 14, 2020 at 8:13
  • 3
    @SimonRichter it's funny how I would have worded that as it's a system similar in purpose to Windows' COM, but much more lightweight and with massively smaller attack surface. — it does not do as much for sure, but that's the point.
    – spectras
    Commented Aug 14, 2020 at 8:19
  • 2
    @SimonRichter this is not what I mean with lightweight. The whole COM model is way heavier. Which does make it faster, because it can do stuff such as loading services right in the caller's process, bypassing IPC altogether. The machinery that makes this possible is way heavier and way more complex than dbus, which in the end is just quite thin a layer on top of sockets.
    – spectras
    Commented Aug 14, 2020 at 10:46
41

There's already a great in-depth answer of D-Bus by @Stewart but I want to amend it with a high-level idea about the design of D-Bus.

The "traditional" way of Inter Process Communication (IPC) on UNIX and Linux systems directly uses sockets, e.g. process A opens /var/run/a.socket and process B reads/writes to it. This works rather fine for tightly-knit programs that were designed to communicate together.

However, you may want to have communication between two programs' processes where program B didn't even exist when program A was written. D-Bus attempts to solve this issue by providing protocols for communication and service discovery. That way, only the interface b needed to exist when A was written and process B implements the interface b.

You could thus describe D-Bus as an IPC "manager".

Historically, command-line interface (CLI) tools usually also use an IPC manager, the shell, to communicate with arbitrary programs using pipes. The problem with this approach is that it doesn't provide data validation, standardised protocols etc. It's thus only usable by power users. GUI tools in general should do this "invisibly". However, more and more CLI tools start using D-Bus, pretty much as an alternative to sudo(1). So you can do, as an unprivileged user, execute systemctl poweroff and it will prompt you for authentication (this can be compared to the UAC on Windows). Depending on your polkit provider this may be even a GUI prompt. At least in theory, this approach is more flexible and allows for more fine-grained privileges and works without setuid binaries (like sudo). This can be seen as a security feature.

Of course, as an abstraction, it introduces some kind of complexity (at least in the dependencies of the programs). However, the more programs make (sane) use of it, the less of a burden this is. Whether you like D-Bus and the current development I cannot tell you. But modern operating systems tend to provide many crucial services outside of the kernel (and now move historical kernel stuff out again, microkernel-ish) due to the more complex requirements of today's computing. So, if you "just" want a "simple" terminal all this might considered be "bloat", but the industry demands it for a good reason and more and more developers note the upsides of using D-Bus. It's today's replacement for the good old pipe in your shell (not the system interface, actually D-Bus makes use of pipe() etc.).

14

In traditional Unix, there is usually little communication between running programs. Every program runs in a fully separate address space and only interacts with the kernel. This model is simple and robust, but access permissions are mostly too coarse for desktop environments, and implementing fine grained access control is too complex in many cases.

One example where the kernel refines access control is the file system -- unprivileged programs can send off a write request to the kernel, which is translated to a write request sent to the harddisk without violating the separation between programs. This is a fairly complex layer though, and control still isn't fine enough for modern desktops where users might want to connect a USB stick.

For other functions, sound card access for example, the kernel only implements a simple access model: once a program has access to the soundcard, it can play and record sound, and manipulate mixer controls, and there is no mechanism for revoking that access except terminating the program.

In a desktop environment, we'd want a finer model: the browser should be able to use the microphone and webcam only after asking the user, and when a user logs out, any running program should lose microphone access, but if the user wants to run a computation over night, that should still be possible.

The X window system is a good precedent for performing access control in a user program -- rendering to a window is done by sending a request to another program that calculates the final screen contents that are displayed. Whether the request is translated to a visible change in screen contents is decided based on current access control settings: pulling a window to the front gives write access to an area of screen space to this program, sending it to the back revokes that access.

Desktop environments now provide lots of these mediator programs, so for each function there needs to be a communications protocol and a method for opening a handle to that program.

dbus provides a generic protocol, and a broker service where programs can ask to be connected to a program providing access control to specific functionality. If the targeted program is already running, the broker will just forward requests, if it isn't running already, the broker will start the program on demand if it knows how to do so.

The equivalent functionality on Windows is COM/DCOM in combination with the registry.

0
8

GNOME's accessibility API relies on it; see e.g. AT-SPI2 on FreeDesktop.org. Before D-BUS, i.e. before GNOME 3, the accessibility API relied on CORBA (Common Object Request Broker Architecture), which was very portable but also heavier than D-BUS. (The page AT-SPI on D-Bus (archival snapshot) contains historical information on this migration.)

Accessibility requires communication between applications on the one hand and assistive technology on the other. For example, blind computer users rely on screen readers, which can render information through synthetic speech or Braille (or both). Blind users rely on keyboard access to applications (e.g. using TAB to cycle through UI components and lots of shortcuts); a screen reader needs to know where the keyboard focus has landed and then query that UI component for its role (e.g. "button", "menu", "checkbox" etc.), name (i.e. its label, e.g. "OK", "Cancel"), and state and properties (e.g. "checked" and "unchecked" for checkboxes, "expanded" for expandable regions, "required" for required input fields, "disabled", etc.). A screen reader would also need to receive push notifications displayed in the application.

The diagram on the page Introducing ATK, AT-SPI, GAIL and GTK+ displays AT-SPI as a layer between the application layer and the assistive technology (AT) layer.

AT-SPI is also supported in Qt, thereby making it easier to develop accessible applications.

Setting NO_AT_BRIDGE=1 (as mentioned in the question) appears turn off the bridge that assistive technologies use to communication with applications. (See jeffcogswell/org_ally1_bus_fix.md.)

2

Everything still seems to work under XFCE (some desktops e.g gnome may be more dependent on dbus). I run apps through firejail so losing any supposed security benefits from dbus is not really a concern.

The following Linux distributions seem to run just fine without dbus & systemd:

There will be minor issues but if you are reasonably competent they are easy to fix.

2
  • thank you. I didn't know about hidepid. But I do have this same functionality through grsecurity. And what is the purpose of changing machine-id every hour? Commented Sep 1, 2021 at 12:25
  • @400theCat - changing machine-id hourly seems to break a pulseaudio volume plugin - I now change it on reboots as Devuan does Commented Sep 1, 2021 at 19:33

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .