From 81cbfc2fc3144cf331a79fc964bbfa7826344b75 Mon Sep 17 00:00:00 2001 From: Peter Krempa Date: Wed, 4 May 2022 15:00:18 +0200 Subject: [PATCH] qemu: Prepare data for FD-passed disk image sources When starting up a VM with FD-passed images we need to look up the corresponding named FD set and associate it with the virStorageSource based on the name. The association is brought into virStorageSource as security labelling code will need to access the FD to perform selinux labelling. Similarly when startup is complete in certain cases we no longer need to keep the copy of FDs and thus can close them. Signed-off-by: Peter Krempa Reviewed-by: Pavel Hrdina --- src/conf/storage_source_conf.c | 5 ++ src/conf/storage_source_conf.h | 2 + src/qemu/qemu_domain.c | 86 ++++++++++++++++++++++++++++++++++ src/qemu/qemu_domain.h | 5 ++ src/qemu/qemu_hotplug.c | 1 + 5 files changed, 99 insertions(+) diff --git a/src/conf/storage_source_conf.c b/src/conf/storage_source_conf.c index 8b67e511e2..1c11eacb9d 100644 --- a/src/conf/storage_source_conf.c +++ b/src/conf/storage_source_conf.c @@ -886,6 +886,9 @@ virStorageSourceCopy(const virStorageSource *src, return NULL; } + if (src->fdtuple) + def->fdtuple = g_object_ref(src->fdtuple); + /* ssh config passthrough for libguestfs */ def->ssh_host_key_check_disabled = src->ssh_host_key_check_disabled; def->ssh_user = g_strdup(src->ssh_user); @@ -1170,6 +1173,8 @@ virStorageSourceClear(virStorageSource *def) virStorageSourceInitiatorClear(&def->initiator); + g_clear_pointer(&def->fdtuple, g_object_unref); + /* clear everything except the class header as the object APIs * will break otherwise */ memset((char *) def + sizeof(def->parent), 0, diff --git a/src/conf/storage_source_conf.h b/src/conf/storage_source_conf.h index 9c07eef200..f981261ff4 100644 --- a/src/conf/storage_source_conf.h +++ b/src/conf/storage_source_conf.h @@ -415,6 +415,8 @@ struct _virStorageSource { * registered with a full index (vda[3]) so that we can properly report just * one event for it */ bool thresholdEventWithIndex; + + virStorageSourceFDTuple *fdtuple; }; G_DEFINE_AUTOPTR_CLEANUP_FUNC(virStorageSource, virObjectUnref); diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index e6cbd4c0cb..9fd3c39646 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -874,6 +874,7 @@ qemuDomainStorageSourcePrivateDispose(void *obj) g_clear_pointer(&priv->encinfo, qemuDomainSecretInfoFree); g_clear_pointer(&priv->httpcookie, qemuDomainSecretInfoFree); g_clear_pointer(&priv->tlsKeySecret, qemuDomainSecretInfoFree); + g_clear_pointer(&priv->fdpass, qemuFDPassFree); } @@ -10824,6 +10825,61 @@ qemuDomainPrepareDiskSourceLegacy(virDomainDiskDef *disk, } +static int +qemuDomainPrepareStorageSourceFDs(virStorageSource *src, + qemuDomainObjPrivate *priv) +{ + qemuDomainStorageSourcePrivate *srcpriv = NULL; + virStorageType actualType = virStorageSourceGetActualType(src); + virStorageSourceFDTuple *fdt = NULL; + size_t i; + + if (actualType != VIR_STORAGE_TYPE_FILE && + actualType != VIR_STORAGE_TYPE_BLOCK) + return 0; + + if (!virStorageSourceIsFD(src)) + return 0; + + if (!(fdt = virHashLookup(priv->fds, src->fdgroup))) { + virReportError(VIR_ERR_INVALID_ARG, + _("file descriptor group '%s' was not associated with the domain"), + src->fdgroup); + return -1; + } + + srcpriv = qemuDomainStorageSourcePrivateFetch(src); + + srcpriv->fdpass = qemuFDPassNew(src->nodestorage, priv); + + for (i = 0; i < fdt->nfds; i++) { + g_autofree char *idx = g_strdup_printf("%zu", i); + int tmpfd; + + if (fdt->testfds) { + /* when testing we want to use stable FD numbers provided by the test + * case */ + tmpfd = dup2(fdt->fds[i], fdt->testfds[i]); + } else { + tmpfd = dup(fdt->fds[i]); + } + + if (tmpfd < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("failed to duplicate file descriptor for fd group '%s'"), + src->fdgroup); + return -1; + } + + qemuFDPassAddFD(srcpriv->fdpass, &tmpfd, idx); + } + + src->fdtuple = g_object_ref(fdt); + + return 0; +} + + int qemuDomainPrepareStorageSourceBlockdevNodename(virDomainDiskDef *disk, virStorageSource *src, @@ -10861,6 +10917,9 @@ qemuDomainPrepareStorageSourceBlockdevNodename(virDomainDiskDef *disk, if (qemuDomainPrepareStorageSourceNFS(src) < 0) return -1; + if (qemuDomainPrepareStorageSourceFDs(src, priv) < 0) + return -1; + return 0; } @@ -12213,6 +12272,28 @@ qemuDomainSchedCoreStop(qemuDomainObjPrivate *priv) } +/** + * qemuDomainCleanupStorageSourceFD: + * @src: start of the chain to clear + * + * Cleans up the backing chain starting at @src of FD tuple structures for + * all FD-tuples which didn't request explicit relabelling and thus the struct + * is no longer needed. + */ +void +qemuDomainCleanupStorageSourceFD(virStorageSource *src) +{ + virStorageSource *n; + + for (n = src; virStorageSourceIsBacking(n); n = n->backingStore) { + if (virStorageSourceIsFD(n) && n->fdtuple) { + if (!n->fdtuple->tryRestoreLabel) + g_clear_pointer(&n->fdtuple, g_object_unref); + } + } +} + + /** * qemuDomainStartupCleanup: * @@ -12222,5 +12303,10 @@ qemuDomainSchedCoreStop(qemuDomainObjPrivate *priv) void qemuDomainStartupCleanup(virDomainObj *vm) { + size_t i; + qemuDomainSecretDestroy(vm); + + for (i = 0; i < vm->def->ndisks; i++) + qemuDomainCleanupStorageSourceFD(vm->def->disks[i]->src); } diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 11ef3e7b64..5114a311fb 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -305,6 +305,9 @@ struct _qemuDomainStorageSourcePrivate { /* key for decrypting TLS certificate */ qemuDomainSecretInfo *tlsKeySecret; + + /* file descriptors if user asks for FDs to be passed */ + qemuFDPass *fdpass; }; virObject *qemuDomainStorageSourcePrivateNew(void); @@ -925,6 +928,8 @@ int qemuDomainSecretChardevPrepare(virQEMUDriverConfig *cfg, ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4); +void qemuDomainCleanupStorageSourceFD(virStorageSource *src); + void qemuDomainStartupCleanup(virDomainObj *vm); int qemuDomainSecretPrepare(virQEMUDriver *driver, diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 6e300f547c..dba699a8a8 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1016,6 +1016,7 @@ qemuDomainAttachDeviceDiskLiveInternal(virQEMUDriver *driver, ignore_value(qemuHotplugRemoveManagedPR(vm, VIR_ASYNC_JOB_NONE)); } qemuDomainSecretDiskDestroy(disk); + qemuDomainCleanupStorageSourceFD(disk->src); return ret; }