bit-team / backintime

Back In Time - An easy-to-use backup tool for GNU Linux using rsync in the back
https://backintime.readthedocs.io
GNU General Public License v2.0
2.02k stars 198 forks source link

Can't open BiT on Wayland after Qt theme tweak #1349

Open sojusnik opened 1 year ago

sojusnik commented 1 year ago

I've tweaked my Qt apps to look like GTK apps by

sudo apt install qt5-style-plugins
sudo sh -c "echo 'export QT_QPA_PLATFORMTHEME=gtk2' >> /etc/environment"

but after doing that, I can't open Back in Time any more! The following error message appears:

$ backintime-qt_polkit

Back In Time
Version: 1.3.2

Back In Time comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions; type `backintime --license' for details.

QStandardPaths: runtime directory '/run/user/1000' is not owned by UID 0, but a directory permissions 0700 owned by UID 1000 GID 1000
Authorization required, but no authorization protocol specified

(python3:336124): Gtk-WARNING **: 17:23:47.221: cannot open display: :0.0

Did somebody stumble upon this issue and could solve it?

Under X11, BiT launches as usual, but not on Wayland.

I'm on Ubuntu 22.10 with the following packages installed:

backintime-common/kinetic,kinetic,now 1.3.2-0.1 all
backintime-qt/kinetic,kinetic,now 1.3.2-0.1 all
backintime-qt4/kinetic,kinetic,now 1.3.2-0.1 all
qtwayland5
buhtz commented 1 year ago

You run "Back In Time (root)", right? How is it when you try it as a user?

Please show the output of /usr/bin/backintime-qt --debug and /usr/bin/backintime-qt_polkit --debug.

aryoda commented 1 year ago

QStandardPaths: runtime directory '/run/user/1000' is not owned by UID 0, but a directory permissions 0700 owned by UID 1000 GID 1000 Authorization required, but no authorization protocol specified

I think running BiT (root) with the polkit script still uses the "home" folder of the user while running BiT as root:

$ pkexec echo $HOME
/home/user1
$ pkexec id
uid=0(root) gid=0(root) groups=0(root)

That is why according to above error message the user 0 (root) tries to access a folder of user 1000 (the first "human" user on an installed Linux).

There is a known issue with this in Qt themes but I have never tried to fix this myself:

https://wiki.archlinux.org/title/qt#Theme_not_applied_to_root_applications

This problem is not BiT-specific, so someone must have found and tested a solution for this already (I am searching...)

emtiu commented 1 year ago

Possibly related to #836?

sojusnik commented 1 year ago

You run "Back In Time (root)", right? How is it when you try it as a user?

Please show the output of /usr/bin/backintime-qt --debug and /usr/bin/backintime-qt_polkit --debug.

$ /usr/bin/backintime-qt --debug
DEBUG: [common/backintime.py:583 argParse] Arguments: {'debug': True} | unknownArgs: []

Back In Time
Version: 1.3.2

Back In Time comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions; type `backintime --license' for details.

DEBUG: [common/backintime.py:670 getConfig] config file: /home/sojusnik/.config/backintime/config
DEBUG: [common/backintime.py:671 getConfig] share path: /home/sojusnik/.local/share/backintime
DEBUG: [common/backintime.py:672 getConfig] profiles: 1=Hauptprofil
DEBUG: [common/pluginmanager.py:90 PluginManager.load] Register plugin path /usr/share/backintime/plugins
DEBUG: [common/pluginmanager.py:106 PluginManager.load] Add plugin qt4plugin.py
DEBUG: [common/pluginmanager.py:106 PluginManager.load] Add plugin notifyplugin.py
Warning: Ignoring XDG_SESSION_TYPE=wayland on Gnome. Use QT_QPA_PLATFORM=wayland to run on Wayland anyway.
Gtk-Message: 22:52:53.669: Failed to load module "canberra-gtk-module"
DEBUG: [common/tools.py:829 keyringSupported] No appropriate keyring found. 'keyring.backends.chainer' can't be used with BackInTime
DEBUG: [common/tools.py:829 keyringSupported] No appropriate keyring found. 'keyring.backends.chainer' can't be used with BackInTime
DEBUG: [common/tools.py:829 keyringSupported] No appropriate keyring found. 'keyring.backends.chainer' can't be used with BackInTime
DEBUG: [common/configfile.py:529 Config.setCurrentProfile] change current profile: 1=Hauptprofil
Segmentation fault (core dumped)
$ /usr/bin/backintime-qt_polkit --debug
DEBUG: [common/backintime.py:583 argParse] Arguments: {'debug': True} | unknownArgs: []

Back In Time
Version: 1.3.2

Back In Time comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions; type `backintime --license' for details.

DEBUG: [common/backintime.py:670 getConfig] config file: /root/.config/backintime/config
DEBUG: [common/backintime.py:671 getConfig] share path: /root/.local/share/backintime
DEBUG: [common/backintime.py:672 getConfig] profiles: 1=Hauptprofil, 2=Datenarchiv
DEBUG: [common/pluginmanager.py:90 PluginManager.load] Register plugin path /usr/share/backintime/plugins
DEBUG: [common/pluginmanager.py:106 PluginManager.load] Add plugin notifyplugin.py
QStandardPaths: runtime directory '/run/user/1000' is not owned by UID 0, but a directory permissions 0700 owned by UID 1000 GID 1000
Authorization required, but no authorization protocol specified

(python3:443298): Gtk-WARNING **: 22:54:51.435: cannot open display: :0.0
aryoda commented 1 year ago

I am wondering which message is really causing BiT to fail starting:

a) QStandardPaths: runtime directory '/run/user/1000' is not owned by UID 0, but a directory permissions 0700 owned by UID 1000 GID 1000 b) (python3:443298): Gtk-WARNING **: 22:54:51.435: cannot open display: :0.0

After some "search machine research" it looks like a) is "just" a warning so I would focus on b).

Did anybody find a documentation if gtk2 is supported for wayland at all? It may be an X11-only platform plugin...

@sojusnik Can I assume that /usr/bin/backintime-qt --debug did start the GUI successfully with Wayland? Did it use the gtk2 theme then?

Edit: My current hypothesis is: gtk2 is only supported on X11. Circumstantial evidence: qt5-style-plugins depends on qt5-gtk2-platformtheme depends on libx11-6 (but not on any Wayland package, see https://packages.debian.org/bookworm/qt5-gtk2-platformtheme). This seems plausible to the error message b) which indicates an X11 display number (not Wayland):

# In a Wayland session:
> echo $WAYLAND_DISPLAY
wayland-0
# In an X11 session:
> echo $DISPLAY
:1

Edit 2: What happens if you send xhost +si:localuser:root (to give Wayland access rights to the X server for user root) in the terminal before starting BiT with backintime-qt_polkit? This is a known work-around even though I cannot understand why Wayland and X11 should work together (except you are using XWayland): https://askubuntu.com/questions/961967/why-dont-gksu-gksudo-or-launching-a-graphical-application-with-sudo-work-with-w

sojusnik commented 1 year ago

@sojusnik Can I assume that /usr/bin/backintime-qt --debug did start the GUI successfully with Wayland? Did it use the gtk2 theme then?

It only opened a window where you are asked to restore the settings from a previous config file and then the settings window, but after dismissing both windows (both use the GTK2 theme), the main BiT window doesn't appear.

Out of curiosity, I've started BiT on X11 as well. Maybe it will lead to some clues:

$ /usr/bin/backintime-qt --debug
DEBUG: [common/backintime.py:583 argParse] Arguments: {'debug': True} | unknownArgs: []

Back In Time
Version: 1.3.2

Back In Time comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions; type `backintime --license' for details.

DEBUG: [common/backintime.py:670 getConfig] config file: /home/sojusnik/.config/backintime/config
DEBUG: [common/backintime.py:671 getConfig] share path: /home/sojusnik/.local/share/backintime
DEBUG: [common/backintime.py:672 getConfig] profiles: 1=Hauptprofil
DEBUG: [common/pluginmanager.py:90 PluginManager.load] Register plugin path /usr/share/backintime/plugins
DEBUG: [common/pluginmanager.py:106 PluginManager.load] Add plugin qt4plugin.py
DEBUG: [common/pluginmanager.py:106 PluginManager.load] Add plugin notifyplugin.py
Gtk-Message: 11:05:31.915: Failed to load module "canberra-gtk-module"
DEBUG: [common/tools.py:829 keyringSupported] No appropriate keyring found. 'keyring.backends.chainer' can't be used with BackInTime
DEBUG: [common/tools.py:829 keyringSupported] No appropriate keyring found. 'keyring.backends.chainer' can't be used with BackInTime
DEBUG: [common/tools.py:829 keyringSupported] No appropriate keyring found. 'keyring.backends.chainer' can't be used with BackInTime
DEBUG: [common/configfile.py:529 Config.setCurrentProfile] change current profile: 1=Hauptprofil
Segmentation fault (core dumped)

Surprisingly, the non-root version still doesn't work, even on X11, but the root version does work and is properly themed:

$ /usr/bin/backintime-qt_polkit --debug
DEBUG: [common/backintime.py:583 argParse] Arguments: {'debug': True} | unknownArgs: []

Back In Time
Version: 1.3.2

Back In Time comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions; type `backintime --license' for details.

DEBUG: [common/backintime.py:670 getConfig] config file: /root/.config/backintime/config
DEBUG: [common/backintime.py:671 getConfig] share path: /root/.local/share/backintime
DEBUG: [common/backintime.py:672 getConfig] profiles: 1=Hauptprofil, 2=Datenarchiv
DEBUG: [common/pluginmanager.py:90 PluginManager.load] Register plugin path /usr/share/backintime/plugins
DEBUG: [common/pluginmanager.py:106 PluginManager.load] Add plugin qt4plugin.py
DEBUG: [common/pluginmanager.py:106 PluginManager.load] Add plugin notifyplugin.py
QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/tmp/runtime-root'
Gtk-Message: 11:06:38.070: Failed to load module "canberra-gtk-module"
DEBUG: [common/tools.py:805 keyringSupported] No keyring due to import error.
DEBUG: [common/mount.py:73 Mount.__init__] pw-cache is not running
DEBUG: [common/mount.py:81 Mount.__init__] Call command: /usr/bin/backintime pw-cache start
DEBUG: [common/tools.py:1237 readCrontab] Read 4 lines from users crontab
DEBUG: [common/config.py:1466 Config.removeOldCrontab] Clearing system Back In Time entries
DEBUG: [common/config.py:1500 Config.cronLine] Profile: Hauptprofil | Automatic backup: Benutzerdefinierte Stunden
DEBUG: [common/config.py:1500 Config.cronLine] Profile: Datenarchiv | Automatic backup: Benutzerdefinierte Stunden
DEBUG: [common/tools.py:1274 writeCrontab] Wrote 4 lines to users crontab
DEBUG: [common/tools.py:805 keyringSupported] No keyring due to import error.
DEBUG: [common/mount.py:73 Mount.__init__] pw-cache is not running
DEBUG: [common/mount.py:81 Mount.__init__] Call command: /usr/bin/backintime pw-cache start

Edit 2: What happens if you send xhost +si:localuser:root (to give Wayland access rights to the X server for user root) in the terminal before starting BiT with backintime-qt_polkit? This is a known work-around even though I cannot understand why Wayland and X11 should work together (except you are using XWayland): https://askubuntu.com/questions/961967/why-dont-gksu-gksudo-or-launching-a-graphical-application-with-sudo-work-with-w

How can I find out if I'm using XWayland? I just did a fresh installation of Ubuntu 22.10 without any substantial tweaks besides this performance tweak to decrease mouse latency.

Applying xhost +si:localuser:root helps! BiT opens and is themed, but I guess it's a security issue, so I reverted with xhost -si:localuser:root for the time being.

$ xhost +si:localuser:root
localuser:root being added to access control list
$ /usr/bin/backintime-qt_polkit --debug
DEBUG: [common/backintime.py:583 argParse] Arguments: {'debug': True} | unknownArgs: []

Back In Time
Version: 1.3.2

Back In Time comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions; type `backintime --license' for details.

DEBUG: [common/backintime.py:670 getConfig] config file: /root/.config/backintime/config
DEBUG: [common/backintime.py:671 getConfig] share path: /root/.local/share/backintime
DEBUG: [common/backintime.py:672 getConfig] profiles: 1=Hauptprofil, 2=Datenarchiv
DEBUG: [common/pluginmanager.py:90 PluginManager.load] Register plugin path /usr/share/backintime/plugins
DEBUG: [common/pluginmanager.py:106 PluginManager.load] Add plugin qt4plugin.py
DEBUG: [common/pluginmanager.py:106 PluginManager.load] Add plugin notifyplugin.py
QStandardPaths: runtime directory '/run/user/1000' is not owned by UID 0, but a directory permissions 0700 owned by UID 1000 GID 1000
Gtk-Message: 11:40:22.090: Failed to load module "canberra-gtk-module"
DEBUG: [common/tools.py:805 keyringSupported] No keyring due to import error.
DEBUG: [common/mount.py:73 Mount.__init__] pw-cache is not running
DEBUG: [common/mount.py:81 Mount.__init__] Call command: /usr/bin/backintime pw-cache start
DEBUG: [common/tools.py:1237 readCrontab] Read 4 lines from users crontab
DEBUG: [common/config.py:1466 Config.removeOldCrontab] Clearing system Back In Time entries
DEBUG: [common/config.py:1500 Config.cronLine] Profile: Hauptprofil | Automatic backup: Benutzerdefinierte Stunden
DEBUG: [common/config.py:1500 Config.cronLine] Profile: Datenarchiv | Automatic backup: Benutzerdefinierte Stunden
DEBUG: [common/config.py:1450 setupCron] Crontab didn't change. Skip writing.
aryoda commented 1 year ago

How can I find out if I'm using XWayland? I just did a fresh installation of Ubuntu 22.10 without any substantial tweaks

Sorry, I didn't give enough context:

Ubuntu automatically installs the "XWayland" package together with "wayland" which allows "old" apps to use the "old" X11 API against the wayland display server (kinda "compatibility layer").

See also: https://wayland.freedesktop.org/xserver.html

To find out if BiT (or another app) is using XWayland there is a good description here (including the funny "xeyes" way):

https://askubuntu.com/questions/1393618/how-can-i-tell-if-an-application-is-using-xwayland

$ /usr/bin/backintime-qt --debug ... Warning: Ignoring XDG_SESSION_TYPE=wayland on Gnome. Use QT_QPA_PLATFORM=wayland to run on Wayland anyway.

BiT "userland" (= not started as root) does not use wayland but X11 (via above mentioned XWayland).

I have opened a new issue #1350 since BiT should consistently use either X11 or Wayland API for both BiT root and BiT "userland".

$ /usr/bin/backintime-qt_polkit --debug ... QStandardPaths: runtime directory '/run/user/1000' is not owned by UID 0, but a directory permissions 0700 owned by UID 1000 GID 1000 Authorization required, but no authorization protocol specified (python3:443298): Gtk-WARNING **: 22:54:51.435: cannot open display: :0.0

This is an expected error since running a GUI as root is not allowed with wayland and polkit starts BiT as root.

[aryoda]: Can I assume that /usr/bin/backintime-qt --debug did start the GUI successfully with Wayland? Did it use the gtk2 theme then?

It only opened a window where you are asked to restore the settings from a previous config file and then the settings window, but after dismissing both windows (both use the GTK2 theme), the main BiT window doesn't appear.

This is OK if your BiT profile is stored only in BiT (root) - the config files are stored "per user" in their home folder and if you did not create a config BiT will quit if none exists (not very intuitive or user-friendly I have to admit).

Surprisingly, the non-root version still doesn't work, even on X11

I guess with "doesn't work" you mean the same BiT behaviour to ask for a new config and quit if you do not create one. This works as designed ;-)

Applying xhost +si:localuser:root helps! BiT opens and is themed, but I guess it's a security issue, so I reverted with xhost -si:localuser:root for the time being.

Yes, this weakens the wayland security idea and revoking it after BiT has quit is the best you can do. In practice the security impact is nearly zero unless ALL your apps use the wayland API, we get rid of X11 and fix some more issues in Linux Desktop Environments.

For a good explanation see this video: https://www.youtube.com/watch?v=-T1LoHTZDvs

Still it is the best option so far (and often used by other apps too).

BTW: There was a non-merged PR (#1347) for using this "work-around" which I'd consider as a possible solution for you since it does revoke automatically:

https://github.com/bit-team/backintime/pull/1347/files

If you want you could try this script and post your feed-back here...

sojusnik commented 1 year ago

I guess with "doesn't work" you mean the same BiT behaviour to ask for a new config and quit if you do not create one. This works as designed ;-)

I had the impression that it crashed even before asking to set up a new config, but I checked it again under X11 with the non-root version and BiT quits after I press "cancel" twice, in order not to set up a new config. So I guess it's working like it should.

BTW: There was a non-merged PR (#1347) for using this "work-around" which I'd consider as a possible solution for you since it does revoke automatically:

https://github.com/bit-team/backintime/pull/1347/files

Setting a script at the moment is too cumbersome for me. I hope for a quick fix and will use the manual way with xhost +si:localuser:root in the meantime.

Thanks for your help!

aryoda commented 1 year ago

Internal note:

Without setting XDG_RUNTIME_DIR a warning appears:

QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/tmp/runtime-root'

Setting it throws:

QStandardPaths: wrong ownership on runtime directory /run/user/1000, 1000 instead of 0

since it is set to the user's value (/run/user/1000).

TODO: Examine the behavior in all variations of X11/Wayland display server with different Qt5 platform plugins (xcb for X11, wayland and XWayland variations...

aryoda commented 1 year ago

Short summary of findings so far:

When BiT (root) is started on wayland this warning appears (since the backintime-qt_polkit starter script uses the temp configuration files from the user 1000 instead of the root user 0):

QStandardPaths: runtime directory '/run/user/1000' is not owned by UID 0, but a directory permissions 0700 owned by UID 1000 GID 1000

This is just a warning, but

So I am afraid only a refactoring to use a user BiT Qt GUI + as-required elevated rights in the backend will really bring a sustainable solution (which is very much work).

buhtz commented 1 year ago

So I am afraid only a refactoring to use a user BiT Qt GUI + as-required elevated rights in the backend will really bring a sustainable solution (which is very much work).

Thanks for for your research here. Do you mean that backintime-qt should always run as user? Andspawning the backintime process via subprocess.Popen() should do it (somehow?) with root rights if needed?

aryoda commented 1 year ago

Do you mean that backintime-qt should always run as user?

Yes, this a wayland security requirement.

And spawning the backintime process via subprocess.Popen() should do it (somehow?) with root rights if needed?

Yes, this could be one way to go to make a non-root GUI usable for certain privileged actions. Other options would be

polkit is already used in BiT (see https://github.com/bit-team/backintime/blob/dev/qt/net.launchpad.backintime.policy) but I don't know enough so far how this behaves on wayland and what is missing, e.g.:

https://stackoverflow.com/questions/76699399/how-can-a-non-root-qt5-wayland-gui-also-show-all-root-files-and-paths-in-a-fil

PS: I may have found a work-around by setting WAYLAND_DISPLAY="$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY" in the starter script (I have to try it on my VMs first): https://unix.stackexchange.com/a/709811 Update: I have more VMs available that reproduces the original problem sporadically so we have to wait until it happens again :-(

aryoda commented 8 months ago
  • on some newer systems with wayland the missing authorization (meant to be better than X11) is missing, see this error message:

    Authorization required, but no authorization protocol specified

    Granting the rights (and weakening wayland's security) to make BiT (root) working can be done via xhost +si:localuser:root

  • even when BiT (root) works with the Qt5 wayland plugin then the systray icon willl NOT work with wayland (at least not in my tests) since QSystemTrayIcon.isSystemTrayAvailable() returns False (a dbus end point which is not available as root, see https://stackoverflow.com/questions/74573870/why-is-qsystemtrayicon-issystemtrayavailable-false-running-as-root-but-true-as)

Authorization required, but no authorization protocol specified looks like related to #1580 and #1592 (but xhost +si:localuser:root did not help there)...

@sojusnik I think your problem may also be fixed with the fix of #1592 which is contained in the upcoming release planned for end of January 2024. It would be great if you could test that release then and tell us if it works now.

I have modified the BiT GUI (root) starter script to prefer xcb (X11) over wayland-egl and removed the code that overwrites XDG_RUNTIME_DIR in case of Wayland so it should work now...