[libvirt] [PATCH v1 10/11] storage_driver: Protect pool def during startup and build

John Ferlan jferlan at redhat.com
Fri Aug 23 11:47:39 UTC 2019



On 5/24/19 10:35 AM, Michal Privoznik wrote:
> In near future the storage pool object lock will be released
> during startPool and buildPool callback (in some backends). But
> this means that another thread may acquire the pool object lock
> and change its definition rendering the former thread access not
> only stale definition but also access freed memory
> (virStoragePoolObjAssignDef() will free old def when setting a
> new one).
> 
> One way out of this would be to have the pool appear as active
> because our code deals with obj->def and obj->newdef just fine.
> But we can't declare a pool as active if it's not started or
> still building up. Therefore, have a boolean flag that is very
> similar and forces virStoragePoolObjAssignDef() to store new
> definition in obj->newdef even for an inactive pool. In turn, we
> have to move the definition to correct place when unsetting the
> flag. But that's as easy as calling
> virStoragePoolUpdateInactive().
> 
> Technically speaking, change made to
> storageDriverAutostartCallback() is not needed because until
> storage driver is initialized no storage API can run therefore
> there can't be anyone wanting to change the pool's definition.
> But I'm doing the change there for consistency anyways.
> 
> Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
> ---
>  src/conf/virstorageobj.c     | 26 +++++++++++++++++++++++++-
>  src/conf/virstorageobj.h     |  6 ++++++
>  src/libvirt_private.syms     |  2 ++
>  src/storage/storage_driver.c | 31 ++++++++++++++++++++++++++++++-
>  4 files changed, 63 insertions(+), 2 deletions(-)
> 

[...]

> diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c
> index def4123b82..60bfa48e25 100644
> --- a/src/storage/storage_driver.c
> +++ b/src/storage/storage_driver.c
> @@ -201,12 +201,14 @@ storageDriverAutostartCallback(virStoragePoolObjPtr obj,
>  
>      if (virStoragePoolObjIsAutostart(obj) &&
>          !virStoragePoolObjIsActive(obj)) {
> +
> +        virStoragePoolObjSetStarting(obj, true);
>          if (backend->startPool &&
>              backend->startPool(obj) < 0) {
>              virReportError(VIR_ERR_INTERNAL_ERROR,
>                             _("Failed to autostart storage pool '%s': %s"),
>                             def->name, virGetLastErrorMessage());
> -            return;
> +            goto cleanup;
>          }
>          started = true;
>      }
> @@ -225,6 +227,13 @@ storageDriverAutostartCallback(virStoragePoolObjPtr obj,
>              virStoragePoolObjSetActive(obj, true);
>          }
>      }
> +
> + cleanup:
> +    if (virStoragePoolObjIsStarting(obj)) {
> +        if (!virStoragePoolObjIsActive(obj))
> +            virStoragePoolUpdateInactive(obj);
> +        virStoragePoolObjSetStarting(obj, false);
> +    }
>  }
>  
>  
> @@ -750,6 +759,8 @@ storagePoolCreateXML(virConnectPtr conn,
>      newDef = NULL;
>      def = virStoragePoolObjGetDef(obj);
>  

Coverity let me know this morning that there's quite a few lines above
here which goto cleanup; however, cleanup expects @obj != NULL (or at
least virStoragePoolObjIsStarting does). Probably need similar logic
like you added in storagePool{Create|Build}.

John

> +    virStoragePoolObjSetStarting(obj, true);
> +
>      if (backend->buildPool) {
>          if (flags & VIR_STORAGE_POOL_CREATE_WITH_BUILD_OVERWRITE)
>              build_flags |= VIR_STORAGE_POOL_BUILD_OVERWRITE;
> @@ -786,6 +797,11 @@ storagePoolCreateXML(virConnectPtr conn,
>      pool = virGetStoragePool(conn, def->name, def->uuid, NULL, NULL);
>  
>   cleanup:
> +    if (virStoragePoolObjIsStarting(obj)) {
> +        if (!virStoragePoolObjIsActive(obj))
> +            virStoragePoolUpdateInactive(obj);
> +        virStoragePoolObjSetStarting(obj, false);
> +    }
>      virObjectEventStateQueue(driver->storageEventState, event);
>      virStoragePoolObjEndAPI(&obj);
>      return pool;

[...]




More information about the libvir-list mailing list