XScreenSaver version 6 beta 1

I have significantly refactored the XScreenSaver daemon, the component of the XScreenSaver suite that provides screen locking on X11 systems.

These changes greatly reduce the amount of code running in the "critical" section: the part of the code where a crash would cause the screen to unlock. That critical section is now only around 1,800 lines of code, a reduction of roughly 87%.

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. -- Antoine de Saint-Exupery

My approach with XScreenSaver, as I've written about extensively, has always been to minimize the amount of code in the critical section: to link with as few libraries as possible, and to sandbox as much of the rest as possible in separate processes. This approach has worked out very well; XScreenSaver has had an excellent security track record over these last three decades. Not perfect, but pretty damned good. Especially as compared to its putative "competition".

But, it still contains quite a lot of code, and keeping up with new operating system features like hot-swapping of monitors, new ways of detecting user activity and so on, has caused more and more code to creep into it. Remember that XScreenSaver predates not only HDMI, but USB! I wrote the first version on a 1-bit monochrome display.

So I stepped back and took a fresh look at the whole thing from the perspective of, "what needs to be here?" In addition, dropping support for X11 systems more than fifteen years old -- an eminently reasonable thing to do -- allowed me to simplify the flow of control a lot.

The new design looks like this:

  • xscreensaver
    • The daemon. Links with Xlib and nothing else.
    • Requires the XInput2 extension, standard since X11R7 in 2005.
    • Handles grabs, idle detection, and client messages.
    • Maps no windows.
  • xscreensaver-gfx
    • Launched by xscreensaver to blank the screen.
    • Launches the screenhacks as sub-processes.
    • Handles monitor reconfiguration, fading, visuals, etc.
    • If it crashes, the desktop will momentarily be visible, but the keyboard and mouse will remain grabbed and the screen will remain locked.
  • xscreensaver-auth
    • Launched by xscreensaver to authenticate the user.
    • Draws the unlock dialog, and talks to PAM.
    • Exit code indicates success or failure, so if it crashes, that has the same behavior as "incorrect password".

The old XScreenSaver daemon contained 14.5k lines of code in a single executable. The new one contains 12.5k lines across three different executables -- a 14% reduction overall. But as I said earlier, the critical section -- the process whose crash will result in an unlock -- now contains only 1.8k lines -- an 87% reduction. This is great not just because it reduces the attack surface, but also because it's easier to understand and audit.

Since this is a very large change, I would like to get a lot of testing on this before calling it ready for release. Please beat on it, eyeball it, throw whatever you can at it, and see if you can make it crash. Particularly, see if can make it crash and unlock.

Let me know if any of these things don't work by default:

  • There should be no compilation errors that "configure" didn't warn you of first.
  • Locking should work, specifically unlocking.
  • The "xscreensaver-systemd" program should be running in the background.
  • Fonts and font sizes in the unlock dialog should look sensible.
  • Custom fonts should have been installed and used (e.g. "memscroller" should be using an OCR font).
  • Fading and un-fading should be smooth on all screens.

Things that it would be nice to have some testing on, if you have the means:

  • Non-English locales.
  • Passwords containing non-Latin1 characters.
  • Unixen that are not Linux.
  • Linuxen that are not Debian or Fedora.
  • Hot-swapping monitors willy-nilly.
  • Laptops with flaky power management.
  • HiDPI monitors.
  • PBP monitors ("two HDMI one cup").
  • Kerberos.
  • Exotic PAM authentication methods, such as USB or bluetooth fobs, or fingerprint readers.
  • Any PAM setup that prompts for more than one input.
  • Does XScreenSaver interact sanely with remote desktop clients or games that grab the mouse for long periods?
  • Exotic input devices: do you have a controller that does not present as key-press or mouse-motion, and does XScreenSaver recognize it as user activity?

Launch it as "xscreensaver -log log.txt" and if anything goes wrong, send me the entire log file, and as many other details as you can about your system and what was going on at the time.

If there were any compilation problems, send me the entire output from "configure" and "make", as well as the "config.log" file.

Please note, this is a BETA release. Do not download this unless you are willingly participating in the testing of software that is probably flaky! And above all, do not distribute this version to other users.

☢ xscreensaver-6.00b2.tar.gz ☢

Do send me email and let me know what systems you've tried it on and how that went.


Tags: , , , , , ,

28 Responses:

  1. jwz says:

    Also: KDE's "ksmserver" and Gnome's "gsd-screensaver-proxy" prevent "xscreensaver-systemd" from working, meaning the screen will blank while you are playing videos. If you understand the proper way to disable those, tell me.

    • Michael Pyne says:

      ksmserver is the thing that brings up the whole rest of the desktop but there has been very recent work to support launching KDE Plasma using systemd, which claims that ksmserver is then reduced to session management and no longer tied to the window manager.

      I'm not sure what aspect of xscreensaver-systemd is not working due to ksmserver but this appears to at least be relevant.

      • jwz says:

        If ksmserver is not launched with --no-lockscreen, it binds to dbus "org.freedesktop.ScreenSaver" which prevents xscreensaver-systemd from doing so, which prevents xscreensaver from being informed that videos are playing.

        The only way that I know to fix this is to edit /usr/bin/startkde by hand, which is obviously less than ideal.

        • remenic says:

          If you do use systemd and plasma 5.21, it should now be as simple as systemctl --user edit plasma-ksmserver and then uncommenting and changing the ExecStart line.

        • Michael Pyne says:

          From poking around the code a bit I think --no-lockscreen is it, there's no other environment variables or auto-disables aside from a Wayland-specific one added recently.

          If you're wanting to use systemd then I think we'd be interested in making that work somehow but you'd want to talk to David Edmundson (kde at davidedmndson.co.uk ... but spell his name right in the URL).

  2. jwz says:

    Also: Someone should really fix configure.ac to not use IT_PROG_INTLTOOL and rewrite po/Makefile.in from scratch, because how it works now is insane and incomprehensible.

  3. jwz says:

    Also: It would be good if the unlock dialog let you see and alter your keyboard layout. If you understand how to do that portably, send me some code.

    • Linulin says:

      The worst thing is that you have no clue whether the rejected password is mistyped, or entered using a wrong keyboard layout. So, getting access to your screen on the 3rd or 4th attempt is not that uncommon.

      A couple of potential workarounds if you don't find the right solution:

      1. Let users define a custom password in XScreenSaver configuration, thus allowing layout-agnostic (e.g. numeric) screen-locking passwords. (In fact, I find this feature valuable regardless of the keyboard layout issue.)

      2. Add an option to show the actual screen content (or a small part of it?) while entering the password, thus making a desktop-specific locale indicator visible, (which is probably enabled in setups with more than one keyboard layout).

      I'm not sure if XScreenSaver supports any of these options already, or if they fit the internal design nicely. (I use xtrlock where #2 is on by default, and #1 has to be added via a small custom patch.)

  4. moof says:

    This is on NetBSD, so these may be OS specific.

    xscreensaver-gfx linking isn't picking up the -lintl it needs for gettext().

    Have you tried rebuilding with a more recent autoconf? 2.71 doesn't seem to like your gettimeofday checks, and `autoupdate -f` dies in the same area. (NetBSD also uses the same vendor GL header files that you lament in the *-darwin* comment, and I'm thus trying to excise the std=c89 bits similarly.)

    • jwz says:

      The last time I tried to upgrade autoconf (besides config.guess) I came to the conclusion that the reason there is an "autoconf263" package is that that's the last version that works.

  5. Markus Kuhn says:

    One thing to be aware of when splitting the re-login authentication dialogue into a separate process is that $XAUTHORITY may reside on a Kerberos-protected NFS mount, and the Kerberos ticket may have expired. Easy to get locked out then if the authentication GUI only fetches its XAUTHORITY file when the user tries to unlock. It may be too late by then. https://bugs.launchpad.net/ubuntu/+source/lightdm/+bug/1648107

    • jwz says:

      I'm not sure I've seen any evidence that anyone has tried to compile XScreenSaver's Kerberos support in more than a decade -- and I've asked. But if someone ever does, I guess we'll find out.

      • Markus Kuhn says:

        We don't need any Kerberos implementation in a screensaver itself these days, because all Kerberos-related operations (verify password, get a fresh ticket) should be done transparently via PAM instead.

        The Kerberos-related issue I am worried about is indirect, something I have seen with other screensavers happen where the authentication dialog was factored out into a separate program, for example /usr/bin/gnome-screensaver calling /usr/lib/gnome-screensaver/gnome-screensaver-dialog after many hours of locked screen to perform the GUI dialog to ask for the password. If my $HOME can only be accessed via a valid Kerberos ticket, and that has expired, then gnome-screensaver-dialog gets called only at the time I want to unlock the screen (e.g. after a mouse movement), but then fails immediately the X11 authentication, because due to the expired Kerberos ticket in /tmp/krb5cc_$UID it no longer can read ~/.Xauthority. A monolithic screensaver behaves better here: it reads ~/.Xauthority immediately when it locks the screen, and still has GUI access even if (after the screen was locked for 10 hours) the Kerberos ticket has expired. Its password GUI dialog still works, it can pass the password on to PAM, which will use it to refresh the Kerberos ticket in /tmp/krb5cc_$UID and all will be fine.

        So this is not about any Kerberos support in the screensaver, but about it being good practice to load ~/.Xauthority when locking the screen, and using it from memory when unlocking the screen, because $HOME may not be accessible any more at unlock time with Kerberized NFS/SMB/etc. I have seen this cause trouble when gnome-screensaver factored out gnome-screensaver-dialog, so wanted to inquire if this can now happen here as well.

        At what time does xscreensaver-auth try to ready ~/.Xauthority? At lock time or at unlock time? The former would be safer.

        • jwz says:

          Well, if your proposal is "go back to a monolithic design", sorry, that's off the table.

          Is this an actual exists-in-the-real-world problem, or a hypothetical that you think might happen to someone whose Kerberos setup was designed in the 90s and hasn't been updated since? Because as you describe it, every other screen saver system would also fail in this way, and that strongly suggests that either it's not an issue, or nobody's very concerned about it.

          It sounds like a problem that should be solved by making the Kerberos configuration be less stupid. Which I suspect is what anyone suffering from this problem has done.

          • Markus Kuhn says:

            The solution doesn't require a monolithic design, just one where the xauth data needed by the login dialog is read at lock time, not at unlock time. This could be accomplished in several different ways:

            a) Starting the process for the login dialogue at lock time, not at unlock time, and then have it sleep until the user wants to unlock, at which time it could be woken up with a signal.

            b) Fork the process for the login dialogue in a way such that it uses the same already-authenticated Display connection as the parent process, rather than opening a new session and having to reread the $XAUTHORITY file at the time of unlock. This means the password dialog would be implemented in the same binary (or in a shared library), but executed in a separate process that inherits the already opened Display structure.

            Yes, lack of access to $XAUTHORITY at unlock time is a real-world problem for users with $HOME on ticket-authenticated network protocols. There are workarounds, as discussed e.g. at https://bugs.launchpad.net/ubuntu/+source/lightdm/+bug/1648107 but they also have disadvantages.

            • jwz says:

              What are the disadvantages to fixing it as you described in that bug?

            • Ivan says:

              This is an insane setup. Your $HOME just disappears occasionally. And your solution is to design all software to basically cache around that.

              • db48x says:

                I've done work for two companies that used NFS–mounted home directories. It can be pretty nice to log into a random server and have all your tools and customizations available. The other one had all of their engineers logging into a common set of servers to do development. Between the remote X servers and NFS–mounted home directories, you didn't care which dev server you ended up on. I didn't really see the point in going that far, but it was nice that you never had to wait for the subversion server, since it was all local. Not much point in running a screensaver on those dev servers though.

                • Ivan says:

                  Then, as our host has suggested, you configure Kerberos to allow ticket renewal for a month and sssd to do so periodically while you are logged in. I can't accept as normal that every 10h something will crash because it can't access $HOME

                  • db48x says:

                    Well, sure. As I said, there wasn't much point in using something like xscreensaver in either of those circumstances. I just meant that having $HOME on NFS can be quite convenient. It was a few years back, but I recall that there was a risk of losing long–running processes if you left them after you logged out (with screen or nohup, for example). Even with that potential annoyance, they seemed to enjoy their dev environment. Personally I just ran Emacs locally and used TRAMP to access the files on the server. That got me the best of both worlds, since their servers were in Israel and a remote X connection isn't very responsive when your connection is going half–way around the world. SVN checkouts wouldn't have been very fun either.

                    Note however that in Markus's case the problem isn't really that his $HOME can disappear, it's that he's storing his .Xauthority in his home directory. The .Xauthority file has a useful lifetime that isn't related to whether or not his home directory is available, so it should be stored somewhere else.

                  • Ivan says:

                    Having same stuff everywhere is neat. But as you note yourself, now we gotta explicitly store .Xauthority and many other things in some local always-available-to-the-user-and-no-one-else place. I wonder what we should call it.

                  • db48x says:

                    Fedora does this really well. It puts all of these types of files that are unique to both the machine and the user into /var/run/user/$UID. my Xauthority file is /var/run/user/1000/gdm/Xauthority, my emacs server socket is /var/run/user/1000/emacs/server, my ssh ControlMaster sockets go in /var/run/user/1000/ssh, etc, etc.

                    None of these files would be useful on an NFS filesystem, and none of them need to survive a reboot, so this is a tmpfs filesystem.

                  • Ivan says:

                    Right, the XDG base dir attempt to make locations sane. Maybe in another 10 years all those cats will have been herded and it will be reliably supported.

  6. xrayspx says:

    It never occurred to me that my HP laptop fingerprint readers would just be completely unsupported in Linux. I believe I did set this up in the past on a Lenovo, and I may be able to grab a decommissioned one to test with. I need to make fingerprint auth work just out of spite.

  7. genewitch says:

    I appreciate all of the work you've done over almost 30 years according to the changelogs... I believe i first saw xscreensaver in around 1998 on FreeBSD, my first foray out of MacOS8 and Windows NT.

    I like your commentary on this site, too. I think i said that a couple days ago, but it's worth repeating.

  8. Ömer says:

    All is well so far on a fairly standard HiDPI Debian, fvwm3 1.0.3 with goop.

    The issue I wrote to you about on 1 August 2019 with xscreensaver being sent to background seems to be gone as well, though not sure if it's due to the newer version of xscreensaver or fvwm.

    Thank you for all your efforts!

  9. Twiggy says:

    My favorite package! The first thing I do on a new work station is enable all the sandboxes D: