mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-11 07:17:44 +00:00
conf: Validate user supplied aliases
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@redhat.com>
This commit is contained in:
parent
c14f1ed206
commit
e2797e3256
@ -5457,6 +5457,137 @@ 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(const virDomainDef *def,
|
||||
virHashTablePtr *aliases)
|
||||
{
|
||||
struct virDomainDefValidateAliasesData data;
|
||||
int ret = -1;
|
||||
|
||||
/* 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(const virDomainDef *def,
|
||||
virDomainDeviceDefPtr dev)
|
||||
{
|
||||
virHashTablePtr aliases = NULL;
|
||||
virDomainDeviceInfoPtr info = virDomainDeviceGetInfo(dev);
|
||||
int ret = -1;
|
||||
|
||||
if (!info || !info->alias)
|
||||
return 0;
|
||||
|
||||
if (virDomainDefValidateAliases(def, &aliases) < 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(virDomainObjPtr vm,
|
||||
virDomainDeviceDefPtr dev,
|
||||
unsigned int flags)
|
||||
{
|
||||
virDomainDefPtr persDef = NULL;
|
||||
virDomainDefPtr liveDef = NULL;
|
||||
|
||||
if (virDomainObjGetDefs(vm, flags, &liveDef, &persDef) < 0)
|
||||
return -1;
|
||||
|
||||
if (persDef &&
|
||||
virDomainDeviceValidateAliasImpl(vm->def, dev) < 0)
|
||||
return -1;
|
||||
|
||||
if (liveDef &&
|
||||
virDomainDeviceValidateAliasImpl(vm->newDef, dev) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
virDomainDeviceDefValidate(const virDomainDeviceDef *dev,
|
||||
const virDomainDef *def,
|
||||
@ -5679,6 +5810,9 @@ virDomainDefValidateInternal(const virDomainDef *def)
|
||||
if (virDomainDefGetVcpusTopology(def, NULL) < 0)
|
||||
return -1;
|
||||
|
||||
if (virDomainDefValidateAliases(def, NULL) < 0)
|
||||
return -1;
|
||||
|
||||
if (def->iommu &&
|
||||
def->iommu->intremap == VIR_TRISTATE_SWITCH_ON &&
|
||||
(def->features[VIR_DOMAIN_FEATURE_IOAPIC] != VIR_TRISTATE_SWITCH_ON ||
|
||||
|
@ -2639,6 +2639,10 @@ int virDomainDefPostParse(virDomainDefPtr def,
|
||||
virDomainXMLOptionPtr xmlopt,
|
||||
void *parseOpaque);
|
||||
|
||||
int virDomainDeviceValidateAliasForHotplug(virDomainObjPtr vm,
|
||||
virDomainDeviceDefPtr dev,
|
||||
unsigned int flags);
|
||||
|
||||
int virDomainDefValidate(virDomainDefPtr def,
|
||||
virCapsPtr caps,
|
||||
unsigned int parseFlags,
|
||||
|
@ -296,6 +296,7 @@ virDomainDeviceFindControllerModel;
|
||||
virDomainDeviceGetInfo;
|
||||
virDomainDeviceInfoIterate;
|
||||
virDomainDeviceTypeToString;
|
||||
virDomainDeviceValidateAliasForHotplug;
|
||||
virDomainDiskBusTypeToString;
|
||||
virDomainDiskByAddress;
|
||||
virDomainDiskByName;
|
||||
|
@ -8396,6 +8396,9 @@ qemuDomainAttachDeviceLiveAndConfig(virConnectPtr conn,
|
||||
if (dev == NULL)
|
||||
goto cleanup;
|
||||
|
||||
if (virDomainDeviceValidateAliasForHotplug(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
|
||||
|
Loading…
Reference in New Issue
Block a user