Skip to content

ovmf: pin to edk2-stable202502 to fix RTMR0 mismatch on CVMs with memory > 2G#63

Merged
kvinwang merged 2 commits into
mainfrom
fix/ovmf-pin-stable202502
May 26, 2026
Merged

ovmf: pin to edk2-stable202502 to fix RTMR0 mismatch on CVMs with memory > 2G#63
kvinwang merged 2 commits into
mainfrom
fix/ovmf-pin-stable202502

Conversation

@kvinwang
Copy link
Copy Markdown
Collaborator

Summary

PR #50 upgraded OVMF from the 2024-09 snapshot 3a3b12cb to edk2-stable202505. Between those two, EDK2 added six commits in OvmfPkg / MdeModulePkg that rewrite the boot-time RTMR[0] event chain dstack's verifier replays:

Commit Date Effect on RTMR0
fb56dc78ef 2024-09-27 QemuFwCfg measurement → new fw_cfg BootMenu + bootorder events
45a56d7505 2025-01-29 Add BootManagerMenuApp dependency
9d9e3a2ba8 2025-01-29 Use BootManagerMenuApp as Boot0000 (changes its hash)
d433b4c8e4 2025-01-29 Register UiApp as Boot0001 (new entry)
dd5cce3e53 2025-03-04 UiApp marked as optional boot option
cd76265f1a 2025-04-10 Enable SmbiosMeasurementDxe — adds EV_EFI_HANDOFF_TABLES whose digest is sha384(filtered QEMU SMBIOS table)

dstack PR #678 modelled the resulting 17-event layout in dstack-mr and worked for 2 GB CVMs, but EV_EFI_HANDOFF_TABLES was hardcoded to a digest captured from a 2 GB CVM. Memory sizes other than 2 GB produce different SMBIOS Type 16/17/19 fields → different digest → RTMR0 mismatch on KMS verify for any CVM with memory ≠ 2 GB (8 GB / 16 GB / 32 GB all broken).

In principle dstack-mr could replicate QEMU's SMBIOS table generation in Rust and re-hash with EDK2's filter (and ship cpu_id + -smbios type=1 overrides in VmConfig), but it's a lot of code to chase Intel's TCG-PFP-v1.06 compliance commit — when the simpler fix is to stay on the EDK2 stable tag that predates the change.

Fix

edk2-stable202502 (Feb 2025) is the most recent stable tag still before all six of the layout-changing commits, while carrying ~5 months of post-2024-09 EDK2 fixes (incl. CVE patches). Switching to it gives us the legacy 13-event RTMR[0] layout that dstack-mr's Pre202505 code path handles correctly across any memory size, with zero code changes in dstack itself.

Three files:

  • meta-dstack/recipes-core/dstack-ovmf/dstack-ovmf_git.bb — bump PVedk2-stable202502, refresh SRCREV, add OVMF_VARIANT = "pre202505".
  • meta-dstack/recipes-core/dstack-ovmf/dstack-ovmf/0003-Debug-prefix-map.patchGCC_VFRPP_FLAGS context line gained -P in stable202505. Adapt the one context line so quilt applies cleanly against stable202502.
  • mkimage.sh — read OVMF_VARIANT from the recipe via bitbake-getvar and stamp it into metadata.json. dstack-mr's verifier reads this field to pick the right event-layout path (Pre202505 vs Stable202505) instead of guessing from image names.

Test plan

  • bitbake dstack-ovmf rebuilds cleanly with the patched 0003-Debug-prefix-map.patch against stable202502
  • make dist produces dstack-0.5.11.tar.gz with metadata.json carrying "ovmf_variant": "pre202505"
  • Deploy 8 GB / 2 vCPU CVM via dstack-vmm against dstack-0.5.11
  • KMS verify passes (Boot Progress: done, no RTMR0 mismatch in dstack-prepare.sh logs)
  • Live quote RTMR0 = dstack-mr measure prediction byte-for-byte (5bba6288696c9369311fe673001f386b8494ad8d9fbb918b8571eaf73ededa420c2e51f4fe3118556f8afbc1412ff1b6, 13 events on RTMR[0])

Future OVMF upgrades

Every stable tag from 202505 through 202605 (and master) still includes cd76265f1a; no upstream PCD switch exists to disable the SMBIOS measurement. When the next CVE forces an upgrade past stable202502, options are:

  1. Carry a local revert of the SmbiosMeasurementDxe.inf line in OvmfPkg/IntelTdx/IntelTdxX64.{dsc,fdf} (≈10 lines). 13- or 16-event layout depending on whether the BootManagerMenuApp + fw_cfg changes are reverted too.
  2. Replicate QEMU's SMBIOS generation in Rust + add cpu_id / -smbios fields to VmConfig.
  3. Push upstream EDK2 for a build-time PCD to gate SMBIOS measurement.

Option 1 is the most pragmatic and is left as a follow-up.

f9f11f3 ("fix: upgrade OVMF to edk2-stable202505") moved OVMF from the
2024-09 snapshot 3a3b12cb to edk2-stable202505. The six commits below
land between those two and rewrite the boot-time RTMR[0] event chain
that dstack's verifier replays:

  fb56dc78ef  QemuFwCfgLib: cache + measurement
              (adds fw_cfg BootMenu, bootorder)
  45a56d7505  OvmfPkg: add BootManagerMenuApp to dependencies
  9d9e3a2ba8  OvmfPkg: use BootManagerMenuApp as BootManagerMenu
              (Boot0000 hash changes)
  d433b4c8e4  PlatformBootManagerLib: register UiApp as optional
              boot option (new Boot0001)
  dd5cce3e53  PlatformBootManagerCommonLib: set UiApp as optional
  cd76265f1a  OvmfPkg: Enable Smbios measurement (adds
              EV_EFI_HANDOFF_TABLES whose digest is sha384 over the
              filtered QEMU SMBIOS table — content varies with -m,
              -cpu, -smbios type=1 ... so cannot be precomputed from
              VmConfig alone)

dstack PR #678 modelled the new 17-event layout in dstack-mr and worked
for 2 GB CVMs, but EV_EFI_HANDOFF_TABLES was hardcoded to the digest
captured from a 2 GB CVM. Any other memory size produced a different
SMBIOS Type 16/17/19 layout and a different digest, so e.g. 8 GB CVMs
failed KMS verify with `RTMR0 mismatch` regardless of dstack-mr fixes.

Pin to edk2-stable202502 (Feb 2025) — the most recent stable tag still
before all six commits. It produces the same 13-event RTMR[0] layout
as the legacy 3a3b12cb snapshot dstack used pre-upgrade, while still
carrying ~5 months of post-Sep-2024 EDK2 fixes (incl. CVEs).

Three changes here:

  * dstack-ovmf_git.bb: bump PV to edk2-stable202502, refresh SRCREV,
    add OVMF_VARIANT = "pre202505" so mkimage.sh can stamp the layout
    tag into image metadata.

  * 0003-Debug-prefix-map.patch: one context line (GCC_VFRPP_FLAGS)
    differs between stable202502 and stable202505. Add the missing `-P`
    flag to the patch context so quilt applies on stable202502.

  * mkimage.sh: read OVMF_VARIANT from the dstack-ovmf recipe via
    bitbake-getvar and stamp it into metadata.json. dstack-mr's verifier
    reads this field to pick the matching event-layout code path
    (Pre202505 vs Stable202505); without it, verifiers must fall back to
    parsing the image name, which gets the wrong answer for any image
    that ships pre-202505 OVMF under a 0.5.10+ name.

Validated end-to-end on tdxlab: built dstack-0.5.11 with this recipe,
deployed an 8 GB CVM through dstack-vmm, KMS verified successfully,
RTMR0 from the live quote matches dstack-mr's prediction byte-for-byte
(5bba6288696c9369311fe673001f386b8494ad8d9fbb918b8571eaf73ededa420c2e5
1f4fe3118556f8afbc1412ff1b6, 13 events on RTMR0).
Copilot AI review requested due to automatic review settings May 26, 2026 08:48
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Pins the OVMF/EDK2 version to edk2-stable202502 to avoid RTMR[0] event-chain changes introduced in edk2-stable202505 that cause KMS verification (RTMR0 mismatch) for CVMs with memory sizes other than 2GB. It also stamps an explicit OVMF “variant” into the built image metadata so verifiers can choose the correct RTMR layout logic.

Changes:

  • Downgrade/pin dstack-ovmf to edk2-stable202502 and introduce OVMF_VARIANT = "pre202505" in the recipe.
  • Adjust the 0003-Debug-prefix-map.patch context to apply cleanly against the pinned EDK2 base.
  • Update mkimage.sh to read OVMF_VARIANT from the BitBake recipe and embed it into metadata.json.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
mkimage.sh Reads OVMF_VARIANT from BitBake and stamps ovmf_variant into metadata.json.
meta-dstack/recipes-core/dstack-ovmf/dstack-ovmf/0003-Debug-prefix-map.patch Updates patch context to match the pinned EDK2 base so quilt applies cleanly.
meta-dstack/recipes-core/dstack-ovmf/dstack-ovmf_git.bb Pins EDK2 tag/commit to edk2-stable202502 and defines OVMF_VARIANT for downstream consumers.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread mkimage.sh
bitbake-getvar --value emits a single line for any defined variable, so
the `| tail -n1` was defensive padding rather than load-bearing — and
under `set -e` without `set -o pipefail` it would swallow a
bitbake-getvar failure and let `tail` exit 0 with whatever spilled out
of stderr. Match the existing DSTACK_VERSION line a few lines above
that uses the same plain assignment, so `set -e` propagates correctly
and the existing empty-string guard becomes the only thing we rely on.

Addresses Copilot review on #63.
@kvinwang kvinwang merged commit ce04e92 into main May 26, 2026
3 checks passed
@kvinwang kvinwang deleted the fix/ovmf-pin-stable202502 branch May 26, 2026 09:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants