summaryrefslogtreecommitdiff
path: root/drivers/dma
diff options
context:
space:
mode:
authorShuai Xue <xueshuai@linux.alibaba.com>2025-04-04 20:02:14 +0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2025-05-22 14:12:24 +0200
commit6e94a2c3e4c166cd2736ac225fba5889fb1e8ac0 (patch)
treec5fdc74864073f7d1a78ae4648939864b5465a42 /drivers/dma
parentd2d05fd0fc95c4defed6f7b87550e20e8baa1d97 (diff)
downloadlinux-6e94a2c3e4c166cd2736ac225fba5889fb1e8ac0.tar.gz
linux-6e94a2c3e4c166cd2736ac225fba5889fb1e8ac0.tar.bz2
linux-6e94a2c3e4c166cd2736ac225fba5889fb1e8ac0.zip
dmaengine: idxd: fix memory leak in error handling path of idxd_alloc
commit 46a5cca76c76c86063000a12936f8e7875295838 upstream. Memory allocated for idxd is not freed if an error occurs during idxd_alloc(). To fix it, free the allocated memory in the reverse order of allocation before exiting the function in case of an error. Fixes: a8563a33a5e2 ("dmanegine: idxd: reformat opcap output to match bitmap_parse() input") Cc: stable@vger.kernel.org Signed-off-by: Shuai Xue <xueshuai@linux.alibaba.com> Reviewed-by: Dave Jiang <dave.jiang@intel.com> Reviewed-by: Fenghua Yu <fenghuay@nvidia.com> Link: https://lore.kernel.org/r/20250404120217.48772-7-xueshuai@linux.alibaba.com Signed-off-by: Vinod Koul <vkoul@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/dma')
-rw-r--r--drivers/dma/idxd/init.c24
1 files changed, 15 insertions, 9 deletions
diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c
index ab823fb7263b..56e52db45376 100644
--- a/drivers/dma/idxd/init.c
+++ b/drivers/dma/idxd/init.c
@@ -594,28 +594,34 @@ static struct idxd_device *idxd_alloc(struct pci_dev *pdev, struct idxd_driver_d
idxd_dev_set_type(&idxd->idxd_dev, idxd->data->type);
idxd->id = ida_alloc(&idxd_ida, GFP_KERNEL);
if (idxd->id < 0)
- return NULL;
+ goto err_ida;
idxd->opcap_bmap = bitmap_zalloc_node(IDXD_MAX_OPCAP_BITS, GFP_KERNEL, dev_to_node(dev));
- if (!idxd->opcap_bmap) {
- ida_free(&idxd_ida, idxd->id);
- return NULL;
- }
+ if (!idxd->opcap_bmap)
+ goto err_opcap;
device_initialize(conf_dev);
conf_dev->parent = dev;
conf_dev->bus = &dsa_bus_type;
conf_dev->type = idxd->data->dev_type;
rc = dev_set_name(conf_dev, "%s%d", idxd->data->name_prefix, idxd->id);
- if (rc < 0) {
- put_device(conf_dev);
- return NULL;
- }
+ if (rc < 0)
+ goto err_name;
spin_lock_init(&idxd->dev_lock);
spin_lock_init(&idxd->cmd_lock);
return idxd;
+
+err_name:
+ put_device(conf_dev);
+ bitmap_free(idxd->opcap_bmap);
+err_opcap:
+ ida_free(&idxd_ida, idxd->id);
+err_ida:
+ kfree(idxd);
+
+ return NULL;
}
static int idxd_enable_system_pasid(struct idxd_device *idxd)