[PATCH v1 08/14] conf: Validate user supplied aliases

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

 



They have to be unique within the domain. As usual, backwards
compatibility takes its price. In this particular situation we
have a device that is represented twice in a domain and so is its
alias.

Signed-off-by: Michal Privoznik <mprivozn@xxxxxxxxxx>
---
 src/conf/domain_conf.c   | 148 ++++++++++++++++++++++++++++++++++++++++++++++-
 src/conf/domain_conf.h   |   5 ++
 src/libvirt_private.syms |   1 +
 src/qemu/qemu_driver.c   |   3 +
 4 files changed, 155 insertions(+), 2 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index f1386c116..0cf67dff1 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -5458,6 +5458,145 @@ virDomainDeviceDefValidateInternal(const virDomainDeviceDef *dev,
 }
 
 
+struct virDomainDefValidateAliasesData {
+    virHashTablePtr aliases;
+};
+
+
+static int
+virDomainDeviceDefValidateAliasesIterator(virDomainDefPtr def,
+                                          virDomainDeviceDefPtr dev,
+                                          virDomainDeviceInfoPtr info,
+                                          void *opaque)
+{
+    struct virDomainDefValidateAliasesData *data = opaque;
+    const char *alias = info->alias;
+
+    if (!alias)
+        return 0;
+
+    /* Some crazy backcompat for consoles. */
+    if (def->nserials && def->nconsoles &&
+        def->consoles[0]->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE &&
+        def->consoles[0]->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL &&
+        dev->type == VIR_DOMAIN_DEVICE_CHR &&
+        virDomainChrEquals(def->serials[0], dev->data.chr))
+        return 0;
+
+    if (virHashLookup(data->aliases, alias)) {
+        virReportError(VIR_ERR_XML_ERROR,
+                       _("non unique alias detected: %s"),
+                       alias);
+        return -1;
+    }
+
+    if (virHashAddEntry(data->aliases, alias, (void *) 1) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Unable to construct table of device aliases"));
+        return -1;
+    }
+
+    return 0;
+}
+
+
+/**
+ * virDomainDefValidateAliases:
+ *
+ * Check for uniqueness of device aliases. If @aliases is not
+ * NULL return hash table of all the aliases in it.
+ *
+ * Returns 0 on success,
+ *        -1 otherwise (with error reported).
+ */
+static int
+virDomainDefValidateAliases(virDomainXMLOptionPtr xmlopt ATTRIBUTE_UNUSED,
+                            const virDomainDef *def,
+                            virHashTablePtr *aliases,
+                            unsigned int parseFlags)
+{
+    struct virDomainDefValidateAliasesData data;
+    int ret = -1;
+
+    /* validate configuration only in certain places */
+    if (parseFlags & VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE)
+        return 0;
+
+    /* We are not storing copies of aliases. Don't free them. */
+    if (!(data.aliases = virHashCreate(10, NULL)))
+        goto cleanup;
+
+    if (virDomainDeviceInfoIterateInternal((virDomainDefPtr) def,
+                                           virDomainDeviceDefValidateAliasesIterator,
+                                           true, &data) < 0)
+        goto cleanup;
+
+    if (aliases) {
+        *aliases = data.aliases;
+        data.aliases = NULL;
+    }
+
+    ret = 0;
+ cleanup:
+    virHashFree(data.aliases);
+    return ret;
+}
+
+
+static int
+virDomainDeviceValidateAliasImpl(virDomainXMLOptionPtr xmlopt,
+                                 const virDomainDef *def,
+                                 const virDomainDeviceDef *dev)
+{
+    virHashTablePtr aliases = NULL;
+    virDomainDeviceInfoPtr info = virDomainDeviceGetInfo(dev);
+    int ret = -1;
+
+    if (!info || !info->alias)
+        return 0;
+
+    if (virDomainDefValidateAliases(xmlopt, def, &aliases, 0) < 0)
+        goto cleanup;
+
+    if (virHashLookup(aliases, info->alias)) {
+        virReportError(VIR_ERR_XML_ERROR,
+                       _("non unique alias detected: %s"),
+                       info->alias);
+        goto cleanup;
+    }
+
+    ret = 0;
+ cleanup:
+
+    virHashFree(aliases);
+    return ret;
+}
+
+
+int
+virDomainDeviceValidateAliasForHotplug(virDomainXMLOptionPtr xmlopt,
+                                       virDomainObjPtr vm,
+                                       const virDomainDeviceDef *dev,
+                                       unsigned int flags)
+{
+    virDomainDefPtr persDef = NULL;
+    virDomainDefPtr liveDef = NULL;
+
+    if (virDomainObjGetDefs(vm, flags, &liveDef, &persDef) < 0)
+        return -1;
+
+    if (persDef &&
+        virDomainDeviceValidateAliasImpl(xmlopt, vm->def, dev) < 0)
+        return -1;
+
+    if (liveDef &&
+        virDomainDeviceValidateAliasImpl(xmlopt, vm->newDef, dev) < 0)
+        return -1;
+
+    return 0;
+}
+
+
 static int
 virDomainDeviceDefValidate(const virDomainDeviceDef *dev,
                            const virDomainDef *def,
@@ -5615,7 +5754,9 @@ virDomainDefCheckDuplicateDriveAddresses(const virDomainDef *def)
 
 
 static int
-virDomainDefValidateInternal(const virDomainDef *def)
+virDomainDefValidateInternal(virDomainXMLOptionPtr xmlopt,
+                             const virDomainDef *def,
+                             unsigned int parseFlags)
 {
     if (virDomainDefCheckDuplicateDiskInfo(def) < 0)
         return -1;
@@ -5626,6 +5767,9 @@ virDomainDefValidateInternal(const virDomainDef *def)
     if (virDomainDefGetVcpusTopology(def, NULL) < 0)
         return -1;
 
+    if (virDomainDefValidateAliases(xmlopt, def, NULL, parseFlags) < 0)
+        return -1;
+
     if (def->iommu &&
         def->iommu->intremap == VIR_TRISTATE_SWITCH_ON &&
         (def->features[VIR_DOMAIN_FEATURE_IOAPIC] != VIR_TRISTATE_SWITCH_ON ||
@@ -5690,7 +5834,7 @@ virDomainDefValidate(virDomainDefPtr def,
                                            true, &data) < 0)
         return -1;
 
-    if (virDomainDefValidateInternal(def) < 0)
+    if (virDomainDefValidateInternal(xmlopt, def, parseFlags) < 0)
         return -1;
 
     return 0;
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 5ff85057f..2b90e98cb 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2659,6 +2659,11 @@ int virDomainDefPostParse(virDomainDefPtr def,
                           virDomainXMLOptionPtr xmlopt,
                           void *parseOpaque);
 
+int virDomainDeviceValidateAliasForHotplug(virDomainXMLOptionPtr xmlopt,
+                                           virDomainObjPtr vm,
+                                           const virDomainDeviceDef *dev,
+                                           unsigned int flags);
+
 int virDomainDefValidate(virDomainDefPtr def,
                          virCapsPtr caps,
                          unsigned int parseFlags,
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 3b5df28e5..8449e9685 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -294,6 +294,7 @@ virDomainDeviceFindControllerModel;
 virDomainDeviceGetInfo;
 virDomainDeviceInfoIterate;
 virDomainDeviceTypeToString;
+virDomainDeviceValidateAliasForHotplug;
 virDomainDiskBusTypeToString;
 virDomainDiskByAddress;
 virDomainDiskByName;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index fb4d72236..dcd2c2109 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -8375,6 +8375,9 @@ qemuDomainAttachDeviceLiveAndConfig(virConnectPtr conn,
     if (dev == NULL)
         goto cleanup;
 
+    if (virDomainDeviceValidateAliasForHotplug(driver->xmlopt, vm, dev, flags) < 0)
+        goto cleanup;
+
     if (flags & VIR_DOMAIN_AFFECT_CONFIG &&
         flags & VIR_DOMAIN_AFFECT_LIVE) {
         /* If we are affecting both CONFIG and LIVE
-- 
2.13.6

--
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