A new release of bolt is out: 0.9.1 - Unstable icy waters. This is a bug-fix release that addresses some issue on integrated Thunderbolt controller.

Intel's Ice Lake is the first architecture where the Thunderbolt controller is part of the CPU die. This is quite a big difference. There is a good article on wikichip called "A Look At The Ice Lake Thunderbolt 3 Integration" for those that are curious about the technical details. What matters for bolt is that there is no DROM, which means that the udev device representing the host switch does not have the usual name and id attributes for the device and vendor. Additionally, the unique_id attribute has a different UUID every boot. This breaks one of the fundamental assumptions for boltd, which used the unique_id of the host to uniquely identify the corresponding Thunderbolt domain. This is important because we store host devices and domains in the store. Now, with the uuid changing this means that 1) we can not match the previously stored domains and hosts to the ones after a reboot and thus will accumulate "stale" domains in the store. Ironically, the fact that the host device also does not have any name and id information means that boltd would refuse to create the BoltDevice for those which meant we did at least not accumulate the stale host devices in the store. It did break the detection of the generation, i.e. if it is Thunderbolt 3 or USB 4.

To address all these issues, a couple of changes were made to boltd: 1) The PCI id of the native host interface (NHI) is used to detect if we are dealing with an integrated Thunderbolt controller and if so, neither the domain nor the host is stored. 2) If the host udev device does not have name or id information, the SMBIOS/DMI info that is exposed via sysfs is used transparently. 3) The bolt store is now versioned and thus can be upgraded. If no version info is detected, it means the store has version 0 and will be upgraded to 1. On that update, the store is scanned and all stored domains that are currently not online are removed, thus removing the stale domains.

The release already is in Fedora rawhide (aka F34, bodhi) and should also hit the stable releases (F33, F32) soon. It is updated on Arch already, thanks Jaro! Testing would be very welcome. I also encourage all other distributions to upgrade to it.

As readers of this blog might remember, there is a mode where the firmware (BIOS) is responsible for powering the Thunderbolt controller. This means that if no device is connected to the USB type C port the controller will be physically powered down. The obvious upside is battery savings. The downside is that, for a system in that state, we cannot tell if it has a Thunderbolt controller, nor determine any of its properties, like firmware version. Luckily, there is an interface to tell the firmware (BIOS) to "force-power" the controller. The interface is a write only sysfs attribute. The writes are not reference counted, i.e. two separate commands to enable the force-power state followed by a single disable, will indeed disable the controller. For some time boltd and the firmware update daemon both directly poked that interface. This lead to some interference, leading in turn to strange timing bugs. The canonical example goes like this: fwupd force-powers the controller, uevents will be triggered and Thunderbolt entries appear in sysfs. The boltd daemon will be started via udev+systemd activation. The daemon initializes itself and starts enumerating and probing the Thunderbolt controller. Meanwhile fwupd is done with its thing and cuts the power to the controller. That makes boltd and the controller sad because they were still in the middle of getting to know each other.

boltctl force-power

boltctl power -q can be used to inspect the current force power settings

To fix this issue, boltd gained a force-power D-Bus API and fwupd in turn gained support for using that new API. No more fighting over the force-power sysfs interface. So far so good. But an unintended side-effect of that change was that now bolt was always being started, indirectly by fwupd via D-Bus activation, even if there was no Thunderbolt controller in the system to begin with. Since the daemon currently does not exit even if there is no Thunderbolt hardware1, you have a system-daemon running, but not doing anything useful. This understandably made some people unhappy (rhbz#1650881, lp#1801796). I recently made a small change to the fwupd, which should do away with this issue: before making a call to boltd, fwupd now itself checks if the force-power facility is present. If not, don't bother asking boltd and starting it in the process. The change is included in fwupd 1.3.3. Now both machine and people should be happy, I hope.

Footnotes:

  1. That is a complicated story that needs new systemd features. See #92 for the interesting technical details.

Christian Schaller wrote an excellent blog post highlighting a lot of the cool new features and improvements that ship with Fedora 31. I wanted to add to that and give an overview of new things and improvements we did for GameMode that will be in Fedora 31. First of all a quick refresher about GameMode:

GameMode is a solution to optimize performance of a GNU/Linux system for gaming. This is to improve frames-per-seconds as well as make games run smoother, i.e. avoid stuttering. Performance optimization is done by applying various global and per-game tweaks: setting the CPU governor, adjusting the I/O priority, changing the niceness of the game and setting a different kernel scheduler (SCHED_ISO). It recently gained support for setting GPU performance modes (NVIDIA and AMD) and GPU overclocking (NVIDIA). Additionally it will inhibit the screensaver and can execute custom scripts on start and end.

There were two main issues that I focused on: First it was hard to tell if GameMode was currently active and what games/programs were requesting it. The second one was to make GameMode compatible with flatpaks. Both required changes to the GameMode daemon and the API. Upstream was very quick to review and merge all the required patches and roll a release (1.4), thanks a bunch of that.

Visibility and Integration

The whole point of GameMode is to increase the performance of the system in order to have a better gaming experience. This will (almost certainty) come with increased power draw, which is not great for computers attached to the mains but can be very annoying when running on battery. In any way it would be great to have a better idea if GameMode is currently active or not. In Fedora 30 and below this was very hard without dropping to the command line and running something like systemctl status --user gamemoded. Two improvements should make the situation better:

Shell extension

The first one is a smallish Shell extension (source) that will indicate via a status icon if GameMode is currently active or not. Additionally it will display notifications every time the GameMode status changes (this can be disabled). We needed to additional D-Bus API to the daemon for this, most notably a ClientCount property (PR#129) that the extension is watching and reacting to, so it needs GameMode 1.4 to work properly.

GameMode Shell Extension - displays a notification and shows a status icon.

GameMode Shell Extension - displays a notification and shows a status icon.

Usage integration

The other improvement to visibility, that turned out to be a bit more tricky, is indicating in Usage which process is requesting GameMode. This needed another set of additional D-Bus API endpoints (PR#155, PR#161) to expose all the currently active GameMode clients on the bus. With this, the initial support in Usage was quite straight forward (PR#60) and was basically done by maintaining a list of active GameMode clients and then matching those to Usage process entries.

Usage showing a little game icon for active clients

But it turns out that Usage didn't support flatpaks properly and one of the main ways to play games is Steam, which is best used as a flatpak. After quite a bit of internal refactoring that is now also done (PR#63). Speaking of flatpak, this was the other big area that I worked on:

Flatpak Support

Games (or in general clients) are requesting GameMode via a simple D-Bus call RegisterGame(int pid) which as the sole argument has the process identifier (pid) of the process, where it naturally is expected to pass its own pid. Processes can easily discover their own pid via getpid(2). The GameMode client library that games can use for easy integration with GameMode will do exactly that, i.e. effectively calling RegisterGame(getpid()). Flatpak, being Linux application sandboxing and distribution framework, uses a pid namespaces to isolate the process ids in the flatpak from the host. That means that a process will effectively have (at least) two process ids. The one inside the flatpak and the one outside, on the host; and it itself can only see the process id inside the flatpak. That is the whole idea about isolation and sandboxing. Now if the game requests gamemode to be activated via RegisterGame(getpid()), getpid() will give it the process id from the container and the GameMode daemon will be totally confused because the same number on the host will probably not exist or refer to a different process (probably owned by a different user). This prevented e.g. the Steam flatpak to ship with GameMode support (#77).

Flatpak portal

To solve this issue, we created a new flatpak portal. Instead of talking to GameMode directly, games inside a flatpak should talk to the flatpak portal and the portal will translate the process id from the one inside the flatpak container to the one on the host. The actual translation part was actually not straight forward and deserves a future blog post, but for the curious reader I recommend reading the discussion on the pull-request (#314). We patched the upstream GameMode client library to automatically detect that it is inside a flatpak and transparently use the portal (PR #146) and the daemon to find the executable for programs inside the flatpak (PR#136).

Small application to test GameMode

GameMode Tester

While working on the flatpak integration I needed something to quickly test various aspects of the integration, the client libs and the GameMode API all inside and outside of a flatpak. For this I created a small application, GameMode Tester, which someone besides me might find useful.

Summary

Fedora started shipping GameMode with version 28, with version 30 it is included in the workstation standard install. Fedora 31 will ship with all the necessary bits and pieces: GameMode version 1.4, the Shell extension has been packaged (dnf install gnome-shell-extension-gamemode) and a Usage with GameMode integration. Happy gaming, everyone!

A new release of bolt is out: 0.8 - I owe it to the MM U!. It contains a big new feature, which is suppport for IOMMU, a new bolt config command and a bolt-mock script to interactively test boltd and components that interact with it. And of course the usual bugfixes and improvements.

IOMMU support

I already wrote about the general idea when the Thunderclap paper was published. But to quickly refresh everyone's memory: Thunderbolt, via PCIe, can directly access the main memory (DMA). This opens the door to attacks, the recent Thunderclap attack is a prominent example and demonstration of such an attack. To mitigate DMA attacks, security levels were introduced with Thunderbolt version 3. These new security levels require devices to be authorized before they can be used. On newer hardware and recent kernel versions, another mitigation scheme was introduced that facilitates the input–output memory management unit (IOMMU). The basic idea is to allow direct memory access for Thunderbolt devices only to certain safe memory regions and prevent devices accessing any memory area outside those. The availability of that feature is communicated by the kernel to userspace via the iommu_dma_protection sysfs attribute. If support is active boltd will change its behavior in a few novel ways. This is because we assume that as long as IOMMU protection as enabled, it is safe to authorize devices, even without asking the user. New devices that are not authorized are therefore automatically enrolled, but with a new iommu policy. In the case that IOMMU is turned off again, devices with this iommu policy won't automatically be authorized by boltd and will require explicit user interaction. Additionally, devices that are new but already authorized by the firmware, are now automatically imported, so we always have a record of devices that were attached to the system. Anybody who is interested in even more (technical) details can read bolt issues #128 (iommu) and #137 (auto-import).

boltctl config

The boltctl command line tool gained a new sub-command, boltctl config, to list, read and write global, domain and device properties.


boltctl config

boltctl config can be used to list (--describe), get and set properties.

For example, disabling authorization via boltd can now be done via the boltctl config auth-mode disable. This corresponds to the "Direct Access" setting in GNOME Settings. A list of all available properties can be queried via boltctl config --describe. For more details see also the boltctl(1) man page.

the road to 1.0

IOMMU support was the last major item on the TODO list. There are a few bigger things that should get into 0.9, the biggest one probably being exit-on-idle (#92)2. I want all features to land in 0.9 and then 1.0 to just be a bug fix release a few month after 0.9. All the remaining features are "nice to have" and not really pressing so I will continue working on them but more on the side. That also means they are all up for grabs if someone else wants to help.

Footnotes:

  1. NB: GNOME Shell and Settings watch for the dbus service but don't request it to be started, so if there is no Thunderbolt hardware present in the system boltd should not be running at all.

Thunderbolt security has been in the news recently: researchers presented a set of new vulnerabilities involving Thunderbolt which they named Thunderclap1. The authors built a "fake" network card2 and performed various DMA attacks and were able to temper with memory regions that their network card should have no access to whatsoever. In some way this is not all that surprising because the foundation of Thunderbolt are PCIe tunnels to external hardware and one of the reasons that PCIe is fast is because it can do direct memory access (DMA).

Use boltctl domains to inspect the current security level.

The current primary defense against DMA attacks for Thunderbolt 3 are the security levels: if enabled (the default on most systems) it gives the software the ability to decide on a per device level to allow or deny PCIe tunnels (and with that potentially access to all the memory via DMA)3. While not protecting from DMA attacks per se it protects from some — maybe the most — prominent threat scenarios4: 1) somebody plugging that evil device into your computer while you are away or 2) you have to plug in a device into your computer that you don't trust, i.e. a projector at a conference. On GNU/Linux boltd will authorize a plugged-in device only if an admin user is logged in and the screen is unlocked. For untrusted environments the authorization by boltd can be disabled entirely, e.g. when you go to a conference, via the GNOME settings panel. The toggle is called "Direct Access" (see screenshot below).

The panel has a global switch to toggle all authorization performed by bolt.

This is not the full story though, because there is a second way to prevent DMA attacks utilizing the input–output memory management unit (IOMMU). The general idea is to assign a specific memory region to a device which is the only area the device can directly access. Mika Westerberg from Intel has worked on kernel patches (will be in 5.0) to use firmware supported IOMMU virtualization (Intel calls this VT-d) which should make DMA attacks harder. Having said that, Mika was pointing out (thanks!) that there are still two possible issues mentioned in the paper that are not yet addressed (I paraphrase Mika): 1) IOMMU window size granularity is such that it may open a "too big" IOMMU window and 2) IOMMU mappings are not immediately torn down, leaving memory exposed for some time. Intel (Lu Baolu) is working on patches to mitigate those issues. On the bolt side of things, I have recently merged MR!137 which adds the necessary IOMMU plumbing. The big caveat for this is that it needs hardware/firmware support and for most (all?) currently shipping systems we are out of luck.

Security levels and IOMMU based DMA protection are orthogonal and the way support is implemented in Linux 5.0 is that userspace (bolt) is still required to authorize devices (if the security level demands it, i.e. user or secure). This means that you still have the ability to globally disable authorization of any device, e.g. for when you go to a conference.

Thunderbolt 3 Security Levels

Thunderbolt 3 Security Levels in the BIOS: Enable at least "User Authorization"

To sum it all up: For now, make sure you have Thunderbolt 3 security enabled in the BIOS and whenever you are in an untrusted environment (e.g. conference) disable device authorization completely (via the Settings panel). In the future, with Linux 5.0 and new hardware Linux will also get IOMMU based DMA protection that should greatly reduce the risk of DMA attacks and work is underway to plug the remaining known issues.

Footnotes:

  1. Thunderclap: Exploring Vulnerabilities in Operating System IOMMU Protection via DMA from Untrustworthy Peripherals A. Theodore Markettos, Colin Rothwell, Brett F. Gutstein, Allison Pearce, Peter G. Neumann, Simon W. Moore, Robert N. M. Watson. Proceedings of the Network and Distributed Systems Security Symposium (NDSS), 24-27 February 2019, San Diego, USA.
  2. How they did it is pretty cool: "[W]e extracted a software model of an Intel E1000 from the QEMU full-system emulator and ran it on an FPGA". More details in the paper on page 5. The whole platform is also available at github.com/thunderclap-io
  3. The paper states that situation for Linux is: "patches for approval of hotplug devices have been produced by Intel and distributions are beginning to implement user interfaces." So this is not super up to date (long paper review process I guess). The current situation is: kernel level support landed in 4.13; bolt was included in Fedora 27, RHEL 7.6 and is now included in many distributions. IOMMU support will land in 5.0 (but see the text for remaining issues).
  4. Assuming that you trust manufacturers of hardware (attacks can also happen at the "supply chain").

With the release of bolt 0.61 "Make the firmware do it!" boltd gained support for preboot access control list (bootacl). The quick summary of that feature is best given by explaining what problem it solves: You are using a Thunderbolt 3 dock that has the main keyboard and mouse connected to it and you want to use the mouse and keyboard during pre- or early-boot, e.g. to enter a password to unlock the hard-drive. If the "pre-boot ACL" feature is enabled in the BIOS, boltd will now do the right thing and Thunderbolt 3 peripherals will be functioning from early on. It comes with one big security caveat though: no device verification is possible, which means the effective security level is user mode during pre-boot (see below for details). The requirements checklist is: bolt version >= 0.6, a kernel >= 4.17 as well as recent enough thunderbolt firmware. The feature usually needs to be explicitly enabled in the BIOS as well (it will be called something like "pre-boot ACL").

The pre-boot BIOS settings

To explain in more detail how all of this works let me first quickly recap Thunderbolt 3 security levels: Thunderbolt tunnels PCIe to connect peripherals and thus allows for direct memory access (DMA); this makes in fast but can be used as an attack vector. In order to prevent DMA attacks Thunderbolt 3 introduced different security levels: none (SL0), user (SL1)2, secure (SL2) and dponly (SL3).3 In both user and secure mode the device needs to authorized before the PCIe tunnels to the peripherals are established. This is done by boltd, a system daemon that manages a list of trusted devices. After Thunderbolt devices are enrolled, i.e. stored in boltd trust device database, the daemon will automatically authorize those devices as soon as they appear. Devices are identified via a unique identifier (UUID). But since the device itself is reporting the UUID to the system, a malicious devices could pretend to have the UUID of a already trusted device. To prevent this secure (SL2) mode uses a per-device key that is generated by the host and stored in the device so it can be used to verify the device identity.

As mentioned above, boltd is the user space component that will authorize the devices. As a consequence if boltd is not running, nobody is authorizing the device and the device will not be able to function. Two of important instances where boltd is NOT running but you might want use the mouse and keyboard in BIOS setup and probably way more important during early boot, to enter the LUKS password.

Recent BIOS versions enabled support for storing a limited list of UUIDs directly in the thunderbolt controller. This is called the pre-boot access control list (or preboot ACL), in bolt simply called "bootacl". The devices corresponding to the devices in the bootacl will be authorized during pre-boot (and only then) by the firmware. One big caveat about this feature should be become obvious now: No device verification can happen because only the UUIDs are stored but not the key, so if you are using SECURE mode but enable preboot ACL in the BIOS you effectively will get USER mode during boot.

The kernel exposes the bootacl via a per-domain sysfs attribute boot_acl. Every time a device is enrolled, boltd will automatically add it to the bootacl as well. Conversely if the device is forgotten and it is in the bootacl, boltd will automatically remove it from the bootacl. There are is small complication to these seemingly straight forward operations: in BIOS assist mode, the thunderbolt controller is powered down by the firmware if no device is connected to it. Therefore when devices are forgotten boltd might not be able to directly write to the boot_acl sysfs attribute. In a dual boot scenario this is complicated by the fact that another operating system might also modify the bootacl and thus we might be out of sync. As the solution to this boltd will write individual changes to a journal file if the thunderbolt controller is powered down and re-apply these changes (as good as possible) the next time the controller is powered up.

boltctl showing the list of domains including the bootcl

An easy way to check the current bootacl entries is via boltctl domains. Currently this is read only but issue #139 is open for write support. This would be a perfect issue to start if anyone would like to hack a bit bolt.

Footnotes:

  1. Meanwhile I have released bolt 0.7 'The Known Unknowns', which contains fixes for a few bugs that slipped into 0.6.
  2. This security mode is the default on most systems.
  3. A option called usbonly (SL4) was added added to the new TitanRidge Thunderbolt 3 controller (and support for it was added to kernel 4.17).

TL;DR: Not every USB-C port is a Thunderbolt 3 port. Watch out for the logos!

One thing that I have learned in conversations about Thunderbolt is that it is important to distinguish between Thunderbolt the I/O technology and the physical connector that is used by it, because this seems to be a constant source of confusion. Over the course of its history, Thunderbolt used different types of connectors; Version 1 and 2 used Mini DisplayPort. USB as the older and more ubiquitous I/O tech also uses a myriad of different connectors ([{mini, micro}-]{A, B, AB}, SuperSpeed, ...).

USB Type-C connector on a Thunderbolt 3 cable

USB-C connector on a Thunderbolt 3 cable. NB: The flash logo

In order to simplify this and make things generally better, a new universal connector was designed: the USB Type-C connector. A universal connector for a universal bus, ha! But besides USB, this connector is also used by Thunderbolt 3. It has some nice properties (it is symmetrical!) and is quite versatile, i.e. it can be used to deliver power via USB-PD to peripherals.
On the technical side, this can be done because USB-C supports different Alternate Modes: e.g. DisplayPort, HDMI and Thunderbolt 3, which itself then can also carry DisplayPort. Now the important bit: all of the alternate modes (and USB-PD) are optional. It depends on what kind of controller the USB type C port is connected to. Ergo it is not clear what data can be transported by just looking at the port alone: maybe DisplayPort or it might even support Thunderbolt 3. The crucial bit of information is conveyed via the little logo that is printed next to the port. Since physically different pins are used for different modes, the logos are also important on the USB-C cables. Logo usage is regulated by the USB logo usage guidelines.

Example logo: Super Speed USB 10 Gbps USB Type-C™ Charging Trident Logo + DisplayPort Logo (p. 55)

What this all boils down to is the tl;dr from the top of the article: not every USB-C port is also a Thunderbolt 3 port. If you want to connect a TB3 device to a computer, make sure all involved ports (and cables) have the right logo:

Thunderbolt 3 logo

Some people who own a T480s learned this the hard way when they were wondering why Thunderbolt was not working for them when plugging things into the leftmost USB-C port. I had a few reports of bolt not working, followed by noticeable embarrassment, although it is arguably the design of the port itself which is at fault.

T480s: plain USB 3 port with USB-PD support (left in red) and Thunderbolt 3 port (right in green)

NB: Since there are also different types of Thunderbolt 3 cables (active, passive), you might get different maximum speeds (20Gbit/s vs 40Gbit/s) depending on the cable you use. For the few different cables that I have seen so far, they could not be distinguished based on their appearance alone.

bolt 0.5 "You've got the power"

In related news: bolt 0.5 is out (since about a month now) and will be shipped with Fedora 29. Have a look at the release notes for a complete list of changes, but the most important one I want to highlight here is the new force power D-Bus API. What is it and why do we need it? The Thunderbolt controller can be in two different modes: one in which it is constantly powered (native enumeration mode) and one in which it is controlled by the BIOS. In the latter mode, if nothing is plugged into the Thunderbolt port the controller is completely powered down and it looks as if there is no Thunderbolt hardware present at all. This is great because it saves battery, but there are two problems: 1) boltd wants to know what security level the Thunderbolt controller is in, and more importantly 2) the firmware update daemon (fwupd) wants to know the firmware version of the Thunderbolt controller, so that it can check if there are updates available (and if so, show them in GNOME Software). Luckily, newer kernel versions have (on supported platforms) a sysfs interface that can be used to "force-power" the Thunderbolt controller. Both boltd and fwupd have support for that, which is great, but also the root of a race: the force-power interface is not reference counted and also write only (you cannot ask for the current status). Now if boltd force-powers the controller, uevents will be generated which, in turn, will be processed by fwupd and it will try to read the firmware version. If, in the meantime, boltd is done with its thing and powers the controller down again but fwupd is not yet done reading the firmware, then that read will fail. Or the other way around: fwupd powers the controller, boltd gets started due to the uevents, but meanwhile fwupd is powering the controller down again, boltd might e.g. hang reading the boot-acl.

boltctl power --help for more information

The solution to the problem that Mika, Mario and I came up with was to have only boltd talk to the "force-power" interface and provide a D-Bus API for clients (fwupd) to use. Internally, boltd keeps track of open force-power requests and only when there is none left does the controller get powered down. If you have bolt 0.5 installed, you query the force power status via boltctl power -q or actually request force-powering with boltctl power.

What's next?

I am currently working on boot acl support (#77), which will be the main feature of bolt 0.6. It is still work in progress, but it is very close to being finished and could use some testing. The code is in the bootacl branch and there is a merge request !119 for potential feedback.

Thunderbolt allows for peer-to-peer network connections by connecting two computers directly via a thunderbolt cable. Mika from Intel added support for this to the 4.15 kernel. Recently, Thomas Haller from NetworkManager and I worked together to figure out what needs to be done in userspace to make it work. As it turns out, it was not that hard and the pull-request was merged swiftly.


GNOME Settings' Network Panel

So now if you connect your GNU/Linux box to another machine, NetworkManager will configure the connection to be a Link-Local one.

pinging macOS

ping Linux from macOS

I have successfully tested Fedora to Fedora, Fedora to macOS and Fedora to Windows 10. The other operating systems also use a Link-Local address by default.


Copying from Linux to Windows

The technical details

When another host is connected via thunderbolt, we get a new device in sysfs that resembles a normal thunderbolt device but is of DEVTYPE thunderbolt_xdomain. Like a normal thunderbolt device, it has a unique_id and a device_name, but is missing the authorized and key attributes. A new udev rule in NetworkManager was added to load the thunderbolt-net kernel module. As a result, we get a new network device (thunderbolt0).

nmcli showing the thunderbolt networking device

Another udev rule will set a new udev property (NM_AUTO_DEFAULT_LINK_LOCAL_ONLY) to all network devices where the driver is thunderbolt-net to instruct NetworkManager to use the Link-Local configuration on these interfaces.

The dev snapshot release 1.11.3-dev has the thunderbolt networking support. Grab it, build it, and start playing around with it! Feel free to post your record transfer speeds in the comments ⚡ 🏆.

Fedora 28 is around the corner and I wanted to highlight what we did to make the Thunderbolt 3 experience as smooth as possible. Although this post focuses on Fedora 28 for what is currently packaged and shipping, all changes are of course available upstream and should hit other distributions in the future.

The new thunderbolt control center panel

The new Control Center Thunderbolt Panel

bolt

First of all, the home of bolt has moved from Github to the new Gitlab instance at freedesktop.org1. File issues and spread your love in the form of stars ★ there now ;)

I released version 0.3 of bolt about a week ago, with a lot of internal changes, small D-Bus API changes and support for future kernel changes2. For example it already supports the new USBONLY security level of the upcoming Titan Ridge controller, and the boot attribute; kernel level support for both landed in 4.17.

GNOME Shell

The GNOME shell bits to enable Thunderbolt 3 support were merged some time ago and made it into 3.28. This means that the GNOME shell will act as authorization agent and will automatically authorize new thunderbolt 3 devices — if the user has administrator rights, is currently logged in and the session is unlocked. It will also show a little indicator (called the cable_snake by some) in the status indicator section while devices are being authorized because the whole authorization dance can take quite a while.

Activity indicator, aka The Cable Snake

GNOME Control Center

We have a new panel to manage Thunderbolt 3 devices, woohoo 🎉! It landed in master not too long ago and will be in 3.30, but we backported it to Fedora 28. It lets you remove currently enrolled devices and shows if devices need authorization (they will be listed under "Pending Devices"). The latter might be happening, for example, because the devices were connected while the session was locked. The device detail dialog can then be used to authorize them.

Authorizing a device

Another important feature is the possibility to temporarily disable authorization of Thunderbolt devices. In the panel this is called "Direct Access", because disabling it will stop the authorization of Thunderbolt 3 peripherals, but the DisplayPort and "pure" USB functionality of the thunderbolt port will be preserved. In technical terms, it means that without authorization no PCIe tunnels are allowed to be created, but due to a feature called alternate modes, the thunderbolt port will still allow USB devices and DisplayPort streams to connect.

Switching "Direct Access" on and off

This feature might come in handy if you are traveling, say to defcon: while you don't want malicious devices (like specially prepared thunderbolt cables) to read your main memory, you still want attached projectors to work correctly.

Firmware updates

Support for updating the firmware of the Thunderbolt host controller and devices landed in fwupd quite some time ago and is of course available in F28 as well. On supported platforms, like Dell, it is therefore only one click away in GNOME Software. Mario also added support to force power the host controller during firmware updates, so updating the host controller is possible without the need to have something plugged into the Thunderbolt port.

Outlook

All in all I am quite happy with the current state of Thunderbolt on GNU/Linux and what we will be shipping in Fedora 28. For most people, connecting Thunderbolt 3 devices should just work. In the next few weeks I will focus on adding support for authorizing devices during pre- and early boot.

Footnotes

  1. The bolt Github repository will continue to exist and be a mirror of the main Gitlab repo. Release tarballs will also be available in both locations at least for the next few releases, but not forever, so please update your links.
  2. If you are upgrading from bolt 0.1: the database default location has changed to /var/lib/boltd so you might have to re-authorize your devices. Also, devices names are now cleaned-up and stored in the clean form in the DB. If you were running earlier versions of bolt, you might see "Vendor Vendor Device-Name" in the Control Center (see #89). The easiest way to fix this is to forget and re-authorize the device.

Thunderbolt icon by jimmac

 

Thunderbolt 3 security levels

Thunderbolt is an I/O technology that can be used to connect external peripherals to a computer — similar to USB and FireWire. It works by bridging PCIe between the controllers on each end of the connection, which in turn means that devices connected via Thunderbolt are ultimately connected via PCIe. Therefore thunderbolt can achieve very high connection speeds, fast enough to even drive external graphics cards. The downside is that it also makes certain attacks possible (e.g. Thunderstrike, DMA attack).
To mitigate these security problems, the latest version — known as Thunderbolt 3 — supports different security levels:

  • none: No security. The behavior is identical to previous Thunderbolt versions.
  • dponly: No PCIe tunnels are created at all, but DisplayPort tunnels are allowed and will work.
  • user: Connected devices must be authorized by the user. Only then will the PCIe tunnels be activated.
  • secure: Basically the same as user mode, but additionally a key will be written to the device the first time the device is connected. This key will then be used to verify the identity of the connected device.

The active security level can normally be selected prior boot via a BIOS option, but it is interesting to note that in the future the none option is likely to go away. This of course means connected thunderbolt devices wont work at all unless they are authorized by the user from with the running operating system.

Intel has added support for the different security levels to the kernel and starting with Linux 4.13. The interface to interact with the devices is via files in sysfs. Since July we have been working on the userspace bits to make Thunderbolt 3 support "just work" 😉. The UX design design was drafted by Jimmac. The solution that we came up with to implement it consists of two parts: a generic system daemon and for GNOME a (new) component in gnome-shell. The latter will use the daemon to automatically authorize new devices. This will happen if and only if the currently active user is an administrator and the session is not locked.

bolt 0.1 Accidentally Working

Today I released the first version 0.1 (aka "Accidentally Working") of bolt, a system daemon that manages Thunderbolt 3 devices. It provides a D-Bus API to list devices, enroll them (authorize and store them in the local database) and forget them again (remove previously enrolled devices). It also emits signals if new devices are connected (or removed). During enrollment devices can be set to be automatically authorized as soon as they are connected. A command line tool, called boltctl, can be used to control the daemon and perform all the above mentioned tasks (see the man page of boltctl(1) for details).

I hope that other desktop environments will also find that daemon useful and use it. As this is not a stable release yet, we still have room for API changes, so feedback is welcome.

botlctl example output

New software needs testers, so everybody who has a computer with Thunderbolt 3 and feels courageous enough is welcome to give it a try. I created a copr with builds for Fedora 27 & rawhide and Jaroslav created a PKGBUILD file so Arch users can find it already in the AUR. As this is very fresh software it will contain bugs and those can be filed at the issue tracker of the github repo.

what's next: gnome-shell integration

I am locally running a Proof-of-Concept gnome-shell extension that implements the user session bits to complete the aforementioned : It uses bolt's D-Bus interface and listens for new Thunderbolt devices and then enrolls them, if the user is logged in. Since it can take a while until all the devices that are attached via thunderbolt are properly connected the daemon has a Probing property that is used to display a little icon as a way to inform the user that something is happening on the thunderbolt bus. All of this is already working quite well here on my test machine. In the next few days (weeks?) I will be working on integrating that code into gnome-shell. There are a few open UX questions that need to be addressed, but all in all things looking good.


thunderbolt activity indicator (aka cable snake)

Special thanks to Alberto Ruiz, Benjamin Berg, Hans de Goede, Harald Hoyer, Javier Martinez Canillas, Jaroslav Lichtblau, Jakub Steiner, Richard Hughes who all helped and supported this project during the last few months! ❤️

Made by ThemesKult