[libvirt] [PATCH 4/4] libvirt-domain: add new virDomainGetSevVmMeasurement() API

Brijesh Singh brijesh.singh at amd.com
Mon Feb 26 17:53:36 UTC 2018


The virDomainGetSevVmMeasurement() can be used to retrieve the measurement
of encrypted VM launched using AMD SEV feature. The measurement is a
signature of the memory contents that can be sent to the guest owner as
an attestation that the memory was encrypted correctly by the firmware
before booting the guest.

Signed-off-by: Xiaogang Chen <Xiaogang.Chen at amd.com>
Signed-off-by: Brijesh Singh <brijesh.singh at amd.com>
---
 include/libvirt/libvirt-domain.h |  4 +++
 src/driver-hypervisor.h          |  4 +++
 src/libvirt-domain.c             | 41 +++++++++++++++++++++++++++++
 src/libvirt_public.syms          |  1 +
 src/qemu/qemu_driver.c           | 57 ++++++++++++++++++++++++++++++++++++++++
 src/qemu/qemu_monitor.c          |  8 ++++++
 src/qemu/qemu_monitor.h          |  3 +++
 src/qemu/qemu_monitor_json.c     | 33 +++++++++++++++++++++++
 src/qemu/qemu_monitor_json.h     |  2 ++
 src/remote/remote_driver.c       |  3 ++-
 src/remote/remote_protocol.x     | 17 +++++++++++-
 11 files changed, 171 insertions(+), 2 deletions(-)

diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index 4048acf38aaf..c0bcfea4723c 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -4756,4 +4756,8 @@ int virDomainSetLifecycleAction(virDomainPtr domain,
                                 unsigned int action,
                                 unsigned int flags);
 
+char *
+virDomainGetSevVmMeasurement(virDomainPtr domain,
+                             unsigned int flags);
+
 #endif /* __VIR_LIBVIRT_DOMAIN_H__ */
diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h
index ce0e2b252552..73edcd8f059f 100644
--- a/src/driver-hypervisor.h
+++ b/src/driver-hypervisor.h
@@ -1283,6 +1283,9 @@ typedef int
                                   unsigned int action,
                                   unsigned int flags);
 
+typedef char *
+(*virDrvDomainGetSevVmMeasurement)(virDomainPtr dommain,
+                                   unsigned int flags);
 
 typedef struct _virHypervisorDriver virHypervisorDriver;
 typedef virHypervisorDriver *virHypervisorDriverPtr;
@@ -1528,6 +1531,7 @@ struct _virHypervisorDriver {
     virDrvDomainSetVcpu domainSetVcpu;
     virDrvDomainSetBlockThreshold domainSetBlockThreshold;
     virDrvDomainSetLifecycleAction domainSetLifecycleAction;
+    virDrvDomainGetSevVmMeasurement domainGetSevVmMeasurement;
 };
 
 
diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
index eaec0979ad49..f285a3121548 100644
--- a/src/libvirt-domain.c
+++ b/src/libvirt-domain.c
@@ -12095,3 +12095,44 @@ int virDomainSetLifecycleAction(virDomainPtr domain,
     virDispatchError(domain->conn);
     return -1;
 }
+
+/**
+ * virDomainGetSevVmMeasurement:
+ * @domain: pointer to domain object
+ * @flags: currently unused, pass 0
+ *
+ * Get launch measurement of SEV guest VM
+ *
+ * Returns a measurement string, or NULL in case of error.
+ */
+char *
+virDomainGetSevVmMeasurement(virDomainPtr domain,
+                             unsigned int flags)
+{
+    virConnectPtr conn;
+    VIR_DOMAIN_DEBUG(domain, "flags=0x%x", flags);
+
+    virResetLastError();
+
+    virCheckDomainReturn(domain, NULL);
+    conn = domain->conn;
+
+    virCheckReadOnlyGoto(conn->flags, error);
+
+    if (conn->driver->domainGetSevVmMeasurement) {
+        char *ret;
+
+        ret = conn->driver->domainGetSevVmMeasurement(domain,
+                                                     flags);
+        if (!ret)
+            goto error;
+
+        return ret;
+    }
+
+    virReportUnsupportedError();
+
+error:
+    virDispatchError(domain->conn);
+    return NULL;
+}
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index 95df3a0dbc7b..6e956d965a26 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -783,6 +783,7 @@ LIBVIRT_3.9.0 {
 LIBVIRT_4.1.0 {
     global:
         virStoragePoolLookupByTargetPath;
+        virDomainGetSevVmMeasurement;
 } LIBVIRT_3.9.0;
 
 # .... define new API here using predicted next version number ....
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 313d730c791f..852d1f0fd2f7 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -21254,6 +21254,62 @@ qemuDomainSetLifecycleAction(virDomainPtr dom,
     return ret;
 }
 
+static char *
+qemuDomainGetSevVmMeasurement(virDomainPtr dom,
+                              unsigned int flags)
+{
+    virQEMUDriverPtr driver = dom->conn->privateData;
+    virDomainObjPtr vm;
+    char *ret = NULL, *tmp;
+
+    virCheckFlags(0, NULL);
+
+    if (!(vm = qemuDomObjFromDomain(dom)))
+        goto cleanup;
+
+    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
+        goto cleanup;
+
+    if (!virDomainObjIsActive(vm)) {
+        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                       _("domain is not running"));
+       goto endjob;
+    }
+
+    if (virDomainGetSevVmMeasurementEnsureACL(dom->conn, vm->def) < 0){
+        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                       _("get sev vm measurement is not allowed"));
+        goto cleanup;
+    }
+
+    if (vm->def->sev) {
+        goto endjob;
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("domain is not SEV guest"));
+    }
+
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, QEMU_ASYNC_JOB_NONE) < 0)
+        goto endjob;
+
+    VIR_DEBUG("query sev launch measurement");
+    if(!(tmp = qemuMonitorGetSevMeasurement(QEMU_DOMAIN_PRIVATE(vm)->mon))){
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("failed to get measurement"));
+        goto endjob;
+    }
+
+    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+        goto endjob;
+
+    ret = tmp;
+
+ endjob:
+    qemuDomainObjEndJob(driver, vm);
+
+ cleanup:
+    virDomainObjEndAPI(&vm);
+    return ret;
+}
 
 static virHypervisorDriver qemuHypervisorDriver = {
     .name = QEMU_DRIVER_NAME,
@@ -21474,6 +21530,7 @@ static virHypervisorDriver qemuHypervisorDriver = {
     .domainSetVcpu = qemuDomainSetVcpu, /* 3.1.0 */
     .domainSetBlockThreshold = qemuDomainSetBlockThreshold, /* 3.2.0 */
     .domainSetLifecycleAction = qemuDomainSetLifecycleAction, /* 3.9.0 */
+    .domainGetSevVmMeasurement = qemuDomainGetSevVmMeasurement, /* 4.2.0 */
 };
 
 
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 195248c88ae1..e3dd078e4e73 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -4400,3 +4400,11 @@ qemuMonitorSetWatchdogAction(qemuMonitorPtr mon,
 
     return qemuMonitorJSONSetWatchdogAction(mon, action);
 }
+
+char *
+qemuMonitorGetSevMeasurement(qemuMonitorPtr mon)
+{
+    QEMU_CHECK_MONITOR_NULL(mon);
+
+    return qemuMonitorJSONGetSevMeasurement(mon);
+}
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 1b2513650c58..dd0821178c47 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -1176,4 +1176,7 @@ virJSONValuePtr qemuMonitorQueryNamedBlockNodes(qemuMonitorPtr mon);
 
 int qemuMonitorSetWatchdogAction(qemuMonitorPtr mon,
                                  const char *action);
+char *
+qemuMonitorGetSevMeasurement(qemuMonitorPtr mon);
+
 #endif /* QEMU_MONITOR_H */
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 4424abfa7148..1d7f0e7c168e 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -7974,3 +7974,36 @@ qemuMonitorJSONSetWatchdogAction(qemuMonitorPtr mon,
     virJSONValueFree(reply);
     return ret;
 }
+
+char *
+qemuMonitorJSONGetSevMeasurement(qemuMonitorPtr mon)
+{
+    const char *tmp;
+    char *measurement = NULL;
+    virJSONValuePtr cmd;
+    virJSONValuePtr reply = NULL;
+    virJSONValuePtr data;
+
+    if (!(cmd = qemuMonitorJSONMakeCommand("query-sev-launch-measure", NULL)))
+         return NULL;
+
+    if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
+        goto cleanup;
+
+    if (qemuMonitorJSONCheckError(cmd, reply) < 0)
+        goto cleanup;
+
+    data = virJSONValueObjectGetObject(reply, "return");
+
+    if (!(tmp = virJSONValueObjectGetString(data, "data")))
+        goto cleanup;
+
+    if (VIR_STRDUP(measurement, tmp) < 0){
+        goto cleanup;
+    }
+
+cleanup:
+    virJSONValueFree(cmd);
+    virJSONValueFree(reply);
+    return measurement;
+}
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index 305f789902e9..b03b35ae0e8b 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -342,6 +342,8 @@ int qemuMonitorJSONGetBlockIoThrottle(qemuMonitorPtr mon,
 
 int qemuMonitorJSONSystemWakeup(qemuMonitorPtr mon);
 
+char * qemuMonitorJSONGetSevMeasurement(qemuMonitorPtr mon);
+
 int qemuMonitorJSONGetVersion(qemuMonitorPtr mon,
                               int *major,
                               int *minor,
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 9ea726dc45c0..080d244db156 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -8497,7 +8497,8 @@ static virHypervisorDriver hypervisor_driver = {
     .domainSetGuestVcpus = remoteDomainSetGuestVcpus, /* 2.0.0 */
     .domainSetVcpu = remoteDomainSetVcpu, /* 3.1.0 */
     .domainSetBlockThreshold = remoteDomainSetBlockThreshold, /* 3.2.0 */
-    .domainSetLifecycleAction = remoteDomainSetLifecycleAction /* 3.9.0 */
+    .domainSetLifecycleAction = remoteDomainSetLifecycleAction, /* 3.9.0 */
+    .domainGetSevVmMeasurement = remoteDomainGetSevVmMeasurement /* 4.2.0 */
 };
 
 static virNetworkDriver network_driver = {
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index 9dbd497b2fff..227ee8345683 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -3448,6 +3448,15 @@ struct remote_domain_set_lifecycle_action_args {
     unsigned int flags;
 };
 
+struct remote_domain_get_sev_vm_measurement_args {
+    remote_nonnull_domain dom;
+    unsigned int flags;
+};
+
+struct remote_domain_get_sev_vm_measurement_ret {
+    remote_nonnull_string sev_measurement;
+};
+
 /*----- Protocol. -----*/
 
 /* Define the program number, protocol version and procedure numbers here. */
@@ -6135,5 +6144,11 @@ enum remote_procedure {
      * @priority: high
      * @acl: storage_pool:getattr
      */
-    REMOTE_PROC_STORAGE_POOL_LOOKUP_BY_TARGET_PATH = 391
+    REMOTE_PROC_STORAGE_POOL_LOOKUP_BY_TARGET_PATH = 391,
+
+    /**
+     * @generate: both
+     * @acl: domain:read
+     */
+   REMOTE_PROC_DOMAIN_GET_SEV_VM_MEASUREMENT = 392
 };
-- 
2.14.3




More information about the libvir-list mailing list