diff mbox

hw/bt/sdp: Fix resource leak detect by coverity

Message ID 1426326454-7216-1-git-send-email-zhaoshenglong@huawei.com
State New
Headers show

Commit Message

Shannon Zhao March 14, 2015, 9:47 a.m. UTC
Free data in function sdp_attr_write after use.

Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
---
    For minimum modification, just add a variable to record the data.
---
 hw/bt/sdp.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

Comments

Stefan Weil March 14, 2015, 10:07 a.m. UTC | #1
Am 14.03.2015 um 10:47 schrieb Shannon Zhao:
> Free data in function sdp_attr_write after use.
>
> Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
> Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
> ---
>      For minimum modification, just add a variable to record the data.
> ---
>   hw/bt/sdp.c | 5 +++--
>   1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/hw/bt/sdp.c b/hw/bt/sdp.c
> index 218e075..8be0d14 100644
> --- a/hw/bt/sdp.c
> +++ b/hw/bt/sdp.c
> @@ -698,7 +698,7 @@ static void sdp_service_record_build(struct sdp_service_record_s *record,
>                   struct sdp_def_service_s *def, int handle)
>   {
>       int len = 0;
> -    uint8_t *data;
> +    uint8_t *data, *pt;
>       int *uuid;
>   
>       record->uuids = 0;
> @@ -712,7 +712,7 @@ static void sdp_service_record_build(struct sdp_service_record_s *record,
>               g_malloc0(record->attributes * sizeof(*record->attribute_list));
>       record->uuid =
>               g_malloc0(record->uuids * sizeof(*record->uuid));
> -    data = g_malloc(len);
> +    pt = data = g_malloc(len);
>   
>       record->attributes = 0;
>       uuid = record->uuid;
> @@ -735,6 +735,7 @@ static void sdp_service_record_build(struct sdp_service_record_s *record,
>           record->attribute_list[record->attributes ++].len = len;
>           data += len;
>       }
> +    g_free(pt);
>   
>       /* Sort the attribute list by the AttributeID */
>       qsort(record->attribute_list, record->attributes,

This fixes the memory leak, but I still don't understand what is done here.
data is allocated, then filled with values, now it is also deallocated. 
But I'm
missing the part where all those data is used.

Stefan
Paolo Bonzini March 15, 2015, 9:21 a.m. UTC | #2
On 14/03/2015 11:07, Stefan Weil wrote:
> 
> This fixes the memory leak, but I still don't understand what is done here.
> data is allocated, then filled with values, now it is also deallocated.
> But I'm missing the part where all those data is used.

"data" escapes in record->attribute_list[record->attributes].pair.

The bug is in bt_l2cap_sdp_close_ch which does an invalid free every
time it frees the first sdp->service_list[i].attribute_list->pair (but
the qsort could have moved it elsewhere in the list).  The right fix is
to do a separate malloc for each attribute, instead of a single one.

In any case, it seems simpler to just leave this code aside.

Paolo
Michael Tokarev March 15, 2015, 10:23 a.m. UTC | #3
15.03.2015 12:21, Paolo Bonzini wrote:
> On 14/03/2015 11:07, Stefan Weil wrote:
>>
>> This fixes the memory leak, but I still don't understand what is done here.
>> data is allocated, then filled with values, now it is also deallocated.
>> But I'm missing the part where all those data is used.
> 
> "data" escapes in record->attribute_list[record->attributes].pair.
> 
> The bug is in bt_l2cap_sdp_close_ch which does an invalid free every
> time it frees the first sdp->service_list[i].attribute_list->pair (but
> the qsort could have moved it elsewhere in the list).  The right fix is
> to do a separate malloc for each attribute, instead of a single one.

Or, alternatively, to keep this `data' pointer in sdp to use it in
bt_l2cap_sdp_close_ch().

> In any case, it seems simpler to just leave this code aside.

How many times this code is called?

We have many many places in qemu where resources are allocated once
at startup and never freed just because there's no need to.

Thanks,

/mjt
Paolo Bonzini March 15, 2015, 2:11 p.m. UTC | #4
On 15/03/2015 11:23, Michael Tokarev wrote:
> Or, alternatively, to keep this `data' pointer in sdp to use it in
> bt_l2cap_sdp_close_ch().

Yes.

>> > In any case, it seems simpler to just leave this code aside.
> How many times this code is called?
> 
> We have many many places in qemu where resources are allocated once
> at startup and never freed just because there's no need to.

Well, in this case the bug in bt_l2cap_sdp_close_ch is much worse than a
resource leak.  But bluetooth is not the utmost priority in QEMU
development...

Paolo
Markus Armbruster March 16, 2015, 7:29 a.m. UTC | #5
Paolo Bonzini <pbonzini@redhat.com> writes:

> On 15/03/2015 11:23, Michael Tokarev wrote:
>> Or, alternatively, to keep this `data' pointer in sdp to use it in
>> bt_l2cap_sdp_close_ch().
>
> Yes.
>
>>> > In any case, it seems simpler to just leave this code aside.
>> How many times this code is called?
>> 
>> We have many many places in qemu where resources are allocated once
>> at startup and never freed just because there's no need to.
>
> Well, in this case the bug in bt_l2cap_sdp_close_ch is much worse than a
> resource leak.  But bluetooth is not the utmost priority in QEMU
> development...

To put it more bluntly: it's rotting in peace.

Occasional drive-by fixes won't stop the rot, a dedicated maintener
could.
Paolo Bonzini March 16, 2015, 8:13 a.m. UTC | #6
On 16/03/2015 08:29, Markus Armbruster wrote:
> > Well, in this case the bug in bt_l2cap_sdp_close_ch is much worse than a
> > resource leak.  But bluetooth is not the utmost priority in QEMU
> > development...
> 
> To put it more bluntly: it's rotting in peace.
> 
> Occasional drive-by fixes won't stop the rot, a dedicated maintener
> could.

I disagree.  The code is not that good, but apparently it works.
Samsung folks are using it and presented their work at KVM Forum 2014.

Paolo
diff mbox

Patch

diff --git a/hw/bt/sdp.c b/hw/bt/sdp.c
index 218e075..8be0d14 100644
--- a/hw/bt/sdp.c
+++ b/hw/bt/sdp.c
@@ -698,7 +698,7 @@  static void sdp_service_record_build(struct sdp_service_record_s *record,
                 struct sdp_def_service_s *def, int handle)
 {
     int len = 0;
-    uint8_t *data;
+    uint8_t *data, *pt;
     int *uuid;
 
     record->uuids = 0;
@@ -712,7 +712,7 @@  static void sdp_service_record_build(struct sdp_service_record_s *record,
             g_malloc0(record->attributes * sizeof(*record->attribute_list));
     record->uuid =
             g_malloc0(record->uuids * sizeof(*record->uuid));
-    data = g_malloc(len);
+    pt = data = g_malloc(len);
 
     record->attributes = 0;
     uuid = record->uuid;
@@ -735,6 +735,7 @@  static void sdp_service_record_build(struct sdp_service_record_s *record,
         record->attribute_list[record->attributes ++].len = len;
         data += len;
     }
+    g_free(pt);
 
     /* Sort the attribute list by the AttributeID */
     qsort(record->attribute_list, record->attributes,