Message ID | 20250107153353.1144978-1-kraxel@redhat.com (mailing list archive) |
---|---|
Headers | show |
Series | hw/uefi: add uefi variable service | expand |
On Tue, Jan 07, 2025 at 04:33:27PM +0100, Gerd Hoffmann wrote: > This patch adds a virtual device to qemu which the uefi firmware can use > to store variables. This moves the UEFI variable management from > privileged guest code (managing vars in pflash) to the host. Main > advantage is that the need to have privilege separation in the guest > goes away. > > On x86 privileged guest code runs in SMM. It's supported by kvm, but > not liked much by various stakeholders in cloud space due to the > complexity SMM emulation brings. > > On arm privileged guest code runs in el3 (aka secure world). This is > not supported by kvm, which is unlikely to change anytime soon given > that even el2 support (nested virt) is being worked on for years and is > not yet in mainline. > > The design idea is to reuse the request serialization protocol edk2 uses > for communication between SMM and non-SMM code, so large chunks of the > edk2 variable driver stack can be used unmodified. Only the driver > which traps into SMM mode must be replaced by a driver which talks to > qemu instead. In the coconut-svsm project there's a likely need for coconut to provide a UEFI variable store, since we can't store plain text variables in host context for confidential VMs. Am I right in thinking that this design approach could be reused in coconut context with coconut providing the equivalent backend service, and EDK2 using the same driver to talk to either QEMU or Coconut's service ? With regards, Daniel
Hi, > > The design idea is to reuse the request serialization protocol edk2 uses > > for communication between SMM and non-SMM code, so large chunks of the > > edk2 variable driver stack can be used unmodified. Only the driver > > which traps into SMM mode must be replaced by a driver which talks to > > qemu instead. > > In the coconut-svsm project there's a likely need for coconut to > provide a UEFI variable store, since we can't store plain text > variables in host context for confidential VMs. > > Am I right in thinking that this design approach could be reused > in coconut context with coconut providing the equivalent backend > service, and EDK2 using the same driver to talk to either QEMU > or Coconut's service ? Yes, that is the idea. Right now the edk2 driver has two modes, one talking to the isa device and one talking to the sysbus device. Adding a third mode which uses a svsm protocol should be easy. Writing the efi variable service for coconut is the more challenging item here. /me plans to look into that later this year. take care, Gerd
Hi On Tue, Jan 7, 2025 at 7:34 PM Gerd Hoffmann <kraxel@redhat.com> wrote: > > This patch adds a virtual device to qemu which the uefi firmware can use > to store variables. This moves the UEFI variable management from > privileged guest code (managing vars in pflash) to the host. Main > advantage is that the need to have privilege separation in the guest > goes away. > > On x86 privileged guest code runs in SMM. It's supported by kvm, but > not liked much by various stakeholders in cloud space due to the > complexity SMM emulation brings. > > On arm privileged guest code runs in el3 (aka secure world). This is > not supported by kvm, which is unlikely to change anytime soon given > that even el2 support (nested virt) is being worked on for years and is > not yet in mainline. > > The design idea is to reuse the request serialization protocol edk2 uses I suppose this is a stable protocol. (some parts are set by the UEFI spec probably) There doesn't seem to be a defined way to query either side version or capability, I suppose this could be added later assuming an initial behaviour/magic etc. > for communication between SMM and non-SMM code, so large chunks of the > edk2 variable driver stack can be used unmodified. Only the driver > which traps into SMM mode must be replaced by a driver which talks to > qemu instead. > > A edk2 test branch can be found here (build with "-D QEMU_VARS=TRUE"). > https://github.com/kraxel/edk2/commits/devel/secure-boot-external-vars > ok, perhaps it would be nice to have some basic unit tests in qemu too. Almost none of this new code is exercised by the qemu tests yet. > The uefi-vars device re-implements the privileged edk2 protocols > (i.e. the code running in SMM mode). Typically the kind of new code that I wish would be in Rust. But I suppose it is too early yet, and you came to the same conclusion. Probably a good candidate for rewrite though! > > v2 changes: > - fully implement authenticated variables. > - various cleanups and fixes. > > enjoy & take care, > Gerd > > Gerd Hoffmann (21): > hw/uefi: add include/hw/uefi/var-service-api.h > hw/uefi: add include/hw/uefi/var-service-edk2.h > hw/uefi: add include/hw/uefi/var-service.h > hw/uefi: add var-service-guid.c > hw/uefi: add var-service-utils.c > hw/uefi: add var-service-vars.c > hw/uefi: add var-service-auth.c > hw/uefi: add var-service-policy.c > hw/uefi: add var-service-core.c > hw/uefi: add var-service-pkcs7.c > hw/uefi: add var-service-pkcs7-stub.c > hw/uefi: add var-service-siglist.c > hw/uefi: add var-service-json.c + qapi for NV vars. > hw/uefi: add trace-events > hw/uefi: add UEFI_VARS to Kconfig > hw/uefi: add to meson > hw/uefi: add uefi-vars-sysbus device > hw/uefi: add uefi-vars-isa device > hw/arm: add uefi variable support to virt machine type > docs: add uefi variable service documentation > hw/uefi: add MAINTAINERS entry > > include/hw/arm/virt.h | 2 + > include/hw/uefi/var-service-api.h | 40 ++ > include/hw/uefi/var-service-edk2.h | 227 +++++++++ > include/hw/uefi/var-service.h | 186 ++++++++ > hw/arm/virt.c | 41 ++ > hw/uefi/var-service-auth.c | 361 ++++++++++++++ > hw/uefi/var-service-core.c | 237 ++++++++++ > hw/uefi/var-service-guid.c | 99 ++++ > hw/uefi/var-service-isa.c | 91 ++++ > hw/uefi/var-service-json.c | 242 ++++++++++ > hw/uefi/var-service-pkcs7-stub.c | 16 + > hw/uefi/var-service-pkcs7.c | 436 +++++++++++++++++ > hw/uefi/var-service-policy.c | 370 +++++++++++++++ > hw/uefi/var-service-siglist.c | 212 +++++++++ > hw/uefi/var-service-sysbus.c | 90 ++++ > hw/uefi/var-service-utils.c | 241 ++++++++++ > hw/uefi/var-service-vars.c | 725 +++++++++++++++++++++++++++++ > MAINTAINERS | 6 + > docs/devel/index-internals.rst | 1 + > docs/devel/uefi-vars.rst | 66 +++ > hw/Kconfig | 1 + > hw/meson.build | 1 + > hw/uefi/Kconfig | 9 + > hw/uefi/LIMITATIONS.md | 7 + > hw/uefi/meson.build | 24 + > hw/uefi/trace-events | 17 + > meson.build | 1 + > qapi/meson.build | 1 + > qapi/qapi-schema.json | 1 + > qapi/uefi.json | 45 ++ > 30 files changed, 3796 insertions(+) > create mode 100644 include/hw/uefi/var-service-api.h > create mode 100644 include/hw/uefi/var-service-edk2.h > create mode 100644 include/hw/uefi/var-service.h > create mode 100644 hw/uefi/var-service-auth.c > create mode 100644 hw/uefi/var-service-core.c > create mode 100644 hw/uefi/var-service-guid.c > create mode 100644 hw/uefi/var-service-isa.c > create mode 100644 hw/uefi/var-service-json.c > create mode 100644 hw/uefi/var-service-pkcs7-stub.c > create mode 100644 hw/uefi/var-service-pkcs7.c > create mode 100644 hw/uefi/var-service-policy.c > create mode 100644 hw/uefi/var-service-siglist.c > create mode 100644 hw/uefi/var-service-sysbus.c > create mode 100644 hw/uefi/var-service-utils.c > create mode 100644 hw/uefi/var-service-vars.c > create mode 100644 docs/devel/uefi-vars.rst > create mode 100644 hw/uefi/Kconfig > create mode 100644 hw/uefi/LIMITATIONS.md > create mode 100644 hw/uefi/meson.build > create mode 100644 hw/uefi/trace-events > create mode 100644 qapi/uefi.json > > -- > 2.47.1 >
On Wed, Jan 08, 2025 at 03:53:21PM +0400, Marc-André Lureau wrote: > Hi > > On Tue, Jan 7, 2025 at 7:34 PM Gerd Hoffmann <kraxel@redhat.com> wrote: > > > > This patch adds a virtual device to qemu which the uefi firmware can use > > to store variables. This moves the UEFI variable management from > > privileged guest code (managing vars in pflash) to the host. Main > > advantage is that the need to have privilege separation in the guest > > goes away. > > > > On x86 privileged guest code runs in SMM. It's supported by kvm, but > > not liked much by various stakeholders in cloud space due to the > > complexity SMM emulation brings. > > > > On arm privileged guest code runs in el3 (aka secure world). This is > > not supported by kvm, which is unlikely to change anytime soon given > > that even el2 support (nested virt) is being worked on for years and is > > not yet in mainline. > > > > The design idea is to reuse the request serialization protocol edk2 uses > > I suppose this is a stable protocol. (some parts are set by the UEFI > spec probably) > > There doesn't seem to be a defined way to query either side version or > capability, I suppose this could be added later assuming an initial > behaviour/magic etc. > > > for communication between SMM and non-SMM code, so large chunks of the > > edk2 variable driver stack can be used unmodified. Only the driver > > which traps into SMM mode must be replaced by a driver which talks to > > qemu instead. > > > > A edk2 test branch can be found here (build with "-D QEMU_VARS=TRUE"). > > https://github.com/kraxel/edk2/commits/devel/secure-boot-external-vars > > > > ok, perhaps it would be nice to have some basic unit tests in qemu > too. Almost none of this new code is exercised by the qemu tests yet. > > > The uefi-vars device re-implements the privileged edk2 protocols > > (i.e. the code running in SMM mode). > > Typically the kind of new code that I wish would be in Rust. But I > suppose it is too early yet, and you came to the same conclusion. > Probably a good candidate for rewrite though! Perhaps too early for the device impl, but I would have thought the general var-service code could be done in rust today. It does not have all that much interaction with other parts of the QEMU codebase & thus wouldn't be building on the moving target of the QOM/Device abstractions. It would also be the prime part that could be shared with coconut-svsm too. > > > > > v2 changes: > > - fully implement authenticated variables. > > - various cleanups and fixes. > > > > enjoy & take care, > > Gerd > > > > Gerd Hoffmann (21): > > hw/uefi: add include/hw/uefi/var-service-api.h > > hw/uefi: add include/hw/uefi/var-service-edk2.h > > hw/uefi: add include/hw/uefi/var-service.h > > hw/uefi: add var-service-guid.c > > hw/uefi: add var-service-utils.c > > hw/uefi: add var-service-vars.c > > hw/uefi: add var-service-auth.c > > hw/uefi: add var-service-policy.c > > hw/uefi: add var-service-core.c > > hw/uefi: add var-service-pkcs7.c > > hw/uefi: add var-service-pkcs7-stub.c > > hw/uefi: add var-service-siglist.c > > hw/uefi: add var-service-json.c + qapi for NV vars. > > hw/uefi: add trace-events > > hw/uefi: add UEFI_VARS to Kconfig > > hw/uefi: add to meson > > hw/uefi: add uefi-vars-sysbus device > > hw/uefi: add uefi-vars-isa device > > hw/arm: add uefi variable support to virt machine type > > docs: add uefi variable service documentation > > hw/uefi: add MAINTAINERS entry > > > > include/hw/arm/virt.h | 2 + > > include/hw/uefi/var-service-api.h | 40 ++ > > include/hw/uefi/var-service-edk2.h | 227 +++++++++ > > include/hw/uefi/var-service.h | 186 ++++++++ > > hw/arm/virt.c | 41 ++ > > hw/uefi/var-service-auth.c | 361 ++++++++++++++ > > hw/uefi/var-service-core.c | 237 ++++++++++ > > hw/uefi/var-service-guid.c | 99 ++++ > > hw/uefi/var-service-isa.c | 91 ++++ > > hw/uefi/var-service-json.c | 242 ++++++++++ > > hw/uefi/var-service-pkcs7-stub.c | 16 + > > hw/uefi/var-service-pkcs7.c | 436 +++++++++++++++++ > > hw/uefi/var-service-policy.c | 370 +++++++++++++++ > > hw/uefi/var-service-siglist.c | 212 +++++++++ > > hw/uefi/var-service-sysbus.c | 90 ++++ > > hw/uefi/var-service-utils.c | 241 ++++++++++ > > hw/uefi/var-service-vars.c | 725 +++++++++++++++++++++++++++++ > > MAINTAINERS | 6 + > > docs/devel/index-internals.rst | 1 + > > docs/devel/uefi-vars.rst | 66 +++ > > hw/Kconfig | 1 + > > hw/meson.build | 1 + > > hw/uefi/Kconfig | 9 + > > hw/uefi/LIMITATIONS.md | 7 + > > hw/uefi/meson.build | 24 + > > hw/uefi/trace-events | 17 + > > meson.build | 1 + > > qapi/meson.build | 1 + > > qapi/qapi-schema.json | 1 + > > qapi/uefi.json | 45 ++ > > 30 files changed, 3796 insertions(+) > > create mode 100644 include/hw/uefi/var-service-api.h > > create mode 100644 include/hw/uefi/var-service-edk2.h > > create mode 100644 include/hw/uefi/var-service.h > > create mode 100644 hw/uefi/var-service-auth.c > > create mode 100644 hw/uefi/var-service-core.c > > create mode 100644 hw/uefi/var-service-guid.c > > create mode 100644 hw/uefi/var-service-isa.c > > create mode 100644 hw/uefi/var-service-json.c > > create mode 100644 hw/uefi/var-service-pkcs7-stub.c > > create mode 100644 hw/uefi/var-service-pkcs7.c > > create mode 100644 hw/uefi/var-service-policy.c > > create mode 100644 hw/uefi/var-service-siglist.c > > create mode 100644 hw/uefi/var-service-sysbus.c > > create mode 100644 hw/uefi/var-service-utils.c > > create mode 100644 hw/uefi/var-service-vars.c > > create mode 100644 docs/devel/uefi-vars.rst > > create mode 100644 hw/uefi/Kconfig > > create mode 100644 hw/uefi/LIMITATIONS.md > > create mode 100644 hw/uefi/meson.build > > create mode 100644 hw/uefi/trace-events > > create mode 100644 qapi/uefi.json > > > > -- > > 2.47.1 > > > With regards, Daniel
Hi, > > Typically the kind of new code that I wish would be in Rust. But I > > suppose it is too early yet, and you came to the same conclusion. > > Probably a good candidate for rewrite though! > > Perhaps too early for the device impl, but I would have thought > the general var-service code could be done in rust today. It does > not have all that much interaction with other parts of the QEMU > codebase & thus wouldn't be building on the moving target of the > QOM/Device abstractions. It would also be the prime part that > could be shared with coconut-svsm too. That remains to be seen. The svsm code will indeed most likely be written in rust. There are a number of noteworthy differences though: * It's a totally different environment (no_std). * Persistent storage for the vars will be different. * Crypto code will be different (probably openssl because the vTPM needs that too, possibly native rust crypto). So not fully sure the code sharing part will actually work out ... I plan to keep this in mind when designing the svsm code though, and then revisit things once I have some actual rust code for this and the rust support in qemu is more mature. take care, Gerd
Hi, > > The design idea is to reuse the request serialization protocol edk2 uses > > I suppose this is a stable protocol. (some parts are set by the UEFI > spec probably) Partly yes, partly this is edk2-internal stuff. In theory there is some freedom to change the internal parts, in practice I have not seen this changing in incompatible ways to far. > There doesn't seem to be a defined way to query either side version or > capability, I suppose this could be added later assuming an initial > behaviour/magic etc. There is a 'magic' device register, so should the need arise there is the option to define a new magic cookie for incompatible changes. > > A edk2 test branch can be found here (build with "-D QEMU_VARS=TRUE"). > > https://github.com/kraxel/edk2/commits/devel/secure-boot-external-vars > > ok, perhaps it would be nice to have some basic unit tests in qemu > too. Almost none of this new code is exercised by the qemu tests yet. I have some unit tests, they are using edk2 though. So having unit tests right from the start is somewhat difficult. I don't feel like re-implementing the guest side of the serialization protocol for the qemu unit tests. Once the edk2 changes have landed in a edk2 stable tag and qemu bundled firmware has been updated it should be relatively easy to add those tests to qemu. With updated edk2 firmware we can also add some end-to-end testing such as booting a fedora cloud image with secure boot turned on. take care, Gerd