From d19319affb6c84ef45185588f63dc28f8ff95ea3 Mon Sep 17 00:00:00 2001 From: Takeshi Yoshimura Date: Mon, 15 Jun 2015 02:43:59 +0900 Subject: [PATCH] pcmcia: Fix resource leaks in yenta_probe() and _close() 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 Signed-off-by: Dominik Brodowski --- drivers/pcmcia/yenta_socket.c | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index 56c83437271c..5d6d9b1549bc 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c @@ -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; } -- 2.20.1