| From 9dbf34a834563dada91366c2ac266f32ff34641a Mon Sep 17 00:00:00 2001 |
| From: Shuah Khan <skhan@linuxfoundation.org> |
| Date: Mon, 29 Mar 2021 19:36:49 -0600 |
| Subject: usbip: stub-dev synchronize sysfs code paths |
| |
| From: Shuah Khan <skhan@linuxfoundation.org> |
| |
| commit 9dbf34a834563dada91366c2ac266f32ff34641a 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. |
| |
| Use sysfs_lock to protect sysfs paths in stub-dev. |
| |
| Cc: stable@vger.kernel.org |
| Reported-and-tested-by: syzbot+a93fba6d384346a761e3@syzkaller.appspotmail.com |
| Signed-off-by: Shuah Khan <skhan@linuxfoundation.org> |
| Link: https://lore.kernel.org/r/2b182f3561b4a065bf3bf6dce3b0e9944ba17b3f.1616807117.git.skhan@linuxfoundation.org |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/usb/usbip/stub_dev.c | 11 +++++++++-- |
| 1 file changed, 9 insertions(+), 2 deletions(-) |
| |
| --- a/drivers/usb/usbip/stub_dev.c |
| +++ b/drivers/usb/usbip/stub_dev.c |
| @@ -63,6 +63,7 @@ static ssize_t usbip_sockfd_store(struct |
| |
| dev_info(dev, "stub up\n"); |
| |
| + mutex_lock(&sdev->ud.sysfs_lock); |
| spin_lock_irq(&sdev->ud.lock); |
| |
| if (sdev->ud.status != SDEV_ST_AVAILABLE) { |
| @@ -87,13 +88,13 @@ static ssize_t usbip_sockfd_store(struct |
| tcp_rx = kthread_create(stub_rx_loop, &sdev->ud, "stub_rx"); |
| if (IS_ERR(tcp_rx)) { |
| sockfd_put(socket); |
| - return -EINVAL; |
| + goto unlock_mutex; |
| } |
| tcp_tx = kthread_create(stub_tx_loop, &sdev->ud, "stub_tx"); |
| if (IS_ERR(tcp_tx)) { |
| kthread_stop(tcp_rx); |
| sockfd_put(socket); |
| - return -EINVAL; |
| + goto unlock_mutex; |
| } |
| |
| /* get task structs now */ |
| @@ -112,6 +113,8 @@ static ssize_t usbip_sockfd_store(struct |
| wake_up_process(sdev->ud.tcp_rx); |
| wake_up_process(sdev->ud.tcp_tx); |
| |
| + mutex_unlock(&sdev->ud.sysfs_lock); |
| + |
| } else { |
| dev_info(dev, "stub down\n"); |
| |
| @@ -122,6 +125,7 @@ static ssize_t usbip_sockfd_store(struct |
| spin_unlock_irq(&sdev->ud.lock); |
| |
| usbip_event_add(&sdev->ud, SDEV_EVENT_DOWN); |
| + mutex_unlock(&sdev->ud.sysfs_lock); |
| } |
| |
| return count; |
| @@ -130,6 +134,8 @@ sock_err: |
| sockfd_put(socket); |
| err: |
| spin_unlock_irq(&sdev->ud.lock); |
| +unlock_mutex: |
| + mutex_unlock(&sdev->ud.sysfs_lock); |
| return -EINVAL; |
| } |
| static DEVICE_ATTR_WO(usbip_sockfd); |
| @@ -270,6 +276,7 @@ static struct stub_device *stub_device_a |
| sdev->ud.side = USBIP_STUB; |
| sdev->ud.status = SDEV_ST_AVAILABLE; |
| spin_lock_init(&sdev->ud.lock); |
| + mutex_init(&sdev->ud.sysfs_lock); |
| sdev->ud.tcp_socket = NULL; |
| sdev->ud.sockfd = -1; |
| |