Linux firmware_class enhancements
This page documents progress on ongoing enhancements to the firmware_class, both ongoing development, theoretical issues, and desired bells/whistles.
Usermode helper review
The firmware API makes use of a custom usermode helper fallback mechanism should direct filesystem loading fail. Its a custom usermode helper mechanism since it only uses the core kernel kobject uevent (which is one real user of the core kernel usermode helper) as an optional feature, but also always relies on the core usermode helper lock. There are a slew of issue with this. Daniel Wagner has nose dived into this code to help compartamentalize it as best as possible first without creating any side effects, with long term plans to replace custom hacks with generic functionality in the kernel.
Since a lot of the usermode helper functionality is tied to the core kernel usermode helper or implicates it or its users if we make any changes to it the firmware usermode helper functionality and enhancement considerations are currently being documented on the [https://kernelnewbies.org/KernelProjects/user-mode-helper-enhancements usermode helper enhancement] page. An overview of the key enhancement ideas though:
- The core usermode helper lock is only being used by the firmware API
- This was added originally by Rafael to warn if users made use of the firmware API on suspend/resume, this would usually stall the kernel and create bad experiences
- Although originally added to add a warning for users of the API on suspend/resume the code also prevented a small race on init
- The firmware cache which was later added helps avoid the race concerns which we originally had when using the firmware API on suspend/resume, it only works for firmware API users which do not explicitly request use of the firmware usermode helper fallback mechanism
There exists a kernel functionality to help address races with block devices -- freeze_super() can be used to queue superblock filesystem operations. For inspiration we can review and consider the patch being worked on by [https://git.kernel.org/cgit/linux/kernel/git/jikos/jikos.git/commit/?h=might-rebase/get-rid-of-kthread-freezer&id=394aa67810abefde6d79ea96a90e5d41a7df99f4 Jiri Kosina which freezes all filesystems during suspend]. This would resolve the suspend/resume race concerns for the lock, it however does not solve the races on init.
- We need a generic facility for races on init. The lock helps protect against this but all the other core kernel usermode helpers do not use it, why not? Don't they race as well?
- Compartmentalize the usermode helper functionality code within drivers/base/firmware_class.c and alter shove into its own file
- The current firmware UMH code can and should be ported over to swait
Extensible firmware API
At the 2015 kernel summit it was agreed that the firmware signing facility would be generalized, callers of the firmware API already exist outside of "firmware" use, so re-branding is over due to annotate for this. [http://lkml.kernel.org/r/20151006090821.GB9030@kroah.com Greg has noted we cannot get rid of the usermode helper], but even [http://lkml.kernel.org/r/CA+55aFwOT3azA9pBXeJFOm5oxNhQFOKWMX7Gq9Ey8mKrrFJQAw@mail.gmail.com Linus has called for deprecating the usermode helper], a compromise is to phase the usermode helper out of most common kernel users by having the usermode helper exist only for old users. A clean series of APIs for "firmware loading" with a rebranded set of APIs will be added to enable to skip the usermode helper, make emphasis that the loader is not just for firmware, but for other things, and later get support for "firmware signing". The usermode helper code then would be compartmentalized and slowly faded.
One particular prospect user of the user mode helper was Daniel Vetter for graphics driver (hopefully he can add some info here on prospective requirements).
Proposed mock-up by Andy at the 2015 Kernel summit, sent October 26, 2015:
This is a simple mockup.
Suppose that there's some trusted keypair. The SHA256 hash of the public key is cdbcba8ee7cd604391d409872a0655d9170fcf93fd3cfca4b648559881ce4a70. There's a firmware file called "firmware.bin". The firmware file has sha256sum 81357924283b5a6a803e8bcc8fce12b0f11bf575abff9356d1a32f987b0f0022.
To sign it, create a file that looks like:
Linux firmware signature 1.0 firmware.bin 81357924283b5a6a803e8bcc8fce12b0f11bf575abff9356d1a32f987b0f0022
Then sign that using whatever signature algorithm. The signature is the public key hash followed by the raw signature. RSA PKCS #1 2.0 signatures would be fine. PKCS #1 1.5 would be okay, too, but it's a little sad. ECDSA over P-256 would probably be fine.
To verify it, you sha256sum the provided firmware blob and regenerate the same signed data:
Linux firmware signature data 1.0 firmware.bin 81357924283b5a6a803e8bcc8fce12b0f11bf575abff9356d1a32f987b0f0022
then you look up the provided key to see if you have a trusted key that hashes to the provided key hash. If you do, verify the signature.
The kernel could have any number of global trusted keys that are trusted for any firmware file whatsoever as well as any number of per-driver keys.
FWIW, I don't actually see how to use the openssl client to generate a PKCS#7 blob with authenticated data, but I didn't look that hard.
Firmware calls on init and probe
Asynchronous probe was added to help with delayed boots caused by use of fw API calls, and by the generic 30 second systemd timeout. There is still an issue present when fw APIs are used on init or probe: the kernel cannot be sure that /lib/firmware is ready. In particular when switching initramfs with pivot_root(), for example. In such cases even if you use asynchronous probe on probe you might end up with a system that finds no firmware yet on /lib/firmware as the filesystem for it might not be ready.
A coccinelle rule is being worked on which maps out the users of the firmware API on init and probe, interprocedurally (calls that calls fw API too), the list is pretty big, the patch / details wil be posted soon for review.
A userspace hint to the kernel when /lib/firmware is ready is needed. Note that this hint might be something we likely can make use of for other subsystems which may need file loading on other paths on the filesystem, depending on where the subsystem is loading files from the kernel.
Core file loader
There are now 5 known kernel core file loaders, we should unify these. This effort is being documented and planned on [http://kernelnewbies.org/KernelProjects/common-kernel-loader this separate file loader page]. Of importance there to this effort on firmware_class is the historical issues on using firmware_read() on init/probe, and races against mounted filesystems (pivot_root() and perhaps other things, maybe long delays due to NFS being used). Refer to that page for more details.
Add a hook to let drivers stale cache (or should the OS only do this and hide the symbol?)