Re: [PATCH 06/12] qemu: Extend QEMU with external TPM support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 05/23/2018 11:41 AM, Ján Tomko wrote:
On Tue, May 22, 2018 at 04:44:47PM -0400, Stefan Berger wrote:
Implement functions for managing the storage of the external swtpm as well as starting and stopping it. Also implement functions to use swtpm_setup,
which simulates the manufacturing of a TPM, which includes creation of
certificates for the device.

Further, the external TPM needs storage on the host that we need to set
up before it can be run. We can clean up the host once the domain is
undefined.

This patch also implements a small layer for external device support that
calls into the TPM device layer if a domain has an attached TPM. This is
the layer we will wire up later on.


Later on meaning in other patch series? Adding it for just one device
seems excessive, but that might be my personal opinion.

Signed-off-by: Stefan Berger <stefanb@xxxxxxxxxxxxxxxxxx>
Reviewed-by: John Ferlan <jferlan@xxxxxxxxxx>
---
src/qemu/Makefile.inc.am  |   4 +
src/qemu/qemu_domain.c    |   2 +
src/qemu/qemu_extdevice.c | 154 ++++++++++
src/qemu/qemu_extdevice.h |  53 ++++
src/qemu/qemu_process.c   |  12 +
src/qemu/qemu_tpm.c       | 751 ++++++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_tpm.h       |  50 +++
7 files changed, 1026 insertions(+)
create mode 100644 src/qemu/qemu_extdevice.c
create mode 100644 src/qemu/qemu_extdevice.h
create mode 100644 src/qemu/qemu_tpm.c
create mode 100644 src/qemu/qemu_tpm.h


+/*
+ * virtTPMGetTPMStorageDir:
+ *
+ * @storagepath: directory for swtpm's persistent state
+ *
+ * Derive the 'TPMStorageDir' from the storagepath by searching
+ * for the last '/'.
+ */
+static char *
+qemuTPMGetTPMStorageDir(const char *storagepath)
+{
+    const char *tail = strrchr(storagepath, '/');
+    char *path = NULL;
+
+    if (!tail) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Could not get tail of storagedir %s"),
+                       storagepath);
+        return NULL;
+    }
+    ignore_value(VIR_STRNDUP(path, storagepath, tail - storagepath));
+
+    return path;
+}

In other places we already use mdir_name from gnulib for this
functionality.


I didn't know about this API. I will change it to that.



+/*
+ * qemuTPMCreateEmulatorStorage
+ *
+ * @storagepath: directory for swtpm's persistent state
+ * @created: a pointer to a bool that will be set to true if the
+ *           storage was created because it did not exist yet

Can't the caller call virFileExists and act accordingly?


We could, except that we have to call this function since it is adjusting access rights to files for the swtpm_user and swtpm_group.



+ * @swtpm_user: The uid that needs to be able to access the directory
+ * @swtpm_group: The gid that needs to be able to access the directory
+ *
+ * Unless the storage path for the swtpm for the given VM
+ * already exists, create it and make it accessible for the given userid.
+ * Adapt ownership of the directory and all swtpm's state files there.
+ */

[...]

+static int
+qemuTPMEmulatorPrepareHost(virDomainTPMDefPtr tpm,
+                           const char *logDir,
+                           const char *vmname,
+                           uid_t swtpm_user,
+                           gid_t swtpm_group,
+                           const char *swtpmStateDir,
+                           uid_t qemu_user,
+                           const char *shortName)
+{
+    int ret = -1;
+
+    if (qemuTPMEmulatorInit() < 0)
+        return -1;
+
+    /* create log dir ... allow 'tss' user to cd into it */
+    if (virFileMakePathWithMode(logDir, 0711) < 0)
+        return -1;
+
+    /* ... and adjust ownership */
+    if (virDirCreate(logDir, 0730, swtpm_user, swtpm_group,
+                     VIR_DIR_CREATE_ALLOW_EXIST) < 0)
+        goto cleanup;
+
+    /* create logfile name ... */
+    if (!tpm->data.emulator.logfile &&
+        virAsprintf(&tpm->data.emulator.logfile, "%s/%s-swtpm.log",
+                    logDir, vmname) < 0)

This should also use shortName.


The shortName has the ID of the domain in the name. So for short-lived logs I would say yes. Though this should be a log like the one for the VM that gets appended to every time the VM restarts. I'd rather not change this.



+        goto cleanup;
+
+    /* ... and make sure it can be accessed by swtpm_user */
+    if (virFileExists(tpm->data.emulator.logfile) &&
+        chown(tpm->data.emulator.logfile, swtpm_user, swtpm_group) < 0) {
+        virReportSystemError(errno,
+                             _("Could not chown on swtpm logfile %s"),
+                             tpm->data.emulator.logfile);
+        goto cleanup;
+    }
+
+    /*
+      create our swtpm state dir ...
+      - QEMU user needs to be able to access the socket there
+      - swtpm group needs to be able to create files there
+      - in privileged mode 0570 would be enough, for non-privileged mode
+        we need 0770
+    */
+    if (virDirCreate(swtpmStateDir, 0770, qemu_user, swtpm_group,
+                     VIR_DIR_CREATE_ALLOW_EXIST) < 0)
+        goto cleanup;
+
+    /* create the socket filename */
+    if (!tpm->data.emulator.source.data.nix.path &&
+        !(tpm->data.emulator.source.data.nix.path =
+          qemuTPMCreateEmulatorSocket(swtpmStateDir, shortName)))
+        goto cleanup;
+    tpm->data.emulator.source.type = VIR_DOMAIN_CHR_TYPE_UNIX;
+
+    ret = 0;
+
+ cleanup:
+
+    return ret;
+}
+

[...]

+static int
+qemuExtTPMStartEmulator(virQEMUDriverPtr driver,
+                        virDomainDefPtr def,
+                        qemuDomainLogContextPtr logCtxt)
+{
+    int ret = -1;
+    virCommandPtr cmd = NULL;
+    int exitstatus;
+    char *errbuf = NULL;
+    virQEMUDriverConfigPtr cfg;
+    virDomainTPMDefPtr tpm = def->tpm;
+    char *shortName = virDomainDefGetShortName(def);
+
+    if (!shortName)
+        return -1;
+
+    cfg = virQEMUDriverGetConfig(driver);
+
+    /* stop any left-over TPM emulator for this VM */
+    qemuTPMEmulatorStop(cfg->swtpmStateDir, shortName);
+
+    if (!(cmd = qemuTPMEmulatorBuildCommand(tpm, def->name, def->uuid,
+ driver->privileged,
+                                            cfg->swtpm_user,
+ cfg->swtpm_group)))
+        goto cleanup;
+
+    if (qemuExtDeviceLogCommand(logCtxt, cmd, "TPM Emulator") < 0)
+        goto cleanup;
+
+    virCommandSetErrorBuffer(cmd, &errbuf);
+
+    if (virCommandRun(cmd, &exitstatus) < 0 || exitstatus != 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Could not start 'swtpm'. exitstatus: %d, "
+                       "error: %s"), exitstatus, errbuf);

Indentation is off here  ^

Fixed.


+        goto cleanup;
+    }
+
+    ret = 0;
+

Jano


Thanks..

   Stefan

--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list




[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]

  Powered by Linux