[libvirt] [PATCH v2 06/11] qemu: Grab modify job for changing domain XML
Nikolay Shirokovskiy
nshirokovskiy at virtuozzo.com
Thu Jun 6 13:51:11 UTC 2019
On 05.06.2019 12:09, Michal Privoznik wrote:
> Changing domain definition must be guarded with acquiring modify
> job. The problem is if there is a thread executing say
> qemuDomainSetMemoryStatsPeriod() which is an API that acquires
> modify job and then possibly unlock the domain object and locks
> it again. However, becasue virDomainObjAssignDef() does not take
> a job (only object lock) it may have changed the domain
> definition while the other thread unlocked the domain object in
> order to talk on the monitor. For instance:
>
> Thread1:
> 1) lookup domain object and lock it
> 2) acquire job
> 3) get pointers to live and persistent defs
> 4) unlock the domain object
> 5) talk to qemu on the monitor
>
> Thread2 (Execute qemuDomainDefineXMLFlags):
> 1) lookup domain object and lock it
> 2) virDomainObjAssignDef() which overwrites persistent def and
> frees the old one
> 3) unlock domain object
>
> Thread1:
> 6) lock the domain object again
> 7) try to access the persistent def via pointer stored in 3)
>
> Now, this will crash because the pointer from step 3) points to a
> memory that was freed.
>
> However, if Thread2 waited and acquired modify job (just like
> Thread1) then these two would serialize and no harm would be
> done.
>
> Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
> ---
> src/qemu/qemu_domain.c | 55 +++++++++++++++++++++++++++++++++++++++
> src/qemu/qemu_domain.h | 6 +++++
> src/qemu/qemu_driver.c | 27 ++++++-------------
> src/qemu/qemu_migration.c | 5 +---
> 4 files changed, 70 insertions(+), 23 deletions(-)
>
> diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
> index 4d3a8868b2..f6b677c69e 100644
> --- a/src/qemu/qemu_domain.c
> +++ b/src/qemu/qemu_domain.c
> @@ -7055,6 +7055,61 @@ virDomainDefParserConfig virQEMUDriverDomainDefParserConfig = {
> };
>
>
> +/**
> + * qemuDomainObjListAdd:
> + * @driver: qemu driver
> + * @def: domain definition
> + * @oldDef: previous domain definition
> + * @live: whether @def is live definition
> + * @flags: an bitwise-OR of virDomainObjListAdd flags
> + *
> + * Add a domain onto the list of domain object and sets its
> + * definition. If @oldDef is not NULL and there was pre-existing
> + * definition it's returned in @oldDef.
> + *
> + * In addition to that, if definition of an existing domain is
> + * changed a MODIFY job is acquired prior to that.
> + *
> + * Returns: domain object pointer on success,
> + * NULL otherwise.
> + */
> +virDomainObjPtr
> +qemuDomainObjListAdd(virQEMUDriverPtr driver,
> + virDomainDefPtr def,
> + virDomainDefPtr *oldDef,
> + bool live,
> + unsigned int flags)
> +{
> + virDomainObjPtr vm = NULL;
> +
> + if (!(vm = virDomainObjListAdd(driver->domains, def, driver->xmlopt, flags)))
> + return NULL;
> +
> + /* At this point, @vm is locked. If it doesn't have any
> + * definition set, then the call above just added it and
> + * there can't be anybody else using the object. It's safe to
> + * just set the definition without acquiring job. */
> + if (!vm->def) {
> + virDomainObjAssignDef(vm, def, live, oldDef);
> + VIR_RETURN_PTR(vm);
> + }
> +
> + /* Bad luck. Domain was pre-existing and this call is trying
> + * to update its definition. Modify job MUST be acquired. */
> + if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) {
> + qemuDomainRemoveInactive(driver, vm);
Here we can remove transient domain.
Nikolay
More information about the libvir-list
mailing list