diff mbox series

[v4,11/12] usb: usbip: stub: add automatic recovery to usbip_sockfd_store()

Message ID 20210304152455.3685-12-penguin-kernel@I-love.SAKURA.ne.jp
State New
Headers show
Series usb: usbip: serialize attach/detach operations | expand

Commit Message

Tetsuo Handa March 4, 2021, 3:24 p.m. UTC
Handle kthread_create() failure by replacing kthread_get_run() with
usbip_prepare_threads()/usbip_unprepare_threads().

Tested-by: syzbot <syzbot+a93fba6d384346a761e3@syzkaller.appspotmail.com>
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
---
 drivers/usb/usbip/stub_dev.c | 29 +++++++++++++----------------
 1 file changed, 13 insertions(+), 16 deletions(-)
diff mbox series

Patch

diff --git a/drivers/usb/usbip/stub_dev.c b/drivers/usb/usbip/stub_dev.c
index cea5663d1994..ff7d0cd5a557 100644
--- a/drivers/usb/usbip/stub_dev.c
+++ b/drivers/usb/usbip/stub_dev.c
@@ -44,7 +44,7 @@  static ssize_t __usbip_sockfd_store(struct device *dev, struct device_attribute
 {
 	struct stub_device *sdev = dev_get_drvdata(dev);
 	int sockfd = 0;
-	struct socket *socket;
+	struct usbip_thread_info uti = { };
 	int rv;
 
 	if (!sdev) {
@@ -57,7 +57,11 @@  static ssize_t __usbip_sockfd_store(struct device *dev, struct device_attribute
 		return -EINVAL;
 
 	if (sockfd != -1) {
-		int err;
+		int err = usbip_prepare_threads(&uti, &sdev->ud, sockfd,
+						stub_tx_loop, "stub_tx", stub_rx_loop, "stub_rx");
+
+		if (err)
+			return err;
 
 		dev_info(dev, "stub up\n");
 
@@ -68,24 +72,15 @@  static ssize_t __usbip_sockfd_store(struct device *dev, struct device_attribute
 			goto err;
 		}
 
-		socket = sockfd_lookup(sockfd, &err);
-		if (!socket)
-			goto err;
-
-		sdev->ud.tcp_socket = socket;
+		sdev->ud.tcp_socket = uti.tcp_socket;
 		sdev->ud.sockfd = sockfd;
-
-		spin_unlock_irq(&sdev->ud.lock);
-
-		sdev->ud.tcp_rx = kthread_get_run(stub_rx_loop, &sdev->ud,
-						  "stub_rx");
-		sdev->ud.tcp_tx = kthread_get_run(stub_tx_loop, &sdev->ud,
-						  "stub_tx");
-
-		spin_lock_irq(&sdev->ud.lock);
+		sdev->ud.tcp_rx = uti.tcp_rx;
+		sdev->ud.tcp_tx = uti.tcp_tx;
 		sdev->ud.status = SDEV_ST_USED;
 		spin_unlock_irq(&sdev->ud.lock);
 
+		wake_up_process(sdev->ud.tcp_rx);
+		wake_up_process(sdev->ud.tcp_tx);
 	} else {
 		dev_info(dev, "stub down\n");
 
@@ -102,6 +97,8 @@  static ssize_t __usbip_sockfd_store(struct device *dev, struct device_attribute
 
 err:
 	spin_unlock_irq(&sdev->ud.lock);
+	if (uti.tcp_socket)
+		usbip_unprepare_threads(&uti);
 	return -EINVAL;
 }
 static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *attr,