I’m currently working on an embedded project based on Linux which involves a graphical user interface based on Qt.
In our case Qt accesses framebuffer as well as the LinuxInput devices directly – there is no further layer (DirectFB, Xorg, Wayland, etc.) in between.
In this quite common scenario I noticed that Qt is treating the LinuxInput devices in a quite counterintuitive way which may lead into severe security problems.
The embedded device we are using in this particular project has a keyboard which to the userland is exposed as LinuxInput device.
Everything worked quite well, however our Qt application crashed once due to a programming error (our fault) and I was shown the underlying UNIX console which reflected every single keystroke I did inside the Qt application – all typing input within the Qt application also got passed to other applications / underlying shells!
An exposed root shell to the active TTY – possibly hidden by the GUI – is therewith also capturing all input. Since almost all linux (embedded) distributions are exposing login prompts / shells to all TTYs by default, this scenario is far from being unlikely.
My expected behavior would have been: the Qt application is opening the LinuxInput devices exclusively, so that only the Qt application receives data from the input devices.
After some research and asking around I got pointed to the EVIOCGRAB IOCTL implemented in the LinuxInput subsystem.
As stated in $(LINUX_KERNEL)/include/input/linux.h:
@grab: input handle that currently has the device grabbed (via
EVIOCGRAB ioctl). When a handle grabs a device it becomes sole
recipient for all input events coming from the device
This means: When opening LinuxInput devices they’re not grabbed, they’re not opened exclusively by default.
Okay, I got it 🙂
So let’s just find the magic option / command which tells Qt to set up an EVIOCGRAB with an appropriate argument on the going-to-be-used LinuxInput device. Since I didn’t find any documentation I grep’ed through the Qt source:
> ~/src/qt.git$ git grep EVIOCGRAB
nothing… so I took a closer look into how Qt implemented support for LinuxInput devices (src/gui/embedded/qkbdlinuxinput_qws.cpp) – still nothing…
So I implemented support for telling Qt to open LinuxInput devices exclusively by optionally passing an ‘grab’-argument to the LinuxInput drivers inside Qt.
And here it is – a patch which adds support for passing another parameter named ‘grab’ to the LinuxInput device driver of Qt – to specify whether the device should be opened exclusively (grabbed) or not.
Conclusion: Take care when using Qt and its LinuxInput drivers – all input might be received and used by other applications as well – including shells running on TTYs.
UPDATE: The patch finally git committed and went upstream. Grabbing can now be configured since Qt version 4.8 (http://www.qt.gitorious.org/qt/qt/commit/947aaa79b05adec527c7500e36766c7ff19f118d/diffs)