Skip to content

Commit

Permalink
staging: usbip: Don't leak struct file.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Bernard Blackham authored and Greg Kroah-Hartman committed Oct 22, 2012
1 parent c7f0089 commit 3d0a2a2
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 6 deletions.
3 changes: 2 additions & 1 deletion drivers/staging/usbip/stub_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/

#include <linux/device.h>
#include <linux/file.h>
#include <linux/kthread.h>
#include <linux/module.h>

Expand Down Expand Up @@ -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;
}

Expand Down
4 changes: 3 additions & 1 deletion drivers/staging/usbip/usbip_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
10 changes: 7 additions & 3 deletions drivers/staging/usbip/vhci_hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/

#include <linux/init.h>
#include <linux/file.h>
#include <linux/kernel.h>
#include <linux/kthread.h>
#include <linux/module.h>
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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);
Expand Down
6 changes: 5 additions & 1 deletion drivers/staging/usbip/vhci_sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/

#include <linux/kthread.h>
#include <linux/file.h>
#include <linux/net.h>

#include "usbip_common.h"
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}
Expand Down

0 comments on commit 3d0a2a2

Please sign in to comment.