aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorThomas Chou <thomas@wytron.com.tw>2010-05-23 12:44:02 -0400
committerDavid S. Miller <davem@davemloft.net>2010-05-24 02:11:09 -0400
commitee02a4ef40f2e049c80f9cc04e21a9b48288b6ff (patch)
tree26a6accadf8b370425b7c7c5e15351375a1fbf10 /drivers
parent253683bbfb6bc5864417c8c35cb6ef13b5e259e6 (diff)
ethoc: fix null dereference in ethoc_probe
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() and ethoc_remove(). Reported-by: Dan Carpenter <error27@gmail.com> Signed-off-by: Thomas Chou <thomas@wytron.com.tw> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/ethoc.c34
1 files changed, 30 insertions, 4 deletions
diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index 14cbde5cf68e..6ed2df14ec84 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -174,6 +174,7 @@ MODULE_PARM_DESC(buffer_size, "DMA buffer allocation size");
174 * @iobase: pointer to I/O memory region 174 * @iobase: pointer to I/O memory region
175 * @membase: pointer to buffer memory region 175 * @membase: pointer to buffer memory region
176 * @dma_alloc: dma allocated buffer size 176 * @dma_alloc: dma allocated buffer size
177 * @io_region_size: I/O memory region size
177 * @num_tx: number of send buffers 178 * @num_tx: number of send buffers
178 * @cur_tx: last send buffer written 179 * @cur_tx: last send buffer written
179 * @dty_tx: last buffer actually sent 180 * @dty_tx: last buffer actually sent
@@ -193,6 +194,7 @@ struct ethoc {
193 void __iomem *iobase; 194 void __iomem *iobase;
194 void __iomem *membase; 195 void __iomem *membase;
195 int dma_alloc; 196 int dma_alloc;
197 resource_size_t io_region_size;
196 198
197 unsigned int num_tx; 199 unsigned int num_tx;
198 unsigned int cur_tx; 200 unsigned int cur_tx;
@@ -943,6 +945,7 @@ static int ethoc_probe(struct platform_device *pdev)
943 priv = netdev_priv(netdev); 945 priv = netdev_priv(netdev);
944 priv->netdev = netdev; 946 priv->netdev = netdev;
945 priv->dma_alloc = 0; 947 priv->dma_alloc = 0;
948 priv->io_region_size = mmio->end - mmio->start + 1;
946 949
947 priv->iobase = devm_ioremap_nocache(&pdev->dev, netdev->base_addr, 950 priv->iobase = devm_ioremap_nocache(&pdev->dev, netdev->base_addr,
948 resource_size(mmio)); 951 resource_size(mmio));
@@ -1047,20 +1050,34 @@ static int ethoc_probe(struct platform_device *pdev)
1047 ret = register_netdev(netdev); 1050 ret = register_netdev(netdev);
1048 if (ret < 0) { 1051 if (ret < 0) {
1049 dev_err(&netdev->dev, "failed to register interface\n"); 1052 dev_err(&netdev->dev, "failed to register interface\n");
1050 goto error; 1053 goto error2;
1051 } 1054 }
1052 1055
1053 goto out; 1056 goto out;
1054 1057
1058error2:
1059 netif_napi_del(&priv->napi);
1055error: 1060error:
1056 mdiobus_unregister(priv->mdio); 1061 mdiobus_unregister(priv->mdio);
1057free_mdio: 1062free_mdio:
1058 kfree(priv->mdio->irq); 1063 kfree(priv->mdio->irq);
1059 mdiobus_free(priv->mdio); 1064 mdiobus_free(priv->mdio);
1060free: 1065free:
1061 if (priv->dma_alloc) 1066 if (priv) {
1062 dma_free_coherent(NULL, priv->dma_alloc, priv->membase, 1067 if (priv->dma_alloc)
1063 netdev->mem_start); 1068 dma_free_coherent(NULL, priv->dma_alloc, priv->membase,
1069 netdev->mem_start);
1070 else if (priv->membase)
1071 devm_iounmap(&pdev->dev, priv->membase);
1072 if (priv->iobase)
1073 devm_iounmap(&pdev->dev, priv->iobase);
1074 }
1075 if (mem)
1076 devm_release_mem_region(&pdev->dev, mem->start,
1077 mem->end - mem->start + 1);
1078 if (mmio)
1079 devm_release_mem_region(&pdev->dev, mmio->start,
1080 mmio->end - mmio->start + 1);
1064 free_netdev(netdev); 1081 free_netdev(netdev);
1065out: 1082out:
1066 return ret; 1083 return ret;
@@ -1078,6 +1095,7 @@ static int ethoc_remove(struct platform_device *pdev)
1078 platform_set_drvdata(pdev, NULL); 1095 platform_set_drvdata(pdev, NULL);
1079 1096
1080 if (netdev) { 1097 if (netdev) {
1098 netif_napi_del(&priv->napi);
1081 phy_disconnect(priv->phy); 1099 phy_disconnect(priv->phy);
1082 priv->phy = NULL; 1100 priv->phy = NULL;
1083 1101
@@ -1089,6 +1107,14 @@ static int ethoc_remove(struct platform_device *pdev)
1089 if (priv->dma_alloc) 1107 if (priv->dma_alloc)
1090 dma_free_coherent(NULL, priv->dma_alloc, priv->membase, 1108 dma_free_coherent(NULL, priv->dma_alloc, priv->membase,
1091 netdev->mem_start); 1109 netdev->mem_start);
1110 else {
1111 devm_iounmap(&pdev->dev, priv->membase);
1112 devm_release_mem_region(&pdev->dev, netdev->mem_start,
1113 netdev->mem_end - netdev->mem_start + 1);
1114 }
1115 devm_iounmap(&pdev->dev, priv->iobase);
1116 devm_release_mem_region(&pdev->dev, netdev->base_addr,
1117 priv->io_region_size);
1092 unregister_netdev(netdev); 1118 unregister_netdev(netdev);
1093 free_netdev(netdev); 1119 free_netdev(netdev);
1094 } 1120 }