[libvirt] [PATCH 06/12] qemu: Extend QEMU with external TPM support
Ján Tomko
jtomko at redhat.com
Wed May 23 15:41:56 UTC 2018
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 at linux.vnet.ibm.com>
>Reviewed-by: John Ferlan <jferlan at redhat.com>
>---
> 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.
>+/*
>+ * 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?
>+ * @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.
>+ 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 ^
>+ goto cleanup;
>+ }
>+
>+ ret = 0;
>+
Jano
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: Digital signature
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20180523/60b6255f/attachment-0001.sig>
More information about the libvir-list
mailing list