platform/x86/intel/vsec: Fix xa_alloc memory leak

[ Upstream commit 8cbcc1dbf8a62c730fadd60de761e0658547a589 ]

Commit 936874b77d ("platform/x86/intel/vsec: Add PCI error recovery
support to Intel PMT") added an xarray to track the list of vsec devices to
be recovered after a PCI error. But it did not provide cleanup for the list
leading to a memory leak that was caught by kmemleak.  Do xa_alloc() before
devm_add_action_or_reset() so that the list may be cleaned up with
xa_erase() in the release function.

Fixes: 936874b77d ("platform/x86/intel/vsec: Add PCI error recovery support to Intel PMT")
Signed-off-by: David E. Box <david.e.box@linux.intel.com>
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Link: https://lore.kernel.org/r/20231129222132.2331261-2-david.e.box@linux.intel.com
[hdegoede@redhat.com: Add missing xa_erase() on error-exit
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
David E. Box 2023-11-29 14:21:13 -08:00 committed by Greg Kroah-Hartman
parent 0ff5cd92bb
commit 426710a2bc
2 changed files with 16 additions and 10 deletions

View File

@ -130,6 +130,8 @@ static void intel_vsec_dev_release(struct device *dev)
{
struct intel_vsec_device *intel_vsec_dev = dev_to_ivdev(dev);
xa_erase(&auxdev_array, intel_vsec_dev->id);
mutex_lock(&vsec_ida_lock);
ida_free(intel_vsec_dev->ida, intel_vsec_dev->auxdev.id);
mutex_unlock(&vsec_ida_lock);
@ -145,19 +147,28 @@ int intel_vsec_add_aux(struct pci_dev *pdev, struct device *parent,
struct auxiliary_device *auxdev = &intel_vsec_dev->auxdev;
int ret, id;
mutex_lock(&vsec_ida_lock);
ret = ida_alloc(intel_vsec_dev->ida, GFP_KERNEL);
mutex_unlock(&vsec_ida_lock);
ret = xa_alloc(&auxdev_array, &intel_vsec_dev->id, intel_vsec_dev,
PMT_XA_LIMIT, GFP_KERNEL);
if (ret < 0) {
kfree(intel_vsec_dev->resource);
kfree(intel_vsec_dev);
return ret;
}
mutex_lock(&vsec_ida_lock);
id = ida_alloc(intel_vsec_dev->ida, GFP_KERNEL);
mutex_unlock(&vsec_ida_lock);
if (id < 0) {
xa_erase(&auxdev_array, intel_vsec_dev->id);
kfree(intel_vsec_dev->resource);
kfree(intel_vsec_dev);
return id;
}
if (!parent)
parent = &pdev->dev;
auxdev->id = ret;
auxdev->id = id;
auxdev->name = name;
auxdev->dev.parent = parent;
auxdev->dev.release = intel_vsec_dev_release;
@ -183,12 +194,6 @@ int intel_vsec_add_aux(struct pci_dev *pdev, struct device *parent,
if (ret < 0)
return ret;
/* Add auxdev to list */
ret = xa_alloc(&auxdev_array, &id, intel_vsec_dev, PMT_XA_LIMIT,
GFP_KERNEL);
if (ret)
return ret;
return 0;
}
EXPORT_SYMBOL_NS_GPL(intel_vsec_add_aux, INTEL_VSEC);

View File

@ -38,6 +38,7 @@ struct intel_vsec_device {
struct ida *ida;
struct intel_vsec_platform_info *info;
int num_resources;
int id; /* xa */
void *priv_data;
size_t priv_data_size;
};