#943917 95dbus_update-activation-env in dbus-x11 overwrites systemd environment variables

Package:
dbus-x11
Source:
dbus
Description:
simple interprocess messaging system (X11 deps)
Submitter:
Thomas Koch
Date:
2024-02-02 12:36:06 UTC
Severity:
normal
#943917#5
Date:
2019-10-31 20:23:54 UTC
From:
To:
`man 5 environment.d` describes a mechanism to set environment variables for the global and user-session systemd instance.

However when dbus-x11 is installed, the user session environment defined in the above way is overwritten by /etc/X11/Xsession.d/95dbus_update-activation-env[1], more exactly by

dbus-update-activation-environment --verbose --systemd --all

The --systemd option triggers a call to the SetEnvironment method:
https://sources.debian.org/src/dbus/1.12.16-2/tools/dbus-update-activation-environment.c/#L244

"SetEnvironment() may be used to alter the environment block that is passed to all spawned processes. [...] Settings passed will override previously set variables."[2]

https://bugs.debian.org/833318 suggests that the --systemd option does not work anyways. If that is the case, then I propose to just remove it.

If that is not an possible, than I'm not sure what the solution is. Maybe it makes sense to go to the drawing board and check how environment variables are set right now in dbus, systemd and the session leader process and how we think it should be. - Any prior art here?

[1] https://sources.debian.org/src/dbus/1.12.16-2/debian/95dbus_update-activation-env
[2] https://www.freedesktop.org/wiki/Software/systemd/dbus#Manager-SetEnvironment

P.s.: My workspace policy enforces dbus-x11 and purges dbus-user-session. But even with dbus-x11, I consider it a bug if the documented mechanism to set the systemd environment does quietly fail.

#943917#10
Date:
2019-10-31 22:26:42 UTC
From:
To:
This is done because various packages rely on being able to set
environment variables in /etc/X11/Xsession.d and have them inherited by
"all" user processes. It's a backwards-compat compromise that I wish
wasn't necessary.

If we could rely on environment.d, then packages wouldn't have to set
environment variables in /etc/X11/Xsession.d, but then they wouldn't
work in non-systemd environments.

The reason why this backwards-compat mechanism is in dbus-x11 (and not
dbus-user-session) is in the hope that systems that rely on
systemd --user and environment.d can eventually remove dbus-x11.

Do you have evidence that the attempt to call SetEnvironment() does
anything (whether desired or not) when not using dbus-user-session,
or are you reporting this bug on the basis that if it worked, it would
have a result that you don't want?

My understanding is that it doesn't have any effect (good or bad) when not
using dbus-user-session, because when not using dbus-user-session,
systemd --user is not aware of the D-Bus session bus and is not connected
to it; this means it can't be controlled with D-Bus session bus method
calls like SetEnvironment().

The purpose of dbus-user-session is that it selects the mode of
operation where there is only one D-Bus session bus per uid, which
makes it reasonable for the one-per-user systemd --user to connect to
that single session bus and make itself available to be controlled by
session bus method calls.

If you have chosen to purge dbus-user-session and use dbus-x11 instead,
then the same uid can have multiple D-Bus session buses, but there
is still only one systemd --user per uid. It can't possibly have the
right value of DBUS_SESSION_BUS_ADDRESS for all of them, and it seems
reasonable to me that it doesn't get the Xsession.d environment variables
from any of them? This is the same thing that always happened before
dbus-user-session was added.

If you are using dbus-x11 and not dbus-user-session, then D-Bus-activated
session services are all children of dbus-daemon --session, not
children of systemd --user; so they get their environment variables
from dbus-daemon's UpdateActivationEnvironment(), not from systemd's
SetEnvironment(). (This might mean they're different.)

Complicating matters further, if you are using dbus-user-session, the
dbus-daemon also responds to UpdateActivationEnvironment() calls by
forwarding the same environment variables to systemd's SetEnvironment().
This is to avoid breaking programs like gnome-session, which expect that
they can call UpdateActivationEnvironment() to set the given environment
variable for all user services, when session services get converted into
systemd --user services. Again, as far as I'm aware, this won't/can't
work if you are not using dbus-user-session, because in that case systemd
is not present as a session bus service.

(We kept --systemd anyway, because it can matter in rare corner cases
involving environment variables whose values are not UTF-8 - the
dbus-daemon's API cannot represent those, but systemd's can.)

I'm open to suggestions.

From past experience, pinning down what the desired semantics even are
is likely to be difficult; doubly so when making them work for all three
modes, with different expectations and constraints for each:

- session bus per X11 session, not using systemd
- session bus per X11 session, using systemd (you are here)
- session bus per systemd --user (this is dbus-user-session)

I usually recommend dbus-user-session, which has a reasonably coherent
model for what is in a session and how it communicates; but it isn't
the model that everyone wants (multiple X11 displays for one uid are
the usual problem area), which is why it isn't mandatory in Debian,
unlike e.g. Fedora and Arch.

    smcv

#943917#15
Date:
2024-02-02 12:33:14 UTC
From:
To:
I have come to believe this is not a bug.

It may be that environment.d is very nice for systemd integration, but
it is not very granular. Any environment entered via that route will end
up in systemd user environments possibly even when it was not intended.

Scripts in Xsession.d on the other hand may well write over environment
variables but they are written in generic shell scripts and so can be
tailored to only set environment variables in specific circumstances. I
would guess (and I am guessing here) that environment.d gets processed
before Xsession.d, and so scripts in Xsession.d could choose not
override environment variables that have already been set if appropriate.