This is one of those blog posts which is going to escalate quickly; in my effort to make it understandable I might simplify some of the theory, so if you know all this stuff already please scroll down a few paragraphs and try not to be pedantic.
UEFI Secure Boot is protection technology that is designed to protect a system against malicious code being executed early in the boot process. It defines a way to “lock down” the platform so only binaries signed with a specific key will run. The certificate authority is managed by Microsoft, which is unimportant generally, but was hugely important before Microsoft agreed to sign loaders like shim as it meant hardware wouldn’t run Linux. SecureBoot isn’t evil by itself, and having SecureBoot turned on protects your hardware from real world attacks and in theory secures most of the boot process to where the Linux kernel takes over. In the case where you don’t love or trust Microsoft you can configure another certificate authority to manage the trust somewhere else, but that’s a blog post for another day.
Anyway — I alluded that Microsoft has a special process for signing our Linux binaries so we could still keep running Linux on hardware that can’t turn off SecureBoot for one reason or another. What happened with the BootHole set of CVEs was that a researcher from Eclypsium found a nasty bug in the GRUB project (of which the binary was signed by Microsoft) which allowed complete circumvention of the SecureBoot architecture. This would mean a bootkit that previously would only work with SB turned off (which is fairly uncommon, as Microsoft forces OEMs to turn it on by default) now could be easily deployed onto hardware with SB enabled using an old version of shim packaged in the bootkit.
Luckily, this scenario was planned for by the UEFI people, and as well as having a “binaries must be signed by this certificate” functionality we also have a “the binary must not have this checksum” back up plan. Microsoft recently invoked the back-up-plan and added quite a few checksums of binaries like shim and grub to the latest dbx update. They’ve done this three times since 2010, but only traditionally for things like the Symantec recovery binary which most people won’t have installed. The signed “blocklist of checksums” is called the
dbx internally, and can only be updated and can never be downgraded for obvious reasons.
If you actually deploy the current UEFI Revocation List (a.k.a dbx) on your Linux box right now using something like
dbxtool it’ll most probably apply fine, and then when you reboot you’ll get a nice red screen and a SECURE BOOT VIOLATION message, and then for most people the computer will be a useless brick. The grub and shim installed into
/boot/efi by your OS is now being blocked, and so nothing works. You can’t even boot a Linux installer to reinstall as the grub on the live media is going to be blocked too.
What we used to do was have a
dbxtool.service that just applied the latest
dbx (if you were not using a LiveCD) and then just hope it all still boots. This mostly worked, as the
dbx contained checksums of things you were not likely to be using, rather than things you are most likely to have. You might also be thinking this also isn’t an awesome way to deploy a single-use binary to millions of computers. It’s like shipping firmware updates in an rpm. Hmm. That gives me an idea.
What we could do is have a fwupd plugin that reads the current dbx and creates a device:
│ └─UEFI dbx: Device ID: 362301da643102b9f38477387e2193e57abaa590 Summary: UEFI Revocation Database Current version: 77 Minimum Version: 77 Install Duration: 1 second GUIDs: 5971a208-da00-5fce-b5f5-1234342f9cf7 ← UEFI\CRT_A9087D1044AD18F7A94916D284CBC01827CF23CD8F60B79072C9CAA1FEF4D649&ARCH_X64 f8ba2887-9411-5c36-9cee-88995bb39731 ← UEFI\CRT_A1117F516A32CEFCBA3F2D1ACE10A87972FD6BBE8FE0D0B996E09E65D802A503&ARCH_X64 Device Flags: • Internal device • Updatable • Supported on remote server • Needs a reboot after installation
Then we could push the dbx updates onto the LVFS so that they get downloaded as required rather than stored into
/usr for all eternity. We could put all the checks into fwupd to verify that the user doesn’t have any blocked binaries into the ESP (as fwupd already knows how to mount the ESPs to deploy UEFI capsules) so that we don’t accidentally brick any systems:
And we could wire this up to the GUI so that it’s super easy to use, and makes it a one-click install to deploy locally or scriptable using the CLI:
If you install fwupd and gnome-software from git master, this is exactly what you can do right now. To test this on your non-production system, you can add something like this to
[fwupd Remote] Enabled=true Title=UEFI dbx Keyring=gpg MetadataURI=https://fwupd.org/downloads/firmware-1d780afd8789afc6bccff638e5e8376604ba082aa32dc06db71d6768824a1efa.xml.gz ReportURI=https://fwupd.org/lvfs/firmware/report OrderBefore=lvfs,fwupd
fwupdmgr refresh gets you the metadata and
fwupdmgr update applies the update only if it’s safe to do so. Again: Do not do this on a system you don’t have backups for.
I’m going to test this myself on a few more machines and then once the
grub builds hit Fedora stable we can think about packaging up the new fwupd so that we can deploy the
dbx configuration using the LVFS easily. Of course, nobody is taking away doing it manually with
dbxtool, but now it’s integrated into the system and easy for the user to deploy. Comments and corrections most welcome.