Distribution management – how Upstream ensures Downstream keeps the Quality

I read Emmanuele Bassi’s very interesting blog post about software distribution this week and thought a lot about it. Emmanuele kind of answers to a presentation by Richard Brown (from OpenSUSE fame). While I haven’t seen that presentation, I saw a similar one last year at the openSUSE conference and also talked with Richard about the topic. So I dare to think that I understand Richard’s arguments and even agree with most of them.

Nevertheless I want to share some of my thoughts on the topic from the perspective of KWin maintainership. KWin is more part of the OS stack, so distributing through means like Flatpack are not a valid option IMHO. As KWin is close to the OS, we have a very well integration with distributions. Plasma (which KWin is part of) has dedicated packager groups in most distributions, we have a direct communication channel to the distros, we know our packagers in large parts in person, etc. etc. So from the open source distribution model we are in the best category. We are better positioned than let’s say a new game which needs to be distributed.

So this is the background of this blog post. What I’m now going to do is to describe some of the issues we hit just over the last year with distributing our software through distros. What I will show are many issues which would not have been possible if we distributed it ourselves without a distro in between (for the record: this includes KDE Neon!). To make it quite clear: I do not think that it would be a good idea for KWin to be distributed outside distributions. While thinking about this topic I came up with a phrase to what we are doing: “Distribution management”.

We do lot of work to ensure that distributions don’t destroy our software. We actually manage our distributions.

Latest example: QML runtime dependency

Aleix created a new function in extra-cmake-modules to specify the QML runtime dependencies. Once it was available I immediately went through KWin sources, extracted all QML modules we use and added it to CMake, so that it’s shown when running CMake. Reference: D7273

This is a huge issue in fact. Plasma 5.10 introduced support for virtual keyboard in the lock screen. We had to add special code for handling that this runtime dependency is missing. I sent a mail to our distributions mailing list to remind distros to package and ship this dependency.

Obviously: if we distributed the software by ourselves this would not have been an issue at all. We would just bundle Qt Virtual Keyboard and be done. But as we are distributed through distributions we had to write special handling code for the case it’s missing and send out mails to remind distros to package it.

Incorrect dependencies – too many

Although we specify all required dependencies though CMake our distributions might add random other dependencies. For example KWin on Debian depended on QtWayland (both client and server), although KWin does not need the one or the other. This got fixed after I reported it.

This is of course a huge problem. A common saying about KDE is that it has too many dependencies and that you cannot install software on e.g. GNOME, because it pulls in everything and the kitchen sink. That’s of course true if distros add incorrect additional package dependencies.

Incorrect dependencies – too few

Of course the other side is also possible. One can have too few dependencies. Again the example is Debian, which did not make KWin depend on Breeze resulting in incorrect window decoration being set. That we depend on it at compile time is also following the “distribution management” as distros asked us to add all dependencies through CMake. So we did and made KWin optionally depend on Breeze. Of course such distribution management does not help if distributions don’t check the CMake output.

Also here if we distributed ourselves we would have compiled with all dependencies.

Outdated dependencies

Another very common problem is that distributions do not have the dependencies which we need and want to use. In case of KWin this especially became a problem during the Wayland port. For a very long time we had to keep Wayland compile time optional so that distributions like Slackware [1] could continue to compile KWin. When we turned it into a hard dependency we had to inform distros about it and check with them whether it’s working. Of course just because you inform distros does not mean that it will work out later on.

That we have distros with outdated dependencies is always a sore pain. Our users are never running the software which we are, never getting the same testing. We have to keep workarounds for outdated dependencies (e.g. KWin has a workaround for an XWayland issue fixed in 1.19) and that of course results in many, many bug reports we have to handle where we have to tell the users that their software is just too old.

Also we face opposition when trying to increase dependencies, resulting in distros consider dropping the software or to revert the changes.

Handling upgrades

Another reoccurring issue is handling updates. Our users are constantly running outdated software and not getting the bug fixes. E.g. Ubuntu 16.04 (LTS) ships with KWin 5.5. We currently support KWin 5.8 and 5.10. We constantly get bug reports for such old software and that’s just because it’s outdated in the distribution. Such bug reports only cause work for us and are a frustrating experience for the users. Because the only feedback they get is: “no longer maintained, please update to a current version”. Which is of course not true, because the distro does not even allow the user to upgrade.

Even when upgrading it’s a problem. We have to inform distros about how to handle the upgrade, of course that does not help, it fails nevertheless. We also never know what are allowed upgrade paths. For us it’s simple: 5.8 upgraded to 5.9, upgraded to 5.10, etc. If we would ship upgrades ourselves we could ensure that. But distros might go from 5.8 to 5.10 without upgrade to 5.9 ever. So we need to handle such situations. This was extremely challenging for me with a lock screen change in Plasma 5.10 to ensure the upgrade works correctly.

Random distro failure

An older example from Debian: during the gcc-5 transition KWin got broken and started to crash on startup without any chance to recover. This issue would of course not happen if we would have distributed KWin ourselves with all dependencies.

The experience was rather bad as users (rightfully) complained about the brokeness of KDE. I had friends asking me in person how it could be that we ship such broken software. Of course we were innocent and this was only in the distro. But still we (KDE) get the full blame for the breakage caused by the distro.

Useless bug reports

Thanks to distributions all crash reports we get are useless. The debug packages are missing and that’s pointless. Even if debug packages are installed mostly the crash point is missing. This is especially a problem with Arch as they don’t provide debug packages. In 2017 KWin got 71 bug reports which are marked as NEEDSINFO/BACKTRACE as the reported bug is pointless.

Misinformed maintainers

I don’t know how often I got asked this: should we change Qt to be compiled against OpenGL ES? Every time I was close to a heart attack as this would break all Qt applications for all NVIDIA users (at least a few years ago there was no GLES support in the NVIDIA driver). Luckily in most cases the maintainers asked (why me and not Qt?), but I remember one case where they did not ask and just rolled it out. With the expected result.

Thoughts

I could go on with examples for quite some time. But I think it should be obvious what I want to show: even for well integrated software such as KWin the distributions are not able to package and deliver correctly. As an upstream developer one has to spend quite some time on managing the distributions, so that the software is delivered in an acceptable state to the users.

Distros always claim that they provide a level of quality. Looking at the examples above I have to wonder where it is (granted there are positive exceptions like openSUSE). Distros claim they do a licensing check. That’s useful and very much needed, but is it required that openSUSE, Debian and Arch do the same check? Furthermore I personally doubt that distros can do more than a superficial check, they would never find a case where one copies code which is license incompatible.

Given the experience I have made with distros over the last decade working on KWin I am not surprised that projects are looking for better ways to distribute software. Ways where they can control the software distribution and ensure it works. Ways where their software is not degraded due to distros doing mistakes.

All that said, I do agree with Richard in most points, just don’t think it works. If everybody would use openSUSE than Richard would be right with almost all points. But the reality is that we have a bazillion of distributions doing the same work and repeating the same mistakes. Due to that I think that for software distribution Flatpack & Co. are a very valid approach to improve the overall user experience.

[1] Slackware for a long time did not have Wayland as that would need Weston and Weston depends on PAM which is only the optional fallback for no logind support, which Slackware of course does not have

KWin requires C++14

This is a short public service announcement: KWin master as of today requires a compiler which supports C++14. This means at least gcc 5 or clang 3.4. All major distributions support at least one of the two.

Plasma Wayland and Qt 5.9 and beyond

As you might know Qt 5.8 created challenging problems for our Wayland session and threw our efforts back quite a bit. In this post I want to discuss the actual problems it created, how we are addressing them and looking into the future.

How our integration used to work

Our integration uses additional Wayland protocols. We have a protocol for server side window decorations which we use in our Plasma integration plugin to inform KWin whether the window should have a decoration or not. We have a protocol for client provided shadows which is e.g. used by our widget style Breeze to add shadows to the context menus. We have a protocol for the desktop shell, so that it can mark windows as desktop, panel, auto hiding panel, position the window, etc. Also we have a few protocols for interacting with our effect system, e.g. sliding popups, blur behind.

To use these protocols we need to interact with Qt in a low level way. We use the native interface in the Qt Platform Abstraction to get a wl_surface pointer for the QWindow. In order to not have to keep this simple for our applications our KWayland::Client API provides an API point for it: Surface::fromWindow(QWindow*) -> Surface*.

But when exactly to inject our own integration? We found a very handy way which worked much better than what we had used in the past for X11 (and based on that also transitioned X11 code to use it). Qt emits an event once it has created the native platform surface (in case of Wayland the wl_surface*) for a QWindow. Verbatim quote of the documentation:

The QPlatformSurfaceEvent class is used to notify about native platform surface events.

Platform window events are synchronously sent to windows and offscreen surfaces when their underlying native surfaces are created or are about to be destroyed.

Applications can respond to these events to know when the underlying platform surface exists.

Awesome! We get an event when the surface is created and when it gets destroyed. This made it very simple to create the integration and what is really important for us is that we get this event before the window is shown. So we can prepare everything so that KWin gets a good state.

And the KWin side was to a large part implemented on assumptions on how the sequence will work. We first get the surface, then the (xdg) shell surface, then the integration bits. Sure it would be nice if KWin handled also other sequences, but as the only implementation of this is Qt it doesn’t make sense to really care about it. We know that it was not perfect, we even had the test cases for it, which expect failed.

What broke with Qt 5.8?

In Qt 5.8 our complete integration broke. When the platform surface created event was emitted the wl_surface was not created, see QTBUG 58423. This is in my humble opinion a clear violation of the documented behavior and thus a breakage of the stability guarantees Qt provides, but others might disagree. After some discussion, trying out patches by those who had a Qt 5.8 build we had a patch for Qt which made things mostly work together with a patch to KWin. But at the time we had the patch ready Qt 5.8 was already declared end of life with no prospect of a Qt 5.8.1 bug fix release. For our Wayland session it was just impossible to get Qt 5.8 compatible again. All we could do was to advise distributions to not combine Qt 5.8 with the Wayland session. From our side it was fine for distros to ship Qt 5.8, but if they do they should make it impossible to install the Wayland session. The state was just too broken.

Qt 5.9

With Qt 5.9 the situation looks better. The required patch is merged, it’s an LTS release and we already had the first bug fix release. Qt wants to create more bug fix releases for it and this allows us to use it as a new target for integration. But still the situation is not as good as it used to be. If you currently use our Wayland session with Qt 5.9 you will still see quite some rough corners compared to where we were with Qt 5.7.

The main problem for us is that the platform surface regression was not the only change affecting us. Pre Qt 5.7 a wl_surface lived as long as a QWindow. Now the wl_surface gets destroyed whenever the window gets hidden and a new one created on every show. Unfortunately without a platform surface created event. This means our integration breaks as soon as a window gets hidden. E.g. after closing KRunner the integration for KRunner is broken.

We tried to address this problem in various places, but it is challenging. On the show event we don’t have the wl_surface yet (too early), on the expose event the window is already mapped (too late). This creates problems for KWin which is not prepared for the integration bits to hit when the window is mapped. Our protocols were designed with the platform surface created event semantics. For example in KRunner we face an issue with the integration. KRunner is a panel, which accepts focus and allows windows to go below, also it positions manually. Now when it gets re-shown KWin doesn’t know that this window is supposed to position itself and positions it. Now we get the request to put it as panel, KWin adjusts and moves maximized windows around. And then we get the request that the panel allows windows to go below. KWin shuffles the windows again as the maximized area changed again.

This is a rather tricky situation as we cannot really do something about it. If the window is mapped it’s too late. Even if we improve our API to handle the situation better it will be too late.

There are two possibilities to handle this: Qt stops to destroy the surface or sends a platform surface created event when it recreates the surface. The latter would be my personally preferred solution as this would match the documentation again and allow us to just use the one event handler.

Other regression

The situation around the changed behavior in Qt 5.8 caused a few steps back. Our code needed to be adjusted and that sometimes caused issues. We had a few regressions which also affected the compositor, so the stability of the whole system suffered. These issues are luckily investigated and fixed. But there are still bugs lurking in the system.

For me personally the most annoying bug is a crash in Qt which affects the auto completion of kdevelop. This makes hacking in a Wayland session rather difficult. I’m running currently a patched KWin which disables the virtual keyboard integration to not hit this issue.

A huge problem is that context menus are not marked as transient windows. This means that the Wayland compositor does not know that it is a menu and positions the menu anywhere on the screen. It gives the system a very unfinished touch.

If KRunner is closed through the escape key, the key starts to repeat on the window constantly and due to that it is not possible to open KRunner again. Similar if you start an application in Kickoff through the enter key, when opening Kickoff again it automatically launches the currently selected item. This again makes it very difficult to use the session and gives the whole system an unfinished look. We are working on a workaround for this issue in the server.

Towards the future

Qt 5.9 is here to stay and that’s what we have to use as integration target. Given that Qt 5.9 and Qt 5.7 behave very differently it will become difficult for us to maintain support for both. My suggestion is that we drop support for Qt 5.7 and require Qt 5.9 for the Wayland session. In addition there is hope that we can improve the integration. Marco and David have been working on adding support for XDG Shell unstable v6 which is already supported by Qt and makes it easier to integrate with. Once this landed in KWin Qt will be switched from wl_shell to xdg shell. This will improve the situation for us quite a bit as we then have one code path for both Qt and GTK applications.

How to prevent such regressions in the future

The change of behavior in Qt 5.8 threw our Wayland efforts back a few months. This is something we communicated to Qt quite early and it’s something which worries me a lot. We cannot spend time on changing our integration every time Qt releases a new version. Given that we need to look into how to prevent that such a situation happens again.

I hope that we can improve the integration on the testing front between Qt and KDE. We have a huge test suite which can find regressions in Qt. If Qt would run KDE’s tests during the integration phase Qt would notice regressions before they hit the code base. Given that all our tests are free software it should be possible for Qt to integrate them.

But also the other side would be interesting: if we could get the latest Qt into our CI system we could also discover breakages early. We have now a new docker based CI system which allows running multiple builds of the same change (e.g. Plasma gets build on openSUSE tumbleweed and on FreeBSD) – an image with a daily or weekly Qt snapshot could help us and Qt a lot to detect breakages early.

I also hope in openQA which allows to test the full operating system. This would spot regressions like the misplaced context menus even if KWin’s own auto tests would not spot them (KWin doesn’t care about Qt there, only about the Wayland and X11 protocols). There we might need to invest some work to make sure that KWin/Wayland can be properly run in the openQA tests.

I hope that our Plasma devs can discuss this in more detail with Qt devs during Akademy in person. Unfortunately I cannot be at Akademy this year 🙁 so I cannot discuss in person.

Last but not least it is important that developers test. It would help a lot if the developers working on QtWayland test their changes in a running Plasma Wayland session. We are now overall in a state that the session is suited for hacking on. I do all my Wayland hacking in a Wayland session, experiencing all the glitches like kdevelop crashing.

Of course you might wonder what about us? Shouldn’t we KDE devs also test against the latest Qt? For me personally that is not the case. I’m working on the server side and not on the client side. I’m also not testing the latest GTK for example. Nevertheless I tried to use Qt 5.9 before it got released. Used the installer, spent a day to compile everything on top of it it, just to notice that it doesn’t have QtWayland and won’t get it. I didn’t give up that easily. So I tried to compile QtWayland myself. But when I tried to use it, it turned out to not have any keyboard support, because qtbase was compiled without support for xbkcommon. At that point I gave up. Not having QtWayland is one thing, but not being able to use keyboard is another, it’s rather pointless. The only other option is to compile Qt, but that is hardly an option as it’s really difficult to compile an actually working Qt with all components. The last times I tried, I failed, wasting days compiling. If there were usable weekly images for Qt I would be happy to try it, but of course only with a properly compiled and included QtWayland.

Running KWin’s auto test suite

KDE’s sysadmins set up a new CI system and over the last weeks I have been helping in getting the yellow dots blue again. As I think it’s quite useful I decided to write a blog post on how to setup the test environment for KWin.

For setting up a test suite of KWin one also needs to consider the most important dependencies. In case of KWin these are KWindowSystem, which provides a library for building an X11 window manager, and KWayland, which provides a library for building a Wayland compositor. Given that, let’s start with those.

Testing KWindowSystem

KWindowSystem is a platform independent library to provide access to windowing system functionality. For the X11 part it has an implementation for the NetWM specification and that’s what is important for KWin. The NetWM implementation has a window manager mode which KWin uses. So all the “what’s the window title”, “is the window maximized”, “minimize the window” is implemented in KWindowSystem and KWin only calls into this functionality.

For frameworks 5 this code got reimplemented using xcb and at the same time gained a nice test suite. According to the latest build the X11 implementation of KWindowSystem has a line coverage of 68 % with the NetWM implementation even having 83 %. Testing this piece of code is not trivial, classic unit testing with mocking is not really an option (I don’t care whether my code is correct with the mock object if the one and only X server behaves differently) so the tests are from a definition point of view integration tests.

We have in KWindowSystem two kind of tests: some which need a running window server and X server and some which don’t. The recommendation is to run the tests with Xvfb and openbox as the window manager on Xvfb. This might be surprising given that our aim is to test KWin, so why openbox? KWindowSystem is a dependency of KWin. When you test KWindowSystem you normally don’t have KWin yet, so another window manager needs to be used. Btw. our test suite found bugs in openbox 😉

The tests which don’t need a window manager as they test the window manager functionality start their own Xvfb from within the test to have a clean setup.

The framework has also a small Wayland part and we have a test which starts weston. So overall to test KWindowSystem you need:

  • Xvfb
  • openbox
  • Weston

Testing KWayland

KWayland is our young framework which implements a Qt style wrapper around the Wayland server and client API. It has been implemented in a test-driven manner from the start. The line coverage is around 90 % and to a large degree the client side only exists to be able to properly test the server side.

Testing KWayland thus does not require lots of effort, most tests don’t need any environment. There is one test which needs Weston (fullscreen shell, the only interface we only have in the client, but not in the server library) and one which starts a test with a QtWayland powered Qt application. So one needs

  • Weston
  • QtWayland QPA

Testing KWin

Now the real challenge: KWin. We still don’t have KWin blue, one test is waiting for newer software in the base image. KWin uses a combination of unit tests, integration tests and full system tests with deep introspection. The last part is where most code gets tested and your bugs normally get fixed by writing a new test, see for example latest bug fix.

KWin uses for the unit and integration tests the Xvfb+Openbox variant just like KWindowSystem. If you run the test locally: remember to start Xvfb and don’t run them on your actual X server, they will fail. We have tests which assume the default DPI of Xvfb and on your high resolution display they will fail. You can spend quite some time investigating why they fail if you forget that. Also remember to set QT_QPA_PLATFORM=xcb when running the test suite if you are on Wayland. Your tests will fail if not and you will spend quite some time investigating why they fail.

There is one test which needs yet another Xserver: Xephyr. It’s a test to verify the screen setup.

The most requirements have the system tests. The system tests (in KWin code called “integration” tests) start a full KWin on KWin’s virtual framebuffer platform. As it’s a full KWin it will behave like KWin to the outside world. It registers on DBus, it tries to get kglobalaccel, it locks the screen, etc. It is important to separate the execution. If you use ctest each test is run in an own dedicated dbus session. If you invoke the tests manually, please remember to first run export $(dbus-launch). If not your global shortcuts of the KWin session are gone.

Of course the tests bring in yet another X server: Xwayland. Like KWin itself it needs Xwayland. So the list of X servers to test KWin is now: Xvfb, Xephyr and Xwayland.

The next requirement is breeze. Please compile KWin with breeze support. Otherwise KWin will have to use Aurorae and that uses QtQuick and might fail on the virtual framebuffer. That brings us to OpenGL. Our old CI system couldn’t do OpenGL and now our new system is finally able to execute the OpenGL tests. For this you need to compile KWin with gbm support and the system you are executing the test should either have a render node or the drm/vgem device. If the system does not have a /dev/dri/card0 the test is skipped. If you use a vgem device please make sure to give the user running the test the right to read/write the dev node. Unlike “normal” drm/gbm plugin KWin does not use logind to open the drm device in the virtual environment.

KWin also starts some external applications during the tests. If we find an application which e.g. crashes KWin it’s best to integrate it in the test suite. Due to that the test suite runtime depends on glxgears (yes we had a crash when closing glxgears). Like KWayland KWin also tests Qt and thus needs QtWayland and the xcb platform (one test starts an application once under Wayland and once under X11).

And the most interesting dependency is the DMZ-White cursor theme. We have tests verifying that the cursor handling works correctly and needed a good theme which has the sizes we want to test and the cursors we want to test.

So overall we have:

  • Run tests in own dedicated Dbus session
  • export QT_QPA_PLATFORM=xcb
  • run Xvfb with openbox
  • Xephyr
  • Xwayland
  • Weston
  • glxgears
  • Qt Wayland
  • Qt XCB platform
  • gbm as compile time dependency
  • breeze as compile time dependency
  • vgem drm device
  • DMZ-White cursor theme

And I’m sure the list is going to grow as we create more tests. I’m especially looking forward to test our OpenGL renderer. Now that we have support on the CI system for it, this becomes really interesting.

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.

How input works – touch screen edge swipe gestures

Continuing my series about how input works in KWin/Wayland I want to discuss a brand new feature we implemented for Plasma 5.10. This year we had a developer sprint in Stuttgart and discussed what kind of touchpad and touch screen gestures we want to support and how to implement it. Now the result of this discussion got merged into our master branch and we are currently discussing which actions to use by default.

Gesture Recognizer

Touchpad and touch screen gestures are kind of similar so the approach we took is able to handle both of them. We introduced a GestureRecognizer which is able to recognize gestures (surprise) in a very abstract way. It doesn’t know how the input events look like, whether a touch screen, touchpad, mouse or whatever input device generated the event.

To use the GestureRecognizer a Gesture needs to be registered. The Gesture describes the actual Gesture which needs to be recognized. E.g. how many fingers need to participate in the gesture (for our touch screen gestures it is one, for our touchpad gestures it is four), the direction of the gesture (leftwards, rightwards, downwards, upwards), the minimum distance, the trigger position, etc. etc.

Now input events can be fed into the GestureRecognizer and the GestureRecognizer decides whether a Gesture is active or becomes non-active. As said this is absolutely generic, it doesn’t care how the events are triggered.

This alone does not yet allow to do anything with it, we don’t have any way to use the GestureRecognizer yet.
At this point our implementations for touchpad and touch screen divide. We have different existing implementations which are more suited than trying to have something shared for both.

Touchpad gestures

For touchpad gestures our global shortcuts handling is used. GlobalShortcutsManager is a KWin internal (!) mechanism to register some internal actions to tigger in a global way through input events. The GlobalShortcutsManager gained a GestureRecognizer and various areas in KWin can now register a QAction as a global touchpad gesture.

So far we still haven’t reached the elements we discussed in the previous posts like InputEventFilter. There is of course an InputEventFilter which feeds events into the GlobalShortcutsManager. This filter got extended to support touchpad gestures and now we have the full stack together:

  • libinput reports a touchpad gesture event
  • InputEventFilter passes the touchpad gesture event to the GlobalShortcutsManager
  • The GlobalShortcutsManager passes the information to the GestureRecognizer
  • The GestureRecognizer triggers the QAction
  • something happens

By default the following gestures are supported:

  • 4 finger swipe down: Present Windows
  • 4 finger swipe up: Desktop Grid
  • 4 finger swipe left/right: desktop next/previous

Screen edge support for touch

For touch screen gestures we used a different area in KWin which already provides a fairly similar functionality: Screen edge activation for mouse events.

It’s similar in the way that it activates an action when an input event happens at a screen edge. The main difference is the direction of the input event: for mouse it’s towards the edge, for touch it is from the edge.

The ScreenEdges gained a GestureRecognizer (you see there are two different, independently acting GestureRecognizers) and every Edge defines a Gesture. The Gesture is only passed to the GestureRecognizer if the Edge is reserved for a touch action. Each Edge can have a different action configured and of course you can configure different (or same) action for touch and mouse on the same Edge. When a Gesture for an Edge gets started we provide the same visual feedback as for the edges started through mouse events.

For ScreenEdges there is also a dedicated InputEventFilter which now gained support for touch events and feeds the touch events into the GestureRecognizer.

But there is more to it. This feature got backported to X11. Our X11-standalone platform plugin gained support for XInput 2.2 and touch events. KWin now listens for touch events on X11 and passes these events into the GestureRecognizer of the ScreenEdges. Thus the feature which we implemented on Wayland for Wayland is also available on X11 and directly usable for all users – be it on X11 or on Wayland.

Touchpad gestures are unfortunately only available on Wayland.

A typical day in bugs.kde.org

Me:

I’m sorry that $feature behaves differently to how you expect it. But it’s the way it is and that’s by design. The feature work exactly as it’s supposed to work. I’m sorry, this won’t be changed.

User:

With decisions like that, no wonder KDE is still a broken mess.

I wonder why the hell I even bother reporting issues. Bugs are by design these days.

Never again.

Have a nice life.

Virtual Keyboard on Lock Screen

As part of our efforts to improve out of box experience for touch screens I’m pleased to announce that Plasma 5.10 will provide integration for virtual keyboard.

Plasma 5.10 finally integrates qtvirtualkeyboard directly in the lockscreen component of the look and feel package. Support for Qt’s virtual keyboard is not new in Plasma in general, it is already fully integrated into the Plasma Wayland session. This change, though, can be used on both Wayland and X11.

Greeter with new Virtual Keyboard button

The lockscreen got extended by a new button next to the keyboard layout switcher: “Virtual Keyboard”. When clicking this button the virtual keyboard gets enabled and one can use it (with both touch and mouse) to enter the password and unlock the screen.

Virtual Keyboard in the lock screen

As a nice side effect this finally enables the possibility to enter east Asian languages in the lock screen. So far we had to actively disable input methods on the lockscreen to prevent that the screen cannot be unlocked. As a side effect this meant that only latin characters can be used in the password. I hope that the new virtual keyboard can help here by providing a better experience.

As a note to our touch screen users. It’s possible to use Qt’s virtual keyboard for all Qt application. One just needs to specify the env variable QT_IM_MODULE=qtvirtualkeyboard. When entering text Qt pops up the virtual keyboard as an additional window. This is only needed in an X11 session. In a Wayland session KWin provides the integration and Qt apps (and other apps) get the virtual keyboard through the Wayland text input protocol.

Editing files as root

For years I have told people to not start Kate as root to edit files. The normal response I got was “but I have to edit this file”. The problem with starting GUI applications as root is that X11 is extremely insecure and it’s considerable easy for another application to attack this.

An application like Kate depends on libraries such as Qt. Qt itself disallows running as an setuid-app:

Qt is not an appropriate solution for setuid programs due to its large attack surface.

If Qt is not an appropriate solution for command line arguments running as root, it’s also not an appropriate solution for running GUI applications. And Qt is just one of the dependencies of graphical applications. There is obviously also xcb, Xlib, OpenGL, xkbcommon, etc. etc.

So how can another application attack an application running as root? A year ago I implemented a simple proof of concept attack against Dolphin. The attack is waiting for dolphin getting started as root. As soon as it starts, it uses the XTest extension to fake input, enable the embedded konsole window and type into it.

This is just one example. The elephant in the room is string handling, though. Every X11 window has many window properties and every process can write to it. We just have to accept that string handling is complex and can easily trigger a crash.

Luckily there is no need for editing a file to run the editor as root. There is a neat tool called sudoedit. That does the magic of starting the editor as the user and takes care of storing the file as root when you save.

Today I pushed a change for Kate and KWrite which does no longer allow to be run as root. Instead it educates the user about how to do the same with sudoedit.

Now I understand that this will break the workflow for some users. But with a minor adjustment to your workflow you get the same. In fact it will be better, because the Kate you start is able to pick up your configured styling. And it will also work on Wayland. And most importantly it will be secure.

I am also aware that if you run an application which is malicious you are already owned. I think that we should protect nevertheless.

How input works – touch input

Last year I started a blog post series about how input works in KWin/Wayland. This blog post resumes this series by talking about touch input.

Several people wondered why it took so long for this blog post. After all it’s more than a month since the last one. Of course there is a good reason for it. I was reworking parts of the input stack and wanted to discuss the changes with the next post of the input blog post series. Unfortunately there are still a few changes missing, so I decided to nevertheless do the touch input post first.

Touch input is the new kid in the block concerning input events. It’s a technology which was created after X11 got created and thus it is not part of the X11 core protocol. On X11 this makes touch a weird beast. E.g. there is always an emulation to a pointer event. Applications which do not support touch can still be used as the touch events generate pointer events. Now this is actually a huge sacrifice for the API and means that touch feels – at least to me – as a second class citizen in X11.

On Wayland the situation is way better. Touch is part of the core input protocol and does not emulate pointer events. Applications need to support touch in order to get touch events. If an application does not support touch, the touch events won’t trigger any actions. This is a good thing as it means applications need to do something sensible with touch events.

Like with the other events touch events are reported to KWin by libinput. Touch events are quite straight forward. We get touch down events (when a finger touches the screen), touch up events (when a finger gets lifted again) and touch motion events (when the finger moves on a screen). This is fully multi-touch aware, meaning we can follow multiple touch points individually.

The events are sent through KWin’s internal filter architecture like all other events. Currently KWin does not really intercept events yet. We do support touch events on window decoration and KWin’s own internal windows. But in those cases we emulate mouse events. We don’t have any UI elements which would benefit from multi touch events, thus emulating mouse events internally is sufficient for the time being. If in future we add multi touch aware UI elements that would require changes.

In case KWin does not intercept the touch sequence the events are passed on to the KWayland Server component which forwards the events to the Wayland window which is currently receiving touch events. KWin determines the window by using the window at the first touch down of the sequence. While a sequence is in progress the window cannot change.

The touch events are then processed by the application and can provide sensible functionality. E.g. our Plasma calendar supports a pinch-zoom gesture to switch to an overview of all months. This was developed under X11 and just works on Wayland without any adjustments. Good job, Qt devs!

Last week at the Plasma sprint touch gestures were an important discussion point during the last days. We decided which global gestures we want to support in Plasma. We hope to be able to deliver this for Plasma 5.10 on Wayland and will also look to get the same on X11 by reusing the architecture written for Wayland. But this might land in a later release.

Global touch gestures have an interesting and useful feature. When a sequence starts KWin does not know whether that will be a global gesture or a gesture which needs to be forwarded to the applications. Thus all events must be sent to the applications. Once KWin knows that this is a global gesture it can send a cancel event to the application. This informs the application that the touch sequence got canceled. This prevents conflicts between the global and application touch gestures. On X11 this is not so comfortable, so we will have to see how we can support this.