mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-08 20:51:26 +00:00
lib: Grab write lock when modifying list of domains
In some places where virDomainObjListForEach() is called the passed callback calls virDomainObjListRemoveLocked(). Well, this is unsafe, because the former only grabs a read lock but the latter modifies the list. I've identified the following unsafe calls: - qemuProcessReconnectAll() - libxlReconnectDomains() The rest seem to be safe. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> Reviewed-by: Ján Tomko <jtomko@redhat.com>
This commit is contained in:
parent
56f024f457
commit
d301bc8d08
@ -114,7 +114,7 @@ bhyveAutostartDomains(bhyveConnPtr driver)
|
|||||||
|
|
||||||
struct bhyveAutostartData data = { driver, conn };
|
struct bhyveAutostartData data = { driver, conn };
|
||||||
|
|
||||||
virDomainObjListForEach(driver->domains, bhyveAutostartDomain, &data);
|
virDomainObjListForEach(driver->domains, false, bhyveAutostartDomain, &data);
|
||||||
|
|
||||||
virObjectUnref(conn);
|
virObjectUnref(conn);
|
||||||
}
|
}
|
||||||
|
@ -466,7 +466,7 @@ virBhyveProcessReconnectAll(bhyveConnPtr driver)
|
|||||||
data.driver = driver;
|
data.driver = driver;
|
||||||
data.kd = kd;
|
data.kd = kd;
|
||||||
|
|
||||||
virDomainObjListForEach(driver->domains, virBhyveProcessReconnect, &data);
|
virDomainObjListForEach(driver->domains, false, virBhyveProcessReconnect, &data);
|
||||||
|
|
||||||
kvm_close(kd);
|
kvm_close(kd);
|
||||||
}
|
}
|
||||||
|
@ -818,24 +818,32 @@ virDomainObjListHelper(void *payload,
|
|||||||
/**
|
/**
|
||||||
* virDomainObjListForEach:
|
* virDomainObjListForEach:
|
||||||
* @doms: Pointer to the domain object list
|
* @doms: Pointer to the domain object list
|
||||||
|
* @modify: Whether to lock @doms for modify operation
|
||||||
* @callback: callback to run over each domain on the list
|
* @callback: callback to run over each domain on the list
|
||||||
* @opaque: opaque data to pass to @callback
|
* @opaque: opaque data to pass to @callback
|
||||||
*
|
*
|
||||||
* For every domain on the list (@doms) run @callback on it. If
|
* For every domain on the list (@doms) run @callback on it. If
|
||||||
* @callback fails (i.e. returns a negative value), the iteration
|
* @callback fails (i.e. returns a negative value), the iteration
|
||||||
* carries still on until all domains are visited.
|
* carries still on until all domains are visited. Moreover, if
|
||||||
|
* @callback wants to modify the list of domains (@doms) then
|
||||||
|
* @modify must be set to true.
|
||||||
*
|
*
|
||||||
* Returns: 0 on success,
|
* Returns: 0 on success,
|
||||||
* -1 otherwise.
|
* -1 otherwise.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
virDomainObjListForEach(virDomainObjListPtr doms,
|
virDomainObjListForEach(virDomainObjListPtr doms,
|
||||||
|
bool modify,
|
||||||
virDomainObjListIterator callback,
|
virDomainObjListIterator callback,
|
||||||
void *opaque)
|
void *opaque)
|
||||||
{
|
{
|
||||||
struct virDomainListIterData data = {
|
struct virDomainListIterData data = {
|
||||||
callback, opaque, 0,
|
callback, opaque, 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (modify)
|
||||||
|
virObjectRWLockWrite(doms);
|
||||||
|
else
|
||||||
virObjectRWLockRead(doms);
|
virObjectRWLockRead(doms);
|
||||||
virHashForEach(doms->objs, virDomainObjListHelper, &data);
|
virHashForEach(doms->objs, virDomainObjListHelper, &data);
|
||||||
virObjectRWUnlock(doms);
|
virObjectRWUnlock(doms);
|
||||||
|
@ -91,6 +91,7 @@ typedef int (*virDomainObjListIterator)(virDomainObjPtr dom,
|
|||||||
void *opaque);
|
void *opaque);
|
||||||
|
|
||||||
int virDomainObjListForEach(virDomainObjListPtr doms,
|
int virDomainObjListForEach(virDomainObjListPtr doms,
|
||||||
|
bool modify,
|
||||||
virDomainObjListIterator callback,
|
virDomainObjListIterator callback,
|
||||||
void *opaque);
|
void *opaque);
|
||||||
|
|
||||||
|
@ -497,7 +497,7 @@ libxlReconnectDomain(virDomainObjPtr vm,
|
|||||||
static void
|
static void
|
||||||
libxlReconnectDomains(libxlDriverPrivatePtr driver)
|
libxlReconnectDomains(libxlDriverPrivatePtr driver)
|
||||||
{
|
{
|
||||||
virDomainObjListForEach(driver->domains, libxlReconnectDomain, driver);
|
virDomainObjListForEach(driver->domains, true, libxlReconnectDomain, driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -800,10 +800,12 @@ libxlStateInitialize(bool privileged,
|
|||||||
NULL, NULL) < 0)
|
NULL, NULL) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
virDomainObjListForEach(libxl_driver->domains, libxlAutostartDomain,
|
virDomainObjListForEach(libxl_driver->domains, false,
|
||||||
|
libxlAutostartDomain,
|
||||||
libxl_driver);
|
libxl_driver);
|
||||||
|
|
||||||
virDomainObjListForEach(libxl_driver->domains, libxlDomainManagedSaveLoad,
|
virDomainObjListForEach(libxl_driver->domains, false,
|
||||||
|
libxlDomainManagedSaveLoad,
|
||||||
libxl_driver);
|
libxl_driver);
|
||||||
|
|
||||||
return VIR_DRV_STATE_INIT_COMPLETE;
|
return VIR_DRV_STATE_INIT_COMPLETE;
|
||||||
@ -832,7 +834,8 @@ libxlStateReload(void)
|
|||||||
libxl_driver->xmlopt,
|
libxl_driver->xmlopt,
|
||||||
NULL, libxl_driver);
|
NULL, libxl_driver);
|
||||||
|
|
||||||
virDomainObjListForEach(libxl_driver->domains, libxlAutostartDomain,
|
virDomainObjListForEach(libxl_driver->domains, false,
|
||||||
|
libxlAutostartDomain,
|
||||||
libxl_driver);
|
libxl_driver);
|
||||||
|
|
||||||
virObjectUnref(cfg);
|
virObjectUnref(cfg);
|
||||||
|
@ -1639,7 +1639,7 @@ virLXCProcessAutostartAll(virLXCDriverPtr driver)
|
|||||||
|
|
||||||
struct virLXCProcessAutostartData data = { driver, conn };
|
struct virLXCProcessAutostartData data = { driver, conn };
|
||||||
|
|
||||||
virDomainObjListForEach(driver->domains,
|
virDomainObjListForEach(driver->domains, false,
|
||||||
virLXCProcessAutostartDomain,
|
virLXCProcessAutostartDomain,
|
||||||
&data);
|
&data);
|
||||||
|
|
||||||
@ -1760,6 +1760,6 @@ virLXCProcessReconnectDomain(virDomainObjPtr vm,
|
|||||||
int virLXCProcessReconnectAll(virLXCDriverPtr driver,
|
int virLXCProcessReconnectAll(virLXCDriverPtr driver,
|
||||||
virDomainObjListPtr doms)
|
virDomainObjListPtr doms)
|
||||||
{
|
{
|
||||||
virDomainObjListForEach(doms, virLXCProcessReconnectDomain, driver);
|
virDomainObjListForEach(doms, false, virLXCProcessReconnectDomain, driver);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -304,7 +304,7 @@ qemuAutostartDomain(virDomainObjPtr vm,
|
|||||||
static void
|
static void
|
||||||
qemuAutostartDomains(virQEMUDriverPtr driver)
|
qemuAutostartDomains(virQEMUDriverPtr driver)
|
||||||
{
|
{
|
||||||
virDomainObjListForEach(driver->domains, qemuAutostartDomain, driver);
|
virDomainObjListForEach(driver->domains, false, qemuAutostartDomain, driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1055,10 +1055,12 @@ qemuStateInitialize(bool privileged,
|
|||||||
* the driver with. This is to avoid race between autostart and reconnect
|
* the driver with. This is to avoid race between autostart and reconnect
|
||||||
* threads */
|
* threads */
|
||||||
virDomainObjListForEach(qemu_driver->domains,
|
virDomainObjListForEach(qemu_driver->domains,
|
||||||
|
false,
|
||||||
qemuDomainFindMaxID,
|
qemuDomainFindMaxID,
|
||||||
&qemu_driver->lastvmid);
|
&qemu_driver->lastvmid);
|
||||||
|
|
||||||
virDomainObjListForEach(qemu_driver->domains,
|
virDomainObjListForEach(qemu_driver->domains,
|
||||||
|
false,
|
||||||
qemuDomainNetsRestart,
|
qemuDomainNetsRestart,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
@ -1072,14 +1074,17 @@ qemuStateInitialize(bool privileged,
|
|||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
virDomainObjListForEach(qemu_driver->domains,
|
virDomainObjListForEach(qemu_driver->domains,
|
||||||
|
false,
|
||||||
qemuDomainSnapshotLoad,
|
qemuDomainSnapshotLoad,
|
||||||
cfg->snapshotDir);
|
cfg->snapshotDir);
|
||||||
|
|
||||||
virDomainObjListForEach(qemu_driver->domains,
|
virDomainObjListForEach(qemu_driver->domains,
|
||||||
|
false,
|
||||||
qemuDomainCheckpointLoad,
|
qemuDomainCheckpointLoad,
|
||||||
cfg->checkpointDir);
|
cfg->checkpointDir);
|
||||||
|
|
||||||
virDomainObjListForEach(qemu_driver->domains,
|
virDomainObjListForEach(qemu_driver->domains,
|
||||||
|
false,
|
||||||
qemuDomainManagedSaveLoad,
|
qemuDomainManagedSaveLoad,
|
||||||
qemu_driver);
|
qemu_driver);
|
||||||
|
|
||||||
|
@ -8369,7 +8369,8 @@ void
|
|||||||
qemuProcessReconnectAll(virQEMUDriverPtr driver)
|
qemuProcessReconnectAll(virQEMUDriverPtr driver)
|
||||||
{
|
{
|
||||||
struct qemuProcessReconnectData data = {.driver = driver};
|
struct qemuProcessReconnectData data = {.driver = driver};
|
||||||
virDomainObjListForEach(driver->domains, qemuProcessReconnectHelper, &data);
|
virDomainObjListForEach(driver->domains, true,
|
||||||
|
qemuProcessReconnectHelper, &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -990,7 +990,7 @@ static int vmwareDomainObjListUpdateDomain(virDomainObjPtr dom, void *data)
|
|||||||
static void
|
static void
|
||||||
vmwareDomainObjListUpdateAll(virDomainObjListPtr doms, struct vmware_driver *driver)
|
vmwareDomainObjListUpdateAll(virDomainObjListPtr doms, struct vmware_driver *driver)
|
||||||
{
|
{
|
||||||
virDomainObjListForEach(doms, vmwareDomainObjListUpdateDomain, driver);
|
virDomainObjListForEach(doms, false, vmwareDomainObjListUpdateDomain, driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
Loading…
x
Reference in New Issue
Block a user