A sandbox for the screen locker

Making our screen locker as secure as possible has been an aim for us for a long time. A fully secure screen locker is difficult to achieve on the X11 platform as I outlined in the past. But Wayland is coming which gives us a better and more secure platform in general.

With Wayland it is not as trivial as on X11 to install a key logger and to gain the user’s password. For attackers the user’s password is interesting – on a sudo enabled system it might be possible to use it to become root – and there is a chance that it is the facebook password as well. So gaining a password is interesting. The lock screen is an area where we know that the password will be entered. This means the lock screen is an interesting target.

On X11 it is not interesting as it’s easier to just block the lock screen and exchange it with a custom application which looks like the lock screen. But on Wayland attacking the lock screen becomes interesting again.

What is important to us is to prevent possible attacks before it can become an issue. For that let’s first look at the threat level. Our lock screen implementation can be customized using look and feel packages and Plasma wallpaper packages. The user can download and install them from e.g. store.kde.org. The look and feel package has full access to all key codes entered while the screen is locked. Thus it could be a key logger. When we integrated QtQuick support in the lock screen we identified this potential threat and ensured that the look and feel package has no access to Internet.

In Plasma 5.10 we take this protection to a new level. For Plasma 5.10 the architecture got reworked for putting the lock screen into a sandbox. Our lock screen accepts the password and passes this to another executable called kcheckpass which verifies that the password is correct. Kcheckpass had been unchanged for years and there were several areas of bitrot. It supports two methods for communication – a binary and a “legacy”. I do not know since when the legacy mode is legacy but as long as I have been working on the lock screen it was around as legacy. As kscreenlocker_greet only interacts through the binary protocol the legacy mode got removed. Also kcheckpass supports various ways of authenticating a user. The default is PAM, but there is also checking /etc/shadow and /etc/passwd and some more obscure legacy technologies. We consulted our distributions which methods are actually used and as a result dropped support for everything except PAM and /etc/shadow – everybody uses PAM except Slackware. Due to issues in the past we also adjusted the building to enforce PAM unless a build option is set. Too often users had problems with unlocking the screen due to lock screen built without PAM support.

Back to the sandbox. With these changes kcheckpass got significantly smaller and easier to hack on. A prerequisite to change the interaction and make it possible to introduce a sandbox. The sandbox introduced in Plasma 5.10 is based on libseccomp and introducing this was a challenge. The idea was to enable it prior to loading any QtQuick code. But once seccomp is enabled, the kernel forbids gaining more privs for the process and any children. Thus kcheckpass would be broken. In the end kcheckpass must read a file which can only be read by root, it invokes a setuid root binary. With seccomp enabled this is bound to fail.

Thus the interaction for kcheckpass had to be changed. So far kcheckpass only supported asking for the password and the return code indicated whether the password was correct or wrong. In order to use seccomp we have to start kcheckpass prior to enabling seccomp. Kcheckpass needs to support several authentication attempts and return success through the binary protocol.

In Plasma 5.10 the new reworked architecture is now enabled together with seccomp. The technology seccomp allows to filter and restrict syscalls. Unfortunately a white list approach did not work at all, instead we use a black list approach to forbid some operations such as connecting to the Internet, opening files in write mode, creating files, etc. Thus we can be sure that the executed QtQuick is constrained. We added a bunch of unit tests which verify that our sandbox works as we envision. This means we also removed all possibilities to show advertisement on the lock screen. We think that the security of our users is more important than a financial profit. We won’t sell your security!

Seccomp is currently an optional dependency and can only be used on Linux. I informed our distributions about it and hope that many enable it by default. At least Neon and openSUSE informed me that it got enabled in the build. Distributions which use /etc/shadow based authentication instead of PAM are unfortunately not able to use this new security feature. I highly recommend those distributions to switch to PAM as it means a more secure lock screen and also means they run the same code path. At the moment we have one code path for one distribution and it means it is completely untested and in truth not maintained by us.

Of course no sandbox is perfect, so let’s talk about how to escape this sandbox: DBus. Our lock screen uses DBus for various legitimate tasks such as switching keyboard layout, showing music player information, etc. This allows a malicious look and feel package to escape the sandbox and perform actions which it should not be allowed to do. With seccomp we cannot protect against it, but apparmor could be used. Apparmor allows to restrict DBus access. Now the obvious question: why not use apparmor directly instead of seccomp. The answer is that it is two solutions to different problems. Seccomp allows us to restrict what the process is allowed to do. It does not require that the user runs apparmor. We restrict ourselves vs. we get restricted. I think that both is needed.

So for the future we will look into enabling an apparmor profile to restrict dbus access. But also in other areas introducing a sandbox would be very interesting. I would love to see KWin/Wayland using seccomp, but it is considerably more difficult than in the case of kscreenlocker. For example KWin starts kscreenlocker. If seccomp is enabled when KWin starts the lockscreen we once again are not able to check the password. So a more difficult task unfortunately.

As a final word: we have no indications that there has ever been a malicious look and feel package which eavesdrops the password. This change is a protection method prior to any harm happening.