User: Password:
Subscribe / Log in / New account

Reworking kexec for signatures

This article brought to you by LWN subscribers

Subscribers to made this article — and everything that surrounds it — possible. If you appreciate our content, please buy a subscription and make the next set of articles possible.

By Jake Edge
June 25, 2014

The kernel execution (kexec) subsystem allows a running kernel to switch to a different kernel. This allows for faster booting, as the system firmware and bootloader are bypassed, but it can also be used to produce crash dumps using Kdump. However, as Matthew Garret explained on his blog, kexec could be used to circumvent UEFI secure boot restrictions, which led him to propose a way to disable kexec on secure boot systems. That was not terribly popular, but a more recent patch set would provide a path for kexec to only boot signed kernels, which would solve the problem Garrett was trying to address, without completely disabling the facility.

The kexec subsystem consists of the kexec_load() system call that loads a new kernel into memory, which can then be booted using the reboot() system call. There is also a kexec command that will both load the new kernel and boot it, without entering the system firmware (e.g. BIOS or UEFI) and bootloader.

But the UEFI firmware is what enforces the secure boot restrictions. Garrett was concerned that a Linux kernel could be used to boot an unsigned (and malicious) Windows operating system by way of kexec because it circumvents secure boot. That might lead Microsoft to blacklist the keys used to sign Linux bootloaders, which would make it difficult to boot Linux on commodity hardware. Using kexec that way could affect secure-booted Linux systems too, of course, though Microsoft might not be so quick to revoke keys under those circumstances.

In any case, Garrett eventually removed the kexec-disabling portion of his patch set (though he strongly suggested that distributions should still disable kexec if they are going to support secure boot). Those patches have not been merged (yet?). More recently, Vivek Goyal has put together a patch set that is intended to address Garrett's secure boot concerns, but would also protect systems that only allow loading signed kernel modules. As Garrett showed in his blog post, that restriction can be trivially bypassed by executing a new kernel that simply alters the sig_enforce sysfs parameter in the original kernel's memory and then jumps back to that original kernel.

Goyal's patches start down the path toward being able to restrict kexec so that it will only load signed code. To that end, this patch set defines a new system call:

    long kexec_file_load(int kernel_fd, int initrd_fd,
			 const char *cmdline_ptr, unsigned long cmdline_len,
                         unsigned long flags);
It will load the kernel executable from the kernel_fd file descriptor and will associate the "initial ramdisk" (initrd) from the initrd_fd descriptor. It will also associate the kernel command line passed as cmdline_ptr and cmdline_len. The initrd and command-line information will be used when the kernel is actually booted. This contrasts with the existing kexec system call:
    long kexec_load(unsigned long entry, unsigned long nr_segments,
                    struct kexec_segment *segments, unsigned long flags);
It expects to get segments that have been parsed out of a kernel binary in user space and to just blindly load them into memory. As can be seen, kexec_file_load() puts the kernel in the loop so that it can (eventually) verify what is being loaded and executed.

As one of the segments that get loaded, there is a standalone executable object, called "purgatory", that runs between the two kernels. At reboot() time, the "exiting" kernel jumps to the purgatory code. Its main function is to check the SHA-256 hashes of the other segments that were loaded. If those have not been corrupted, booting can proceed. The purgatory code will copy some memory to a backup region and do some architecture-specific setup, then jump to the new kernel.

The purgatory code currently lives in kexec-tools, but if the kernel is to take responsibility for setting up the segments from the kernel binary and initrd, it will need a purgatory of its own. Goyal's patch set adds that code for x86 to arch/x86/purgatory/.

Goyal also copied code from crypto/sha256_generic.c into the purgatory directory. It's clear he would rather simply just use the code directly from the crypto/ directory, but could not find a way to do so:

I could not #include sha256_generic.c file here as some of the function signature [required a] little tweaking. Original functions work with crypto API but these ones don't

So instead of doing #include on sha256_generic.c I just copied relevant portions of code into arch/x86/purgatory/sha256.c. Now we shouldn't have to touch this code at all. Do let me know if there are better ways to handle it.

While the patch set is at version 3 (earlier versions: v2, v1), it is still a "request for comment" (RFC) patch. There are various unfinished pieces, with signature verification topping the list. So far, the new facility is only available for the x86_64 architecture and bzImage kernel images. Adding other architectures and support for the ELF kernel format still remain to be done. There is also a need for some documentation, including a man page.

Goyal did explain his vision for how the signature verification will work. It is based on David Howells's work on verifying the signatures for loadable kernel modules. Essentially, the signature will be verified when kexec_load_file() is called. That is also when the SHA-256 hashes for each segment are calculated and stored in the purgatory segment. So, all purgatory has to do is verify the hashes (which it already does to avoid running corrupted code) to ensure that only a properly signed kernel will be executed.

There have been plenty of comments on each version of the patch set, but most of those on v3 were technical suggestions for improving the code. So far, there have been no complaints about the overall idea, which means we may well see the ability to require cryptographic signatures on the kernels passed to kexec added as a feature sometime in the next year—hopefully sooner than that. It would be a nice feature to have when Garrett's secure boot patches get merged.

(Log in to post comments)

Reworking kexec for signatures

Posted Jun 26, 2014 15:49 UTC (Thu) by paulj (subscriber, #341) [Link]

Of course, if the goal is to prevent Linux from being a means to boot Windows without checking its SecureBoot signatures, then ultimately the end-user must be prevented from being able to modify the Linux they have installed.

Reworking kexec for signatures

Posted Jun 26, 2014 16:11 UTC (Thu) by raven667 (subscriber, #5198) [Link]

Not quite. The locally present end user can modify their machine however they wish, the question is can attackers modify the machine remotely without raising any alarm to the end user.

Reworking kexec for signatures

Posted Jun 27, 2014 17:01 UTC (Fri) by paulj (subscriber, #341) [Link]

True, at present users can still add their own keys to *some* UEFI key databases or disable SecureBoot on *some* UEFI systems (some UEFI systems do not allow one or both, either by design (e.g. ARM) or by bug/accident).

How long local users will still be allowed to subvert Windows SecureBoot on UEFI PCs, we shall see. I hope I'm proven to be an unnecessarily alarmist skeptic, however the number of systems afflicted by DRM/locked-down-computing seems to keep steadily increasing over the decades, rather than decreasing.

Reworking kexec for signatures

Posted Jun 27, 2014 17:43 UTC (Fri) by mjg59 (subscriber, #23239) [Link]

Which x86 UEFI systems have you seen that shipped with secure boot enabled and have no way to disable secure boot and modify the key database?

Reworking kexec for signatures

Posted Jun 28, 2014 2:14 UTC (Sat) by zlynx (subscriber, #2285) [Link]

You aren't doing any "subverting" if you turn it off or change the keys. Windows 8 will not boot until reinstalled and then it won't be in secure mode. So it isn't subverted. It just won't work.

I don't deny that there are some motherboard makers that really truly SUCK at software quality control and won't listen to bug reports about non-Windows operating systems. I just don't like the word "subvert" here.

Reworking kexec for signatures

Posted Oct 7, 2014 1:48 UTC (Tue) by linuxrocks123 (subscriber, #34648) [Link]

What? Windows won't boot if you disable SecureBoot? That doesn't sound right ... why wouldn't it just warn you you're not in "secure" mode, disable some DRM shite, and be done with it? I never heard before that it required a REINSTALL!

...and I have a fairly recent system which booted Windows once or twice before I bulldozed it and installed Linux. And it booted with not just Secure Boot disabled but with the legacy BIOS support enabled. What systems have you seen that didn't allow this?

Reworking kexec for signatures

Posted Oct 7, 2014 3:36 UTC (Tue) by mjg59 (subscriber, #23239) [Link]

> That doesn't sound right

It's not right.

Reworking kexec for signatures

Posted Jul 1, 2014 22:47 UTC (Tue) by jwarnica (guest, #27492) [Link]

I don't buy systems that have 2 or less DIMM slots; I wouldn't buy a motherboard that doesn't allow UEFI manipulation. Yet my computer today has only 2 of its slots populated, and I might trash the motherboard before I upgrade the memory. I have no plans to ever use the... I have no idea, 38 SW/HW/JOBD SATA ports the beast has. But some people would, apparently, and there is a huge market for hackable systems.

That set-top boxes aren't today easily SW hackable is largely irrelevant; not being able to add memory or an additional drive largely makes them not legitimate targets for playing with. Except outside of some circle-jerk geekathon type scenario.

Reworking kexec for signatures

Posted Mar 11, 2015 1:14 UTC (Wed) by scientes (guest, #83068) [Link]

I am having a difficulty where kexec_file_load() always returns -ENOMEM, when kexec_load() (via kexec-tools) always works. The files pointed to are the same, so it isn't that the file is huge.

Reworking kexec for signatures

Posted Mar 11, 2015 20:53 UTC (Wed) by scientes (guest, #83068) [Link]

The patch went in with a differn't type signature that the article describes. The cmdline_len and cmdline_ptr options have been switched.

long kexec_file_load(int kernel_fd, int initrd_fd,
unsigned long cmdline_len, const char *cmdline_ptr,
unsigned long flags);

Copyright © 2014, Eklektix, Inc.
This article may be redistributed under the terms of the Creative Commons CC BY-SA 4.0 license
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds