From: Dan Carpenter <dan.carpenter@linaro.org>
To: Ma Ke <make24@iscas.ac.cn>
Cc: dpenkler@gmail.com, gregkh@linuxfoundation.org,
matchstick@neverthere.org,
dominik.karol.piatkowski@protonmail.com, arnd@arndb.de,
nichen@iscas.ac.cn, paul.retourne@orange.fr,
linux-staging@lists.linux.dev, linux-kernel@vger.kernel.org,
akpm@linux-foundation.org, stable@vger.kernel.org
Subject: Re: [PATCH] staging: gpib: Fix device reference leak in fmh_gpib driver
Date: Mon, 22 Sep 2025 09:28:52 +0300 [thread overview]
Message-ID: <aNDspDsgj5I5KGLe@stanley.mountain> (raw)
In-Reply-To: <20250922023831.21343-1-make24@iscas.ac.cn>
On Mon, Sep 22, 2025 at 10:38:31AM +0800, Ma Ke wrote:
> The fmh_gpib driver contains a device reference count leak in
> fmh_gpib_attach_impl() where driver_find_device() increases the
> reference count of the device by get_device() when matching but this
> reference is not properly decreased. Add put_device() in
> fmh_gpib_attach_impl() and add put_device() in fmh_gpib_detach(),
> which ensures that the reference count of the device is correctly
> managed.
>
> Found by code review.
>
> Cc: stable@vger.kernel.org
> Fixes: 8e4841a0888c ("staging: gpib: Add Frank Mori Hess FPGA PCI GPIB driver")
> Signed-off-by: Ma Ke <make24@iscas.ac.cn>
> ---
> drivers/staging/gpib/fmh_gpib/fmh_gpib.c | 23 +++++++++++++++++++++--
> 1 file changed, 21 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/staging/gpib/fmh_gpib/fmh_gpib.c b/drivers/staging/gpib/fmh_gpib/fmh_gpib.c
> index 4138f3d2bae7..245c8fe87eaa 100644
> --- a/drivers/staging/gpib/fmh_gpib/fmh_gpib.c
> +++ b/drivers/staging/gpib/fmh_gpib/fmh_gpib.c
> @@ -1395,14 +1395,17 @@ static int fmh_gpib_attach_impl(struct gpib_board *board, const struct gpib_boar
> pdev = to_platform_device(board->dev);
>
> retval = fmh_gpib_generic_attach(board);
> - if (retval)
> + if (retval) {
> + put_device(board->dev);
> return retval;
Do this with an unwind goto.
if (reval)
goto put_dev;
...
retval = fmh_gpib_init(...); /* this bug wasn't fixed btw */
if (retval)
goto put_dev;
return 0;
put_dev:
put_device(board->dev);
return retval;
Actually, this function needs a bunch of other frees as well. See
my blog for more details:
https://staticthinking.wordpress.com/2022/04/28/free-the-last-thing-style/
> + }
>
> e_priv = board->private_data;
> nec_priv = &e_priv->nec7210_priv;
>
> res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "gpib_control_status");
> if (!res) {
> + put_device(board->dev);
> dev_err(board->dev, "Unable to locate mmio resource\n");
> return -ENODEV;
> }
> @@ -1410,6 +1413,7 @@ static int fmh_gpib_attach_impl(struct gpib_board *board, const struct gpib_boar
> if (request_mem_region(res->start,
> resource_size(res),
> pdev->name) == NULL) {
> + put_device(board->dev);
> dev_err(board->dev, "cannot claim registers\n");
> return -ENXIO;
> }
request_mem_region() needs a release_region().
> @@ -1418,6 +1422,7 @@ static int fmh_gpib_attach_impl(struct gpib_board *board, const struct gpib_boar
> nec_priv->mmiobase = ioremap(e_priv->gpib_iomem_res->start,
> resource_size(e_priv->gpib_iomem_res));
> if (!nec_priv->mmiobase) {
> + put_device(board->dev);
> dev_err(board->dev, "Could not map I/O memory\n");
> return -ENOMEM;
> }
ioremap() needs an iounmap();
> @@ -1426,12 +1431,14 @@ static int fmh_gpib_attach_impl(struct gpib_board *board, const struct gpib_boar
>
> res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma_fifos");
> if (!res) {
> + put_device(board->dev);
> dev_err(board->dev, "Unable to locate mmio resource for gpib dma port\n");
> return -ENODEV;
> }
> if (request_mem_region(res->start,
> resource_size(res),
> pdev->name) == NULL) {
> + put_device(board->dev);
> dev_err(board->dev, "cannot claim registers\n");
> return -ENXIO;
> }
release_region()
> @@ -1439,6 +1446,7 @@ static int fmh_gpib_attach_impl(struct gpib_board *board, const struct gpib_boar
> e_priv->fifo_base = ioremap(e_priv->dma_port_res->start,
> resource_size(e_priv->dma_port_res));
> if (!e_priv->fifo_base) {
> + put_device(board->dev);
> dev_err(board->dev, "Could not map I/O memory for fifos\n");
> return -ENOMEM;
> }
iounmap();
> @@ -1447,10 +1455,14 @@ static int fmh_gpib_attach_impl(struct gpib_board *board, const struct gpib_boar
> (unsigned long)resource_size(e_priv->dma_port_res));
>
> irq = platform_get_irq(pdev, 0);
> - if (irq < 0)
> + if (irq < 0) {
> + put_device(board->dev);
> return -EBUSY;
> + }
> +
> retval = request_irq(irq, fmh_gpib_interrupt, IRQF_SHARED, pdev->name, board);
> if (retval) {
> + put_device(board->dev);
> dev_err(board->dev,
> "cannot register interrupt handler err=%d\n",
> retval);
request_irq() needs a release_irq()
> @@ -1461,6 +1473,7 @@ static int fmh_gpib_attach_impl(struct gpib_board *board, const struct gpib_boar
> if (acquire_dma) {
> e_priv->dma_channel = dma_request_slave_channel(board->dev, "rxtx");
> if (!e_priv->dma_channel) {
> + put_device(board->dev);
> dev_err(board->dev, "failed to acquire dma channel \"rxtx\".\n");
> return -EIO;
> }
This needs a free too. There may be other things outside of what I
can see in this email.
> @@ -1517,6 +1530,12 @@ void fmh_gpib_detach(struct gpib_board *board)
> resource_size(e_priv->gpib_iomem_res));
> }
> fmh_gpib_generic_detach(board);
> +
> + if (board->dev) {
> + dev_set_drvdata(board->dev, NULL);
> + put_device(board->dev);
> + board->dev = NULL;
I explain this in my blog, that the free function should be a cut
and paste of the cleanup. So this stuff isn't done in the cleanup
so one or the other of these is not correct.
The question is should this be done in one patch or several patches?
Adding cleanup to one function is generally considered One Thing
in terms of One Thing Per Path. If we were going to backport bits
of cleanup to different stable kernels then we would want to break
it up into the easiest way for backporting. But realistically we're
not going to do that here because this doesn't affect real life
users generally. It's just from review. It's not a security patch.
And this is staging as well so the standards for backports are not
necessarily as strict. (Staging drivers are often really really bad).
regards,
dan carpenter
prev parent reply other threads:[~2025-09-22 6:28 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-09-22 2:38 [PATCH] staging: gpib: Fix device reference leak in fmh_gpib driver Ma Ke
2025-09-22 6:28 ` Dan Carpenter [this message]
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=aNDspDsgj5I5KGLe@stanley.mountain \
--to=dan.carpenter@linaro.org \
--cc=akpm@linux-foundation.org \
--cc=arnd@arndb.de \
--cc=dominik.karol.piatkowski@protonmail.com \
--cc=dpenkler@gmail.com \
--cc=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-staging@lists.linux.dev \
--cc=make24@iscas.ac.cn \
--cc=matchstick@neverthere.org \
--cc=nichen@iscas.ac.cn \
--cc=paul.retourne@orange.fr \
--cc=stable@vger.kernel.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox