Commit 6ee626e349 for qemu.org

commit 6ee626e34979eae2d3e2318b00f0c340a474dd23
Author: Daniel Paziyski <danielpaziyski@gmail.com>
Date:   Sat Sep 5 14:18:12 2026 +0200

    hw/nvme: fix memory leak on sr-iov capable nvme controller removal

    If a nvme controller is SR-IOV capable, its list of secondary controllers
    (virtual functions) is stored in the sec_ctrl_list dynamically allocated
    array, located in the NvmeCtrl struct.

    Free the secondary controller list after destroying the virtual functions and
    freeing their controller IDs.

    QEMU command line (boot with a hotunplug-aware OS, such as Linux):

        qemu-system-x86_64 -M q35 -device pcie-root-port,id=rp -monitor stdio \
        -device nvme-subsys,id=subsys0 \
        -device nvme,subsys=subsys0,serial=ctrl0,sriov_max_vfs=1,\
    sriov_vq_flexible=2,sriov_vi_flexible=1,max_ioqpairs=4,msix_qsize=2,bus=rp,id=ctrl0

    In the QEMU monitor:

        device_del ctrl0
        quit

    ASAN splat:

    ==78982==ERROR: LeakSanitizer: detected memory leaks

    Direct leak of 32 byte(s) in 1 object(s) allocated from:
        #0 0x7fcbab32bea9 in calloc (/usr/lib/libasan.so.8+0x12bea9) (BuildId: 7f2845989b820f536270e19ec47df085ae89a675)
        #1 0x7fcbaa2a34b2 in g_malloc0 (/usr/lib/libglib-2.0.so.0+0x694b2) (BuildId: cb17d184459352a7985a010f1cd3acef4a4f90d8)
        #2 0x559c531fff4b in nvme_subsys_register_ctrl ../hw/nvme/subsys.c:65
        #3 0x559c531d715e in nvme_init_subsys ../hw/nvme/ctrl.c:9582
        #4 0x559c531d7a7d in nvme_realize ../hw/nvme/ctrl.c:9637
        #5 0x559c5323c0da in pci_qdev_realize ../hw/pci/pci.c:2316
        #6 0x559c54001e88 in device_set_realized ../hw/core/qdev.c:514
        #7 0x559c5402462e in property_set_bool ../qom/object.c:2484
        #8 0x559c5401dbd2 in object_property_set ../qom/object.c:1548
        #9 0x559c5402b76c in object_property_set_qobject ../qom/qom-qobject.c:28
        #10 0x559c5401e24c in object_property_set_bool ../qom/object.c:1618
        #11 0x559c53fffd77 in qdev_realize ../hw/core/qdev.c:277
        #12 0x559c53934166 in qdev_device_add_from_qdict ../system/qdev-monitor.c:740
        #13 0x559c53934272 in qdev_device_add ../system/qdev-monitor.c:758
        #14 0x559c538867c8 in device_init_func ../system/vl.c:1217
        #15 0x559c5487236a in qemu_opts_foreach ../util/qemu-option.c:1148
        #16 0x559c53891205 in qemu_create_cli_devices ../system/vl.c:2762
        #17 0x559c53891968 in qmp_x_exit_preconfig ../system/vl.c:2822
        #18 0x559c53898108 in qemu_init ../system/vl.c:3862
        #19 0x559c545efabf in main ../system/main.c:71
        #20 0x7fcba7627780  (/usr/lib/libc.so.6+0x27780) (BuildId: 1fa174a830cef40a5b2388add4318ee2795f573e)
        #21 0x7fcba76278b8 in __libc_start_main (/usr/lib/libc.so.6+0x278b8) (BuildId: 1fa174a830cef40a5b2388add4318ee2795f573e)
        #22 0x559c524df1f4 in _start (BuildId: 35402cb4fc46114b7a4102258726bbdec82cd9bc)

    Cc: qemu-stable@nongnu.org
    Fixes: c6159d0e384f ("hw/nvme: Allocate sec-ctrl-list as a dynamic array")
    Signed-off-by: Daniel Paziyski <danielpaziyski@gmail.com>
    Reviewed-by: Klaus Jensen <k.jensen@samsung.com>
    Signed-off-by: Klaus Jensen <k.jensen@samsung.com>

diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
index 1047961b03..578421c217 100644
--- a/hw/nvme/ctrl.c
+++ b/hw/nvme/ctrl.c
@@ -9738,6 +9738,10 @@ static void nvme_exit(PCIDevice *pci_dev)

     nvme_subsys_unregister_ctrl(n->subsys, n);

+    if (!pci_is_vf(pci_dev) && n->params.sriov_max_vfs) {
+        g_free(n->sec_ctrl_list);
+    }
+
     g_free(n->cq);
     g_free(n->sq);
     g_free(n->aer_reqs);