Skip to content

Commit 9dbf34a

Browse files
shuahkhgregkh
authored andcommitted
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: [email protected] Reported-and-tested-by: [email protected] Signed-off-by: Shuah Khan <[email protected]> Link: https://lore.kernel.org/r/2b182f3561b4a065bf3bf6dce3b0e9944ba17b3f.1616807117.git.skhan@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 4e9c93a commit 9dbf34a

File tree

1 file changed

+9
-2
lines changed

1 file changed

+9
-2
lines changed

drivers/usb/usbip/stub_dev.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a
6363

6464
dev_info(dev, "stub up\n");
6565

66+
mutex_lock(&sdev->ud.sysfs_lock);
6667
spin_lock_irq(&sdev->ud.lock);
6768

6869
if (sdev->ud.status != SDEV_ST_AVAILABLE) {
@@ -87,13 +88,13 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a
8788
tcp_rx = kthread_create(stub_rx_loop, &sdev->ud, "stub_rx");
8889
if (IS_ERR(tcp_rx)) {
8990
sockfd_put(socket);
90-
return -EINVAL;
91+
goto unlock_mutex;
9192
}
9293
tcp_tx = kthread_create(stub_tx_loop, &sdev->ud, "stub_tx");
9394
if (IS_ERR(tcp_tx)) {
9495
kthread_stop(tcp_rx);
9596
sockfd_put(socket);
96-
return -EINVAL;
97+
goto unlock_mutex;
9798
}
9899

99100
/* get task structs now */
@@ -112,6 +113,8 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a
112113
wake_up_process(sdev->ud.tcp_rx);
113114
wake_up_process(sdev->ud.tcp_tx);
114115

116+
mutex_unlock(&sdev->ud.sysfs_lock);
117+
115118
} else {
116119
dev_info(dev, "stub down\n");
117120

@@ -122,6 +125,7 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a
122125
spin_unlock_irq(&sdev->ud.lock);
123126

124127
usbip_event_add(&sdev->ud, SDEV_EVENT_DOWN);
128+
mutex_unlock(&sdev->ud.sysfs_lock);
125129
}
126130

127131
return count;
@@ -130,6 +134,8 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a
130134
sockfd_put(socket);
131135
err:
132136
spin_unlock_irq(&sdev->ud.lock);
137+
unlock_mutex:
138+
mutex_unlock(&sdev->ud.sysfs_lock);
133139
return -EINVAL;
134140
}
135141
static DEVICE_ATTR_WO(usbip_sockfd);
@@ -270,6 +276,7 @@ static struct stub_device *stub_device_alloc(struct usb_device *udev)
270276
sdev->ud.side = USBIP_STUB;
271277
sdev->ud.status = SDEV_ST_AVAILABLE;
272278
spin_lock_init(&sdev->ud.lock);
279+
mutex_init(&sdev->ud.sysfs_lock);
273280
sdev->ud.tcp_socket = NULL;
274281
sdev->ud.sockfd = -1;
275282

0 commit comments

Comments
 (0)