Thread (30 messages) 30 messages, 3 authors, 2021-03-05
STALE1936d REVIEWED: 1 (0M)

[PATCH v4 10/12] usb: usbip: vudc: add automatic recovery to usbip_sockfd_store()

From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Date: 2021-03-04 15:27:32
Subsystem: the rest, usb over ip driver, usb subsystem · Maintainers: Linus Torvalds, Valentina Manea, Shuah Khan, Greg Kroah-Hartman

Handle kthread_create() failure by replacing kthread_get_run() with
usbip_prepare_threads()/usbip_unprepare_threads().

Tested-by: syzbot <redacted>
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
---
 drivers/usb/usbip/vudc_sysfs.c | 37 ++++++++++++++++------------------
 1 file changed, 17 insertions(+), 20 deletions(-)
diff --git a/drivers/usb/usbip/vudc_sysfs.c b/drivers/usb/usbip/vudc_sysfs.c
index ebf6a127fcc3..ff3cf225a4fa 100644
--- a/drivers/usb/usbip/vudc_sysfs.c
+++ b/drivers/usb/usbip/vudc_sysfs.c
@@ -96,8 +96,7 @@ static ssize_t __usbip_sockfd_store(struct device *dev, struct device_attribute
 	struct vudc *udc = (struct vudc *) dev_get_drvdata(dev);
 	int rv;
 	int sockfd = 0;
-	int err;
-	struct socket *socket;
+	struct usbip_thread_info uti = { };
 	unsigned long flags;
 	int ret;
 
@@ -109,6 +108,14 @@ static ssize_t __usbip_sockfd_store(struct device *dev, struct device_attribute
 		dev_err(dev, "no device");
 		return -ENODEV;
 	}
+
+	if (sockfd != -1) {
+		ret = usbip_prepare_threads(&uti, &udc->ud, sockfd,
+					    v_tx_loop, "vudc_tx", v_rx_loop, "vudc_rx");
+		if (ret)
+			return ret;
+	}
+
 	spin_lock_irqsave(&udc->lock, flags);
 	/* Don't export what we don't have */
 	if (!udc->driver || !udc->pullup) {
@@ -130,28 +137,17 @@ static ssize_t __usbip_sockfd_store(struct device *dev, struct device_attribute
 			ret = -EINVAL;
 			goto unlock_ud;
 		}
-
-		socket = sockfd_lookup(sockfd, &err);
-		if (!socket) {
-			dev_err(dev, "failed to lookup sock");
-			ret = -EINVAL;
-			goto unlock_ud;
-		}
-
-		udc->ud.tcp_socket = socket;
-
+		udc->ud.tcp_socket = uti.tcp_socket;
+		udc->ud.tcp_rx = uti.tcp_rx;
+		udc->ud.tcp_tx = uti.tcp_tx;
+		udc->ud.status = SDEV_ST_USED;
 		spin_unlock_irq(&udc->ud.lock);
 		spin_unlock_irqrestore(&udc->lock, flags);
 
-		udc->ud.tcp_rx = kthread_get_run(&v_rx_loop,
-						    &udc->ud, "vudc_rx");
-		udc->ud.tcp_tx = kthread_get_run(&v_tx_loop,
-						    &udc->ud, "vudc_tx");
+		wake_up_process(udc->ud.tcp_rx);
+		wake_up_process(udc->ud.tcp_tx);
 
 		spin_lock_irqsave(&udc->lock, flags);
-		spin_lock_irq(&udc->ud.lock);
-		udc->ud.status = SDEV_ST_USED;
-		spin_unlock_irq(&udc->ud.lock);
 
 		ktime_get_ts64(&udc->start_time);
 		v_start_timer(udc);
@@ -181,7 +177,8 @@ static ssize_t __usbip_sockfd_store(struct device *dev, struct device_attribute
 	spin_unlock_irq(&udc->ud.lock);
 unlock:
 	spin_unlock_irqrestore(&udc->lock, flags);
-
+	if (uti.tcp_socket)
+		usbip_unprepare_threads(&uti);
 	return ret;
 }
 static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *attr,
-- 
2.18.4
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help