* [PATCH 1/2] dmaengine: idxd: fix double free in idxd_free() [not found] <20261028003708.834341-1-jinli@purestorage.com> @ 2026-10-28 0:37 ` Jingyi Li 2026-10-28 15:04 ` Frank Li 2026-10-28 0:37 ` [PATCH 2/2] dmaengine: idxd: fix destroy of NULL or already destroyed workqueue Jingyi Li 1 sibling, 1 reply; 4+ messages in thread From: Jingyi Li @ 2026-10-28 0:37 UTC (permalink / raw) To: vkoul, vinicius.gomes Cc: dave.jiang, xueshuai, fenghuay, Frank.Li, dmaengine, linux-kernel, stable, Jingyi Li idxd_free() calls put_device() on the conf device, which drops the last reference and runs idxd_conf_device_release(). The release callback already frees idxd->opcap_bmap, the IDA id and idxd itself, so the subsequent bitmap_free(), ida_free() and kfree() in idxd_free() operate on freed memory. idxd_free() is called from the error path of idxd_pci_probe_alloc() when idxd_probe() fails, for example when the device reports HALTED after reset. We hit this in a kdump crash kernel, where the DSA device fails to reset: the double free corrupts the slab and the crash kernel dies before the dump is saved. With slub_debug=FZPU it shows up as general protection faults on 0x6b6b6b6b6b6b6b6b. Let the release callback do all the freeing. Fixes: 90022b3a6981 ("dmaengine: idxd: fix memory leak in error handling path of idxd_pci_probe") Cc: stable@vger.kernel.org Signed-off-by: Jingyi Li <jinli@purestorage.com> --- drivers/dma/idxd/init.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c index 4b827a329756..1577d22b299c 100644 --- a/drivers/dma/idxd/init.c +++ b/drivers/dma/idxd/init.c @@ -581,9 +581,6 @@ static void idxd_free(struct idxd_device *idxd) return; put_device(idxd_confdev(idxd)); - bitmap_free(idxd->opcap_bmap); - ida_free(&idxd_ida, idxd->id); - kfree(idxd); } static struct idxd_device *idxd_alloc(struct pci_dev *pdev, struct idxd_driver_data *data) -- 2.43.0 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH 1/2] dmaengine: idxd: fix double free in idxd_free() 2026-10-28 0:37 ` [PATCH 1/2] dmaengine: idxd: fix double free in idxd_free() Jingyi Li @ 2026-10-28 15:04 ` Frank Li 0 siblings, 0 replies; 4+ messages in thread From: Frank Li @ 2026-10-28 15:04 UTC (permalink / raw) To: Jingyi Li Cc: vkoul, vinicius.gomes, dave.jiang, xueshuai, fenghuay, Frank.Li, dmaengine, linux-kernel, stable On Wed, Oct 28, 2026 at 12:37:06AM +0000, Jingyi Li wrote: > [You don't often get email from jinli@purestorage.com. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ] > > idxd_free() calls put_device() on the conf device, which drops the last > reference and runs idxd_conf_device_release(). The release callback > already frees idxd->opcap_bmap, the IDA id and idxd itself, so the > subsequent bitmap_free(), ida_free() and kfree() in idxd_free() operate > on freed memory. > > idxd_free() is called from the error path of idxd_pci_probe_alloc() > when idxd_probe() fails, for example when the device reports HALTED > after reset. We hit this in a kdump crash kernel, where the DSA device > fails to reset: the double free corrupts the slab and the crash kernel > dies before the dump is saved. With slub_debug=FZPU it shows up as > general protection faults on 0x6b6b6b6b6b6b6b6b. > > Let the release callback do all the freeing. > > Fixes: 90022b3a6981 ("dmaengine: idxd: fix memory leak in error handling path of idxd_pci_probe") > Cc: stable@vger.kernel.org > Signed-off-by: Jingyi Li <jinli@purestorage.com> > --- Similar fixes at https://patchwork.kernel.org/project/linux-dmaengine/patch/20261012-wt-idxd-fixes-v1-2-30a35a445077@intel.com/ Frank > drivers/dma/idxd/init.c | 3 --- > 1 file changed, 3 deletions(-) > > diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c > index 4b827a329756..1577d22b299c 100644 > --- a/drivers/dma/idxd/init.c > +++ b/drivers/dma/idxd/init.c > @@ -581,9 +581,6 @@ static void idxd_free(struct idxd_device *idxd) > return; > > put_device(idxd_confdev(idxd)); > - bitmap_free(idxd->opcap_bmap); > - ida_free(&idxd_ida, idxd->id); > - kfree(idxd); > } > > static struct idxd_device *idxd_alloc(struct pci_dev *pdev, struct idxd_driver_data *data) > -- > 2.43.0 > ^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 2/2] dmaengine: idxd: fix destroy of NULL or already destroyed workqueue [not found] <20261028003708.834341-1-jinli@purestorage.com> 2026-10-28 0:37 ` [PATCH 1/2] dmaengine: idxd: fix double free in idxd_free() Jingyi Li @ 2026-10-28 0:37 ` Jingyi Li 2026-10-28 15:07 ` Frank Li 1 sibling, 1 reply; 4+ messages in thread From: Jingyi Li @ 2026-10-28 0:37 UTC (permalink / raw) To: vkoul, vinicius.gomes Cc: dave.jiang, xueshuai, fenghuay, Frank.Li, dmaengine, linux-kernel, stable, Jingyi Li idxd_conf_device_release() unconditionally calls destroy_workqueue(idxd->wq). This is wrong in two cases: - If idxd_probe() fails before idxd_setup_internals() has created the workqueue, for example when the device reports HALTED after reset, idxd->wq is still NULL and the final put_device() in the probe error path oopses: BUG: kernel NULL pointer dereference, address: 00000000000000d0 RIP: 0010:destroy_workqueue+0xe/0x300 Call Trace: <TASK> idxd_conf_device_release+0x15/0x90 [idxd] device_release+0x3c/0x90 kobject_put+0x7e/0x1e0 idxd_pci_probe_alloc+0x300/0x15e0 [idxd] local_pci_probe+0x22/0x60 pci_device_probe+0xd4/0x260 - idxd_cleanup_internals() and the err_evl path of idxd_setup_internals() destroy the workqueue but leave idxd->wq pointing to it, so the release callback destroys it a second time. Clear idxd->wq after the early destroys and skip the destroy in the release callback when there is no workqueue. We hit the NULL case in a kdump crash kernel, where the DSA device fails to reset and the oops kills the crash kernel before the dump is saved. Fixes: 3d33de353b1f ("dmaengine: idxd: Fix not releasing workqueue on .release()") Cc: stable@vger.kernel.org Signed-off-by: Jingyi Li <jinli@purestorage.com> --- drivers/dma/idxd/init.c | 2 ++ drivers/dma/idxd/sysfs.c | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c index 1577d22b299c..5962cacef060 100644 --- a/drivers/dma/idxd/init.c +++ b/drivers/dma/idxd/init.c @@ -389,6 +389,7 @@ static void idxd_cleanup_internals(struct idxd_device *idxd) idxd_clean_engines(idxd); idxd_clean_wqs(idxd); destroy_workqueue(idxd->wq); + idxd->wq = NULL; } static int idxd_init_evl(struct idxd_device *idxd) @@ -460,6 +461,7 @@ static int idxd_setup_internals(struct idxd_device *idxd) err_evl: destroy_workqueue(idxd->wq); + idxd->wq = NULL; err_wkq_create: idxd_clean_groups(idxd); err_group: diff --git a/drivers/dma/idxd/sysfs.c b/drivers/dma/idxd/sysfs.c index 6d251095c350..d5ffc641c856 100644 --- a/drivers/dma/idxd/sysfs.c +++ b/drivers/dma/idxd/sysfs.c @@ -1836,7 +1836,8 @@ static void idxd_conf_device_release(struct device *dev) { struct idxd_device *idxd = confdev_to_idxd(dev); - destroy_workqueue(idxd->wq); + if (idxd->wq) + destroy_workqueue(idxd->wq); kfree(idxd->groups); bitmap_free(idxd->wq_enable_map); kfree(idxd->wqs); -- 2.43.0 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH 2/2] dmaengine: idxd: fix destroy of NULL or already destroyed workqueue 2026-10-28 0:37 ` [PATCH 2/2] dmaengine: idxd: fix destroy of NULL or already destroyed workqueue Jingyi Li @ 2026-10-28 15:07 ` Frank Li 0 siblings, 0 replies; 4+ messages in thread From: Frank Li @ 2026-10-28 15:07 UTC (permalink / raw) To: Jingyi Li Cc: vkoul, vinicius.gomes, dave.jiang, xueshuai, fenghuay, Frank.Li, dmaengine, linux-kernel, stable On Wed, Oct 28, 2026 at 12:37:07AM +0000, Jingyi Li wrote: > [You don't often get email from jinli@purestorage.com. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ] > > idxd_conf_device_release() unconditionally calls > destroy_workqueue(idxd->wq). This is wrong in two cases: > > - If idxd_probe() fails before idxd_setup_internals() has created the > workqueue, for example when the device reports HALTED after reset, > idxd->wq is still NULL and the final put_device() in the probe error > path oopses: > > BUG: kernel NULL pointer dereference, address: 00000000000000d0 > RIP: 0010:destroy_workqueue+0xe/0x300 > Call Trace: > <TASK> > idxd_conf_device_release+0x15/0x90 [idxd] > device_release+0x3c/0x90 > kobject_put+0x7e/0x1e0 > idxd_pci_probe_alloc+0x300/0x15e0 [idxd] > local_pci_probe+0x22/0x60 > pci_device_probe+0xd4/0x260 > > - idxd_cleanup_internals() and the err_evl path of > idxd_setup_internals() destroy the workqueue but leave idxd->wq > pointing to it, so the release callback destroys it a second time. > > Clear idxd->wq after the early destroys and skip the destroy in the > release callback when there is no workqueue. > > We hit the NULL case in a kdump crash kernel, where the DSA device > fails to reset and the oops kills the crash kernel before the dump is > saved. > > Fixes: 3d33de353b1f ("dmaengine: idxd: Fix not releasing workqueue on .release()") > Cc: stable@vger.kernel.org > Signed-off-by: Jingyi Li <jinli@purestorage.com> > --- This one better than https://lore.kernel.org/dmaengine/20261012-wt-idxd-fixes-v1-1-30a35a445077@intel.com/ Reviewed-by: Frank Li <Frank.Li@nxp.com> > drivers/dma/idxd/init.c | 2 ++ > drivers/dma/idxd/sysfs.c | 3 ++- > 2 files changed, 4 insertions(+), 1 deletion(-) > > diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c > index 1577d22b299c..5962cacef060 100644 > --- a/drivers/dma/idxd/init.c > +++ b/drivers/dma/idxd/init.c > @@ -389,6 +389,7 @@ static void idxd_cleanup_internals(struct idxd_device *idxd) > idxd_clean_engines(idxd); > idxd_clean_wqs(idxd); > destroy_workqueue(idxd->wq); > + idxd->wq = NULL; > } > > static int idxd_init_evl(struct idxd_device *idxd) > @@ -460,6 +461,7 @@ static int idxd_setup_internals(struct idxd_device *idxd) > > err_evl: > destroy_workqueue(idxd->wq); > + idxd->wq = NULL; > err_wkq_create: > idxd_clean_groups(idxd); > err_group: > diff --git a/drivers/dma/idxd/sysfs.c b/drivers/dma/idxd/sysfs.c > index 6d251095c350..d5ffc641c856 100644 > --- a/drivers/dma/idxd/sysfs.c > +++ b/drivers/dma/idxd/sysfs.c > @@ -1836,7 +1836,8 @@ static void idxd_conf_device_release(struct device *dev) > { > struct idxd_device *idxd = confdev_to_idxd(dev); > > - destroy_workqueue(idxd->wq); > + if (idxd->wq) > + destroy_workqueue(idxd->wq); > kfree(idxd->groups); > bitmap_free(idxd->wq_enable_map); > kfree(idxd->wqs); > -- > 2.43.0 > ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-10-28 15:07 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20261028003708.834341-1-jinli@purestorage.com>
2026-10-28 0:37 ` [PATCH 1/2] dmaengine: idxd: fix double free in idxd_free() Jingyi Li
2026-10-28 15:04 ` Frank Li
2026-10-28 0:37 ` [PATCH 2/2] dmaengine: idxd: fix destroy of NULL or already destroyed workqueue Jingyi Li
2026-10-28 15:07 ` Frank Li
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox