Bug 1366097

Summary: some memory leak in qemuDomainAssignAddresses
Product: Red Hat Enterprise Linux 7 Reporter: Luyao Huang <lhuang>
Component: libvirtAssignee: Ján Tomko <jtomko>
Status: CLOSED ERRATA QA Contact: Virtualization Bugs <virt-bugs>
Severity: low Docs Contact:
Priority: low    
Version: 7.3CC: dyuan, jtomko, pzhang, rbalakri, xuzhang
Target Milestone: rc   
Target Release: ---   
Hardware: x86_64   
OS: Linux   
Whiteboard:
Fixed In Version: libvirt-2.0.0-6.el7 Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2016-11-03 18:52:16 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Luyao Huang 2016-08-11 03:40:08 UTC
Description of problem:
some memory leak in qemuDomainAssignAddresses

Version-Release number of selected component (if applicable):
libvirt-2.0.0-5.el7.x86_64

How reproducible:
100%

Steps to Reproduce:
1.

memory leak during guest start and destroy which guest have some device on usb bus like this:

    <redirdev bus='usb' type='pty'>
      <alias name='redir0'/>
      <address type='usb' bus='0' port='2'/>
    </redirdev>
    <redirdev bus='usb' type='spicevmc'>
      <alias name='redir1'/>
      <address type='usb' bus='0' port='3'/>
    </redirdev>


==8783== 272 (32 direct, 240 indirect) bytes in 2 blocks are definitely lost in loss record 1,615 of 2,005
==8783==    at 0x4C29975: calloc (vg_replace_malloc.c:711)
==8783==    by 0x54B1123: virAlloc (viralloc.c:144)
==8783==    by 0x5530792: virDomainUSBAddressSetCreate (domain_addr.c:1294)
==8783==    by 0x21FFCCD4: qemuDomainAssignUSBAddresses (qemu_domain_address.c:1735)
==8783==    by 0x21FFCCD4: qemuDomainAssignAddresses (qemu_domain_address.c:1791)
==8783==    by 0x22012FA5: qemuProcessPrepareDomain (qemu_process.c:4885)
==8783==    by 0x2201A2DF: qemuProcessStart (qemu_process.c:5460)
==8783==    by 0x220761E7: qemuDomainObjStart.constprop.48 (qemu_driver.c:7059)
==8783==    by 0x22076925: qemuDomainCreateWithFlags (qemu_driver.c:7113)
==8783==    by 0x55C3E3B: virDomainCreate (libvirt-domain.c:6787)
==8783==    by 0x14AF7A: remoteDispatchDomainCreate (remote_dispatch.h:4116)
==8783==    by 0x14AF7A: remoteDispatchDomainCreateHelper (remote_dispatch.h:4092)
==8783==    by 0x562F931: virNetServerProgramDispatchCall (virnetserverprogram.c:437)
==8783==    by 0x562F931: virNetServerProgramDispatch (virnetserverprogram.c:307)
==8783==    by 0x15BC2C: virNetServerProcessMsg (virnetserver.c:148)
==8783==    by 0x15BC2C: virNetServerHandleJob (virnetserver.c:169)

...

==8666== 48 bytes in 1 blocks are definitely lost in loss record 462 of 684
==8666==    at 0x4C29975: calloc (vg_replace_malloc.c:711)
==8666==    by 0x54B118C: virAllocN (viralloc.c:191)
==8666==    by 0x552E12A: virDomainUSBAddressHubNew (domain_addr.c:1384)
==8666==    by 0x5530C34: virDomainUSBAddressSetAddController (domain_addr.c:1422)
==8666==    by 0x5530C34: virDomainUSBAddressSetAddControllers (domain_addr.c:1547)
==8666==    by 0x21FFCE39: qemuDomainAssignUSBAddresses (qemu_domain_address.c:1741)
==8666==    by 0x21FFCE39: qemuDomainAssignAddresses (qemu_domain_address.c:1791)
==8666==    by 0x22012FA5: qemuProcessPrepareDomain (qemu_process.c:4885)
==8666==    by 0x2201A2DF: qemuProcessStart (qemu_process.c:5460)
==8666==    by 0x220761E7: qemuDomainObjStart.constprop.48 (qemu_driver.c:7059)
==8666==    by 0x22076925: qemuDomainCreateWithFlags (qemu_driver.c:7113)
==8666==    by 0x55C3E3B: virDomainCreate (libvirt-domain.c:6787)
==8666==    by 0x14AF7A: remoteDispatchDomainCreate (remote_dispatch.h:4116)
==8666==    by 0x14AF7A: remoteDispatchDomainCreateHelper (remote_dispatch.h:4092)
==8666==    by 0x562F931: virNetServerProgramDispatchCall (virnetserverprogram.c:437)
==8666==    by 0x562F931: virNetServerProgramDispatch (virnetserverprogram.c:307)
==8666== 
==8666== 144 bytes in 3 blocks are definitely lost in loss record 528 of 684
==8666==    at 0x4C29975: calloc (vg_replace_malloc.c:711)
==8666==    by 0x54B118C: virAllocN (viralloc.c:191)
==8666==    by 0x552E12A: virDomainUSBAddressHubNew (domain_addr.c:1384)
==8666==    by 0x5530C34: virDomainUSBAddressSetAddController (domain_addr.c:1422)
==8666==    by 0x5530C34: virDomainUSBAddressSetAddControllers (domain_addr.c:1547)
==8666==    by 0x21FFCE39: qemuDomainAssignUSBAddresses (qemu_domain_address.c:1741)
==8666==    by 0x21FFCE39: qemuDomainAssignAddresses (qemu_domain_address.c:1791)
==8666==    by 0x21FEFDCC: qemuDomainDefAssignAddresses (qemu_domain.c:2510)
==8666==    by 0x554FC8A: virDomainDefPostParse (domain_conf.c:4558)
==8666==    by 0x5561165: virDomainDefParseXML (domain_conf.c:17370)
==8666==    by 0x5565D0F: virDomainDefParseNode (domain_conf.c:17552)
==8666==    by 0x5565E27: virDomainDefParse (domain_conf.c:17499)
==8666==    by 0x220609DB: qemuDomainDefineXMLFlags (qemu_driver.c:7160)
==8666==    by 0x55C3359: virDomainDefineXMLFlags (libvirt-domain.c:6464)
==8666== 
==8666== 544 (64 direct, 480 indirect) bytes in 4 blocks are definitely lost in loss record 640 of 684
==8666==    at 0x4C29975: calloc (vg_replace_malloc.c:711)
==8666==    by 0x54B1123: virAlloc (viralloc.c:144)
==8666==    by 0x5530792: virDomainUSBAddressSetCreate (domain_addr.c:1294)
==8666==    by 0x21FFCCD4: qemuDomainAssignUSBAddresses (qemu_domain_address.c:1735)
==8666==    by 0x21FFCCD4: qemuDomainAssignAddresses (qemu_domain_address.c:1791)
==8666==    by 0x22012FA5: qemuProcessPrepareDomain (qemu_process.c:4885)
==8666==    by 0x2201A2DF: qemuProcessStart (qemu_process.c:5460)
==8666==    by 0x220761E7: qemuDomainObjStart.constprop.48 (qemu_driver.c:7059)
==8666==    by 0x22076925: qemuDomainCreateWithFlags (qemu_driver.c:7113)
==8666==    by 0x55C3E3B: virDomainCreate (libvirt-domain.c:6787)
==8666==    by 0x14AF7A: remoteDispatchDomainCreate (remote_dispatch.h:4116)
==8666==    by 0x14AF7A: remoteDispatchDomainCreateHelper (remote_dispatch.h:4092)
==8666==    by 0x562F931: virNetServerProgramDispatchCall (virnetserverprogram.c:437)
==8666==    by 0x562F931: virNetServerProgramDispatch (virnetserverprogram.c:307)
==8666==    by 0x15BC2C: virNetServerProcessMsg (virnetserver.c:148)
==8666==    by 0x15BC2C: virNetServerHandleJob (virnetserver.c:169)


2.
3.

Actual results:
some memory leak in qemuDomainAssignAddresses

Expected results:
no memory leak

Additional info:

I guess the problem is here:

In qemuDomainAssignUSBAddresses:

    if (obj && obj->privateData) {
        priv = obj->privateData;
        priv->usbaddrs = addrs;
        addrs = NULL;
    }

Libvirt will pass a new pointer to priv->usbaddrs, however not free priv->usbaddrs during destroy guest, so the old pointer saved in priv->usbaddrs
will be leaked.

1758	    if (obj && obj->privateData) {
(gdb) p *((qemuDomainObjPrivatePtr) obj->privateData)->usbaddrs
$12 = {buses = 0x7fb638014ba0, nbuses = 1}
(gdb) n
1760	        priv->usbaddrs = addrs;
(gdb) 
1761	        addrs = NULL;
(gdb) p *((qemuDomainObjPrivatePtr) obj->privateData)->usbaddrs
$13 = {buses = 0x7fb638000d70, nbuses = 1}

Comment 1 Ján Tomko 2016-08-15 16:14:57 UTC
Upstream patch:
https://www.redhat.com/archives/libvir-list/2016-August/msg00760.html

Comment 2 Ján Tomko 2016-08-16 10:40:27 UTC
Fixed upstream by:
commit d49f6853b36234ea0ec175dc39a5d67ba2a75123
Author:     Ján Tomko <jtomko>
CommitDate: 2016-08-16 12:31:41 +0200

    conf: free the ports array of a USB hub
    
    The array needs to be freed too, not just its members.
    
    https://bugzilla.redhat.com/show_bug.cgi?id=1366097

git describe: v2.1.0-137-gd49f685

Comment 5 Pei Zhang 2016-09-02 08:14:53 UTC
Verified version :
libvirt-2.0.0-6.el7.x86_64
qemu-kvm-rhev-2.6.0-22.el7.x86_64

Steps :
1. In termimal one, start libvirtd with valgrind:
# valgrind --leak-check=full libvirtd
==4874== Memcheck, a memory error detector
==4874== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==4874== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==4874== Command: libvirtd
==4874== 

2. In termianl 2, start a guest like following 
#virsh start vm2
# virsh dumpxml vm2  | grep usb -A 4
    <controller type='usb' index='0'>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
    </controller>  
    <input type='mouse' bus='usb'>
      <address type='usb' bus='0' port='2'/>
    </input>
    <input type='keyboard' bus='usb'>
      <address type='usb' bus='0' port='1.1'/>
    </input>
    <redirdev bus='usb' type='spicevmc'>
      <address type='usb' bus='0' port='1.2'/>
    </redirdev>
    <redirdev bus='usb' type='spicevmc'>
      <address type='usb' bus='0' port='1.3'/>
    </redirdev>
    <hub type='usb'>
      <address type='usb' bus='0' port='1'/>
    </hub>

After guest fully started, destroy guest 
#virsh destroy vm2
Domain vm2 destroyed

3.Check in terminal 1 again, There is NO info like qemuDomainAssignUSBAddresses
and no memory leak now. 
......
==4338== LEAK SUMMARY:
==4338==    definitely lost: 0 bytes in 0 blocks
==4338==    indirectly lost: 0 bytes in 0 blocks
==4338==      possibly lost: 720 bytes in 1 blocks
==4338==    still reachable: 734,454 bytes in 8,865 blocks
==4338==         suppressed: 0 bytes in 0 blocks
==4338== Reachable blocks (those to which a pointer was found) are not shown.
==4338== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==4338== 

Move to verified.

Comment 7 errata-xmlrpc 2016-11-03 18:52:16 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory, and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://rhn.redhat.com/errata/RHSA-2016-2577.html