]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
dmaengine: idxd: fix memory leak in error handling path of idxd_alloc
authorShuai Xue <xueshuai@linux.alibaba.com>
Fri, 4 Apr 2025 12:02:14 +0000 (20:02 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 22 May 2025 12:31:56 +0000 (14:31 +0200)
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>
drivers/dma/idxd/init.c

index 6fde6498dee6adf97bb8d44ec5d7bbc5f000d9d8..98dd7bb050edc8b60983064b721763d8e339efec 100644 (file)
@@ -604,28 +604,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)