Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for firmware updates via UEFI capsule #4855

Closed
DemiMarie opened this issue Mar 2, 2019 · 17 comments
Closed

Support for firmware updates via UEFI capsule #4855

DemiMarie opened this issue Mar 2, 2019 · 17 comments
Assignees
Labels
C: firmware C: updates P: major Priority: major. Between "default" and "critical" in severity. release notes This issue should be mentioned in the release notes.
Milestone

Comments

@DemiMarie
Copy link

Qubes OS version:

Qubes release 4.0 (R4.0)

Affected component(s) or functionality:

dom0


Steps to reproduce the behavior:

Look for a way to update the UEFI firmware securely

Expected or desired behavior:

QubesOS supports this, provided that it is supported by the hardware vendor. That is, the hardware vendor supplies digitially signed update files, and provides the public keys for the signatures, in a way that Qubes can check the signatures before using the UEFI capsule mechanism to submit the update.

Actual behavior:

No such method

General notes:

Firmware vendors do release security updates. That said, this should be optional.


I have consulted the following relevant documentation:

I am aware of the following related, non-duplicate issues:

@marmarek
Copy link
Member

marmarek commented Mar 2, 2019

This looks like a perfect, self-contained task for someone from the community to contribute.

@marmarek marmarek added enhancement help wanted This issue will probably not get done in a timely fashion without help from community contributors. release notes This issue should be mentioned in the release notes. labels Mar 2, 2019
@marmarek marmarek added this to the Far in the future milestone Mar 2, 2019
@marmarek marmarek added the P: major Priority: major. Between "default" and "critical" in severity. label Mar 2, 2019
@DemiMarie
Copy link
Author

@marmarek do you believe that this can be done securely in practice?

@marmarek
Copy link
Member

marmarek commented Mar 2, 2019

It very much depends on firmware vendors. Most importantly, whether updates are properly signed.
If updates are not signed, there is not much we can do. Even if updates are signed, but the hardware doesn't verify it there is a huge problem, if you consider attacker with physical access to the hardware.
I'd start by looking at https://fwupd.org/
To get something like this integrated into qubes, it needs to be at least separated into separate components (similar to qubes-dom0-update). There is also privacy concern, as the query for new firmware may contain private information (serial numbers etc).
Note that it may be also a good idea to update firmware of USB-connected devices too (so, not directly connected to dom0). I'm not sure whether such updates should be coordinated by dom0, or sys-usb itself.

@DemiMarie
Copy link
Author

@marmarek if the hardware doesn’t verify the updates, we do have a huge problem. That said, Qubes can at least check the signatures itself.

Is it okay to check the signatures in dom0? My understanding is that parsing arbitrary X.509 certificates in dom0 is not a good idea, but that it is okay to parse X.509 certificates that we know to be safe. Therefore, dom0 would need to include the certificates, or at least their hashes.

@marmarek
Copy link
Member

marmarek commented Mar 2, 2019

Dom0 would need some kind of root of trust for such updates anyway.

@DemiMarie
Copy link
Author

Current idea: dom0 spawns a dispVM to get the updates using fwupd. The dispVM returns the updates to dom0. dom0 then checks the signatures against the vendor certificate of the board on which it is running. If it merely checked the signature against a list of certificates, a malicious fwupd could trick dom0 into installing updates for the wrong board, which would be bad. Finally, dom0 sends the package to the firmware using the standard EFI capsule mechanism.

@marmarek
Copy link
Member

marmarek commented Mar 2, 2019

That could work for the actual update, when you know there is an update to install. But not necessary for periodic update checks, which IMO is also important part of this feature. Spawning DispVMs periodically may not be a good idea, given resource requirements. But maybe we could re-use updatevm for that, which is already there to check and download dom0 updates?

@DemiMarie
Copy link
Author

@marmarek That would be a good idea, yes.

As far as spawning DispVMs periodically, anyone who runs SaltStack on a cron job does that anyway, though most people do not.

@iamahuman
Copy link

iamahuman commented Jun 28, 2020

EFI System Resource Table, and in turn fwupd, is not supported under paravirtualised Linux kernel, since it cannot retrieve EFI memory maps from the firmware directly. To solve this, pvops for obtaining EFI memmap shall be added to the Xen tree of the kernel.

A workaround is to bypass the memmap check entirely in esrt.c. This works, but I don't feel safe with this solution--esp. with buggy firmwares. (shall we trust vendors?)

@iamahuman
Copy link

LVFS update metadata are in XML format, not covered by signatues. The only essential thing in it AFAICT is the capsule UUID, so perhaps we can just extract it and use it for each update's filename.

FYI for package updates (qubes-dom0-update) we only retrieve individual RPMs and verify each of them independently.

@marmarek
Copy link
Member

You can find some status update on this here: https://blog.3mdeb.com/2020/2020-06-17-qubes_summation/ (I don't see slides from this specific presentation, but there is video available). It covers some of your concerns.

@solardiz
Copy link

solardiz commented Jan 30, 2022

On currently updated Qubes 4.1-ish with kernel-latest, the esrt entry under the /sys/... path doesn't appear for me - I guess that's the issue @iamahuman mentioned above? Perhaps the suggested workaround "to bypass the memmap check entirely in esrt.c" should in fact be included in Qubes kernels, or at least in kernel-latest?

Edit: maybe another option is to also install/boot a Xen-less kernel for the time of firmware update? Would need to pre-download and pre-copy the update to the dom0 system before rebooting into that kernel.

@marmarek
Copy link
Member

marmarek commented Jan 30, 2022

Perhaps the suggested workaround "to bypass the memmap check entirely in esrt.c" should in fact be included in Qubes kernels, or at least in kernel-latest?

The check needs to happen somewhere (otherwise you risk accidentally interpreting "random" memory area as ESRT, including VM-controlled one in the worst case). There is ongoing progress on moving the check to Xen, and only then skipping it in Linux.

Edit: maybe another option is to also install/boot a Xen-less kernel for the time of firmware update? Would need to pre-download and pre-copy the update to the dom0 system before rebooting into that kernel.

The problem with this is, you need ESRT (mainly) to know what firmware to download, not only for installing it. If ESRT is static (should be, right?), it could be copied to a file on Xen-less kernel, but it sounds risky (using outdated copy).

@jevank
Copy link

jevank commented Jan 30, 2022

The check needs to happen somewhere (otherwise you risk accidentally interpreting "random" memory area as ESRT, including VM-controlled one in the worst case). There is ongoing progress on moving the check to Xen, and only then skipping it in Linux.

Wrong link?

@marmarek
Copy link
Member

Yup, edited.

@iamahuman
Copy link

The problem with this is, you need ESRT (mainly) to know what firmware to download, not only for installing it. If ESRT is static (should be, right?), it could be copied to a file on Xen-less kernel, but it sounds risky (using outdated copy).

ESRT is mostly static, with one exception: update status. fwupd uses this value to report whether the firmware update has succeeded.

@marmarek marmarek modified the milestones: Release TBD, Release 4.2 May 23, 2022
@DemiMarie
Copy link
Author

Support for this has already been upstreamed as a contrib package in fwupd. Tasks that need to be resolved:

  • Use Admin API (qubesadmin.Qubes.app.run_service) instead of manual qvm-run command
  • Do not use dynamically generated shell commands (subprocess.Popen with shell=True)
  • Use OpenPGP instead of jcat for metadata validation
  • Add tests for bad cab files
  • (optional) Unpack the cab files in a sandbox

@DemiMarie DemiMarie added S: in progress Status: in progress. The assignee is currently working on this issue. and removed help wanted This issue will probably not get done in a timely fashion without help from community contributors. labels Feb 7, 2023
marmarek added a commit to QubesOS/qubes-builderv2 that referenced this issue May 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C: firmware C: updates P: major Priority: major. Between "default" and "critical" in severity. release notes This issue should be mentioned in the release notes.
Projects
None yet
Development

No branches or pull requests

6 participants