A race condition can occur when virConnectClose is called parallel to the execution of the connection close callback in remoteClientCloseFunc. The race happens if the connection object is destroyed (including the mutex) while remoteClientCloseFunc is waiting for the connection mutex. After the destruction of the (non error checking) mutex remoteClientCloseFunc starts to process the callbacks. However the operations can occur against a freed (or even worse, reallocated) object. Another issue is that the closeFreeCallback is invoked even if it's NULL (this is the case for virsh). The solution is to clean out the callback pointers in virConnectDispose before destroying the mutex. This way remoteClientCloseFunc will return immediately after passing virMutexLock, thus avoiding potential data corruption. There's still the slight chance that the concluding virMutexUnlock could do harm on the freed connection object. This could be fixed using an error checking mutex which however has a much broader scope and impact. Signed-off-by: Viktor Mihajlovski <mihajlov@xxxxxxxxxxxxxxxxxx> --- src/datatypes.c | 8 +++++++- src/remote/remote_driver.c | 3 ++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/datatypes.c b/src/datatypes.c index b04e100..2358bdf 100644 --- a/src/datatypes.c +++ b/src/datatypes.c @@ -146,8 +146,14 @@ virConnectDispose(void *obj) virMutexLock(&conn->lock); - if (conn->closeFreeCallback) + if (conn->closeCallback) + conn->closeCallback = NULL; + + if (conn->closeFreeCallback) { conn->closeFreeCallback(conn->closeOpaque); + conn->closeFreeCallback = NULL; + conn->closeOpaque = NULL; + } virResetError(&conn->err); diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 3721af9..885120e 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -358,7 +358,8 @@ static void remoteClientCloseFunc(virNetClientPtr client ATTRIBUTE_UNUSED, closeCallback(conn, reason, closeOpaque); virMutexLock(&conn->lock); conn->closeDispatch = false; - if (conn->closeUnregisterCount != closeUnregisterCount) + if (conn->closeUnregisterCount != closeUnregisterCount && + closeFreeCallback) closeFreeCallback(closeOpaque); } virMutexUnlock(&conn->lock); -- 1.7.9.5 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list