pcmcia: Fix resource leaks in yenta_probe() and _close()
authorTakeshi Yoshimura <yos@sslab.ics.keio.ac.jp>
Sun, 14 Jun 2015 17:43:59 +0000 (02:43 +0900)
committerDominik Brodowski <linux@dominikbrodowski.net>
Sun, 14 Jun 2015 19:35:45 +0000 (21:35 +0200)
There are some resource leaks in yenta_probe() and _close(). I fixed
the following issues with some code cleanups. Thanks to Dominik's
suggestions.

On the error path in yenta_probe():
- a requested irq is not released
- yenta_free_resources() and pci_set_drvdata(dev, NULL) are not called

In yenta_close():
- kfree(sock) is not called
- sock->base is always set to non-NULL when yenta_close() is called,
  therefore the check in yenta_close() is not necessary.

Signed-off-by: Takeshi Yoshimura <yos@sslab.ics.keio.ac.jp>
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
drivers/pcmcia/yenta_socket.c

index 56c83437271ca17486f544c2e58d272a02059ce8..5d6d9b1549bc4fa345a613da000e6efc1ea01b91 100644 (file)
@@ -801,13 +801,13 @@ static void yenta_close(struct pci_dev *dev)
        else
                del_timer_sync(&sock->poll_timer);
 
-       if (sock->base)
-               iounmap(sock->base);
+       iounmap(sock->base);
        yenta_free_resources(sock);
 
        pci_release_regions(dev);
        pci_disable_device(dev);
        pci_set_drvdata(dev, NULL);
+       kfree(sock);
 }
 
 
@@ -1254,25 +1254,34 @@ static int yenta_probe(struct pci_dev *dev, const struct pci_device_id *id)
 
        /* Register it with the pcmcia layer.. */
        ret = pcmcia_register_socket(&socket->socket);
-       if (ret == 0) {
-               /* Add the yenta register attributes */
-               ret = device_create_file(&dev->dev, &dev_attr_yenta_registers);
-               if (ret == 0)
-                       goto out;
-
-               /* error path... */
-               pcmcia_unregister_socket(&socket->socket);
-       }
+       if (ret)
+               goto free_irq;
+
+       /* Add the yenta register attributes */
+       ret = device_create_file(&dev->dev, &dev_attr_yenta_registers);
+       if (ret)
+               goto unregister_socket;
 
+       return ret;
+
+       /* error path... */
+ unregister_socket:
+       pcmcia_unregister_socket(&socket->socket);
+ free_irq:
+       if (socket->cb_irq)
+               free_irq(socket->cb_irq, socket);
+       else
+               del_timer_sync(&socket->poll_timer);
  unmap:
        iounmap(socket->base);
+       yenta_free_resources(socket);
  release:
        pci_release_regions(dev);
  disable:
        pci_disable_device(dev);
  free:
+       pci_set_drvdata(dev, NULL);
        kfree(socket);
- out:
        return ret;
 }