Message ID | 20231115151242.184645-17-kraxel@redhat.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | hw/uefi: add uefi variable service | expand |
On Wed, Nov 15, 2023 at 04:12:38PM +0100, Gerd Hoffmann wrote: > Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> > --- > docs/devel/index-internals.rst | 1 + > docs/devel/uefi-vars.rst | 66 ++++++++++++++++++++++++++++++++++ > hw/uefi/TODO.md | 17 +++++++++ > 3 files changed, 84 insertions(+) > create mode 100644 docs/devel/uefi-vars.rst > create mode 100644 hw/uefi/TODO.md > + > +Guest UEFI variable management > +============================== > + > +Traditional approach for UEFI Variable storage in qemu guests is to The traditional > +work as close as possible to physical hardware. That means provide providing > +pflash as storage and leave the management of variables and flash to leaving > +the guest. > + > +Secure boot support comes with the requirement that the UEFI variable > +storage must be protected against direct access by the OS. All update > +requests must pass the sanity checks. (Parts of) the firmware must > +run with a higher priviledge level than the OS so this can be enforced privilege > +by the firmware. On x86 this has been implemented using System > +Management Mode (SMM) in qemu and kvm, which again is the same > +approach taken by physical hardware. Only priviedged code running in privileged > +SMM mode is allowed to access flash storage. > + > +Communication with the firmware code running in SMM mode works by > +serializing the requests to a shared buffer, then trapping into SMM > +mode via SMI. The SMM code processes the request, stores the reply in > +the same buffer and returns. > + > +Host UEFI variable service > +========================== > + > +Instead of running the priviledged code inside the guest we can run it privileged > +on the host. The serialization protocol cen be reused. The can > +communication with the host uses a virtual device, which essentially > +allows to configure the shared buffer location and size and to trap to s/allows to configure/configures/ s/and to trap/, and traps/ > +the host to process the requests. > + > +The ``uefi-vars`` device implements the UEFI virtual device. It comes > +in ``uefi-vars-isa`` and ``uefi-vars-sysbus`` flavours. The device > +reimplements the handlers needed, specifically > +``EfiSmmVariableProtocol`` and ``VarCheckPolicyLibMmiHandler``. It > +also consumes events (``EfiEndOfDxeEventGroup``, > +``EfiEventReadyToBoot`` and ``EfiEventExitBootServices``). > + > +The advantage of the approach is that we do not need a special > +prividge level for the firmware to protect itself, i.e. it does not privilege > +depend on SMM emulation on x64, which allows to remove a bunch of s/allows to remove/allows the removal of/ > +complex code for SMM emulation from the linux kernel > +(CONFIG_KVM_SMM=n). It also allows to support secure boot on arm s/to support/support for/ > +without implementing secure world (el3) emulation in kvm. > + > +Of course there are also downsides. The added device increases the > +attack surface of the host, and we are adding some code duplication > +because we have to reimplement some edk2 functionality in qemu. > +
diff --git a/docs/devel/index-internals.rst b/docs/devel/index-internals.rst index 6f81df92bcab..eee676704cfa 100644 --- a/docs/devel/index-internals.rst +++ b/docs/devel/index-internals.rst @@ -17,6 +17,7 @@ Details about QEMU's various subsystems including how to add features to them. s390-cpu-topology s390-dasd-ipl tracing + uefi-vars vfio-migration writing-monitor-commands virtio-backends diff --git a/docs/devel/uefi-vars.rst b/docs/devel/uefi-vars.rst new file mode 100644 index 000000000000..8da69f3545af --- /dev/null +++ b/docs/devel/uefi-vars.rst @@ -0,0 +1,66 @@ +============== +UEFI variables +============== + +Guest UEFI variable management +============================== + +Traditional approach for UEFI Variable storage in qemu guests is to +work as close as possible to physical hardware. That means provide +pflash as storage and leave the management of variables and flash to +the guest. + +Secure boot support comes with the requirement that the UEFI variable +storage must be protected against direct access by the OS. All update +requests must pass the sanity checks. (Parts of) the firmware must +run with a higher priviledge level than the OS so this can be enforced +by the firmware. On x86 this has been implemented using System +Management Mode (SMM) in qemu and kvm, which again is the same +approach taken by physical hardware. Only priviedged code running in +SMM mode is allowed to access flash storage. + +Communication with the firmware code running in SMM mode works by +serializing the requests to a shared buffer, then trapping into SMM +mode via SMI. The SMM code processes the request, stores the reply in +the same buffer and returns. + +Host UEFI variable service +========================== + +Instead of running the priviledged code inside the guest we can run it +on the host. The serialization protocol cen be reused. The +communication with the host uses a virtual device, which essentially +allows to configure the shared buffer location and size and to trap to +the host to process the requests. + +The ``uefi-vars`` device implements the UEFI virtual device. It comes +in ``uefi-vars-isa`` and ``uefi-vars-sysbus`` flavours. The device +reimplements the handlers needed, specifically +``EfiSmmVariableProtocol`` and ``VarCheckPolicyLibMmiHandler``. It +also consumes events (``EfiEndOfDxeEventGroup``, +``EfiEventReadyToBoot`` and ``EfiEventExitBootServices``). + +The advantage of the approach is that we do not need a special +prividge level for the firmware to protect itself, i.e. it does not +depend on SMM emulation on x64, which allows to remove a bunch of +complex code for SMM emulation from the linux kernel +(CONFIG_KVM_SMM=n). It also allows to support secure boot on arm +without implementing secure world (el3) emulation in kvm. + +Of course there are also downsides. The added device increases the +attack surface of the host, and we are adding some code duplication +because we have to reimplement some edk2 functionality in qemu. + +usage on x86_64 (isa) +--------------------- + +.. code:: + + qemu-system-x86_64 -device uefi-vars-isa,jsonfile=/path/to/vars.json + +usage on aarch64 (sysbus) +------------------------- + +.. code:: + + qemu-system-aarch64 -M virt,x-uefi-vars=on diff --git a/hw/uefi/TODO.md b/hw/uefi/TODO.md new file mode 100644 index 000000000000..5d1cd15a798e --- /dev/null +++ b/hw/uefi/TODO.md @@ -0,0 +1,17 @@ + +uefi variable service - todo list +--------------------------------- + +* implement reading/writing variable update time. +* implement authenticated variable updates. + - used for 'dbx' updates. + +known issues and limitations +---------------------------- + +* secure boot variables are read-only + - due to auth vars not being implemented yet. +* works only on little endian hosts + - accessing structs in guest ram is done without endian conversion. +* works only for 64-bit guests + - UINTN is mapped to uint64_t, for 32-bit guests that would be uint32_t
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- docs/devel/index-internals.rst | 1 + docs/devel/uefi-vars.rst | 66 ++++++++++++++++++++++++++++++++++ hw/uefi/TODO.md | 17 +++++++++ 3 files changed, 84 insertions(+) create mode 100644 docs/devel/uefi-vars.rst create mode 100644 hw/uefi/TODO.md