null dereference in ethoc_probe()
Subsystems (2)
The patch 0baa080c75c: "ethoc: use system memory as buffer" introduced a potential null dereference.
1060 free:
1061 if (priv->dma_alloc)
^^^^^^^^^^^^^^^
priv can be null here.
1062 dma_free_coherent(NULL, priv->dma_alloc, priv->membase,
1063 netdev->mem_start);
1064 free_netdev(netdev);
Also I think the error handling is not as complete as it should be. It seems like we should call devm_iounmap() and release some of the other resources as well.
regards,
dan carpenter
Quoted 12 lines · Dan Carpenter
The patch
0baa080c75c: "ethoc: use system memory as buffer" introduced a potential null dereference.1060 free:
1061 if (priv->dma_alloc)
^^^^^^^^^^^^^^^
priv can be null here.1062 dma_free_coherent(NULL,
priv->dma_alloc,priv->membase,
1063netdev->mem_start);
1064free_netdev(netdev);
Quoted 9 lines
Also I think the error handling is not as complete as it should be. It seems like we should call
devm_iounmap()and release some of the other resources as well.regards,
dan carpenter
Hi Dan,
Thank you for reporting this bug. I will submit patch to fix this mistake.
Best regards,
Thomas
PATCH 1/1 ethoc: fix null dereference in ethoc_probe
In reply to Dan CarpenterDan reported the patch 0baa080c75c: "ethoc: use system memory as buffer" introduced a potential null dereference.
1060 free:
1061 if (priv->dma_alloc)
^^^^^^^^^^^^^^^
priv can be null here.
He also suggested that the error handling is not complete.
This patch fixes the null priv issue and improves resources releasing in ethoc_probe() and ethoc_remove().
--- drivers/net/ethoc.c | 34 ++++++++++++++++++++++++++++++---- 1 files changed, 30 insertions(+), 4 deletions(-)
drivers/net/ethoc.c +30 -4
@@ -174,6 +174,7 @@ MODULE_PARM_DESC(buffer_size, "DMA buffer allocation size");* @iobase: pointer to I/O memory region * @membase: pointer to buffer memory region * @dma_alloc: dma allocated buffer size +* @io_region_size: I/O memory region size * @num_tx: number of send buffers * @cur_tx: last send buffer written * @dty_tx: last buffer actually sent
@@ -193,6 +194,7 @@ struct ethoc {void __iomem *iobase;void __iomem *membase;int dma_alloc; +resource_size_t io_region_size;unsigned int num_tx;unsigned int cur_tx;
@@ -944,6 +946,7 @@ static int ethoc_probe(struct platform_device *pdev) priv =netdev_priv (netdev); priv->netdev = netdev; priv->dma_alloc =0 ; + priv->io_region_size = mmio->end - mmio->start +1 ; priv->iobase =devm_ioremap_nocache (&pdev->dev, netdev->base_addr,resource_size (mmio));
@@ -1049,20 +1052,34 @@ static int ethoc_probe(struct platform_device *pdev) ret =register_netdev (netdev);if (ret <0 ) {dev_err (&netdev->dev,"failed to register interface\n" ); - goto error; + goto error2; } goto out; +error2: +netif_napi_del (&priv->napi); error:mdiobus_unregister (priv->mdio); free_mdio:kfree (priv->mdio->irq);mdiobus_free (priv->mdio); free: -if (priv->dma_alloc) -dma_free_coherent (NULL , priv->dma_alloc, priv->membase, - netdev->mem_start); +if (priv) { +if (priv->dma_alloc) +dma_free_coherent (NULL , priv->dma_alloc, priv->membase, + netdev->mem_start); +else if (priv->membase) +devm_iounmap (&pdev->dev, priv->membase); +if (priv->iobase) +devm_iounmap (&pdev->dev, priv->iobase); + } +if (mem) +devm_release_mem_region (&pdev->dev, mem->start, + mem->end - mem->start +1 ); +if (mmio) +devm_release_mem_region (&pdev->dev, mmio->start, + mmio->end - mmio->start +1 );free_netdev (netdev); out:return ret;
@@ -1080,6 +1097,7 @@ static int ethoc_remove(struct platform_device *pdev)platform_set_drvdata (pdev,NULL );if (netdev) { +netif_napi_del (&priv->napi);phy_disconnect (priv->phy); priv->phy =NULL ;
@@ -1091,6 +1109,14 @@ static int ethoc_remove(struct platform_device *pdev)if (priv->dma_alloc)dma_free_coherent (NULL , priv->dma_alloc, priv->membase, netdev->mem_start); +else { +devm_iounmap (&pdev->dev, priv->membase); +devm_release_mem_region (&pdev->dev, netdev->mem_start, + netdev->mem_end - netdev->mem_start +1 ); + } +devm_iounmap (&pdev->dev, priv->iobase); +devm_release_mem_region (&pdev->dev, netdev->base_addr, + priv->io_region_size);unregister_netdev (netdev);free_netdev (netdev); }
Signature · 1 line
1.7.1.86.g0e460
Re: [PATCH] ethoc: fix null dereference in ethoc_probe
From: Thomas Chou <[email protected]>
Date: Mon, 24 May 2010 10:44:02 +0800
Quoted 8 lines
Dan reported the patch
0baa080c75c: "ethoc: use system memory as buffer" introduced a potential null dereference.1060 free:
1061 if (priv->dma_alloc)
^^^^^^^^^^^^^^^
priv can be null here.
Quoted 7 lines
He also suggested that the error handling is not complete.
This patch fixes the null priv issue and improves resources releasing in
ethoc_probe()andethoc_remove().Reported-by Dan Carpenter <[email protected]>Signed-off-by Thomas Chou <[email protected]>
Applied.
Re: [Nios2-dev] [PATCH] ethoc: fix null dereference in ethoc_probe
In reply to Thomas ChouQuoted 40 lines · Thomas Chou
Dan reported the patch
0baa080c75c: "ethoc: use system memory as buffer" introduced a potential null dereference.1060 free:
1061 if (priv->dma_alloc)
^^^^^^^^^^^^^^^
priv can be null here.He also suggested that the error handling is not complete.
This patch fixes the null priv issue and improves resources releasing in
ethoc_probe()andethoc_remove().Reported-by Dan Carpenter <[email protected]>Signed-off-by Thomas Chou <[email protected]>--- drivers/net/ethoc.c | 34 ++++++++++++++++++++++++++++++---- 1 files changed, 30 insertions(+), 4 deletions(-)drivers/net/ethoc.c +2
-0@@ -174,6 +174,7 @@ MODULE_PARM_DESC(buffer_size, "DMA buffer allocation size");* @iobase: pointer to I/O memory region * @membase: pointer to buffer memory region * @dma_alloc: dma allocated buffer size +* @io_region_size: I/O memory region size * @num_tx: number of send buffers * @cur_tx: last send buffer written * @dty_tx: last buffer actually sent @@ -193,6 +194,7 @@ struct ethoc {void __iomem *iobase;void __iomem *membase;int dma_alloc; +resource_size_t io_region_size;unsigned int num_tx;unsigned int cur_tx;
drivers/net/ethoc.c static int ethoc_probe(struct platform_device *pdev) · line 949
Quoted 4 lines
drivers/net/ethoc.c +1
-0@@ -944,6 +946,7 @@ static int ethoc_probe(struct platform_device *pdev) priv =netdev_priv (netdev); priv->netdev = netdev; priv->dma_alloc =0 ; + priv->io_region_size = mmio->end - mmio->start +1 ;
Better use the resource_size inline here.
drivers/net/ethoc.c static int ethoc_probe(struct platform_device *pdev) · line 952
Quoted 2 lines
drivers/net/ethoc.c +0
-0priv->iobase =devm_ioremap_nocache (&pdev->dev, netdev->base_addr,resource_size (mmio));
^^^
Then you could use the io_region_size here to avoid calculating the size again.
Quoted 23 lines
drivers/net/ethoc.c +5
-4@@ -1049,20 +1052,34 @@ static int ethoc_probe(struct platform_device *pdev) ret =register_netdev (netdev);if (ret <0 ) {dev_err (&netdev->dev,"failed to register interface\n" ); - goto error; + goto error2; } goto out; +error2: +netif_napi_del (&priv->napi); error:mdiobus_unregister (priv->mdio); free_mdio:kfree (priv->mdio->irq);mdiobus_free (priv->mdio); free: -if (priv->dma_alloc) -dma_free_coherent (NULL , priv->dma_alloc, priv->membase, - netdev->mem_start); +if (priv) { +if (priv->dma_alloc)
drivers/net/ethoc.c static int ethoc_probe(struct platform_device *pdev) · line 1079
Quoted 10 lines
drivers/net/ethoc.c +10
-0+dma_free_coherent (NULL , priv->dma_alloc, priv->membase, + netdev->mem_start); + else if (priv->membase) + devm_iounmap(&pdev->dev, priv->membase); +if (priv->iobase) +devm_iounmap (&pdev->dev, priv->iobase); + } +if (mem) +devm_release_mem_region (&pdev->dev, mem->start, + mem->end - mem->start +1 );
resource_size again
drivers/net/ethoc.c static int ethoc_probe(struct platform_device *pdev) · line 1082
Quoted 3 lines
drivers/net/ethoc.c +3
-0+if (mmio) +devm_release_mem_region (&pdev->dev, mmio->start, + mmio->end - mmio->start +1 );
ditto
Quoted 26 lines
drivers/net/ethoc.c +9
-0free_netdev (netdev); out:return ret;@@ -1080,6 +1097,7 @@ static int ethoc_remove(struct platform_device *pdev)platform_set_drvdata (pdev,NULL );if (netdev) { +netif_napi_del (&priv->napi);phy_disconnect (priv->phy); priv->phy =NULL ;@@ -1091,6 +1109,14 @@ static int ethoc_remove(struct platform_device *pdev)if (priv->dma_alloc)dma_free_coherent (NULL , priv->dma_alloc, priv->membase, netdev->mem_start); +else { +devm_iounmap (&pdev->dev, priv->membase); +devm_release_mem_region (&pdev->dev, netdev->mem_start, + netdev->mem_end - netdev->mem_start +1 ); + } +devm_iounmap (&pdev->dev, priv->iobase); +devm_release_mem_region (&pdev->dev, netdev->base_addr, + priv->io_region_size);unregister_netdev (netdev);free_netdev (netdev); }
Re: [Nios2-dev] [PATCH] ethoc: fix null dereference in ethoc_probe
Quoted 7 lines · Tobias Klauser
drivers/net/ethoc.c static int ethoc_probe(struct platform_device *pdev) · line 949
Quoted 5 lines
drivers/net/ethoc.c +1
-0@@ -944,6 +946,7 @@ static int ethoc_probe(struct platform_device *pdev) priv =netdev_priv (netdev); priv->netdev = netdev; priv->dma_alloc =0 ; + priv->io_region_size = mmio->end - mmio->start +1 ;Better use the
resource_sizeinline here.
Hi Tobias,
I just see your patch of resource_size from the git log. Sorry, I missed this one. I will send update on this. Thank you.
Cheers,
Thomas