Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Qubes fails to start/activate systemd graphical-session.target target #9576

Open
adrelanos opened this issue Nov 12, 2024 · 17 comments
Open
Labels
P: default Priority: default. Default priority for new issues, to be replaced given sufficient information. T: bug Type: bug report. A problem or defect resulting in unintended behavior in something that exists.

Comments

@adrelanos
Copy link
Member

Qubes OS release

R4.2.

Brief summary

The graphical-session.target is missing in Qubes.

This breaks Kicksecure's and Whonix's msgcollector /usr/lib/systemd/user/msgcollector-gui.service.

Steps to reproduce

systemctl --user status graphical-session.target

Expected behavior

Compared to KUbuntu:

systemctl --user status graphical-session.target
● graphical-session.target - Current graphical user session
     Loaded: loaded (/usr/lib/systemd/user/graphical-session.target; static)
     Active: active since Sat 2024-11-09 17:52:48 CST; 2 days ago
       Docs: man:systemd.special(7)

Actual behavior

Qubes Debian Template:

systemctl --user status graphical-session.target
○ graphical-session.target - Current graphical user session
     Loaded: loaded (/usr/lib/systemd/user/graphical-session.target; static)
     Active: inactive (dead)
       Docs: man:systemd.special(7)
@adrelanos adrelanos added P: default Priority: default. Default priority for new issues, to be replaced given sufficient information. T: bug Type: bug report. A problem or defect resulting in unintended behavior in something that exists. labels Nov 12, 2024
@marmarek
Copy link
Member

marmarek commented Nov 12, 2024

Interestingly, there is no graphical-session.target at all in Fedora (but it is documented in the systemd.special man page). my bad, typo

@marmarek
Copy link
Member

This is going to be a bit tricky, as qubes-gui-agent is a system unit, and graphical-session.target is a user unit. I don't think one can bind them across system/user instances boundary. I guess we need a dummy user unit for this...

@ArrayBolt3
Copy link

On my Kubuntu system, I see that /usr/lib/systemd/user/plasma-workspace.target Requires graphical-session.target, BindsTo it, and is Before it. I can test if making and enabling such a service on R4.3 fixes the issue, and make a pull request if so.

@marmarek
Copy link
Member

@ArrayBolt3 the thing is, VM has no equivalent of plasma-workspace.target user unit. There is only qubes-gui-agent.service system unit.

@ArrayBolt3
Copy link

@marmarek Right, but all that needs to be done is making some arbitrary dummy unit like you said, and enabling it (at least I think that will work). I wasn't really coming up with any new ideas, just looking for which settings the dummy unit would need in order to do the right thing.

@ArrayBolt3
Copy link

ArrayBolt3 commented Nov 12, 2024

The following works for me in a whonix-workstation-17 template:

[template workstation user ~]% cat /usr/lib/systemd/user/force-graphical-session.service 
[Unit]
Description=get graphical-session.target to work
BindsTo=graphical-session.target
Before=graphical-session.target
Requires=graphical-session.target

[Service]
ExecStart=/usr/bin/true
Type=oneshot
RemainAfterExit=true

[Install]
WantedBy=default.target

Then systemctl --user enable force-graphical-session.service and reboot. graphical-session.target will be active on boot.

[template workstation user ~]% systemctl --user status graphical-session.target
● graphical-session.target - Current graphical user session
     Loaded: loaded (/usr/lib/systemd/user/graphical-session.target; static)
     Active: active since Tue 2024-11-12 21:58:55 UTC; 1min 50s ago
       Docs: man:systemd.special(7)

Nov 12 21:58:55 host systemd[793]: Reached target graphical-session.target - Current graphical user session.

However, this does NOT seem to make graphical-session.target work in a whonix-workstation-17-dvm machine. Not sure why yet.

edit 1: clarified that this was a whonix-workstation-17 template
edit 2: Switched from WantedBy=basic.target to WantedBy=default.target since that seemed more sensible

@marmarek
Copy link
Member

Well, even it that "works", it would be wrong thing to do, as graphical-session.target is supposed to be active when actual graphical session is active, not just always.

@ArrayBolt3
Copy link

Yeah, that's a good point. Further complicating matters is that enabling a user service in a template doesn't seem to enable it in a DispVM, and disabling the user service in the template doesn't disable it in the DispVM either. Not sure what's happening there, I'm on Qubes OS R4.3.

@ArrayBolt3
Copy link

Hmm. The way it works in KDE Plasma appears to be something like this:

  • SDDM launches /usr/bin/startplasma-x11
  • startplasma-x11 does some setup work, then connects to systemd over D-Bus and instructs it to launch the plasma-workspace-x11.target user target
  • That then kicks off a whole slew of units, including the aforementioned plasma-workspace.target
  • plasma-workspace.target appears to be what reaches graphical-session.target.

So it might be possible for the GUI daemon to do sort of the same thing:

  • Launching a qube launches the guest-side qubes-gui-daemon within the qube
  • qubes-gui-daemon figures out which user the graphical session is running on (how to do this?)
  • qubes-gui-daemon launches some subprocess as the user the graphical session will end up running on (or it forks and changes to the specific user, perhaps)
  • The subprocess tells systemd to start graphical-session.target, probably using D-Bus

That wouldn't require a dummy systemd unit at all, though it would require some substantial complexity. The potentially tricky parts are going to be figuring out which user to "drop" to, and then doing the D-Bus connection.

@ArrayBolt3
Copy link

er, replace gui-daemon with gui-agent, I had them mixed up.

@marmarek
Copy link
Member

The proper place is to plug it into qubes-session somehow - this is what is started under Xorg as the user. But still, not sure how to do it to behave as the documentation says:

   graphical-session.target
       This target is active whenever any graphical session is running. It
       is used to stop user services which only apply to a graphical (X,
       Wayland, etc.) session when the session is terminated. Such
       services should have "PartOf=graphical-session.target" in their
       [Unit] section. A target for a particular session (e. g.
       gnome-session.target) starts and stops "graphical-session.target"
       with "BindsTo=graphical-session.target".

So, we need to ensure not only it gets started at proper time, but also it gets stopped when graphical session (qubes-session / qubes-gui-agent) are stopped.

@marmarek
Copy link
Member

Or maybe even one step earlier - plug it into qubes-run-xorg to call the whole xinit etc (see final lines of the script) under user unit. But then, monitoring if the X server is still running will get tricky, qubes-run-xorg shouldn't exit before X server exits, and systemctl --user start doesn't normally wait for the unit to stop... (maybe systemctl --user --wait start could be used?)

@ArrayBolt3
Copy link

To me it seems like qubes-session is the equivalent of startplasma-x11 as far as sessions are concerned. My initial instinct would be to put it here: https://github.com/QubesOS/qubes-gui-agent-linux/blob/main/appvm-scripts/usrbin/qubes-session#L40-L49 Have a user systemd unit with the needed BindsTo that calls qsvc qubes-gui-agent, and start that unit using systemctl in qubes-session. When qubes-gui-agent dies, so will the unit (if configured properly), which should take down graphical-session.target with it.

@marmarek
Copy link
Member

If going the latter direction, this would need to be done carefully - all the user processes (including most qrexec services, xdg autostart apps etc) are started as children of qubes-session, which means it's sensitive for changes in environment vars, applied limits, cgroups etc...

My initial instinct would be to put it here: https://github.com/QubesOS/qubes-gui-agent-linux/blob/main/appvm-scripts/usrbin/qubes-session#L40-L49

Nope, this part applies only to sys-gui (it starts Xfce or whatever user has configured in sys-gui, which itself runs gui-agent connected to dom0).

@ArrayBolt3
Copy link

ArrayBolt3 commented Nov 12, 2024

Nope, this part applies only to sys-gui (it starts Xfce or whatever user has configured in sys-gui, which itself runs gui-agent connected to dom0).

hmm, I may be severely confused as to the purpose of the qubes-session script then, because I don't see anything else in that script that would launch the GUI agent, and I thought this was the GUI agent launcher each qube ran. edit: or I can't read and just missed the blatant exit that was right there 🤦

@marmarek
Copy link
Member

the flow is: qubes-gui-agent -> qubes-run-xorg -> xinit -> ... -> Xorg + qubes-session

@ArrayBolt3
Copy link

I think your --wait idea will work. man systemctl's documentation on --wait makes it sound like it will work to block until the unit terminates, and I tested the theory with the following simple systemd user unit:

[Unit]
Description=testabcd
[Service]
Type=exec
ExecStart=/usr/bin/sleep 10
[Install]
WantedBy=multi-user.target

With systemctl --user start testabcd, the command returns instantly. With systemctl --user --wait start testabcd, it hangs for 10 seconds.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
P: default Priority: default. Default priority for new issues, to be replaced given sufficient information. T: bug Type: bug report. A problem or defect resulting in unintended behavior in something that exists.
Projects
None yet
Development

No branches or pull requests

3 participants