On 5/13/20 3:30 PM, Daniel Henrique Barboza wrote:
A TPM Proxy device can coexist with a regular TPM. The TPM Proxy
is also always a 'passthrough' device of the 'spapr-tpm-proxy'
model.
This patch adds a pointer to this device in the domain definition
called 'tpmproxy'. This pointer is handled like the existing
'tpm' pointer of the VIR_DOMAIN_TPM_TYPE_PASSTHROUGH type.
Cgroup, DAC/SELinux and qemu validation code was adapted to handle
this new domain device.
XML functions to parse and format this new device from/to XML
will be added in the next patch, together with the logic that
will guarantee the assumptions made in the first paragraph.
Signed-off-by: Daniel Henrique Barboza <danielhb413(a)gmail.com>
AppArmor shouldn't need anything.
Reviewed-by: Stefan Berger <stefanb(a)linux.ibm.com>
---
src/conf/domain_audit.c | 3 +++
src/conf/domain_conf.c | 18 ++++++++++++++++++
src/conf/domain_conf.h | 2 ++
src/qemu/qemu_cgroup.c | 12 +++++++++---
src/qemu/qemu_domain.c | 9 +++++----
src/qemu/qemu_validate.c | 12 ++++++++++++
src/security/security_dac.c | 14 ++++++++++++++
src/security/security_selinux.c | 11 +++++++++++
8 files changed, 74 insertions(+), 7 deletions(-)
diff --git a/src/conf/domain_audit.c b/src/conf/domain_audit.c
index 1b0abb21a0..4575f66e45 100644
--- a/src/conf/domain_audit.c
+++ b/src/conf/domain_audit.c
@@ -824,6 +824,9 @@ virDomainAuditStart(virDomainObjPtr vm, const char *reason, bool
success)
if (vm->def->tpm)
virDomainAuditTPM(vm, vm->def->tpm, "start", true);
+ if (vm->def->tpmproxy)
+ virDomainAuditTPM(vm, vm->def->tpmproxy, "start", true);
+
for (i = 0; i < vm->def->nshmems; i++)
virDomainAuditShmem(vm, vm->def->shmems[i], "start", true);
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index c201fc901d..01a32f62d1 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1165,6 +1165,7 @@ VIR_ENUM_IMPL(virDomainTPMModel,
"tpm-tis",
"tpm-crb",
"tpm-spapr",
+ "spapr-tpm-proxy",
);
VIR_ENUM_IMPL(virDomainTPMBackend,
@@ -3480,6 +3481,7 @@ void virDomainDefFree(virDomainDefPtr def)
VIR_FREE(def->mems);
virDomainTPMDefFree(def->tpm);
+ virDomainTPMDefFree(def->tpmproxy);
for (i = 0; i < def->npanics; i++)
virDomainPanicDefFree(def->panics[i]);
@@ -4318,6 +4320,12 @@ virDomainDeviceInfoIterateInternal(virDomainDefPtr def,
if ((rc = cb(def, &device, &def->tpm->info, opaque)) != 0)
return rc;
}
+ if (def->tpmproxy) {
+ device.type = VIR_DOMAIN_DEVICE_TPM;
+ device.data.tpm = def->tpmproxy;
+ if ((rc = cb(def, &device, &def->tpmproxy->info, opaque)) != 0)
+ return rc;
+ }
device.type = VIR_DOMAIN_DEVICE_PANIC;
for (i = 0; i < def->npanics; i++) {
device.data.panic = def->panics[i];
@@ -24344,6 +24352,16 @@ virDomainDefCheckABIStabilityFlags(virDomainDefPtr src,
goto error;
}
+ if (src->tpmproxy && dst->tpmproxy) {
+ if (!virDomainTPMDefCheckABIStability(src->tpmproxy, dst->tpmproxy))
+ goto error;
+ } else if (src->tpmproxy || dst->tpmproxy) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Either both target and source domains or none of "
+ "them must have TPM Proxy device present"));
+ goto error;
+ }
+
if (src->nmems != dst->nmems) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Target domain memory device count %zu "
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index ddc75d8de2..8f178ade34 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1293,6 +1293,7 @@ typedef enum {
VIR_DOMAIN_TPM_MODEL_TIS,
VIR_DOMAIN_TPM_MODEL_CRB,
VIR_DOMAIN_TPM_MODEL_SPAPR,
+ VIR_DOMAIN_TPM_MODEL_SPAPR_PROXY,
VIR_DOMAIN_TPM_MODEL_LAST
} virDomainTPMModel;
@@ -2628,6 +2629,7 @@ struct _virDomainDef {
virDomainMemballoonDefPtr memballoon;
virDomainNVRAMDefPtr nvram;
virDomainTPMDefPtr tpm;
+ virDomainTPMDefPtr tpmproxy;
virCPUDefPtr cpu;
virSysinfoDefPtr sysinfo;
virDomainRedirFilterDefPtr redirfilter;
diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
index 2e019b64af..2ed4341655 100644
--- a/src/qemu/qemu_cgroup.c
+++ b/src/qemu/qemu_cgroup.c
@@ -333,10 +333,13 @@ qemuSetupChardevCgroupCB(virDomainDefPtr def G_GNUC_UNUSED,
static int
-qemuSetupTPMCgroup(virDomainObjPtr vm)
+qemuSetupTPMCgroup(virDomainObjPtr vm,
+ virDomainTPMDefPtr dev)
{
int ret = 0;
- virDomainTPMDefPtr dev = vm->def->tpm;
+
+ if (!dev)
+ return 0;
switch (dev->type) {
case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
@@ -806,7 +809,10 @@ qemuSetupDevicesCgroup(virDomainObjPtr vm)
vm) < 0)
return -1;
- if (vm->def->tpm && qemuSetupTPMCgroup(vm) < 0)
+ if (qemuSetupTPMCgroup(vm, vm->def->tpm) < 0)
+ return -1;
+
+ if (qemuSetupTPMCgroup(vm, vm->def->tpmproxy) < 0)
return -1;
for (i = 0; i < vm->def->nhostdevs; i++) {
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index a1b250fd0b..a344f8a0e6 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -11574,11 +11574,9 @@ qemuDomainSetupAllChardevs(virQEMUDriverConfigPtr cfg
G_GNUC_UNUSED,
static int
qemuDomainSetupTPM(virQEMUDriverConfigPtr cfg G_GNUC_UNUSED,
- virDomainObjPtr vm,
+ virDomainTPMDefPtr dev,
const struct qemuDomainCreateDeviceData *data)
{
- virDomainTPMDefPtr dev = vm->def->tpm;
-
if (!dev)
return 0;
@@ -11823,7 +11821,10 @@ qemuDomainBuildNamespace(virQEMUDriverConfigPtr cfg,
if (qemuDomainSetupAllChardevs(cfg, vm, &data) < 0)
goto cleanup;
- if (qemuDomainSetupTPM(cfg, vm, &data) < 0)
+ if (qemuDomainSetupTPM(cfg, vm->def->tpm, &data) < 0)
+ goto cleanup;
+
+ if (qemuDomainSetupTPM(cfg, vm->def->tpmproxy, &data) < 0)
goto cleanup;
if (qemuDomainSetupAllGraphics(cfg, vm, &data) < 0)
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
index 584d1375b8..7210be3532 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -3602,6 +3602,7 @@ qemuValidateDomainDeviceDefTPM(virDomainTPMDef *tpm,
case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_TPM_PASSTHROUGH))
goto no_support;
+
break;
case VIR_DOMAIN_TPM_TYPE_EMULATOR:
@@ -3623,6 +3624,17 @@ qemuValidateDomainDeviceDefTPM(virDomainTPMDef *tpm,
case VIR_DOMAIN_TPM_MODEL_SPAPR:
flag = QEMU_CAPS_DEVICE_TPM_SPAPR;
break;
+ case VIR_DOMAIN_TPM_MODEL_SPAPR_PROXY:
+ if (!ARCH_IS_PPC64(def->os.arch)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("TPM Proxy model %s is only available for "
+ "PPC64 guests"),
+ virDomainTPMModelTypeToString(tpm->model));
+ return -1;
+ }
+
+ flag = QEMU_CAPS_DEVICE_SPAPR_TPM_PROXY;
+ break;
case VIR_DOMAIN_TPM_MODEL_LAST:
default:
virReportEnumRangeError(virDomainTPMModel, tpm->model);
diff --git a/src/security/security_dac.c b/src/security/security_dac.c
index bdc2d7edf3..e0542d2839 100644
--- a/src/security/security_dac.c
+++ b/src/security/security_dac.c
@@ -1980,6 +1980,13 @@ virSecurityDACRestoreAllLabel(virSecurityManagerPtr mgr,
rc = -1;
}
+ if (def->tpmproxy) {
+ if (virSecurityDACRestoreTPMFileLabel(mgr,
+ def,
+ def->tpmproxy) < 0)
+ rc = -1;
+ }
+
if (def->sev) {
if (virSecurityDACRestoreSEVLabel(mgr, def) < 0)
rc = -1;
@@ -2159,6 +2166,13 @@ virSecurityDACSetAllLabel(virSecurityManagerPtr mgr,
return -1;
}
+ if (def->tpmproxy) {
+ if (virSecurityDACSetTPMFileLabel(mgr,
+ def,
+ def->tpmproxy) < 0)
+ return -1;
+ }
+
if (def->sev) {
if (virSecurityDACSetSEVLabel(mgr, def) < 0)
return -1;
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index 9a929debe1..e80d43c0a7 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -2763,6 +2763,12 @@ virSecuritySELinuxRestoreAllLabel(virSecurityManagerPtr mgr,
rc = -1;
}
+ if (def->tpmproxy) {
+ if (virSecuritySELinuxRestoreTPMFileLabelInt(mgr, def,
+ def->tpmproxy) < 0)
+ rc = -1;
+ }
+
struct _virSecuritySELinuxChardevCallbackData chardevData = {
.mgr = mgr,
.chardevStdioLogd = chardevStdioLogd
@@ -3171,6 +3177,11 @@ virSecuritySELinuxSetAllLabel(virSecurityManagerPtr mgr,
return -1;
}
+ if (def->tpmproxy) {
+ if (virSecuritySELinuxSetTPMFileLabel(mgr, def, def->tpmproxy) < 0)
+ return -1;
+ }
+
struct _virSecuritySELinuxChardevCallbackData chardevData = {
.mgr = mgr,
.chardevStdioLogd = chardevStdioLogd