10

Let's assume this kind of situation: we have one user logged in, executing some application through sudo or su. This user has got a dbus-daemon running.
However, when an application running with root privileges tries to access D-Bus, it just spawns another dbus-daemon, owned by root user. That's not a desired situation.

Is there a way to gain access to D-Bus session of user who ran the application through sudo or su?

Dr McKay
  • 2,548
  • 2
  • 21
  • 26
  • It should work if you do a `su -` from the user that holds the session to *root*, the other direction will not work, thats not wanted and would be a big security risk. – Thomas Berger Jun 27 '11 at 18:02
  • Indeed, and doesn't `dbus-monitor --system` help you in this case? – karlphillip Jun 27 '11 at 18:19

2 Answers2

10

If you're on a systemd distro, the relatively new machinectl shell command can do the work of su/sudo, and it will also set session variables like XDG_RUNTIME_DIR and DBUS_SESSION_BUS_ADDRESS. So for example, if I want to run systemctl --user as user test, the normal approach will fail:

$ sudo --user=test systemctl --user
Failed to connect to bus: No such file or directory

But this way works:

$ sudo machinectl shell --uid=test .host -- /usr/bin/systemctl --user

If you need to "reach back" into the user session that invoked a sudo script, you could use the SUDO_USER/SUDO_UID to hack something together.

Jack O'Connor
  • 10,068
  • 4
  • 48
  • 53
  • `machinectl` seems to be gone now. I'm on debian testing. I think it was abandoned. – Rolf Mar 29 '18 at 23:39
  • It's on ArchLinux. This did indeed work for me, but I was trying it in a Lua script and it failed :(. – TheFrack Nov 21 '18 at 02:55
  • 1
    *buntu 19.10 contains a `/bin/machinectl` in package `systemd-container` which accepts this syntax: `machinectl shell otheruserlogin@ /full/path/to/command --arguments` and succeeds in reaching that user's DBUS. – Stéphane Gourichon Feb 24 '20 at 18:09
  • The machinectl manpage recommends using `systemd-run` for scripting purposes. I've tried, and this seems to be the equivalent of your `machinectl shell` command above: `sudo systemd-run --quiet --pipe --wait --user --machine test@.host /usr/bin/systemctl --user`. Maybe that would be good to include in your answer? I considered editing it in, but that seemed impolite :-) – Matthijs Kooijman Oct 09 '22 at 14:11
7

First, you need DBUS_SESSION_BUS_ADDRESS environment variable to be preserved when invoking application with su or sudo. Unfortunately, this is not enough, because DBus always checks (as a security measure) whether UIDs of the calling process and the session daemon are the same. The only workaround is to call seteuid from this application before connecting to the session bus. You can regain your privileges then with seteuid(0).

rkhayrov
  • 10,040
  • 2
  • 35
  • 40
  • Sorry for accepting your answer so late, I've had vacation. I didn't even need `DBUS_SESSION_BUS_ADDRESS`, `seteuid` was enough (at least I was able to talk to Zeitgeist in context of invoking user). Thanks! – Dr McKay Jul 27 '11 at 10:40
  • 1
    But if the situation is like this: We have 2 users logged in at the same time(A, B) Is it possible to connect to B's for example session manager from A? – Ojs Jun 03 '16 at 13:16