Handle kthread_create() failure by replacing kthread_get_run() with usbip_prepare_threads()/usbip_unprepare_threads(). Tested-by: syzbot <syzbot+a93fba6d384346a761e3@xxxxxxxxxxxxxxxxxxxxxxxxx> Signed-off-by: Tetsuo Handa <penguin-kernel@xxxxxxxxxxxxxxxxxxx> --- drivers/usb/usbip/stub_dev.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) 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, -- 2.18.4