diff options
author | Martin Pitt <martin@piware.de> | 2020-11-05 13:38:15 +0100 |
---|---|---|
committer | Cole Robinson <crobinso@redhat.com> | 2020-11-08 17:01:40 -0500 |
commit | 49a01b5482ee5009f4a59953d21eb8741670f813 (patch) | |
tree | 6458b6917455de390737fab3490a934322daf638 | |
parent | 04ad8df752c11ef5e4ec8f3ef425ed92ecb2533f (diff) | |
download | virt-manager-49a01b5482ee5009f4a59953d21eb8741670f813.tar.gz |
virtinst: Fix TOCTOU in pool and volume enumeration
_fetch_all_pools_raw() and _fetch_vols_raw() have a race condition where
a pool/volume may disappear (from parallel libvirt operations) in
between enumerating and inspecting the objects.
_fetch_vols_raw() already expected that failure in the loop, but not for
the initial storagePoolLookupByName() call.
Also tighten the expected exception: This *should* crash on errors like
AttributeError or SystemExit, just not on dynamic libvirt errors. (Bare
exceptions are highly frowned upon in Python)
https://bugzilla.redhat.com/show_bug.cgi?id=1894359
-rw-r--r-- | virtinst/connection.py | 20 |
1 files changed, 17 insertions, 3 deletions
diff --git a/virtinst/connection.py b/virtinst/connection.py index b3528c27..fec273b7 100644 --- a/virtinst/connection.py +++ b/virtinst/connection.py @@ -192,7 +192,16 @@ class VirtinstConnection(object): def _fetch_all_pools_raw(self): dummy1, dummy2, ret = pollhelpers.fetch_pools( self, {}, lambda obj, ignore: obj) - return [self._build_pool_raw(poolobj) for poolobj in ret] + pools = [] + for poolobj in ret: + # TOCTOU race: a pool may go away in between enumeration and inspection + try: + pool = self._build_pool_raw(poolobj) + except libvirt.libvirtError as e: # pragma: no cover + log.debug("Fetching pool XML failed: %s", e) + continue + pools.append(pool) + return pools def _fetch_all_nodedevs_raw(self): dummy1, dummy2, ret = pollhelpers.fetch_nodedevs( @@ -202,7 +211,12 @@ class VirtinstConnection(object): def _fetch_vols_raw(self, poolxmlobj): ret = [] - pool = self._libvirtconn.storagePoolLookupByName(poolxmlobj.name) + # TOCTOU race: a volume may go away in between enumeration and inspection + try: + pool = self._libvirtconn.storagePoolLookupByName(poolxmlobj.name) + except libvirt.libvirtError as e: # pragma: no cover + return ret + if pool.info()[0] != libvirt.VIR_STORAGE_POOL_RUNNING: return ret @@ -213,7 +227,7 @@ class VirtinstConnection(object): try: xml = vol.XMLDesc(0) ret.append(StorageVolume(weakref.proxy(self), parsexml=xml)) - except Exception as e: # pragma: no cover + except libvirt.libvirtError as e: # pragma: no cover log.debug("Fetching volume XML failed: %s", e) return ret |