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:
Michal Privoznik 2017-10-18 17:46:18 +02:00
parent c14f1ed206
commit e2797e3256
4 changed files with 142 additions and 0 deletions

View File

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

View File

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

View File

@ -296,6 +296,7 @@ virDomainDeviceFindControllerModel;
virDomainDeviceGetInfo;
virDomainDeviceInfoIterate;
virDomainDeviceTypeToString;
virDomainDeviceValidateAliasForHotplug;
virDomainDiskBusTypeToString;
virDomainDiskByAddress;
virDomainDiskByName;

View File

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