[libvirt] [PATCH 1/2] security: DAC: fix the transaction model's list append

Michal Privoznik mprivozn at redhat.com
Tue Jan 17 14:17:04 UTC 2017


On 01/17/2017 02:56 PM, Erik Skultety wrote:
> The problem is in the way how the list item is created prior to
> appending it to the transaction list - the @path attribute is just a
> shallow copy instead of deep copy of the hostdev device's path.
> Unfortunately, the hostdev devices from which the @path is extracted, in
> order to add them into the transaction list, are only temporary and
> freed before the buildup of the qemu namespace, thus making the @path
> attribute in the transaction list NULL, causing 'permission denied' or
> 'double free' or 'unknown cause' errors.
> 
> Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1413773
> 
> Signed-off-by: Erik Skultety <eskultet at redhat.com>
> ---
>  src/security/security_dac.c | 30 +++++++++++++++++++++---------
>  1 file changed, 21 insertions(+), 9 deletions(-)
> 
> diff --git a/src/security/security_dac.c b/src/security/security_dac.c
> index d457e6a..d7a2de4 100644
> --- a/src/security/security_dac.c
> +++ b/src/security/security_dac.c
> @@ -71,7 +71,7 @@ struct _virSecurityDACCallbackData {
>  typedef struct _virSecurityDACChownItem virSecurityDACChownItem;
>  typedef virSecurityDACChownItem *virSecurityDACChownItemPtr;
>  struct _virSecurityDACChownItem {
> -    const char *path;
> +    char *path;
>      const virStorageSource *src;
>      uid_t uid;
>      gid_t gid;
> @@ -95,22 +95,32 @@ virSecurityDACChownListAppend(virSecurityDACChownListPtr list,
>                                uid_t uid,
>                                gid_t gid)
>  {
> -    virSecurityDACChownItemPtr item;
> +    int ret = -1;
> +    char *tmp = NULL;
> +    virSecurityDACChownItemPtr item = NULL;
>  
>      if (VIR_ALLOC(item) < 0)
>          return -1;
>  
> -    item->path = path;
> +    if (VIR_STRDUP(tmp, path) < 0)
> +        goto cleanup;
> +
> +    item->path = tmp;
>      item->src = src;
>      item->uid = uid;
>      item->gid = gid;
>  
> -    if (VIR_APPEND_ELEMENT(list->items, list->nItems, item) < 0) {
> -        VIR_FREE(item);
> -        return -1;
> -    }
> +    if (VIR_APPEND_ELEMENT(list->items, list->nItems, item) < 0)
> +        goto cleanup;
>  
> -    return 0;
> +    tmp = NULL;
> +    item = NULL;

This 'item = NULL' is not needed. VIR_APPEND_ELEMENT sets @item to NULL
upon successful return. But I agree that it is hard to spot.

> +
> +    ret = 0;
> + cleanup:
> +    VIR_FREE(tmp);
> +    VIR_FREE(item);
> +    return ret;
>  }
>  
>  static void
> @@ -122,8 +132,10 @@ virSecurityDACChownListFree(void *opaque)
>      if (!list)
>          return;
>  
> -    for (i = 0; i < list->nItems; i++)
> +    for (i = 0; i < list->nItems; i++) {
> +        VIR_FREE(list->items[i]->path);
>          VIR_FREE(list->items[i]);
> +    }
>      VIR_FREE(list);
>  }
>  
> 

ACK and safe for the freeze.

Michal




More information about the libvir-list mailing list