Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions dstack/vmm/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1734,7 +1734,7 @@ fn make_vm_config(
tdx_attestation_variant_from_requirements(requirements).unwrap_or_else(|| {
cfg.cvm
.tdx_attestation_variant
.resolve(manifest.memory, image_supports_tdx_lite(image))
.resolve(image_supports_tdx_lite(image))
})
} else {
dstack_types::TdxAttestationVariant::Legacy
Expand Down Expand Up @@ -2565,17 +2565,17 @@ mod tests {
Ok(())
}

/// 1 GiB used to fall back to legacy: it is below 3 GiB and not the 2 GiB
/// exemption. That heuristic existed for images whose OVMF leaves the setup
/// header for QEMU to rewrite, which the build system no longer produces.
#[test]
fn tdx_auto_variant_uses_legacy_for_low_non_2g_memory() -> Result<()> {
fn tdx_auto_variant_uses_lite_for_low_non_2g_memory() -> Result<()> {
let config = test_tdx_config()?;
let manifest = test_manifest(1024);
let image = test_tdx_image(true);
let vm_config = make_vm_config(&config, &manifest, &image, &hex_of(0x22, 32), None, None)?;

assert!(vm_config.get("tdx_attestation_variant").is_none());
// tdx_measurement is attached whenever the image supports it, even
// when the resolved variant is legacy, so a verifier can still
// choose lite verification for this boot.
assert_eq!(vm_config["tdx_attestation_variant"], "lite");
assert!(vm_config.get("tdx_measurement").is_some());
assert_eq!(
vm_config["os_image_hash"]
Expand Down
69 changes: 32 additions & 37 deletions dstack/vmm/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,20 +272,31 @@ pub enum TdxAttestationVariantConfig {
}

impl TdxAttestationVariantConfig {
const TWO_GIB_MIB: u32 = 2 * 1024;
const THREE_GIB_MIB: u32 = 3 * 1024;

pub fn resolve(self, memory_mib: u32, image_supports_lite: bool) -> TdxAttestationVariant {
/// `auto` follows the image and nothing else.
///
/// It used to also refuse lite below 3 GiB, exempting exactly 2 GiB,
/// because QEMU's setup-header rewrite moves the initrd with guest RAM and
/// so makes the patched kernel Authenticode hash memory-dependent. Images
/// whose OVMF normalizes the setup header measure the shipped `bzImage`
/// instead, which no guest RAM size can move, and that is every image the
/// build system can now produce: it hardcodes `kernel_header_normalized`
/// and fails when the OVMF patch does not apply.
///
/// A pre-normalization image is the one case this no longer covers. The
/// no-download verifier still rejects those below the threshold, with an
/// error naming the memory sizes and telling the operator to re-emit the
/// image, so the failure is explicit rather than a silent mismatch. Set
/// `tdx_attestation_variant = "legacy"` to keep running one as is.
pub fn resolve(self, image_supports_lite: bool) -> TdxAttestationVariant {
use TdxAttestationVariant::{Legacy, Lite};
match self {
Self::Legacy => TdxAttestationVariant::Legacy,
Self::Lite => TdxAttestationVariant::Lite,
Self::Legacy => Legacy,
Self::Lite => Lite,
Self::Auto => {
if memory_mib < Self::THREE_GIB_MIB && memory_mib != Self::TWO_GIB_MIB {
TdxAttestationVariant::Legacy
} else if image_supports_lite {
TdxAttestationVariant::Lite
if image_supports_lite {
Lite
} else {
TdxAttestationVariant::Legacy
Legacy
}
}
}
Expand Down Expand Up @@ -360,9 +371,10 @@ pub struct CvmConfig {

/// TDX attestation/hash scheme policy. `legacy` keeps the existing
/// digest.txt measurement path; `lite` opts into split measurement CBOR;
/// `auto` selects `legacy` for
/// CVMs below 3 GiB except exactly 2 GiB, otherwise uses `lite` when the
/// image carries TDX measurement material and falls back to `legacy`.
/// `auto` uses `lite` when the image carries TDX measurement material and
/// falls back to `legacy` when it does not. See
/// [`TdxAttestationVariantConfig::resolve`] for why memory size no longer
/// takes part.
#[serde(default)]
pub tdx_attestation_variant: TdxAttestationVariantConfig,

Expand Down Expand Up @@ -1164,30 +1176,13 @@ mod tests {

use dstack_types::TdxAttestationVariant::{Legacy, Lite};

// Explicit settings bypass auto heuristics.
assert_eq!(
TdxAttestationVariantConfig::Legacy.resolve(2048, true),
Legacy
);
assert_eq!(TdxAttestationVariantConfig::Lite.resolve(1024, false), Lite);

// Auto avoids lite for sub-3 GiB memory sizes except exactly 2 GiB.
assert_eq!(
TdxAttestationVariantConfig::Auto.resolve(1024, true),
Legacy
);
assert_eq!(
TdxAttestationVariantConfig::Auto.resolve(2816, true),
Legacy
);
assert_eq!(TdxAttestationVariantConfig::Auto.resolve(2048, true), Lite);
// Explicit settings bypass auto entirely.
assert_eq!(TdxAttestationVariantConfig::Legacy.resolve(true), Legacy);
assert_eq!(TdxAttestationVariantConfig::Lite.resolve(false), Lite);

// At 3 GiB and above, auto follows image support.
assert_eq!(TdxAttestationVariantConfig::Auto.resolve(3072, true), Lite);
assert_eq!(
TdxAttestationVariantConfig::Auto.resolve(3072, false),
Legacy
);
// Auto follows image support alone; memory no longer takes part.
assert_eq!(TdxAttestationVariantConfig::Auto.resolve(true), Lite);
assert_eq!(TdxAttestationVariantConfig::Auto.resolve(false), Legacy);
}

fn default_config() -> Config {
Expand Down
6 changes: 4 additions & 2 deletions dstack/vmm/vmm.toml
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,10 @@ qemu_hotplug_off = false
# TDX attestation/hash scheme policy:
# - "legacy": digest.txt + legacy verifier
# - "lite": digest.txt + measurement.tdx.cbor + no-QEMU verifier
# - "auto": legacy for CVM memory below 3 GiB except exactly 2 GiB; otherwise
# lite when the image supports it, legacy when it does not.
# - "auto": lite when the image ships measurement.tdx.cbor, legacy when it does
# not. Memory size does not take part: the kernel hash only depended on it
# for images whose OVMF leaves the setup header for QEMU to rewrite, and the
# build system no longer produces those.
Comment thread
kvinwang marked this conversation as resolved.
tdx_attestation_variant = "auto"

host_share_mode = "9p"
Expand Down
Loading