staging: usbip: Don't leak struct file.
authorBernard Blackham <bernard@largestprime.net>
Sun, 21 Oct 2012 19:45:00 +0000 (06:45 +1100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 22 Oct 2012 20:38:04 +0000 (13:38 -0700)
usbip takes a reference on a struct file which is passed in via
sysfs.  Previously, this reference was never cleaned up, although
the socket it referred to was.

This patch drops the corresponding reference (found with the
socket's ->file backpointer) instead of just closing the socket.

Signed-off-by: Bernard Blackham <b-linuxgit@largestprime.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/usbip/stub_dev.c
drivers/staging/usbip/usbip_common.c
drivers/staging/usbip/vhci_hcd.c
drivers/staging/usbip/vhci_sysfs.c

index 1e1eb4c14d7354f50a461ee57fa87a3b68dc6454..79298d068636a7a9e4d19ff73994e41479b74687 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/file.h>
 #include <linux/kthread.h>
 #include <linux/module.h>
 
@@ -203,7 +204,7 @@ static void stub_shutdown_connection(struct usbip_device *ud)
         * not touch NULL socket.
         */
        if (ud->tcp_socket) {
-               sock_release(ud->tcp_socket);
+               fput(ud->tcp_socket->file);
                ud->tcp_socket = NULL;
        }
 
index 4a10034ff2cde86f9a938ffc6664af0d0e618955..75189feac380c5cba44e7264811a94e40c3b46ae 100644 (file)
@@ -413,8 +413,10 @@ struct socket *sockfd_to_socket(unsigned int sockfd)
 
        inode = file->f_dentry->d_inode;
 
-       if (!inode || !S_ISSOCK(inode->i_mode))
+       if (!inode || !S_ISSOCK(inode->i_mode)) {
+               fput(file);
                return NULL;
+       }
 
        socket = SOCKET_I(inode);
 
index a6143781e2a5dd4717692802b722914c7693f89a..77d77f72cb107410613d01fd853288a350cd3b2f 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/file.h>
 #include <linux/kernel.h>
 #include <linux/kthread.h>
 #include <linux/module.h>
@@ -804,8 +805,8 @@ static void vhci_shutdown_connection(struct usbip_device *ud)
        pr_info("stop threads\n");
 
        /* active connection is closed */
-       if (vdev->ud.tcp_socket != NULL) {
-               sock_release(vdev->ud.tcp_socket);
+       if (vdev->ud.tcp_socket) {
+               fput(vdev->ud.tcp_socket->file);
                vdev->ud.tcp_socket = NULL;
        }
        pr_info("release socket\n");
@@ -851,7 +852,10 @@ static void vhci_device_reset(struct usbip_device *ud)
                usb_put_dev(vdev->udev);
        vdev->udev = NULL;
 
-       ud->tcp_socket = NULL;
+       if (ud->tcp_socket) {
+               fput(ud->tcp_socket->file);
+               ud->tcp_socket = NULL;
+       }
        ud->status = VDEV_ST_NULL;
 
        spin_unlock(&ud->lock);
index 7ce9c2f7e442929b28370f1f816fcb31ea583aa6..c66e9c05c76b70bab213fc9c912c7c328a1b7171 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include <linux/kthread.h>
+#include <linux/file.h>
 #include <linux/net.h>
 
 #include "usbip_common.h"
@@ -189,7 +190,8 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
        if (valid_args(rhport, speed) < 0)
                return -EINVAL;
 
-       /* check sockfd */
+       /* Extract socket from fd. */
+       /* The correct way to clean this up is to fput(socket->file). */
        socket = sockfd_to_socket(sockfd);
        if (!socket)
                return -EINVAL;
@@ -206,6 +208,8 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
                spin_unlock(&vdev->ud.lock);
                spin_unlock(&the_controller->lock);
 
+               fput(socket->file);
+
                dev_err(dev, "port %d already used\n", rhport);
                return -EINVAL;
        }