When an error happens after device_initialize(), idxd_setup_wqs()
calls put_device(conf_dev).
The device release callback idxd_conf_wq_release() frees wq,
wq->wqcfg, and wq->opcap_bmap, but the current error paths then free
them again directly, causing a double free.
Keep the cleanup in idxd_conf_wq_release() after put_device() and
avoid freeing those objects again in idxd_setup_wqs().
Fixes: 39aaa337449e7 ("dmaengine: idxd: Fix double free in idxd_setup_wqs()")
Cc: stable@vger.kernel.org
Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
---
drivers/dma/idxd/init.c | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)
diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c
index 2acc34b3daff..b782eb3c191d 100644
--- a/drivers/dma/idxd/init.c
+++ b/drivers/dma/idxd/init.c
@@ -212,7 +212,7 @@ static int idxd_setup_wqs(struct idxd_device *idxd)
rc = dev_set_name(conf_dev, "wq%d.%d", idxd->id, wq->id);
if (rc < 0) {
put_device(conf_dev);
- kfree(wq);
+
goto err_unwind;
}
@@ -226,7 +226,7 @@ static int idxd_setup_wqs(struct idxd_device *idxd)
wq->wqcfg = kzalloc_node(idxd->wqcfg_size, GFP_KERNEL, dev_to_node(dev));
if (!wq->wqcfg) {
put_device(conf_dev);
- kfree(wq);
+
rc = -ENOMEM;
goto err_unwind;
}
@@ -234,9 +234,9 @@ static int idxd_setup_wqs(struct idxd_device *idxd)
if (idxd->hw.wq_cap.op_config) {
wq->opcap_bmap = bitmap_zalloc(IDXD_MAX_OPCAP_BITS, GFP_KERNEL);
if (!wq->opcap_bmap) {
- kfree(wq->wqcfg);
+
put_device(conf_dev);
- kfree(wq);
+
rc = -ENOMEM;
goto err_unwind;
}
@@ -252,12 +252,10 @@ static int idxd_setup_wqs(struct idxd_device *idxd)
err_unwind:
while (--i >= 0) {
wq = idxd->wqs[i];
- if (idxd->hw.wq_cap.op_config)
- bitmap_free(wq->opcap_bmap);
- kfree(wq->wqcfg);
+
conf_dev = wq_confdev(wq);
put_device(conf_dev);
- kfree(wq);
+
}
bitmap_free(idxd->wq_enable_map);
--
2.43.0