staging: usbip: Don't leak struct file.
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>
This commit is contained in:
parent
c7f0089931
commit
3d0a2a22c9
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user