Skip to content

GPU TEE attestation: verify GPU confidential mode and bind it to the CVM (currently unverified) #751

Description

@h4x3rotab

Problem

dstack attaches NVIDIA GPUs to CVMs but never verifies them. The CPU-side stack has no GPU/NRAS logic, and the guest OS flips the GPU to "ready" unconditionally at boot, before the workload runs. Consequences:

  • A non-confidential GPU (CC off in host BIOS, or a normal GPU) is exposed plaintext to the workload with no error that stops it — no attacker required.
  • Even a genuine CC GPU is not bound to the CVM: nothing lets a relying party (or the KMS) trust that a specific attested CVM is backed by a genuine GPU in confidential mode.

"Dual attestation" in docs/security/security-model.md is a documented expectation, not something enforced anywhere.

Full design write-up: docs/gpu-attestation-design.md (branch gpu-tee-nras-verification).

Current gaps (evidence)

  • No CPU-side GPU verification — AttestationQuote is CPU-TEE only; VerificationDetails has no GPU fields (verifier/src/verification.rs).
  • GPU attached as plain vfio-pci, no CC-mode/attestation (vmm/src/app/qemu.rs:840).
  • nvidia-smi conf-compute -srs 1 run unconditionally at boot, no cc_mode check (meta-dstack nvidia-persistenced.service).
  • app-compose.service has no dependency on GPU bring-up — the workload starts even if it fails.
  • No app-facing RPC to query/enable GPU confidentiality.

Threat model (what this closes / doesn't)

Attack Closed?
Forge GPU evidence (no NVIDIA key) ✅ cert chain + RIM, verifier in measured guest
Non-CC / CC-off GPU silently used ✅ fail-fast, cc_mode==ON
Copy attack — GPU-less instance B copies a GPU-attested value from A ✅ only if verdict lives in append-only measured pre-app state; ❌ if in report_data (app-forgeable via guest-agent/src/rpc_service.rs:327)
Stale/replayed GPU evidence ✅ fresh boot nonce
Live relay / cuckoo to a genuine remote CC GPU ❌ residual — no shipping system defeats it; needs TEE-IO/TDISP hardware. Document, don't imply "GPU proven local."

Workstreams

1. Offline local verifier (NVAT)

  • Adopt NVIDIA C++ Attestation SDK (libnvat, NVIDIA/attestation-sdk); Python nvtrust is EOL 2026-09-15.
  • Bake libnvat + pre-provisioned filesystem RIM store into the NVIDIA image (re-provision on driver/VBIOS upgrade).
  • Handle OCSP (the one online dep, ocsp.ndis.nvidia.com): in-CVM caching/replay proxy at --ocsp-url, and/or a Rego policy tolerating x-nvidia-cert-ocsp-status.

2. Binding via measured append-only state (before the app boundary)

  • dstack-util emits a gpu-attestation event committing H(nvat_eat‖cert_chain‖claims) before system-ready.
  • Verifier trusts it via the existing find_event boundary (breaks at system-ready, dstack-attest/src/attestation.rs:176) → RTMR3-bound on TDX.
  • report_data stays for freshness + RA-TLS key binding only — not the GPU verdict.

3. Fail-fast enforcement & app gate

  • dstack-gpu-attest.service: verify every configured GPU (num_gpus>0 is measured), require cc_mode==ON (reject OFF and DEVTOOLS), set -srs 1 only on pass.
  • app-compose.service Requires=+After=dstack-gpu-attest.service; fail closed (no system-ready, no workload).
  • Guest-agent RPC GetGpuAttestation() / EnsureGpuReady() so apps can confirm/enable before use.

4. KMS gating, verifier surfacing, docs

  • KMS gates key release on the gpu-attestation event (like compose-hash).
  • Verifier parses NVAT EAT/claims into VerificationDetails.
  • security-model.md: state the guarantee (measured-guest-vouches + channel-bound) and the co-location residual.

Caveats

  • SEV-SNP is blocked: no runtime measurement register (tpm_runtime_pcr()=None, has_tdx()=false); decode_app_info_sev_snp reads identity from launch-time HOST_DATA/MrConfigV3 and ignores the runtime log. SNP needs an SVSM/coconut-vTPM (PCR channel) before this works — until then SNP GPU attestation is strictly weaker than TDX. (See AMD SEV-SNP support (tracking) #713.)
  • DEVTOOLS CC mode enables CC APIs without memory encryption — must be rejected.
  • Co-location residual stands until Blackwell TEE-IO/TDISP.

Hardware validation checklist (unconfirmed in docs)

  • NVAT behavior on OCSP connection failure (fail-open vs closed); can Rego neutralize revocation?
  • OCSP nextUpdate window; warm-cache ride-through.
  • Exact libnvat env-var spellings; trust-root store overridability.
  • Does -srs 1 error or no-op on a CC-off GPU?
  • Does the driver expose SPDM KEY_EXCHANGE key (optional session-binding stretch)?
  • SNP SVSM vTPM feasibility in meta-dstack.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions