Commit e8071845 authored by David E. Box's avatar David E. Box Committed by jiayingbao
Browse files

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

mainline inclusion
from mainline-v6.7-rc2
commit 8cbcc1dbf8a62c730fadd60de761e0658547a589
category: feature
bugzilla: https://gitee.com/openeuler/intel-kernel/issues/I8WOEO

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=8cbcc1dbf8a62c730fadd60de761e0658547a589



-------------------------------------

Commit 936874b7 ("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.

Intel-SIG: commit 8cbcc1dbf8a6 platform/x86/intel/vsec: Fix xa_alloc memory leak
Backport Intel_tpmi base driver.

Fixes: 936874b7 ("platform/x86/intel/vsec: Add PCI error recovery support to Intel PMT")
Signed-off-by: default avatarDavid E. Box <david.e.box@linux.intel.com>
Reviewed-by: default avatarIlpo 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: default avatarHans de Goede <hdegoede@redhat.com>
[ Yingbao Jia: amend commit log ]
Signed-off-by: default avatarYingbao Jia <yingbao.jia@intel.com>
parent 1e6e498c
Loading
Loading
Loading
Loading
+15 −10
Original line number Diff line number Diff line
@@ -112,6 +112,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);
@@ -127,19 +129,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;
@@ -161,12 +172,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);
+1 −0
Original line number Diff line number Diff line
@@ -44,6 +44,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;
};