From: Vinicius Costa Gomes <vinicius.gomes@intel.com>
To: Guangshuo Li <lgs201920130244@gmail.com>,
Dave Jiang <dave.jiang@intel.com>, Vinod Koul <vkoul@kernel.org>,
Shuai Xue <xueshuai@linux.alibaba.com>,
Fenghua Yu <fenghuay@nvidia.com>,
dmaengine@vger.kernel.org, linux-kernel@vger.kernel.org
Cc: Guangshuo Li <lgs201920130244@gmail.com>, stable@vger.kernel.org
Subject: Re: [PATCH] dmaengine: idxd: fix double free in idxd_alloc() error path
Date: Wed, 01 Apr 2026 16:18:45 -0700 [thread overview]
Message-ID: <87h5puxoa2.fsf@intel.com> (raw)
In-Reply-To: <20260401094003.1482794-1-lgs201920130244@gmail.com>
Hi,
Guangshuo Li <lgs201920130244@gmail.com> writes:
> When dev_set_name() fails after device_initialize(), idxd_alloc()
> calls put_device(conf_dev).
>
> For these devices, conf_dev->type is set from idxd->data->dev_type,
> which resolves to dsa_device_type or iax_device_type, and both use
> idxd_conf_device_release() as their release callback.
>
> That release callback frees idxd, idxd->opcap_bmap, and releases
> idxd->id, but the current error path then frees those resources again
> directly, causing a double free.
>
> Keep the cleanup in idxd_conf_device_release() after put_device() and
> avoid freeing idxd-managed resources again in idxd_alloc().
>
> Fixes: 46a5cca76c76 ("dmaengine: idxd: fix memory leak in error handling path of idxd_alloc")
> Cc: stable@vger.kernel.org
> Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
My preference is for the maintainer making the pull request to decide if
something should be sent to stable or not.
I was trying some AI review bot, I hope you don't mind, and got these
comments, went through them and they seemed good (including that these
patches should be sent as a series, that there are some more work to do
while you are cleaning the error paths), including it verbatim here:
This patch removes bitmap_free(idxd->opcap_bmap) after put_device()
in idxd_alloc()'s err_name path and adds a return NULL to prevent
falling through to the err_opcap and err_ida labels, avoiding
double-frees of opcap_bmap, ida, and idxd itself.
> diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c
> index 4eff74182225..94ce52565e7a 100644
> --- a/drivers/dma/idxd/init.c
> +++ b/drivers/dma/idxd/init.c
> @@ -635,7 +635,7 @@ static struct idxd_device *idxd_alloc(struct pci_dev *pdev, struct idxd_driver_d
>
> err_name:
> put_device(conf_dev);
> - bitmap_free(idxd->opcap_bmap);
> + return NULL;
> err_opcap:
> ida_free(&idxd_ida, idxd->id);
> err_ida:
The double-free analysis is correct, but does the put_device() above
actually work here?
put_device(conf_dev) drops the refcount from 1 to 0 (no device_add()
was called, so nobody else holds a reference) and triggers the release
callback idxd_conf_device_release(), which does:
idxd_conf_device_release() {
destroy_workqueue(idxd->wq);
...
}
At this point in idxd_alloc(), idxd->wq is still NULL -- the
workqueue is created much later in idxd_setup_internals():
idxd_setup_internals() {
...
idxd->wq = create_workqueue(dev_name(dev));
...
}
destroy_workqueue() does not handle a NULL argument -- it immediately
dereferences the pointer:
destroy_workqueue(wq) {
workqueue_sysfs_unregister(wq);
mutex_lock(&wq->mutex); <-- NULL dereference
...
}
So put_device() here will oops before the double-free is even
reached. This is a pre-existing issue (the old code has the same
put_device call), but relying on idxd_conf_device_release() as the
cleanup path for a partially-initialized idxd_device doesn't work.
Would it make sense to skip put_device() and instead free only
what was allocated, similar to the err_opcap and err_ida labels?
Two more things worth noting about this series:
Patch 3 (idxd_setup_engines) includes hunks that remove blank lines
from idxd_setup_groups() -- lines that only exist after Patch 2 is
applied. These four patches should probably be sent as a numbered
series with an explicit ordering rather than as independent patches.
The same put_device()-then-kfree() pattern also exists in
idxd_clean_wqs(), idxd_clean_engines(), idxd_clean_groups(), and
idxd_free(), which are not addressed by this series. It might be
worth fixing all of them together.
Cheers,
--
Vinicius
next prev parent reply other threads:[~2026-04-01 23:18 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-01 9:40 [PATCH] dmaengine: idxd: fix double free in idxd_alloc() error path Guangshuo Li
2026-04-01 23:18 ` Vinicius Costa Gomes [this message]
2026-04-02 12:10 ` Guangshuo Li
2026-04-02 17:36 ` Vinicius Costa Gomes
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87h5puxoa2.fsf@intel.com \
--to=vinicius.gomes@intel.com \
--cc=dave.jiang@intel.com \
--cc=dmaengine@vger.kernel.org \
--cc=fenghuay@nvidia.com \
--cc=lgs201920130244@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=stable@vger.kernel.org \
--cc=vkoul@kernel.org \
--cc=xueshuai@linux.alibaba.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.