core: trust SMBIOS credentials under Intel TDX
SMBIOS OEM strings are host-controlled and normally distrusted by PID1 in confidential VMs. Under TDX, however, the SMBIOS table (including Type 11) is measured into RTMR0 by the firmware (TDVF), so a remote verifier can detect host tampering with credentials delivered this way. Accept them there, while keeping fw_cfg distrusted as those items are not measured even on TDX. This lets systemd-vmspawn deliver credentials to TDX guests via the normal SMBIOS path, unlike SNP which requires the initrd cpio channel. Signed-off-by: Paul Meyer <katexochen0@gmail.com>
This commit is contained in:
@@ -378,12 +378,15 @@
|
||||
When booting a UKI, the whole UKI PE is measured into RTMR 1, and the loaded sections are
|
||||
measured individually by <command>systemd-stub</command> into RTMR 2. For direct linux boot,
|
||||
firmware measures the kernel PE into RTMR 1, and the Linux EFI stub measures initrd and
|
||||
command line into RTMR 2. A vTPM, if attached via <option>--tpm=</option>, must be treated
|
||||
as untrusted by the guest. To obtain TD Quotes for remote attestation, the guest is wired
|
||||
to the host's local TDX Quote Generation Service automatically: the unix socket
|
||||
up <filename>/run/tdx-qgs/qgs.socket</filename> is used if it exists, otherwise vsock port 4050
|
||||
on the host (cid 2). If the QGS is listening on neither channel, the guest's quote requests will
|
||||
fail.
|
||||
command line into RTMR 2. Credentials passed via <option>--set-credential=</option> or
|
||||
<option>--load-credential=</option> are delivered through SMBIOS Type 11 OEM strings, which the
|
||||
firmware (TDVF) measures into RTMR 0. This channel is measured but not confidential with respect
|
||||
to the host or VMM, since the host assembles the SMBIOS table. A vTPM, if attached via
|
||||
<option>--tpm=</option>, must be treated as untrusted by the guest. To obtain TD Quotes for
|
||||
remote attestation, the guest is wired to the host's local TDX Quote Generation Service
|
||||
automatically: the unix socket up <filename>/run/tdx-qgs/qgs.socket</filename> is used if it
|
||||
exists, otherwise vsock port 4050 on the host (cid 2). If the QGS is listening on neither
|
||||
channel, the guest's quote requests will fail.
|
||||
<xi:include href="version-info.xml" xpointer="v262"/></para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v261"/></listitem>
|
||||
|
||||
@@ -622,7 +622,14 @@ static int import_credentials_smbios(ImportCredentialsContext *c) {
|
||||
if (detect_container() > 0) /* don't access /sys/ in a container */
|
||||
return 0;
|
||||
|
||||
if (detect_confidential_virtualization() > 0) /* don't trust firmware if confidential VMs */
|
||||
/* SMBIOS OEM strings are host-controlled, so by default we don't trust them in a confidential VM.
|
||||
* Exception: under Intel TDX the SMBIOS table (including Type 11) is measured into RTMR0 by the
|
||||
* firmware (TDVF's SmbiosMeasurementDxe) on direct boot, and additionally by systemd-stub on UKI
|
||||
* boot, so a remote verifier can detect host tampering with these credentials. As with the kernel
|
||||
* command line (also host-influenced but measured), we can't and needn't locally verify the
|
||||
* measurement actually happened; the verifier anchors the firmware's behaviour via MRTD. */
|
||||
ConfidentialVirtualization cv = detect_confidential_virtualization();
|
||||
if (cv > 0 && cv != CONFIDENTIAL_VIRTUALIZATION_TDX)
|
||||
return 0;
|
||||
|
||||
for (unsigned i = 0;; i++) {
|
||||
|
||||
@@ -3579,7 +3579,7 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
|
||||
* confidential VMs. Instead, package credentials into a cpio archive appended to the initrd
|
||||
* (mirroring what systemd-stub does for ESP credentials) so they enter the launch measurement
|
||||
* via QEMU's "kernel-hashes=on". The new initrd path requires a guest PID1 that knows about
|
||||
* /.extra/system_credentials/, so we keep this scoped to SNP for now. Non-CoCo guests
|
||||
* /.extra/system_credentials/, so we keep this scoped to SNP for now. Non-SNP guests
|
||||
* continue to use the SMBIOS path below, which works with older systemd versions too.
|
||||
* Must run after all credential-mutating calls above so the cpio captures the complete set. */
|
||||
bool use_initrd_cpio = arg_confidential_computing == COCO_AMD_SEV_SNP &&
|
||||
|
||||
Reference in New Issue
Block a user