Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

usbip: stub-dev synchronize sysfs code paths

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>

authored by

Shuah Khan and committed by
Greg Kroah-Hartman
9dbf34a8 4e9c93af

+9 -2
+9 -2
drivers/usb/usbip/stub_dev.c
··· 63 63 64 64 dev_info(dev, "stub up\n"); 65 65 66 + mutex_lock(&sdev->ud.sysfs_lock); 66 67 spin_lock_irq(&sdev->ud.lock); 67 68 68 69 if (sdev->ud.status != SDEV_ST_AVAILABLE) { ··· 88 87 tcp_rx = kthread_create(stub_rx_loop, &sdev->ud, "stub_rx"); 89 88 if (IS_ERR(tcp_rx)) { 90 89 sockfd_put(socket); 91 - return -EINVAL; 90 + goto unlock_mutex; 92 91 } 93 92 tcp_tx = kthread_create(stub_tx_loop, &sdev->ud, "stub_tx"); 94 93 if (IS_ERR(tcp_tx)) { 95 94 kthread_stop(tcp_rx); 96 95 sockfd_put(socket); 97 - return -EINVAL; 96 + goto unlock_mutex; 98 97 } 99 98 100 99 /* get task structs now */ ··· 113 112 wake_up_process(sdev->ud.tcp_rx); 114 113 wake_up_process(sdev->ud.tcp_tx); 115 114 115 + mutex_unlock(&sdev->ud.sysfs_lock); 116 + 116 117 } else { 117 118 dev_info(dev, "stub down\n"); 118 119 ··· 125 122 spin_unlock_irq(&sdev->ud.lock); 126 123 127 124 usbip_event_add(&sdev->ud, SDEV_EVENT_DOWN); 125 + mutex_unlock(&sdev->ud.sysfs_lock); 128 126 } 129 127 130 128 return count; ··· 134 130 sockfd_put(socket); 135 131 err: 136 132 spin_unlock_irq(&sdev->ud.lock); 133 + unlock_mutex: 134 + mutex_unlock(&sdev->ud.sysfs_lock); 137 135 return -EINVAL; 138 136 } 139 137 static DEVICE_ATTR_WO(usbip_sockfd); ··· 276 270 sdev->ud.side = USBIP_STUB; 277 271 sdev->ud.status = SDEV_ST_AVAILABLE; 278 272 spin_lock_init(&sdev->ud.lock); 273 + mutex_init(&sdev->ud.sysfs_lock); 279 274 sdev->ud.tcp_socket = NULL; 280 275 sdev->ud.sockfd = -1; 281 276