380 lines
13 KiB
Diff
380 lines
13 KiB
Diff
From 3f4f38e2f1f05b0484035f96e61ee0de130d3050 Mon Sep 17 00:00:00 2001
|
|
Message-ID: <3f4f38e2f1f05b0484035f96e61ee0de130d3050.1759835600.git.jdenemar@redhat.com>
|
|
From: Zhenzhong Duan <zhenzhong.duan@intel.com>
|
|
Date: Thu, 10 Jul 2025 03:21:09 -0400
|
|
Subject: [PATCH] conf: Add tdx as launch security type
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
When 'tdx' is used, the VM will be launched with Intel TDX feature enabled.
|
|
TDX feature supports running encrypted VM (Trust Domain, TD) under the
|
|
control of KVM. A TD runs in a CPU model which protects the confidentiality
|
|
of its memory and its CPU state from other software.
|
|
|
|
There are four optional child elements. Element policy is 64bit hex, bit 0
|
|
is set to enable TDX debug, bit 28 is set to enable sept-ve-disable, other
|
|
bits are reserved currently. When policy isn't specified, QEMU will use its
|
|
own default value 0x10000000. mrConfigId, mrOwner and mrOwnerConfig are
|
|
base64 encoded SHA384 digest string.
|
|
|
|
For example:
|
|
|
|
<launchSecurity type='tdx'>
|
|
<policy>0x10000001</policy>
|
|
<mrConfigId>xxx</mrConfigId>
|
|
<mrOwner>xxx</mrOwner>
|
|
<mrOwnerConfig>xxx</mrOwnerConfig>
|
|
</launchSecurity>
|
|
|
|
Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
|
|
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
|
|
(cherry picked from commit e919a4dd374535511d962bee2cd64f22f1ac3fa1)
|
|
Resolves: https://issues.redhat.com/browse/RHEL-111840
|
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
|
RHEL: context
|
|
---
|
|
src/conf/domain_conf.c | 49 +++++++++++++++++++++++++++++++
|
|
src/conf/domain_conf.h | 11 +++++++
|
|
src/conf/domain_validate.c | 1 +
|
|
src/conf/schemas/domaincommon.rng | 32 ++++++++++++++++++++
|
|
src/conf/virconftypes.h | 2 ++
|
|
src/qemu/qemu_cgroup.c | 1 +
|
|
src/qemu/qemu_command.c | 3 ++
|
|
src/qemu/qemu_driver.c | 1 +
|
|
src/qemu/qemu_firmware.c | 1 +
|
|
src/qemu/qemu_namespace.c | 1 +
|
|
src/qemu/qemu_process.c | 2 ++
|
|
src/qemu/qemu_validate.c | 1 +
|
|
src/security/security_dac.c | 2 ++
|
|
13 files changed, 107 insertions(+)
|
|
|
|
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
|
|
index 286e59a4c7..92185080a9 100644
|
|
--- a/src/conf/domain_conf.c
|
|
+++ b/src/conf/domain_conf.c
|
|
@@ -1538,6 +1538,7 @@ VIR_ENUM_IMPL(virDomainLaunchSecurity,
|
|
"sev",
|
|
"sev-snp",
|
|
"s390-pv",
|
|
+ "tdx",
|
|
);
|
|
|
|
VIR_ENUM_IMPL(virDomainPstoreBackend,
|
|
@@ -3890,6 +3891,11 @@ virDomainSecDefFree(virDomainSecDef *def)
|
|
g_free(def->data.sev_snp.id_auth);
|
|
g_free(def->data.sev_snp.host_data);
|
|
break;
|
|
+ case VIR_DOMAIN_LAUNCH_SECURITY_TDX:
|
|
+ g_free(def->data.tdx.mrconfigid);
|
|
+ g_free(def->data.tdx.mrowner);
|
|
+ g_free(def->data.tdx.mrownerconfig);
|
|
+ break;
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_LAST:
|
|
@@ -13905,6 +13911,29 @@ virDomainSEVSNPDefParseXML(virDomainSEVSNPDef *def,
|
|
}
|
|
|
|
|
|
+static int
|
|
+virDomainTDXDefParseXML(virDomainTDXDef *def,
|
|
+ xmlXPathContextPtr ctxt)
|
|
+{
|
|
+ int rc;
|
|
+
|
|
+ rc = virXPathULongLongBase("string(./policy)", ctxt, 16, &def->policy);
|
|
+ if (rc == 0) {
|
|
+ def->havePolicy = true;
|
|
+ } else if (rc == -2) {
|
|
+ virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
+ _("failed to get launch security policy for launch security type TDX"));
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ def->mrconfigid = virXPathString("string(./mrConfigId)", ctxt);
|
|
+ def->mrowner = virXPathString("string(./mrOwner)", ctxt);
|
|
+ def->mrownerconfig = virXPathString("string(./mrOwnerConfig)", ctxt);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+
|
|
static virDomainSecDef *
|
|
virDomainSecDefParseXML(xmlNodePtr lsecNode,
|
|
xmlXPathContextPtr ctxt)
|
|
@@ -13928,6 +13957,10 @@ virDomainSecDefParseXML(xmlNodePtr lsecNode,
|
|
if (virDomainSEVSNPDefParseXML(&sec->data.sev_snp, ctxt) < 0)
|
|
return NULL;
|
|
break;
|
|
+ case VIR_DOMAIN_LAUNCH_SECURITY_TDX:
|
|
+ if (virDomainTDXDefParseXML(&sec->data.tdx, ctxt) < 0)
|
|
+ return NULL;
|
|
+ break;
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
|
|
break;
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
|
|
@@ -27219,6 +27252,18 @@ virDomainSEVSNPDefFormat(virBuffer *attrBuf,
|
|
}
|
|
|
|
|
|
+static void
|
|
+virDomainTDXDefFormat(virBuffer *childBuf, virDomainTDXDef *def)
|
|
+{
|
|
+ if (def->havePolicy)
|
|
+ virBufferAsprintf(childBuf, "<policy>0x%llx</policy>\n", def->policy);
|
|
+
|
|
+ virBufferEscapeString(childBuf, "<mrConfigId>%s</mrConfigId>\n", def->mrconfigid);
|
|
+ virBufferEscapeString(childBuf, "<mrOwner>%s</mrOwner>\n", def->mrowner);
|
|
+ virBufferEscapeString(childBuf, "<mrOwnerConfig>%s</mrOwnerConfig>\n", def->mrownerconfig);
|
|
+}
|
|
+
|
|
+
|
|
static void
|
|
virDomainSecDefFormat(virBuffer *buf, virDomainSecDef *sec)
|
|
{
|
|
@@ -27240,6 +27285,10 @@ virDomainSecDefFormat(virBuffer *buf, virDomainSecDef *sec)
|
|
virDomainSEVSNPDefFormat(&attrBuf, &childBuf, &sec->data.sev_snp);
|
|
break;
|
|
|
|
+ case VIR_DOMAIN_LAUNCH_SECURITY_TDX:
|
|
+ virDomainTDXDefFormat(&childBuf, &sec->data.tdx);
|
|
+ break;
|
|
+
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
|
|
break;
|
|
|
|
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
|
|
index e59d2e6c5f..1238f2001f 100644
|
|
--- a/src/conf/domain_conf.h
|
|
+++ b/src/conf/domain_conf.h
|
|
@@ -2924,6 +2924,7 @@ typedef enum {
|
|
VIR_DOMAIN_LAUNCH_SECURITY_SEV,
|
|
VIR_DOMAIN_LAUNCH_SECURITY_SEV_SNP,
|
|
VIR_DOMAIN_LAUNCH_SECURITY_PV,
|
|
+ VIR_DOMAIN_LAUNCH_SECURITY_TDX,
|
|
|
|
VIR_DOMAIN_LAUNCH_SECURITY_LAST,
|
|
} virDomainLaunchSecurity;
|
|
@@ -2958,11 +2959,21 @@ struct _virDomainSEVSNPDef {
|
|
};
|
|
|
|
|
|
+struct _virDomainTDXDef {
|
|
+ bool havePolicy;
|
|
+ unsigned long long policy;
|
|
+ char *mrconfigid;
|
|
+ char *mrowner;
|
|
+ char *mrownerconfig;
|
|
+};
|
|
+
|
|
+
|
|
struct _virDomainSecDef {
|
|
virDomainLaunchSecurity sectype;
|
|
union {
|
|
virDomainSEVDef sev;
|
|
virDomainSEVSNPDef sev_snp;
|
|
+ virDomainTDXDef tdx;
|
|
} data;
|
|
};
|
|
|
|
diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c
|
|
index 522fd0174f..2d4b79032b 100644
|
|
--- a/src/conf/domain_validate.c
|
|
+++ b/src/conf/domain_validate.c
|
|
@@ -1860,6 +1860,7 @@ virDomainDefLaunchSecurityValidate(const virDomainDef *def)
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_SEV:
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
|
|
+ case VIR_DOMAIN_LAUNCH_SECURITY_TDX:
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_LAST:
|
|
break;
|
|
}
|
|
diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng
|
|
index 1b153acc48..552b2f4ced 100644
|
|
--- a/src/conf/schemas/domaincommon.rng
|
|
+++ b/src/conf/schemas/domaincommon.rng
|
|
@@ -528,6 +528,9 @@
|
|
<value>s390-pv</value>
|
|
</attribute>
|
|
</group>
|
|
+ <group>
|
|
+ <ref name="launchSecurityTDX"/>
|
|
+ </group>
|
|
</choice>
|
|
</element>
|
|
</define>
|
|
@@ -623,6 +626,35 @@
|
|
</optional>
|
|
</interleave>
|
|
</define>
|
|
+
|
|
+ <define name="launchSecurityTDX">
|
|
+ <attribute name="type">
|
|
+ <value>tdx</value>
|
|
+ </attribute>
|
|
+ <interleave>
|
|
+ <optional>
|
|
+ <element name="policy">
|
|
+ <ref name="hexuint"/>
|
|
+ </element>
|
|
+ </optional>
|
|
+ <optional>
|
|
+ <element name="mrConfigId">
|
|
+ <data type="string"/>
|
|
+ </element>
|
|
+ </optional>
|
|
+ <optional>
|
|
+ <element name="mrOwner">
|
|
+ <data type="string"/>
|
|
+ </element>
|
|
+ </optional>
|
|
+ <optional>
|
|
+ <element name="mrOwnerConfig">
|
|
+ <data type="string"/>
|
|
+ </element>
|
|
+ </optional>
|
|
+ </interleave>
|
|
+ </define>
|
|
+
|
|
<!--
|
|
Enable or disable perf events for the domain. For each
|
|
of the events the following rules apply:
|
|
diff --git a/src/conf/virconftypes.h b/src/conf/virconftypes.h
|
|
index 59be61cea4..d46da4bdda 100644
|
|
--- a/src/conf/virconftypes.h
|
|
+++ b/src/conf/virconftypes.h
|
|
@@ -216,6 +216,8 @@ typedef struct _virDomainSEVDef virDomainSEVDef;
|
|
|
|
typedef struct _virDomainSEVSNPDef virDomainSEVSNPDef;
|
|
|
|
+typedef struct _virDomainTDXDef virDomainTDXDef;
|
|
+
|
|
typedef struct _virDomainSecDef virDomainSecDef;
|
|
|
|
typedef struct _virDomainShmemDef virDomainShmemDef;
|
|
diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
|
|
index f3c85d65e8..03c1c76ec4 100644
|
|
--- a/src/qemu/qemu_cgroup.c
|
|
+++ b/src/qemu/qemu_cgroup.c
|
|
@@ -865,6 +865,7 @@ qemuSetupDevicesCgroup(virDomainObj *vm)
|
|
return -1;
|
|
break;
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
|
|
+ case VIR_DOMAIN_LAUNCH_SECURITY_TDX:
|
|
break;
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_LAST:
|
|
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
|
|
index 243729800b..6c5e1926a5 100644
|
|
--- a/src/qemu/qemu_command.c
|
|
+++ b/src/qemu/qemu_command.c
|
|
@@ -6990,6 +6990,7 @@ qemuBuildMachineCommandLine(virCommand *cmd,
|
|
}
|
|
break;
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
|
|
+ case VIR_DOMAIN_LAUNCH_SECURITY_TDX:
|
|
virBufferAddLit(&buf, ",confidential-guest-support=lsec0");
|
|
break;
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
|
|
@@ -9766,6 +9767,8 @@ qemuBuildSecCommandLine(virDomainObj *vm, virCommand *cmd,
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
|
|
return qemuBuildPVCommandLine(vm, cmd);
|
|
break;
|
|
+
|
|
+ case VIR_DOMAIN_LAUNCH_SECURITY_TDX:
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_LAST:
|
|
virReportEnumRangeError(virDomainLaunchSecurity, sec->sectype);
|
|
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
|
|
index 13e2838f19..7d0c39c89f 100644
|
|
--- a/src/qemu/qemu_driver.c
|
|
+++ b/src/qemu/qemu_driver.c
|
|
@@ -19174,6 +19174,7 @@ qemuDomainGetLaunchSecurityInfo(virDomainPtr domain,
|
|
goto cleanup;
|
|
break;
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
|
|
+ case VIR_DOMAIN_LAUNCH_SECURITY_TDX:
|
|
break;
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_LAST:
|
|
diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c
|
|
index 2d0ec0b4fa..6c65a2751b 100644
|
|
--- a/src/qemu/qemu_firmware.c
|
|
+++ b/src/qemu/qemu_firmware.c
|
|
@@ -1371,6 +1371,7 @@ qemuFirmwareMatchDomain(const virDomainDef *def,
|
|
}
|
|
break;
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
|
|
+ case VIR_DOMAIN_LAUNCH_SECURITY_TDX:
|
|
break;
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_LAST:
|
|
diff --git a/src/qemu/qemu_namespace.c b/src/qemu/qemu_namespace.c
|
|
index 59421ec9d1..f72da83929 100644
|
|
--- a/src/qemu/qemu_namespace.c
|
|
+++ b/src/qemu/qemu_namespace.c
|
|
@@ -665,6 +665,7 @@ qemuDomainSetupLaunchSecurity(virDomainObj *vm,
|
|
VIR_DEBUG("Set up launch security for SEV");
|
|
break;
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
|
|
+ case VIR_DOMAIN_LAUNCH_SECURITY_TDX:
|
|
break;
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_LAST:
|
|
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
|
|
index a78aa8569d..7586248329 100644
|
|
--- a/src/qemu/qemu_process.c
|
|
+++ b/src/qemu/qemu_process.c
|
|
@@ -6856,6 +6856,7 @@ qemuProcessPrepareDomain(virQEMUDriver *driver,
|
|
return -1;
|
|
break;
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
|
|
+ case VIR_DOMAIN_LAUNCH_SECURITY_TDX:
|
|
break;
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_LAST:
|
|
@@ -6928,6 +6929,7 @@ qemuProcessPrepareLaunchSecurityGuestInput(virDomainObj *vm)
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_SEV_SNP:
|
|
break;
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
|
|
+ case VIR_DOMAIN_LAUNCH_SECURITY_TDX:
|
|
return 0;
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_LAST:
|
|
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
|
|
index ddfb14399a..34bb7e45c7 100644
|
|
--- a/src/qemu/qemu_validate.c
|
|
+++ b/src/qemu/qemu_validate.c
|
|
@@ -1391,6 +1391,7 @@ qemuValidateDomainDef(const virDomainDef *def,
|
|
return -1;
|
|
}
|
|
break;
|
|
+ case VIR_DOMAIN_LAUNCH_SECURITY_TDX:
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_LAST:
|
|
virReportEnumRangeError(virDomainLaunchSecurity, def->sec->sectype);
|
|
diff --git a/src/security/security_dac.c b/src/security/security_dac.c
|
|
index b4d61bc576..bf849090a7 100644
|
|
--- a/src/security/security_dac.c
|
|
+++ b/src/security/security_dac.c
|
|
@@ -2017,6 +2017,7 @@ virSecurityDACRestoreAllLabel(virSecurityManager *mgr,
|
|
rc = -1;
|
|
break;
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
|
|
+ case VIR_DOMAIN_LAUNCH_SECURITY_TDX:
|
|
break;
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_LAST:
|
|
@@ -2259,6 +2260,7 @@ virSecurityDACSetAllLabel(virSecurityManager *mgr,
|
|
return -1;
|
|
break;
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
|
|
+ case VIR_DOMAIN_LAUNCH_SECURITY_TDX:
|
|
break;
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
|
|
case VIR_DOMAIN_LAUNCH_SECURITY_LAST:
|
|
--
|
|
2.51.0
|