[libvirt] [PATCH] libxl: fix vm lock overwritten bug
Michal Privoznik
mprivozn at redhat.com
Mon Jun 13 11:39:21 UTC 2016
On 12.06.2016 12:30, Wang Yufei wrote:
> In libxl driver we do virObjectRef in libxlDomainObjBeginJob,
> If virCondWaitUntil failed, it goes to error, do virObjectUnref,
> There's a chance that someone undefine the vm at the same time,
> and refs unref to zero, vm is freed in libxlDomainObjBeginJob.
> But the vm outside function is not Null, we do virObjectUnlock(vm).
> That's how we overwrite the vm memory after it's freed. I fix it.
>
> Signed-off-by: Wang Yufei <james.wangyufei at huawei.com>
> ---
> src/conf/virdomainobjlist.c | 29 ++++++++--
> src/conf/virdomainobjlist.h | 2 +
> src/libvirt_private.syms | 1 +
> src/libxl/libxl_domain.c | 18 ++-----
> src/libxl/libxl_domain.h | 5 +-
> src/libxl/libxl_driver.c | 127 ++++++++++++++++----------------------------
> src/libxl/libxl_migration.c | 14 ++---
> 7 files changed, 86 insertions(+), 110 deletions(-)
>
> diff --git a/src/conf/virdomainobjlist.c b/src/conf/virdomainobjlist.c
> index 27590c8..485671e 100644
> --- a/src/conf/virdomainobjlist.c
> +++ b/src/conf/virdomainobjlist.c
> @@ -112,24 +112,45 @@ static int virDomainObjListSearchID(const void *payload,
> return want;
> }
>
> -
> -virDomainObjPtr virDomainObjListFindByID(virDomainObjListPtr doms,
> - int id)
> +static virDomainObjPtr
> +virDomainObjListFindByIDInternal(virDomainObjListPtr doms,
> + int id,
> + bool ref)
> {
> virDomainObjPtr obj;
> virObjectLock(doms);
> obj = virHashSearch(doms->objs, virDomainObjListSearchID, &id);
> + if (ref) {
> + virObjectRef(obj);
> + virObjectUnlock(doms);
> + }
> if (obj) {
> virObjectLock(obj);
> if (obj->removing) {
> virObjectUnlock(obj);
> + if (ref)
> + virObjectUnref(obj);
> obj = NULL;
> }
> }
> - virObjectUnlock(doms);
> + if (!ref)
> + virObjectUnlock(doms);
> return obj;
> }
>
> +virDomainObjPtr
> +virDomainObjListFindByID(virDomainObjListPtr doms,
> + int id)
> +{
> + return virDomainObjListFindByIDInternal(doms, id, false);
> +}
> +
> +virDomainObjPtr
> +virDomainObjListFindByIDRef(virDomainObjListPtr doms,
> + int id)
> +{
> + return virDomainObjListFindByIDInternal(doms, id, true);
> +}
>
Okay, I've checked callers and it looks like this will not introduce ref
counting problem.
> static virDomainObjPtr
> virDomainObjListFindByUUIDInternal(virDomainObjListPtr doms,
> diff --git a/src/conf/virdomainobjlist.h b/src/conf/virdomainobjlist.h
> index c0f856c..3c59bd3 100644
> --- a/src/conf/virdomainobjlist.h
> +++ b/src/conf/virdomainobjlist.h
> @@ -34,6 +34,8 @@ virDomainObjListPtr virDomainObjListNew(void);
>
> virDomainObjPtr virDomainObjListFindByID(virDomainObjListPtr doms,
> int id);
> +virDomainObjPtr virDomainObjListFindByIDRef(virDomainObjListPtr doms,
> + int id);
> virDomainObjPtr virDomainObjListFindByUUID(virDomainObjListPtr doms,
> const unsigned char *uuid);
> virDomainObjPtr virDomainObjListFindByUUIDRef(virDomainObjListPtr doms,
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index 85b9cd1..b42e2cd 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -888,6 +888,7 @@ virDomainObjListCollect;
> virDomainObjListConvert;
> virDomainObjListExport;
> virDomainObjListFindByID;
> +virDomainObjListFindByIDRef;
> virDomainObjListFindByName;
> virDomainObjListFindByUUID;
> virDomainObjListFindByUUIDRef;
> diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c
> index 4a21f68..ec1ff51 100644
> --- a/src/libxl/libxl_domain.c
> +++ b/src/libxl/libxl_domain.c
> @@ -123,8 +123,6 @@ libxlDomainObjBeginJob(libxlDriverPrivatePtr driver ATTRIBUTE_UNUSED,
> return -1;
> then = now + LIBXL_JOB_WAIT_TIME;
>
> - virObjectRef(obj);
> -
> while (priv->job.active) {
> VIR_DEBUG("Wait normal job condition for starting job: %s",
> libxlDomainJobTypeToString(job));
> @@ -157,7 +155,6 @@ libxlDomainObjBeginJob(libxlDriverPrivatePtr driver ATTRIBUTE_UNUSED,
> virReportSystemError(errno,
> "%s", _("cannot acquire job mutex"));
>
> - virObjectUnref(obj);
> return -1;
> }
Finally. It just hasn't felt right for BeginJob & EndJob apis to grab a
reference when it should have been in fact driver API impl who did that.
Thank you for posting this patch.
>
> @@ -171,7 +168,7 @@ libxlDomainObjBeginJob(libxlDriverPrivatePtr driver ATTRIBUTE_UNUSED,
> * non-zero, false if the reference count has dropped to zero
> * and obj is disposed.
> */
> -bool
> +void
> libxlDomainObjEndJob(libxlDriverPrivatePtr driver ATTRIBUTE_UNUSED,
> virDomainObjPtr obj)
> {
> @@ -183,8 +180,6 @@ libxlDomainObjEndJob(libxlDriverPrivatePtr driver ATTRIBUTE_UNUSED,
>
> libxlDomainObjResetJob(priv);
> virCondSignal(&priv->job.cond);
> -
> - return virObjectUnref(obj);
> }
>
ACKed and pushed.
Michal
More information about the libvir-list
mailing list