spi: bcm-qspi: return error if neither hif_mspi nor mspi is available

Message ID 20230629134306.95823-1-jonas.gorski@gmail.com
State New
Headers
Series spi: bcm-qspi: return error if neither hif_mspi nor mspi is available |

Commit Message

Jonas Gorski June 29, 2023, 1:43 p.m. UTC
  If neither a "hif_mspi" nor "mspi" resource is present, the driver will
just early exit in probe but still return success. Apart from not doing
anything meaningful, this would then also lead to a null pointer access
on removal, as platform_get_drvdata() would return NULL, which it would
then try to dereferce when trying to unregister the spi master.

Fix this by unconditionally calling devm_ioremap_resource(), as it can
handle a NULL res and will then return a viable ERR_PTR() if we get one.

The "return 0;" was previously a "goto qspi_resource_err;" where then
ret was returned, but since ret was still initialized to 0 at this place
this was a valid conversion in 63c5395bb7a9 ("spi: bcm-qspi: Fix
use-after-free on unbind"). The issue was not introduced by this commit,
only made more obvious.

Fixes: fa236a7ef240 ("spi: bcm-qspi: Add Broadcom MSPI driver")
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
Found by looking a the driver while comparing it to its bindings.

Only build tested, not runtested.

 drivers/spi/spi-bcm-qspi.c | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)
  

Comments

Kamal Dasu June 29, 2023, 3:06 p.m. UTC | #1
On Thu, Jun 29, 2023 at 9:43 AM Jonas Gorski <jonas.gorski@gmail.com> wrote:
>
> If neither a "hif_mspi" nor "mspi" resource is present, the driver will
> just early exit in probe but still return success. Apart from not doing
> anything meaningful, this would then also lead to a null pointer access
> on removal, as platform_get_drvdata() would return NULL, which it would
> then try to dereferce when trying to unregister the spi master.
>
> Fix this by unconditionally calling devm_ioremap_resource(), as it can
> handle a NULL res and will then return a viable ERR_PTR() if we get one.
>
> The "return 0;" was previously a "goto qspi_resource_err;" where then
> ret was returned, but since ret was still initialized to 0 at this place
> this was a valid conversion in 63c5395bb7a9 ("spi: bcm-qspi: Fix
> use-after-free on unbind"). The issue was not introduced by this commit,
> only made more obvious.
>
> Fixes: fa236a7ef240 ("spi: bcm-qspi: Add Broadcom MSPI driver")
> Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
> ---
> Found by looking a the driver while comparing it to its bindings.
>
> Only build tested, not runtested.
>
>  drivers/spi/spi-bcm-qspi.c | 10 +++-------
>  1 file changed, 3 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c
> index 6b46a3b67c41..d91dfbe47aa5 100644
> --- a/drivers/spi/spi-bcm-qspi.c
> +++ b/drivers/spi/spi-bcm-qspi.c
> @@ -1543,13 +1543,9 @@ int bcm_qspi_probe(struct platform_device *pdev,
>                 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
>                                                    "mspi");
>
> -       if (res) {
> -               qspi->base[MSPI]  = devm_ioremap_resource(dev, res);
> -               if (IS_ERR(qspi->base[MSPI]))
> -                       return PTR_ERR(qspi->base[MSPI]);
> -       } else {
> -               return 0;
> -       }

I would rather just do this in the else case

} else {
 -              return 0;
 +             return -ENODEV;
}

 The change below does not check the return of
platform_get_resource_byname() in my opinion rather relies on
devm_ioremap_resource() doing the right thing.

> +       qspi->base[MSPI]  = devm_ioremap_resource(dev, res);
> +       if (IS_ERR(qspi->base[MSPI]))
> +               return PTR_ERR(qspi->base[MSPI]);
>
>         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "bspi");
>         if (res) {
> --
> 2.34.1
>
  
Jonas Gorski June 29, 2023, 3:38 p.m. UTC | #2
On Thu, 29 Jun 2023 at 17:07, Kamal Dasu <kamal.dasu@broadcom.com> wrote:
>
> On Thu, Jun 29, 2023 at 9:43 AM Jonas Gorski <jonas.gorski@gmail.com> wrote:
> >
> > If neither a "hif_mspi" nor "mspi" resource is present, the driver will
> > just early exit in probe but still return success. Apart from not doing
> > anything meaningful, this would then also lead to a null pointer access
> > on removal, as platform_get_drvdata() would return NULL, which it would
> > then try to dereferce when trying to unregister the spi master.
> >
> > Fix this by unconditionally calling devm_ioremap_resource(), as it can
> > handle a NULL res and will then return a viable ERR_PTR() if we get one.
> >
> > The "return 0;" was previously a "goto qspi_resource_err;" where then
> > ret was returned, but since ret was still initialized to 0 at this place
> > this was a valid conversion in 63c5395bb7a9 ("spi: bcm-qspi: Fix
> > use-after-free on unbind"). The issue was not introduced by this commit,
> > only made more obvious.
> >
> > Fixes: fa236a7ef240 ("spi: bcm-qspi: Add Broadcom MSPI driver")
> > Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
> > ---
> > Found by looking a the driver while comparing it to its bindings.
> >
> > Only build tested, not runtested.
> >
> >  drivers/spi/spi-bcm-qspi.c | 10 +++-------
> >  1 file changed, 3 insertions(+), 7 deletions(-)
> >
> > diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c
> > index 6b46a3b67c41..d91dfbe47aa5 100644
> > --- a/drivers/spi/spi-bcm-qspi.c
> > +++ b/drivers/spi/spi-bcm-qspi.c
> > @@ -1543,13 +1543,9 @@ int bcm_qspi_probe(struct platform_device *pdev,
> >                 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
> >                                                    "mspi");
> >
> > -       if (res) {
> > -               qspi->base[MSPI]  = devm_ioremap_resource(dev, res);
> > -               if (IS_ERR(qspi->base[MSPI]))
> > -                       return PTR_ERR(qspi->base[MSPI]);
> > -       } else {
> > -               return 0;
> > -       }
>
> I would rather just do this in the else case
>
> } else {
>  -              return 0;
>  +             return -ENODEV;
> }
>
>  The change below does not check the return of
> platform_get_resource_byname() in my opinion rather relies on
> devm_ioremap_resource() doing the right thing.

This is how devm_ioremap_resource() is intended to be used, see e.g.
the example in its kernel documentation:

https://elixir.bootlin.com/linux/latest/source/lib/devres.c#L167

So I don't see what's wrong with relying on functions doing the right thing.

Also AFAIU the appropriate return code in this case would be rather
-EINVAL, not -ENODEV.

>
> > +       qspi->base[MSPI]  = devm_ioremap_resource(dev, res);
> > +       if (IS_ERR(qspi->base[MSPI]))
> > +               return PTR_ERR(qspi->base[MSPI]);
> >
> >         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "bspi");
> >         if (res) {
> > --
> > 2.34.1
> >

Regards,
Jonas
  
Kamal Dasu June 29, 2023, 4:18 p.m. UTC | #3
On Thu, Jun 29, 2023 at 11:38 AM Jonas Gorski <jonas.gorski@gmail.com> wrote:
>
> On Thu, 29 Jun 2023 at 17:07, Kamal Dasu <kamal.dasu@broadcom.com> wrote:
> >
> > On Thu, Jun 29, 2023 at 9:43 AM Jonas Gorski <jonas.gorski@gmail.com> wrote:
> > >
> > > If neither a "hif_mspi" nor "mspi" resource is present, the driver will
> > > just early exit in probe but still return success. Apart from not doing
> > > anything meaningful, this would then also lead to a null pointer access
> > > on removal, as platform_get_drvdata() would return NULL, which it would
> > > then try to dereferce when trying to unregister the spi master.

s/dereferce/ dereference

> > >
> > > Fix this by unconditionally calling devm_ioremap_resource(), as it can
> > > handle a NULL res and will then return a viable ERR_PTR() if we get one.
> > >
> > > The "return 0;" was previously a "goto qspi_resource_err;" where then
> > > ret was returned, but since ret was still initialized to 0 at this place
> > > this was a valid conversion in 63c5395bb7a9 ("spi: bcm-qspi: Fix
> > > use-after-free on unbind"). The issue was not introduced by this commit,
> > > only made more obvious.
> > >
> > > Fixes: fa236a7ef240 ("spi: bcm-qspi: Add Broadcom MSPI driver")
> > > Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
> > > ---

Reviewed-by:  Kamal Dasu <kamal.dasu@broadcom.com>

> > > Found by looking a the driver while comparing it to its bindings.
> > >
> > > Only build tested, not runtested.
> > >
> > >  drivers/spi/spi-bcm-qspi.c | 10 +++-------
> > >  1 file changed, 3 insertions(+), 7 deletions(-)
> > >
> > > diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c
> > > index 6b46a3b67c41..d91dfbe47aa5 100644
> > > --- a/drivers/spi/spi-bcm-qspi.c
> > > +++ b/drivers/spi/spi-bcm-qspi.c
> > > @@ -1543,13 +1543,9 @@ int bcm_qspi_probe(struct platform_device *pdev,
> > >                 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
> > >                                                    "mspi");
> > >
> > > -       if (res) {
> > > -               qspi->base[MSPI]  = devm_ioremap_resource(dev, res);
> > > -               if (IS_ERR(qspi->base[MSPI]))
> > > -                       return PTR_ERR(qspi->base[MSPI]);
> > > -       } else {
> > > -               return 0;
> > > -       }
> >
> > I would rather just do this in the else case
> >
> > } else {
> >  -              return 0;
> >  +             return -ENODEV;
> > }
> >
> >  The change below does not check the return of
> > platform_get_resource_byname() in my opinion rather relies on
> > devm_ioremap_resource() doing the right thing.
>
> This is how devm_ioremap_resource() is intended to be used, see e.g.
> the example in its kernel documentation:
>
> https://elixir.bootlin.com/linux/latest/source/lib/devres.c#L167
>
> So I don't see what's wrong with relying on functions doing the right thing.
>
> Also AFAIU the appropriate return code in this case would be rather
> -EINVAL, not -ENODEV.
>
> >
> > > +       qspi->base[MSPI]  = devm_ioremap_resource(dev, res);
> > > +       if (IS_ERR(qspi->base[MSPI]))
> > > +               return PTR_ERR(qspi->base[MSPI]);
> > >
> > >         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "bspi");
> > >         if (res) {
> > > --
> > > 2.34.1
> > >
>



> Regards,
> Jonas
  
Mark Brown June 30, 2023, 5:07 p.m. UTC | #4
On Thu, 29 Jun 2023 15:43:05 +0200, Jonas Gorski wrote:
> If neither a "hif_mspi" nor "mspi" resource is present, the driver will
> just early exit in probe but still return success. Apart from not doing
> anything meaningful, this would then also lead to a null pointer access
> on removal, as platform_get_drvdata() would return NULL, which it would
> then try to dereferce when trying to unregister the spi master.
> 
> Fix this by unconditionally calling devm_ioremap_resource(), as it can
> handle a NULL res and will then return a viable ERR_PTR() if we get one.
> 
> [...]

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next

Thanks!

[1/1] spi: bcm-qspi: return error if neither hif_mspi nor mspi is available
      commit: 7c1f23ad34fcdace50275a6aa1e1969b41c6233f

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark
  

Patch

diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c
index 6b46a3b67c41..d91dfbe47aa5 100644
--- a/drivers/spi/spi-bcm-qspi.c
+++ b/drivers/spi/spi-bcm-qspi.c
@@ -1543,13 +1543,9 @@  int bcm_qspi_probe(struct platform_device *pdev,
 		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
 						   "mspi");
 
-	if (res) {
-		qspi->base[MSPI]  = devm_ioremap_resource(dev, res);
-		if (IS_ERR(qspi->base[MSPI]))
-			return PTR_ERR(qspi->base[MSPI]);
-	} else {
-		return 0;
-	}
+	qspi->base[MSPI]  = devm_ioremap_resource(dev, res);
+	if (IS_ERR(qspi->base[MSPI]))
+		return PTR_ERR(qspi->base[MSPI]);
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "bspi");
 	if (res) {