diff mbox

[PULL,24/30] spapr_pci: populate ibm,loc-code

Message ID 1436284182-5063-25-git-send-email-agraf@suse.de
State New
Headers show

Commit Message

Alexander Graf July 7, 2015, 3:49 p.m. UTC
From: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>

Each hardware instance has a platform unique location code.  The OF
device tree that describes a part of a hardware entity must include
the “ibm,loc-code” property with a value that represents the location
code for that hardware entity.

Populate ibm,loc-code.

1) PCI passthru devices need to identify with its own ibm,loc-code
   available on the host. In failure cases use:
   vfio_<name>:<phb-index>:<bus>:<slot>.<fn>

2) Emulated devices encode as following:
   qemu_<name>:<phb-index>:<bus>:<slot>.<fn>

Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
---
 hw/ppc/spapr_pci.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 71 insertions(+), 6 deletions(-)

Comments

Peter Maydell Aug. 9, 2021, 9:57 a.m. UTC | #1
On Tue, 7 Jul 2015 at 16:49, Alexander Graf <agraf@suse.de> wrote:
>
> From: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
>
> Each hardware instance has a platform unique location code.  The OF
> device tree that describes a part of a hardware entity must include
> the “ibm,loc-code” property with a value that represents the location
> code for that hardware entity.
>
> Populate ibm,loc-code.

Ancient patch, but Coverity has just noticed a bug in it
which is still present in current QEMU (CID 1460454):

> +static char *spapr_phb_vfio_get_loc_code(sPAPRPHBState *sphb,  PCIDevice *pdev)
> +{
> +    char *path = NULL, *buf = NULL, *host = NULL;
> +
> +    /* Get the PCI VFIO host id */
> +    host = object_property_get_str(OBJECT(pdev), "host", NULL);
> +    if (!host) {
> +        goto err_out;
> +    }
> +
> +    /* Construct the path of the file that will give us the DT location */
> +    path = g_strdup_printf("/sys/bus/pci/devices/%s/devspec", host);
> +    g_free(host);
> +    if (!path || !g_file_get_contents(path, &buf, NULL, NULL)) {
> +        goto err_out;
> +    }
> +    g_free(path);

Here we create a 'path' string, use it as the argument to
g_file_get_contents() and then free it (either here or in the err_out path)...

> +
> +    /* Construct and read from host device tree the loc-code */
> +    path = g_strdup_printf("/proc/device-tree%s/ibm,loc-code", buf);
> +    g_free(buf);
> +    if (!path || !g_file_get_contents(path, &buf, NULL, NULL)) {
> +        goto err_out;
> +    }
> +    return buf;

...but here we forget to free it before returning in the success case.

> +
> +err_out:
> +    g_free(path);
> +    return NULL;
> +}

Cleanest fix would be to declare 'path' and 'host' as
   g_autofree char *path = NULL;
   g_autofree char *host = NULL;
and then you can remove all the manual g_free(path) and g_free(host) calls.

thanks
-- PMM
David Gibson Aug. 10, 2021, 4:29 a.m. UTC | #2
On Mon, Aug 09, 2021 at 10:57:00AM +0100, Peter Maydell wrote:
> On Tue, 7 Jul 2015 at 16:49, Alexander Graf <agraf@suse.de> wrote:
> >
> > From: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
> >
> > Each hardware instance has a platform unique location code.  The OF
> > device tree that describes a part of a hardware entity must include
> > the “ibm,loc-code” property with a value that represents the location
> > code for that hardware entity.
> >
> > Populate ibm,loc-code.
> 
> Ancient patch, but Coverity has just noticed a bug in it
> which is still present in current QEMU (CID 1460454):
> 
> > +static char *spapr_phb_vfio_get_loc_code(sPAPRPHBState *sphb,  PCIDevice *pdev)
> > +{
> > +    char *path = NULL, *buf = NULL, *host = NULL;
> > +
> > +    /* Get the PCI VFIO host id */
> > +    host = object_property_get_str(OBJECT(pdev), "host", NULL);
> > +    if (!host) {
> > +        goto err_out;
> > +    }
> > +
> > +    /* Construct the path of the file that will give us the DT location */
> > +    path = g_strdup_printf("/sys/bus/pci/devices/%s/devspec", host);
> > +    g_free(host);
> > +    if (!path || !g_file_get_contents(path, &buf, NULL, NULL)) {
> > +        goto err_out;
> > +    }
> > +    g_free(path);
> 
> Here we create a 'path' string, use it as the argument to
> g_file_get_contents() and then free it (either here or in the err_out path)...
> 
> > +
> > +    /* Construct and read from host device tree the loc-code */
> > +    path = g_strdup_printf("/proc/device-tree%s/ibm,loc-code", buf);
> > +    g_free(buf);
> > +    if (!path || !g_file_get_contents(path, &buf, NULL, NULL)) {
> > +        goto err_out;
> > +    }
> > +    return buf;
> 
> ...but here we forget to free it before returning in the success case.
> 
> > +
> > +err_out:
> > +    g_free(path);
> > +    return NULL;
> > +}
> 
> Cleanest fix would be to declare 'path' and 'host' as
>    g_autofree char *path = NULL;
>    g_autofree char *host = NULL;
> and then you can remove all the manual g_free(path) and g_free(host) calls.

Thanks for the report.  I've committed the fix (I hope) below to ppc-for-6.1:

From 70ae61b510dc571c407b28c46498cae60e60ca66 Mon Sep 17 00:00:00 2001
From: David Gibson <david@gibson.dropbear.id.au>
Date: Tue, 10 Aug 2021 14:28:19 +1000
Subject: [PATCH] spapr_pci: Fix leak in spapr_phb_vfio_get_loc_code() with
 g_autofree

This uses g_autofree to simplify logic in spapr_phb_vfio_get_loc_code(),
in the process fixing a leak in one of the paths.  I'm told this fixes
Coverity error CID 1460454

Reported-by: Peter Maydell <peter.maydell@linaro.org>
Fixes: 16b0ea1d852 ("spapr_pci: populate ibm,loc-code")
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 hw/ppc/spapr_pci.c | 17 ++++++-----------
 1 file changed, 6 insertions(+), 11 deletions(-)

diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index 7a725855f9..13d806f390 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -782,33 +782,28 @@ static AddressSpace *spapr_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
 
 static char *spapr_phb_vfio_get_loc_code(SpaprPhbState *sphb,  PCIDevice *pdev)
 {
-    char *path = NULL, *buf = NULL, *host = NULL;
+    g_autofree char *path = NULL;
+    g_autofree char *host = NULL;
+    char *buf = NULL;
 
     /* Get the PCI VFIO host id */
     host = object_property_get_str(OBJECT(pdev), "host", NULL);
     if (!host) {
-        goto err_out;
+        return NULL;
     }
 
     /* Construct the path of the file that will give us the DT location */
     path = g_strdup_printf("/sys/bus/pci/devices/%s/devspec", host);
-    g_free(host);
     if (!g_file_get_contents(path, &buf, NULL, NULL)) {
-        goto err_out;
+        return NULL;
     }
-    g_free(path);
 
     /* Construct and read from host device tree the loc-code */
     path = g_strdup_printf("/proc/device-tree%s/ibm,loc-code", buf);
-    g_free(buf);
     if (!g_file_get_contents(path, &buf, NULL, NULL)) {
-        goto err_out;
+        return NULL;
     }
     return buf;
-
-err_out:
-    g_free(path);
-    return NULL;
 }
 
 static char *spapr_phb_get_loc_code(SpaprPhbState *sphb, PCIDevice *pdev)
Philippe Mathieu-Daudé Aug. 10, 2021, 5:07 a.m. UTC | #3
On 8/10/21 6:29 AM, David Gibson wrote:
> On Mon, Aug 09, 2021 at 10:57:00AM +0100, Peter Maydell wrote:
>> On Tue, 7 Jul 2015 at 16:49, Alexander Graf <agraf@suse.de> wrote:
>>>
>>> From: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
>>>
>>> Each hardware instance has a platform unique location code.  The OF
>>> device tree that describes a part of a hardware entity must include
>>> the “ibm,loc-code” property with a value that represents the location
>>> code for that hardware entity.
>>>
>>> Populate ibm,loc-code.
>>
>> Ancient patch, but Coverity has just noticed a bug in it
>> which is still present in current QEMU (CID 1460454):
>>
>>> +static char *spapr_phb_vfio_get_loc_code(sPAPRPHBState *sphb,  PCIDevice *pdev)
>>> +{
>>> +    char *path = NULL, *buf = NULL, *host = NULL;
>>> +
>>> +    /* Get the PCI VFIO host id */
>>> +    host = object_property_get_str(OBJECT(pdev), "host", NULL);
>>> +    if (!host) {
>>> +        goto err_out;
>>> +    }
>>> +
>>> +    /* Construct the path of the file that will give us the DT location */
>>> +    path = g_strdup_printf("/sys/bus/pci/devices/%s/devspec", host);
>>> +    g_free(host);
>>> +    if (!path || !g_file_get_contents(path, &buf, NULL, NULL)) {
>>> +        goto err_out;
>>> +    }
>>> +    g_free(path);
>>
>> Here we create a 'path' string, use it as the argument to
>> g_file_get_contents() and then free it (either here or in the err_out path)...
>>
>>> +
>>> +    /* Construct and read from host device tree the loc-code */
>>> +    path = g_strdup_printf("/proc/device-tree%s/ibm,loc-code", buf);
>>> +    g_free(buf);
>>> +    if (!path || !g_file_get_contents(path, &buf, NULL, NULL)) {
>>> +        goto err_out;
>>> +    }
>>> +    return buf;
>>
>> ...but here we forget to free it before returning in the success case.
>>
>>> +
>>> +err_out:
>>> +    g_free(path);
>>> +    return NULL;
>>> +}
>>
>> Cleanest fix would be to declare 'path' and 'host' as
>>    g_autofree char *path = NULL;
>>    g_autofree char *host = NULL;
>> and then you can remove all the manual g_free(path) and g_free(host) calls.
> 
> Thanks for the report.  I've committed the fix (I hope) below to ppc-for-6.1:
> 
> From 70ae61b510dc571c407b28c46498cae60e60ca66 Mon Sep 17 00:00:00 2001
> From: David Gibson <david@gibson.dropbear.id.au>
> Date: Tue, 10 Aug 2021 14:28:19 +1000
> Subject: [PATCH] spapr_pci: Fix leak in spapr_phb_vfio_get_loc_code() with
>  g_autofree
> 
> This uses g_autofree to simplify logic in spapr_phb_vfio_get_loc_code(),
> in the process fixing a leak in one of the paths.  I'm told this fixes
> Coverity error CID 1460454
> 
> Reported-by: Peter Maydell <peter.maydell@linaro.org>
> Fixes: 16b0ea1d852 ("spapr_pci: populate ibm,loc-code")
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>

Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>

> ---
>  hw/ppc/spapr_pci.c | 17 ++++++-----------
>  1 file changed, 6 insertions(+), 11 deletions(-)
> 
> diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
> index 7a725855f9..13d806f390 100644
> --- a/hw/ppc/spapr_pci.c
> +++ b/hw/ppc/spapr_pci.c
> @@ -782,33 +782,28 @@ static AddressSpace *spapr_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
>  
>  static char *spapr_phb_vfio_get_loc_code(SpaprPhbState *sphb,  PCIDevice *pdev)
>  {
> -    char *path = NULL, *buf = NULL, *host = NULL;
> +    g_autofree char *path = NULL;
> +    g_autofree char *host = NULL;
> +    char *buf = NULL;
>  
>      /* Get the PCI VFIO host id */
>      host = object_property_get_str(OBJECT(pdev), "host", NULL);
>      if (!host) {
> -        goto err_out;
> +        return NULL;
>      }
>  
>      /* Construct the path of the file that will give us the DT location */
>      path = g_strdup_printf("/sys/bus/pci/devices/%s/devspec", host);
> -    g_free(host);
>      if (!g_file_get_contents(path, &buf, NULL, NULL)) {
> -        goto err_out;
> +        return NULL;
>      }
> -    g_free(path);
>  
>      /* Construct and read from host device tree the loc-code */
>      path = g_strdup_printf("/proc/device-tree%s/ibm,loc-code", buf);
> -    g_free(buf);
>      if (!g_file_get_contents(path, &buf, NULL, NULL)) {
> -        goto err_out;
> +        return NULL;
>      }
>      return buf;
> -
> -err_out:
> -    g_free(path);
> -    return NULL;
>  }
>  
>  static char *spapr_phb_get_loc_code(SpaprPhbState *sphb, PCIDevice *pdev)
>
Peter Maydell Aug. 13, 2021, 3:17 p.m. UTC | #4
On Tue, 10 Aug 2021 at 05:40, David Gibson <david@gibson.dropbear.id.au> wrote:
>
> On Mon, Aug 09, 2021 at 10:57:00AM +0100, Peter Maydell wrote:
> >
> > Cleanest fix would be to declare 'path' and 'host' as
> >    g_autofree char *path = NULL;
> >    g_autofree char *host = NULL;
> > and then you can remove all the manual g_free(path) and g_free(host) calls.
>
> Thanks for the report.  I've committed the fix (I hope) below to ppc-for-6.1:
>
> From 70ae61b510dc571c407b28c46498cae60e60ca66 Mon Sep 17 00:00:00 2001
> From: David Gibson <david@gibson.dropbear.id.au>
> Date: Tue, 10 Aug 2021 14:28:19 +1000
> Subject: [PATCH] spapr_pci: Fix leak in spapr_phb_vfio_get_loc_code() with
>  g_autofree
>
> This uses g_autofree to simplify logic in spapr_phb_vfio_get_loc_code(),
> in the process fixing a leak in one of the paths.  I'm told this fixes
> Coverity error CID 1460454
>
> Reported-by: Peter Maydell <peter.maydell@linaro.org>
> Fixes: 16b0ea1d852 ("spapr_pci: populate ibm,loc-code")
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> ---
>  hw/ppc/spapr_pci.c | 17 ++++++-----------
>  1 file changed, 6 insertions(+), 11 deletions(-)
>
> diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
> index 7a725855f9..13d806f390 100644
> --- a/hw/ppc/spapr_pci.c
> +++ b/hw/ppc/spapr_pci.c
> @@ -782,33 +782,28 @@ static AddressSpace *spapr_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
>
>  static char *spapr_phb_vfio_get_loc_code(SpaprPhbState *sphb,  PCIDevice *pdev)
>  {
> -    char *path = NULL, *buf = NULL, *host = NULL;
> +    g_autofree char *path = NULL;
> +    g_autofree char *host = NULL;
> +    char *buf = NULL;
>
>      /* Get the PCI VFIO host id */
>      host = object_property_get_str(OBJECT(pdev), "host", NULL);
>      if (!host) {
> -        goto err_out;
> +        return NULL;
>      }
>
>      /* Construct the path of the file that will give us the DT location */
>      path = g_strdup_printf("/sys/bus/pci/devices/%s/devspec", host);
> -    g_free(host);
>      if (!g_file_get_contents(path, &buf, NULL, NULL)) {
> -        goto err_out;
> +        return NULL;
>      }
> -    g_free(path);
>
>      /* Construct and read from host device tree the loc-code */
>      path = g_strdup_printf("/proc/device-tree%s/ibm,loc-code", buf);
> -    g_free(buf);

This deletion doesn't look right -- 'buf' is not autofree
(and shouldn't be, since we're returning it).

If you want to delete this 'g_free' you need to make the
first g_file_get_contents() use a separate char* variable from
the variable we use to return the eventual result data buffer;
then you can make that new variable be g_autofree.

>      if (!g_file_get_contents(path, &buf, NULL, NULL)) {
> -        goto err_out;
> +        return NULL;
>      }
>      return buf;
> -
> -err_out:
> -    g_free(path);
> -    return NULL;
>  }

thanks
-- PMM
Philippe Mathieu-Daudé Aug. 15, 2021, 2:36 p.m. UTC | #5
On 8/13/21 5:17 PM, Peter Maydell wrote:
> On Tue, 10 Aug 2021 at 05:40, David Gibson <david@gibson.dropbear.id.au> wrote:
>>
>> On Mon, Aug 09, 2021 at 10:57:00AM +0100, Peter Maydell wrote:
>>>
>>> Cleanest fix would be to declare 'path' and 'host' as
>>>    g_autofree char *path = NULL;
>>>    g_autofree char *host = NULL;
>>> and then you can remove all the manual g_free(path) and g_free(host) calls.
>>
>> Thanks for the report.  I've committed the fix (I hope) below to ppc-for-6.1:
>>
>> From 70ae61b510dc571c407b28c46498cae60e60ca66 Mon Sep 17 00:00:00 2001
>> From: David Gibson <david@gibson.dropbear.id.au>
>> Date: Tue, 10 Aug 2021 14:28:19 +1000
>> Subject: [PATCH] spapr_pci: Fix leak in spapr_phb_vfio_get_loc_code() with
>>  g_autofree
>>
>> This uses g_autofree to simplify logic in spapr_phb_vfio_get_loc_code(),
>> in the process fixing a leak in one of the paths.  I'm told this fixes
>> Coverity error CID 1460454
>>
>> Reported-by: Peter Maydell <peter.maydell@linaro.org>
>> Fixes: 16b0ea1d852 ("spapr_pci: populate ibm,loc-code")
>> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
>> ---
>>  hw/ppc/spapr_pci.c | 17 ++++++-----------
>>  1 file changed, 6 insertions(+), 11 deletions(-)
>>
>> diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
>> index 7a725855f9..13d806f390 100644
>> --- a/hw/ppc/spapr_pci.c
>> +++ b/hw/ppc/spapr_pci.c
>> @@ -782,33 +782,28 @@ static AddressSpace *spapr_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
>>
>>  static char *spapr_phb_vfio_get_loc_code(SpaprPhbState *sphb,  PCIDevice *pdev)
>>  {
>> -    char *path = NULL, *buf = NULL, *host = NULL;
>> +    g_autofree char *path = NULL;
>> +    g_autofree char *host = NULL;
>> +    char *buf = NULL;
>>
>>      /* Get the PCI VFIO host id */
>>      host = object_property_get_str(OBJECT(pdev), "host", NULL);
>>      if (!host) {
>> -        goto err_out;
>> +        return NULL;
>>      }
>>
>>      /* Construct the path of the file that will give us the DT location */
>>      path = g_strdup_printf("/sys/bus/pci/devices/%s/devspec", host);
>> -    g_free(host);
>>      if (!g_file_get_contents(path, &buf, NULL, NULL)) {
>> -        goto err_out;
>> +        return NULL;
>>      }
>> -    g_free(path);
>>
>>      /* Construct and read from host device tree the loc-code */
>>      path = g_strdup_printf("/proc/device-tree%s/ibm,loc-code", buf);
>> -    g_free(buf);
> 
> This deletion doesn't look right -- 'buf' is not autofree
> (and shouldn't be, since we're returning it).

Oops, good catch!

> If you want to delete this 'g_free' you need to make the
> first g_file_get_contents() use a separate char* variable from
> the variable we use to return the eventual result data buffer;
> then you can make that new variable be g_autofree.
> 
>>      if (!g_file_get_contents(path, &buf, NULL, NULL)) {
>> -        goto err_out;
>> +        return NULL;
>>      }
>>      return buf;
>> -
>> -err_out:
>> -    g_free(path);
>> -    return NULL;
>>  }
> 
> thanks
> -- PMM
>
David Gibson Aug. 16, 2021, 4:37 a.m. UTC | #6
On Sun, Aug 15, 2021 at 04:36:18PM +0200, Philippe Mathieu-Daudé wrote:
> On 8/13/21 5:17 PM, Peter Maydell wrote:
> > On Tue, 10 Aug 2021 at 05:40, David Gibson <david@gibson.dropbear.id.au> wrote:
> >>
> >> On Mon, Aug 09, 2021 at 10:57:00AM +0100, Peter Maydell wrote:
> >>>
> >>> Cleanest fix would be to declare 'path' and 'host' as
> >>>    g_autofree char *path = NULL;
> >>>    g_autofree char *host = NULL;
> >>> and then you can remove all the manual g_free(path) and g_free(host) calls.
> >>
> >> Thanks for the report.  I've committed the fix (I hope) below to ppc-for-6.1:
> >>
> >> From 70ae61b510dc571c407b28c46498cae60e60ca66 Mon Sep 17 00:00:00 2001
> >> From: David Gibson <david@gibson.dropbear.id.au>
> >> Date: Tue, 10 Aug 2021 14:28:19 +1000
> >> Subject: [PATCH] spapr_pci: Fix leak in spapr_phb_vfio_get_loc_code() with
> >>  g_autofree
> >>
> >> This uses g_autofree to simplify logic in spapr_phb_vfio_get_loc_code(),
> >> in the process fixing a leak in one of the paths.  I'm told this fixes
> >> Coverity error CID 1460454
> >>
> >> Reported-by: Peter Maydell <peter.maydell@linaro.org>
> >> Fixes: 16b0ea1d852 ("spapr_pci: populate ibm,loc-code")
> >> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> >> ---
> >>  hw/ppc/spapr_pci.c | 17 ++++++-----------
> >>  1 file changed, 6 insertions(+), 11 deletions(-)
> >>
> >> diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
> >> index 7a725855f9..13d806f390 100644
> >> --- a/hw/ppc/spapr_pci.c
> >> +++ b/hw/ppc/spapr_pci.c
> >> @@ -782,33 +782,28 @@ static AddressSpace *spapr_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
> >>
> >>  static char *spapr_phb_vfio_get_loc_code(SpaprPhbState *sphb,  PCIDevice *pdev)
> >>  {
> >> -    char *path = NULL, *buf = NULL, *host = NULL;
> >> +    g_autofree char *path = NULL;
> >> +    g_autofree char *host = NULL;
> >> +    char *buf = NULL;
> >>
> >>      /* Get the PCI VFIO host id */
> >>      host = object_property_get_str(OBJECT(pdev), "host", NULL);
> >>      if (!host) {
> >> -        goto err_out;
> >> +        return NULL;
> >>      }
> >>
> >>      /* Construct the path of the file that will give us the DT location */
> >>      path = g_strdup_printf("/sys/bus/pci/devices/%s/devspec", host);
> >> -    g_free(host);
> >>      if (!g_file_get_contents(path, &buf, NULL, NULL)) {
> >> -        goto err_out;
> >> +        return NULL;
> >>      }
> >> -    g_free(path);
> >>
> >>      /* Construct and read from host device tree the loc-code */
> >>      path = g_strdup_printf("/proc/device-tree%s/ibm,loc-code", buf);
> >> -    g_free(buf);
> > 
> > This deletion doesn't look right -- 'buf' is not autofree
> > (and shouldn't be, since we're returning it).
> 
> Oops, good catch!

Indeed.  Revised version below.  I'll only attempt to push this to 6.1
if we're going to rc4 for other reasons though.

From 705a10b1cfbe6bcdde37f37f3548845970dc4986 Mon Sep 17 00:00:00 2001
From: David Gibson <david@gibson.dropbear.id.au>
Date: Tue, 10 Aug 2021 14:28:19 +1000
Subject: [PATCH] spapr_pci: Fix leak in spapr_phb_vfio_get_loc_code() with
 g_autofree
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This uses g_autofree to simplify logic in spapr_phb_vfio_get_loc_code(),
in the process fixing a leak in one of the paths.  I'm told this fixes
Coverity error CID 1460454

Reported-by: Peter Maydell <peter.maydell@linaro.org>
Fixes: 16b0ea1d852 ("spapr_pci: populate ibm,loc-code")
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 hw/ppc/spapr_pci.c | 22 +++++++++-------------
 1 file changed, 9 insertions(+), 13 deletions(-)

diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index 7a725855f9..7430bd6314 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -782,33 +782,29 @@ static AddressSpace *spapr_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
 
 static char *spapr_phb_vfio_get_loc_code(SpaprPhbState *sphb,  PCIDevice *pdev)
 {
-    char *path = NULL, *buf = NULL, *host = NULL;
+    g_autofree char *path = NULL;
+    g_autofree char *host = NULL;
+    g_autofree char *devspec = NULL;
+    char *buf = NULL;
 
     /* Get the PCI VFIO host id */
     host = object_property_get_str(OBJECT(pdev), "host", NULL);
     if (!host) {
-        goto err_out;
+        return NULL;
     }
 
     /* Construct the path of the file that will give us the DT location */
     path = g_strdup_printf("/sys/bus/pci/devices/%s/devspec", host);
-    g_free(host);
-    if (!g_file_get_contents(path, &buf, NULL, NULL)) {
-        goto err_out;
+    if (!g_file_get_contents(path, &devspec, NULL, NULL)) {
+        return NULL;
     }
-    g_free(path);
 
     /* Construct and read from host device tree the loc-code */
-    path = g_strdup_printf("/proc/device-tree%s/ibm,loc-code", buf);
-    g_free(buf);
+    path = g_strdup_printf("/proc/device-tree%s/ibm,loc-code", devspec);
     if (!g_file_get_contents(path, &buf, NULL, NULL)) {
-        goto err_out;
+        return NULL;
     }
     return buf;
-
-err_out:
-    g_free(path);
-    return NULL;
 }
 
 static char *spapr_phb_get_loc_code(SpaprPhbState *sphb, PCIDevice *pdev)
Peter Maydell Aug. 16, 2021, 9:07 a.m. UTC | #7
On Mon, 16 Aug 2021 at 06:41, David Gibson <david@gibson.dropbear.id.au> wrote:
>
> Indeed.  Revised version below.  I'll only attempt to push this to 6.1
> if we're going to rc4 for other reasons though.

We are doing an rc4, but I don't think we really need this in 6.1,
given that the original leak only happens on a very rare error case
("/sys/ not mounted").

-- PMM
David Gibson Aug. 17, 2021, 3:02 a.m. UTC | #8
On Mon, Aug 16, 2021 at 10:07:12AM +0100, Peter Maydell wrote:
> On Mon, 16 Aug 2021 at 06:41, David Gibson <david@gibson.dropbear.id.au> wrote:
> >
> > Indeed.  Revised version below.  I'll only attempt to push this to 6.1
> > if we're going to rc4 for other reasons though.
> 
> We are doing an rc4, but I don't think we really need this in 6.1,
> given that the original leak only happens on a very rare error case
> ("/sys/ not mounted").

Fair enough, I'll punt it to 6.2.
Philippe Mathieu-Daudé Aug. 17, 2021, 8:42 a.m. UTC | #9
On 8/16/21 6:37 AM, David Gibson wrote:

> From 705a10b1cfbe6bcdde37f37f3548845970dc4986 Mon Sep 17 00:00:00 2001
> From: David Gibson <david@gibson.dropbear.id.au>
> Date: Tue, 10 Aug 2021 14:28:19 +1000
> Subject: [PATCH] spapr_pci: Fix leak in spapr_phb_vfio_get_loc_code() with
>  g_autofree
> MIME-Version: 1.0
> Content-Type: text/plain; charset=UTF-8
> Content-Transfer-Encoding: 8bit
> 
> This uses g_autofree to simplify logic in spapr_phb_vfio_get_loc_code(),
> in the process fixing a leak in one of the paths.  I'm told this fixes
> Coverity error CID 1460454
> 
> Reported-by: Peter Maydell <peter.maydell@linaro.org>
> Fixes: 16b0ea1d852 ("spapr_pci: populate ibm,loc-code")
> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> ---
>  hw/ppc/spapr_pci.c | 22 +++++++++-------------
>  1 file changed, 9 insertions(+), 13 deletions(-)
> 
> diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
> index 7a725855f9..7430bd6314 100644
> --- a/hw/ppc/spapr_pci.c
> +++ b/hw/ppc/spapr_pci.c
> @@ -782,33 +782,29 @@ static AddressSpace *spapr_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
>  
>  static char *spapr_phb_vfio_get_loc_code(SpaprPhbState *sphb,  PCIDevice *pdev)
>  {
> -    char *path = NULL, *buf = NULL, *host = NULL;
> +    g_autofree char *path = NULL;
> +    g_autofree char *host = NULL;
> +    g_autofree char *devspec = NULL;
> +    char *buf = NULL;
>  
>      /* Get the PCI VFIO host id */
>      host = object_property_get_str(OBJECT(pdev), "host", NULL);
>      if (!host) {
> -        goto err_out;
> +        return NULL;
>      }
>  
>      /* Construct the path of the file that will give us the DT location */
>      path = g_strdup_printf("/sys/bus/pci/devices/%s/devspec", host);
> -    g_free(host);
> -    if (!g_file_get_contents(path, &buf, NULL, NULL)) {
> -        goto err_out;
> +    if (!g_file_get_contents(path, &devspec, NULL, NULL)) {
> +        return NULL;
>      }
> -    g_free(path);
>  
>      /* Construct and read from host device tree the loc-code */
> -    path = g_strdup_printf("/proc/device-tree%s/ibm,loc-code", buf);
> -    g_free(buf);
> +    path = g_strdup_printf("/proc/device-tree%s/ibm,loc-code", devspec);
>      if (!g_file_get_contents(path, &buf, NULL, NULL)) {
> -        goto err_out;
> +        return NULL;
>      }
>      return buf;
> -
> -err_out:
> -    g_free(path);
> -    return NULL;
>  }
>  
>  static char *spapr_phb_get_loc_code(SpaprPhbState *sphb, PCIDevice *pdev)
> 

LGTM.
diff mbox

Patch

diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index 7c3621c..7585983 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -747,6 +747,60 @@  static AddressSpace *spapr_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
     return &phb->iommu_as;
 }
 
+static char *spapr_phb_vfio_get_loc_code(sPAPRPHBState *sphb,  PCIDevice *pdev)
+{
+    char *path = NULL, *buf = NULL, *host = NULL;
+
+    /* Get the PCI VFIO host id */
+    host = object_property_get_str(OBJECT(pdev), "host", NULL);
+    if (!host) {
+        goto err_out;
+    }
+
+    /* Construct the path of the file that will give us the DT location */
+    path = g_strdup_printf("/sys/bus/pci/devices/%s/devspec", host);
+    g_free(host);
+    if (!path || !g_file_get_contents(path, &buf, NULL, NULL)) {
+        goto err_out;
+    }
+    g_free(path);
+
+    /* Construct and read from host device tree the loc-code */
+    path = g_strdup_printf("/proc/device-tree%s/ibm,loc-code", buf);
+    g_free(buf);
+    if (!path || !g_file_get_contents(path, &buf, NULL, NULL)) {
+        goto err_out;
+    }
+    return buf;
+
+err_out:
+    g_free(path);
+    return NULL;
+}
+
+static char *spapr_phb_get_loc_code(sPAPRPHBState *sphb, PCIDevice *pdev)
+{
+    char *buf;
+    const char *devtype = "qemu";
+    uint32_t busnr = pci_bus_num(PCI_BUS(qdev_get_parent_bus(DEVICE(pdev))));
+
+    if (object_dynamic_cast(OBJECT(pdev), "vfio-pci")) {
+        buf = spapr_phb_vfio_get_loc_code(sphb, pdev);
+        if (buf) {
+            return buf;
+        }
+        devtype = "vfio";
+    }
+    /*
+     * For emulated devices and VFIO-failure case, make up
+     * the loc-code.
+     */
+    buf = g_strdup_printf("%s_%s:%04x:%02x:%02x.%x",
+                          devtype, pdev->name, sphb->index, busnr,
+                          PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
+    return buf;
+}
+
 /* Macros to operate with address in OF binding to PCI */
 #define b_x(x, p, l)    (((x) & ((1<<(l))-1)) << (p))
 #define b_n(x)          b_x((x), 31, 1) /* 0 if relocatable */
@@ -885,11 +939,12 @@  static void populate_resource_props(PCIDevice *d, ResourceProps *rp)
 
 static int spapr_populate_pci_child_dt(PCIDevice *dev, void *fdt, int offset,
                                        int phb_index, int drc_index,
-                                       const char *drc_name)
+                                       sPAPRPHBState *sphb)
 {
     ResourceProps rp;
     bool is_bridge = false;
-    int pci_status;
+    int pci_status, err;
+    char *buf = NULL;
 
     if (pci_default_read_config(dev, PCI_HEADER_TYPE, 1) ==
         PCI_HEADER_TYPE_BRIDGE) {
@@ -950,7 +1005,18 @@  static int spapr_populate_pci_child_dt(PCIDevice *dev, void *fdt, int offset,
      * processed by OF beforehand
      */
     _FDT(fdt_setprop_string(fdt, offset, "name", "pci"));
-    _FDT(fdt_setprop(fdt, offset, "ibm,loc-code", drc_name, strlen(drc_name)));
+    buf = spapr_phb_get_loc_code(sphb, dev);
+    if (!buf) {
+        error_report("Failed setting the ibm,loc-code");
+        return -1;
+    }
+
+    err = fdt_setprop_string(fdt, offset, "ibm,loc-code", buf);
+    g_free(buf);
+    if (err < 0) {
+        return err;
+    }
+
     _FDT(fdt_setprop_cell(fdt, offset, "ibm,my-drc-index", drc_index));
 
     _FDT(fdt_setprop_cell(fdt, offset, "#address-cells",
@@ -988,7 +1054,7 @@  static int spapr_create_pci_child_dt(sPAPRPHBState *phb, PCIDevice *dev,
     }
     offset = fdt_add_subnode(fdt, node_offset, nodename);
     ret = spapr_populate_pci_child_dt(dev, fdt, offset, phb->index, drc_index,
-                                      drc_name);
+                                      phb);
     g_assert(!ret);
     if (ret) {
         return 0;
@@ -1004,14 +1070,13 @@  static void spapr_phb_add_pci_device(sPAPRDRConnector *drc,
     sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
     DeviceState *dev = DEVICE(pdev);
     int drc_index = drck->get_index(drc);
-    const char *drc_name = drck->get_name(drc);
     void *fdt = NULL;
     int fdt_start_offset = 0, fdt_size;
 
     if (dev->hotplugged) {
         fdt = create_device_tree(&fdt_size);
         fdt_start_offset = spapr_create_pci_child_dt(phb, pdev,
-                                                     drc_index, drc_name,
+                                                     drc_index, NULL,
                                                      fdt, 0);
         if (!fdt_start_offset) {
             error_setg(errp, "Failed to create pci child device tree node");