[PATCH 2/3] hw/nvme: fix memory leak on sr-iov capable nvme controller removal
Daniel Paziyski <[email protected]> Wed, 5 Aug 2026 14:45:17 +0200
| Newsgroups | gmane.comp.emulators.qemu,gmane.comp.emulators.qemu.stable,gmane.comp.emulators.qemu.block |
|---|---|
| Message-ID | <[email protected]> |
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: [email protected]
Fixes: c6159d0e384f ("hw/nvme: Allocate sec-ctrl-list as a dynamic array")
Signed-off-by: Daniel Paziyski <[email protected]>
---
hw/nvme/ctrl.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
index b726c13a56..284f3964e3 100644
--- a/hw/nvme/ctrl.c
+++ b/hw/nvme/ctrl.c
@@ -9682,6 +9682,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);
--
2.55.0