All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/4] usbip: add sysfs_lock to synchronize sysfs code paths
@ 2021-04-16 20:53 Tom Seewald
  2021-04-16 20:53 ` [PATCH 2/4] usbip: stub-dev " Tom Seewald
                   ` (3 more replies)
  0 siblings, 4 replies; 12+ messages in thread
From: Tom Seewald @ 2021-04-16 20:53 UTC (permalink / raw)
  To: stable
  Cc: Shuah Khan, syzbot+a93fba6d384346a761e3, Greg Kroah-Hartman,
	Tom Seewald, Valentina Manea, Shuah Khan

From: Shuah Khan <skhan@linuxfoundation.org>

commit 4e9c93af7279b059faf5bb1897ee90512b258a12 upstream.

Fuzzing uncovered race condition between sysfs code paths in usbip
drivers. Device connect/disconnect code paths initiated through
sysfs interface are prone to races if disconnect happens during
connect and vice versa.

This problem is common to all drivers while it can be reproduced easily
in vhci_hcd. Add a sysfs_lock to usbip_device struct to protect the paths.

Use this in vhci_hcd to protect sysfs paths. For a complete fix, usip_host
and usip-vudc drivers and the event handler will have to use this lock to
protect the paths. These changes will be done in subsequent patches.

Cc: stable@vger.kernel.org # 4.9.x
Reported-and-tested-by: syzbot+a93fba6d384346a761e3@syzkaller.appspotmail.com
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
Link: https://lore.kernel.org/r/b6568f7beae702bbc236a545d3c020106ca75eac.1616807117.git.skhan@linuxfoundation.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Tom Seewald <tseewald@gmail.com>
---
 drivers/usb/usbip/usbip_common.h |  3 +++
 drivers/usb/usbip/vhci_hcd.c     |  1 +
 drivers/usb/usbip/vhci_sysfs.c   | 30 +++++++++++++++++++++++++-----
 3 files changed, 29 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/usbip/usbip_common.h b/drivers/usb/usbip/usbip_common.h
index 0b199a2664c0..3d47c681aea2 100644
--- a/drivers/usb/usbip/usbip_common.h
+++ b/drivers/usb/usbip/usbip_common.h
@@ -278,6 +278,9 @@ struct usbip_device {
 	/* lock for status */
 	spinlock_t lock;
 
+	/* mutex for synchronizing sysfs store paths */
+	struct mutex sysfs_lock;
+
 	int sockfd;
 	struct socket *tcp_socket;
 
diff --git a/drivers/usb/usbip/vhci_hcd.c b/drivers/usb/usbip/vhci_hcd.c
index 8bda6455dfcb..fb7b03029b8e 100644
--- a/drivers/usb/usbip/vhci_hcd.c
+++ b/drivers/usb/usbip/vhci_hcd.c
@@ -907,6 +907,7 @@ static void vhci_device_init(struct vhci_device *vdev)
 	vdev->ud.side   = USBIP_VHCI;
 	vdev->ud.status = VDEV_ST_NULL;
 	spin_lock_init(&vdev->ud.lock);
+	mutex_init(&vdev->ud.sysfs_lock);
 
 	INIT_LIST_HEAD(&vdev->priv_rx);
 	INIT_LIST_HEAD(&vdev->priv_tx);
diff --git a/drivers/usb/usbip/vhci_sysfs.c b/drivers/usb/usbip/vhci_sysfs.c
index ca00d38d22af..3496b402aa1b 100644
--- a/drivers/usb/usbip/vhci_sysfs.c
+++ b/drivers/usb/usbip/vhci_sysfs.c
@@ -161,6 +161,8 @@ static int vhci_port_disconnect(struct vhci_hcd *vhci, __u32 rhport)
 
 	usbip_dbg_vhci_sysfs("enter\n");
 
+	mutex_lock(&vdev->ud.sysfs_lock);
+
 	/* lock */
 	spin_lock_irqsave(&vhci->lock, flags);
 	spin_lock(&vdev->ud.lock);
@@ -171,6 +173,7 @@ static int vhci_port_disconnect(struct vhci_hcd *vhci, __u32 rhport)
 		/* unlock */
 		spin_unlock(&vdev->ud.lock);
 		spin_unlock_irqrestore(&vhci->lock, flags);
+		mutex_unlock(&vdev->ud.sysfs_lock);
 
 		return -EINVAL;
 	}
@@ -181,6 +184,8 @@ static int vhci_port_disconnect(struct vhci_hcd *vhci, __u32 rhport)
 
 	usbip_event_add(&vdev->ud, VDEV_EVENT_DOWN);
 
+	mutex_unlock(&vdev->ud.sysfs_lock);
+
 	return 0;
 }
 
@@ -309,30 +314,36 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
 	vhci = hcd_to_vhci(hcd);
 	vdev = &vhci->vdev[rhport];
 
+	mutex_lock(&vdev->ud.sysfs_lock);
+
 	/* Extract socket from fd. */
 	socket = sockfd_lookup(sockfd, &err);
 	if (!socket) {
 		dev_err(dev, "failed to lookup sock");
-		return -EINVAL;
+		err = -EINVAL;
+		goto unlock_mutex;
 	}
 	if (socket->type != SOCK_STREAM) {
 		dev_err(dev, "Expecting SOCK_STREAM - found %d",
 			socket->type);
 		sockfd_put(socket);
-		return -EINVAL;
+		err = -EINVAL;
+		goto unlock_mutex;
 	}
 
 	/* create threads before locking */
 	tcp_rx = kthread_create(vhci_rx_loop, &vdev->ud, "vhci_rx");
 	if (IS_ERR(tcp_rx)) {
 		sockfd_put(socket);
-		return -EINVAL;
+		err = -EINVAL;
+		goto unlock_mutex;
 	}
 	tcp_tx = kthread_create(vhci_tx_loop, &vdev->ud, "vhci_tx");
 	if (IS_ERR(tcp_tx)) {
 		kthread_stop(tcp_rx);
 		sockfd_put(socket);
-		return -EINVAL;
+		err = -EINVAL;
+		goto unlock_mutex;
 	}
 
 	/* get task structs now */
@@ -353,7 +364,8 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
 		kthread_stop_put(tcp_tx);
 
 		dev_err(dev, "port %d already used\n", rhport);
-		return -EINVAL;
+		err = -EINVAL;
+		goto unlock_mutex;
 	}
 
 	dev_info(dev, "pdev(%u) rhport(%u) sockfd(%d)\n",
@@ -378,7 +390,15 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
 
 	rh_port_connect(vdev, speed);
 
+	dev_info(dev, "Device attached\n");
+
+	mutex_unlock(&vdev->ud.sysfs_lock);
+
 	return count;
+
+unlock_mutex:
+	mutex_unlock(&vdev->ud.sysfs_lock);
+	return err;
 }
 static DEVICE_ATTR(attach, S_IWUSR, NULL, store_attach);
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread
* [PATCH 0/4] usbip synchronize sysfs code paths
@ 2021-03-30  1:36 Shuah Khan
  2021-03-30  1:36 ` [PATCH 1/4] usbip: add sysfs_lock to " Shuah Khan
  0 siblings, 1 reply; 12+ messages in thread
From: Shuah Khan @ 2021-03-30  1:36 UTC (permalink / raw)
  To: valentina.manea.m, shuah, gregkh; +Cc: Shuah Khan, linux-usb, linux-kernel

Fuzzing uncovered race condition between sysfs code paths in usbip
drivers. Device connect/disconnect code paths initiated through
sysfs interface are prone to races if disconnect happens during
connect and vice versa.

This problem is common to all drivers while it can be reproduced easily
in vhci_hcd. Add a sysfs_lock to usbip_device struct to protect the paths.

For a complete fix, all usbip drivers have to use sysfs_lock to protect
sysfs code paths and common event handler will have to use this lock to
synchonize with the sysfs paths in drivers.

This patch series adds sysfs_lock and uses it in vhci_hcd in the first
patch. Subsequent patches fix usbip_host, vudc and the last patch fixes
the common event handler code path.

Shuah Khan (4):
  usbip: add sysfs_lock to synchronize sysfs code paths
  usbip: stub-dev synchronize sysfs code paths
  usbip: vudc synchronize sysfs code paths
  usbip: synchronize event handler with sysfs code paths

 drivers/usb/usbip/stub_dev.c     | 11 +++++++++--
 drivers/usb/usbip/usbip_common.h |  3 +++
 drivers/usb/usbip/usbip_event.c  |  2 ++
 drivers/usb/usbip/vhci_hcd.c     |  1 +
 drivers/usb/usbip/vhci_sysfs.c   | 30 +++++++++++++++++++++++++-----
 drivers/usb/usbip/vudc_dev.c     |  1 +
 drivers/usb/usbip/vudc_sysfs.c   |  5 +++++
 7 files changed, 46 insertions(+), 7 deletions(-)

-- 
2.27.0


^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2021-04-20  7:30 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-16 20:53 [PATCH 1/4] usbip: add sysfs_lock to synchronize sysfs code paths Tom Seewald
2021-04-16 20:53 ` [PATCH 2/4] usbip: stub-dev " Tom Seewald
2021-04-16 21:44   ` Shuah Khan
2021-04-16 20:53 ` [PATCH 3/4] usbip: vudc " Tom Seewald
2021-04-16 21:45   ` Shuah Khan
2021-04-16 20:53 ` [PATCH 4/4] usbip: synchronize event handler with " Tom Seewald
2021-04-16 21:45   ` Shuah Khan
2021-04-16 21:43 ` [PATCH 1/4] usbip: add sysfs_lock to synchronize " Shuah Khan
2021-04-19 12:23   ` Greg Kroah-Hartman
2021-04-19 21:42     ` Shuah Khan
2021-04-20  7:30       ` Greg Kroah-Hartman
  -- strict thread matches above, loose matches on Subject: below --
2021-03-30  1:36 [PATCH 0/4] usbip " Shuah Khan
2021-03-30  1:36 ` [PATCH 1/4] usbip: add sysfs_lock to " Shuah Khan

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.