[vfio-users] OVMF secureboot question.

Laszlo Ersek lersek at redhat.com
Fri Aug 11 15:57:54 UTC 2017


On 08/11/17 17:05, Hagbard Celine wrote:
> 2017-08-11 13:28 GMT+01:00, Laszlo Ersek <lersek at redhat.com>:
>> On 08/11/17 12:50, Hagbard Celine wrote:
>>> Hi, I used to update at every new version form kraxel.org, but at one
>>> point I had to stop updating due to secure-boot changes. As far as I
>>> could see, Q35 was needed for secure-boot on newer versions due to
>>> i440FX not emulating SMM.
>>>
>>> Today I did a search to see if anything had changed on the i440FX
>>> front, which it had not, but I fount this mail:
>>> https://lists.nongnu.org/archive/html/qemu-devel/2017-07/msg00942.html
>>> Wherein the important part for me is the following sub-quote:
>>> --snip
>>> OVMF's default upstream build works fine with
>>> i440fx. But, if you build OVMF with "-D SMM_REQUIRE" -- which is
>>> required for making "-D SECURE_BOOT_ENABLE" actually secure --,
>>> --snip
>>>
>>> Does this say that there exits a build that will let me update my OVMF
>>> and keep i440FX with not-actually-secure secure-boot as with older
>>> version? If so, where can I download this build?
>>>
>>> The reason I need this is:
>>> -I got software that needs to believe it runs on a secure-boot
>>> environment.
>>> -If I change to Q35 I get noticeable degraded performance in VM
>>> -Windows-licensing seriously dislikes having the chipset swapped, one
>>> time I almost totally lost my licence after changing chipset in Qemu.
>>
>> Some time after the implementation of SMM in all of KVM, QEMU (q35
>> only), and OVMF, all of the OVMF builds that I have any connection to
>> started limiting the Secure Boot feature to builds that also enforced
>> SMM_REQUIRE. This is because we shouldn't distribute a fw binary any
>> longer that offers the Secure Boot feature without the means to enforce
>> its security.
>>
>> If you consciously want to do this, you can build OVMF from source. Add
>> -D SECURE_BOOT_ENABLE to the build command line, without adding -D
>> SMM_REQUIRE. The resultant firmware binary will offer the Secure Boot
>> software interfaces, and it will run on both i440fx and Q35. However, a
>> malicious guest OS component will be able to circumvent any Secure Boot
>> settings, via direct hardware access to the varstore pflash chip, and/or
>> to the S3 LockBox data structure in normal RAM (if you use S3 within the
>> guest).
> 
> As I understand varstore pflash is the OVMF_VARS.fd file.

No, OVMF_VARS.fd is a varstore *template*. It is a preformatted,
pristine / "logically empty" variable store file that is built as part
of the build process, and is tied to the other build output file, the
OVMF_CODE.fd binary executable.

"OVMF_VARS.fd" is saved from the build as a *template*, for new virtual
machines that are created with "OVMF_CODE.fd" being their firmware
binary. "OVMF_CODE.fd" may be in use (read-only) by several VMs at the
time. "OVMF_VARS.fd" is *never* in use by any VM at all; it is used by
libvirt (or by custom QEMU wrapper scripts) to instantiate a private
variable store file for the VM being created. Once created, the VM never
looks at "OVMF_VARS.fd", it only uses its private copy (which
immediately diverges from the pristine template, of course) under
/var/lib/libvirt/qemu/nvram/.

> Do it's
> content change during normal operation of a Windows guest?

"OVMF_VARS.fd" should never change, as it is a template.

The VM's private copy of it (that is, the VM's own variable store file)
changes all the time, even without booting a guest OS. Modules in the
firmware read and write non-volatile UEFI variables in it during boot.

Some user-visible configuration lives in it too, of course; UEFI boot
options, Secure Boot certificates, etc.

> My idea was
> keeping a backup that I diff against the live version, to add a little
> more security than I have today.

I'm not sure I understand clearly what you mean to back up, so let me
approach this from to angles:

(1) When you update your firmware package, you get a new OVMF_CODE.fd
and a new OVMF_VARS.fd. Existing VMs will totally ignore the new
OVMF_VARS.fd. (Most of the time the "new" OVMF_VARS.fd template will be
totally identical to the version you had before.) Existing domains will
start using the new OVMF_CODE.fd when they are powered down, and booted
again. The new OVMF_CODE.fd will operate upon the VMs' preexistent
variable store files, which were created from the previously installed
OVMF_VARS.fd template.

Most of the time such upgrades are transparent, because the new
OVMF_CODE.fd is compatible with the previous OVMF_VARS.fd internal
layout. However, there are kinds of OVMF_CODE.fd changes that are
incompatible with preexistent varstore files. This incompatibility has
nice properties, such as:

- It is not predictable what feature or change will cause
incompatibility. It's case by case.

- If you try to boot an OVMF_CODE.fd upon a varstore file that is
incompatible with it, you won't get a nice error message. Most likely
your VM will crash horribly.

- Generally speaking, there is no way to query externally whether an
OVMF_CODE.fd is compatible with a given variable store.

- There are no utilities that convert a variable store from one layout
(matching a given firmware binary) to another layout (matching another
firmware binary).

Therefore, when such an incompatible change is implemented, it falls
upon package distributors to protect their users from breakage. The most
common method is to:
-  package the new (incompatible) OVMF_CODE.fd under a different
filename, hopefully one that reflects the new (incompatible) feature,
- optionally continue updating and shipping the old (compatible) build
of OVMF as well -- excluding the incompatible feature.

I can give you two examples:

- When upstream OVMF switched to the 4MB cumulative build, I notified
Gerd (kraxel repo) and Cole (Fedora package) to stick the -D FD_SIZE_2MB
build option in their SPEC files. This was to protect you guys from OVMF
breaking horribly at the next rebase to upstream. Of course, you don't
get the benefits of the 4MB build, but those benefits are totally
irrelevant for individual end-users.

- In RHEL-7.3 OVMF was tech preview (-> unsupported). In RHEL-7.4 it has
become supported, but for that we also needed the 4MB feature. Because
the previous shipped version of OVMF still used the (then solely
available) 2MB build, *normally* we would have had to continue shipping
that in 7.4, *plus* the new 4MB build (under a different filename).
However, given that in 7.3 OVMF was unsupported, we simply dropped the
2MB build (and started offering the 4MB build under a different
filename). For an existent VM that used to rely on the 2MB firmware
binary, this meant that updates would simply stop arriving.

Now, in your particular case, after adding *just* -D SECURE_BOOT_ENABLE
to the build command line, and keeping -D FD_SIZE_2MB intact, there
should be no incompatibility. (A few years ago I would have said
different.) You should be able to continue using your preexistent
varstore file with your manually rebuilt OVMF_CODE.fd binary. Also, the
OVMF_VARS.fd varstore template that comes out of your local build should
be identical to what you have installed from Gerd's or Fedora's RPM.

(2) With regard to backing up a live variable store file (i.e. one that
lives under /var/lib/libvirt/qemu/nvram). This is a valid idea, but the
"backup" scope is much larger than that. Normally what a user wants here
is snapshots of the entire VM, including domain XML configuration,
varstore, disk(s), and if the VM was running at the time of
snapshotting, memory contents. Unfortunately, neither QEMU nor libvirt
support snapshotting pflash chips (... in a sensible manner), so this
won't work. (Newer versions of libvirt will even openly refuse a
snapshot request.)

So, for now, if you want to back up your varstore file separately,
that's not a bad idea. But, it's also not tragic if you lose a varstore
file; you (and libvirt) can recreate it from the pristine template, and
then the firmware and the guest OS can recreate most of the variables in
it. (You can re-enroll the Secure Boot certificates manually.)

Re: diffing varstore files between each other: the output is mostly
unconsumable for humans. The varstore wire format is the composition of
three or four binary abstractions (= layers of drivers in the firmware).
It's basically an opaque hexdump that is hard to read even if you know
exactly what artifact you are looking for.

>> If you decide to build OVMF from source, and have used Kraxel's RPMs
>> thus far, a caveat: don't forget to add -D FD_SIZE_2MB as well to your
>> build command line. Upstream OVMF has switched to a 4MB combined flash
>> size, which is not compatible with preexistent varstore files that were
>> created for a 2MB combined flash size. (This is another example why the
>> "nvram" stanza in "/etc/libvirt/qemu.conf" associates firmware binaries
>> with their matching varstore templates.) So, if you plan to switch over
>> an existent domain (preserving its current varstore file), then pass -D
>> FD_SIZE_2MB too.
>>
>> Thanks,
>> Laszlo
>>
> 
> Got my new OVMF build now, thanks.

Great, thanks!
Laszlo




More information about the vfio-users mailing list