* [PATCH 0/6] usbip fixes to crashes found by syzbot @ 2021-03-08 3:53 Shuah Khan 2021-03-08 3:53 ` [PATCH 1/6] usbip: fix stub_dev to check for stream socket Shuah Khan ` (6 more replies) 0 siblings, 7 replies; 34+ messages in thread From: Shuah Khan @ 2021-03-08 3:53 UTC (permalink / raw) To: shuah, valentina.manea.m, gregkh Cc: Shuah Khan, linux-usb, linux-kernel, penguin-kernel This patch series fixes the following problems founds in syzbot fuzzing. 1. The first 3 patches fix usbip-host, vhci_hcd, vudc sub-drivers to validate the passed in file descriptor is a stream socket. If the file descriptor passed was a SOCK_DGRAM socket, sock_recvmsg() can't detect end of stream. Reported and fix suggested by Tetsuo Handa 2. All 3 sub-drivers use a common kthread_get_run() to create and start threads. There are races in updating the local and shared status in the current stub-up (usbip-host, vudc) and attach (vhci) sequences resulting in crashes. These stem from starting rx and tx threads before local and shared state is updated correctly to be in sync. 1. Doesn't handle kthread_create() error and saves invalid ptr in local state that drives rx and tx threads. Reported and fix suggested by Tetsuo Handa. 2. Updates tcp_socket and sockfd, starts stub_rx and stub_tx threads before updating usbip_device status to correct state. This opens up a race condition between the threads and tear down sequences. TODO: Once these fixes are in, kthread_get_run() macro can be removed in a cleanup patch. Credit goes to syzbot and Tetsuo Handa for finding and root-causing the kthread_get_run() improper error handling problem and others. This is a hard problem to find and debug since the races aren't seen in a normal case. Fuzzing forces the race window to be small enough for the kthread_get_run() error path bug and starting threads before updating the local and shared state bug in the stub-up sequence. Shuah Khan (6): usbip: fix stub_dev to check for stream socket usbip: fix vhci_hcd to check for stream socket usbip: fix vudc to check for stream socket usbip: fix stub_dev usbip_sockfd_store() races leading to gpf usbip: fix vhci_hcd attach_store() races leading to gpf usbip: fix vudc usbip_sockfd_store races leading to gpf drivers/usb/usbip/stub_dev.c | 42 ++++++++++++++++++++++++----- drivers/usb/usbip/vhci_sysfs.c | 39 +++++++++++++++++++++++---- drivers/usb/usbip/vudc_sysfs.c | 49 +++++++++++++++++++++++++++++----- 3 files changed, 111 insertions(+), 19 deletions(-) -- 2.27.0 ^ permalink raw reply [flat|nested] 34+ messages in thread
* [PATCH 1/6] usbip: fix stub_dev to check for stream socket 2021-03-08 3:53 [PATCH 0/6] usbip fixes to crashes found by syzbot Shuah Khan @ 2021-03-08 3:53 ` Shuah Khan 2021-03-08 3:53 ` [PATCH 2/6] usbip: fix vhci_hcd " Shuah Khan ` (5 subsequent siblings) 6 siblings, 0 replies; 34+ messages in thread From: Shuah Khan @ 2021-03-08 3:53 UTC (permalink / raw) To: shuah, valentina.manea.m, gregkh Cc: Shuah Khan, linux-usb, linux-kernel, penguin-kernel, stable Fix usbip_sockfd_store() to validate the passed in file descriptor is a stream socket. If the file descriptor passed was a SOCK_DGRAM socket, sock_recvmsg() can't detect end of stream. Cc: stable@vger.kernel.org Suggested-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Signed-off-by: Shuah Khan <skhan@linuxfoundation.org> --- drivers/usb/usbip/stub_dev.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/usb/usbip/stub_dev.c b/drivers/usb/usbip/stub_dev.c index 2305d425e6c9..90c105469a07 100644 --- a/drivers/usb/usbip/stub_dev.c +++ b/drivers/usb/usbip/stub_dev.c @@ -69,8 +69,16 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a } socket = sockfd_lookup(sockfd, &err); - if (!socket) + if (!socket) { + dev_err(dev, "failed to lookup sock"); goto err; + } + + if (socket->type != SOCK_STREAM) { + dev_err(dev, "Expecting SOCK_STREAM - found %d", + socket->type); + goto sock_err; + } sdev->ud.tcp_socket = socket; sdev->ud.sockfd = sockfd; @@ -100,6 +108,8 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a return count; +sock_err: + sockfd_put(socket); err: spin_unlock_irq(&sdev->ud.lock); return -EINVAL; -- 2.27.0 ^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 2/6] usbip: fix vhci_hcd to check for stream socket 2021-03-08 3:53 [PATCH 0/6] usbip fixes to crashes found by syzbot Shuah Khan 2021-03-08 3:53 ` [PATCH 1/6] usbip: fix stub_dev to check for stream socket Shuah Khan @ 2021-03-08 3:53 ` Shuah Khan 2021-03-08 3:53 ` [PATCH 3/6] usbip: fix vudc " Shuah Khan ` (4 subsequent siblings) 6 siblings, 0 replies; 34+ messages in thread From: Shuah Khan @ 2021-03-08 3:53 UTC (permalink / raw) To: shuah, valentina.manea.m, gregkh Cc: Shuah Khan, linux-usb, linux-kernel, penguin-kernel, stable Fix attach_store() to validate the passed in file descriptor is a stream socket. If the file descriptor passed was a SOCK_DGRAM socket, sock_recvmsg() can't detect end of stream. Cc: stable@vger.kernel.org Suggested-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Signed-off-by: Shuah Khan <skhan@linuxfoundation.org> --- drivers/usb/usbip/vhci_sysfs.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/usb/usbip/vhci_sysfs.c b/drivers/usb/usbip/vhci_sysfs.c index 96e5371dc335..1e1ae9bd06ab 100644 --- a/drivers/usb/usbip/vhci_sysfs.c +++ b/drivers/usb/usbip/vhci_sysfs.c @@ -349,8 +349,16 @@ static ssize_t attach_store(struct device *dev, struct device_attribute *attr, /* Extract socket from fd. */ socket = sockfd_lookup(sockfd, &err); - if (!socket) + if (!socket) { + dev_err(dev, "failed to lookup sock"); return -EINVAL; + } + if (socket->type != SOCK_STREAM) { + dev_err(dev, "Expecting SOCK_STREAM - found %d", + socket->type); + sockfd_put(socket); + return -EINVAL; + } /* now need lock until setting vdev status as used */ -- 2.27.0 ^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 3/6] usbip: fix vudc to check for stream socket 2021-03-08 3:53 [PATCH 0/6] usbip fixes to crashes found by syzbot Shuah Khan 2021-03-08 3:53 ` [PATCH 1/6] usbip: fix stub_dev to check for stream socket Shuah Khan 2021-03-08 3:53 ` [PATCH 2/6] usbip: fix vhci_hcd " Shuah Khan @ 2021-03-08 3:53 ` Shuah Khan 2021-03-08 3:53 ` [PATCH 4/6] usbip: fix stub_dev usbip_sockfd_store() races leading to gpf Shuah Khan ` (3 subsequent siblings) 6 siblings, 0 replies; 34+ messages in thread From: Shuah Khan @ 2021-03-08 3:53 UTC (permalink / raw) To: shuah, valentina.manea.m, gregkh Cc: Shuah Khan, linux-usb, linux-kernel, penguin-kernel, stable Fix usbip_sockfd_store() to validate the passed in file descriptor is a stream socket. If the file descriptor passed was a SOCK_DGRAM socket, sock_recvmsg() can't detect end of stream. Cc: stable@vger.kernel.org Suggested-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Signed-off-by: Shuah Khan <skhan@linuxfoundation.org> --- drivers/usb/usbip/vudc_sysfs.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/usb/usbip/vudc_sysfs.c b/drivers/usb/usbip/vudc_sysfs.c index 100f680c572a..83a0c59a3de8 100644 --- a/drivers/usb/usbip/vudc_sysfs.c +++ b/drivers/usb/usbip/vudc_sysfs.c @@ -138,6 +138,13 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a goto unlock_ud; } + if (socket->type != SOCK_STREAM) { + dev_err(dev, "Expecting SOCK_STREAM - found %d", + socket->type); + ret = -EINVAL; + goto sock_err; + } + udc->ud.tcp_socket = socket; spin_unlock_irq(&udc->ud.lock); @@ -177,6 +184,8 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a return count; +sock_err: + sockfd_put(socket); unlock_ud: spin_unlock_irq(&udc->ud.lock); unlock: -- 2.27.0 ^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 4/6] usbip: fix stub_dev usbip_sockfd_store() races leading to gpf 2021-03-08 3:53 [PATCH 0/6] usbip fixes to crashes found by syzbot Shuah Khan ` (2 preceding siblings ...) 2021-03-08 3:53 ` [PATCH 3/6] usbip: fix vudc " Shuah Khan @ 2021-03-08 3:53 ` Shuah Khan 2021-03-08 7:35 ` Tetsuo Handa 2021-03-08 3:53 ` [PATCH 5/6] usbip: fix vhci_hcd attach_store() " Shuah Khan ` (2 subsequent siblings) 6 siblings, 1 reply; 34+ messages in thread From: Shuah Khan @ 2021-03-08 3:53 UTC (permalink / raw) To: shuah, valentina.manea.m, gregkh Cc: Shuah Khan, linux-usb, linux-kernel, penguin-kernel, syzbot, syzbot, syzbot, stable usbip_sockfd_store() is invoked when user requests attach (import) detach (unimport) usb device from usbip host. vhci_hcd sends import request and usbip_sockfd_store() exports the device if it is free for export. Export and unexport are governed by local state and shared state - Shared state (usbip device status, sockfd) - sockfd and Device status are used to determine if stub should be brought up or shut down. - Local state (tcp_socket, rx and tx thread task_struct ptrs) A valid tcp_socket controls rx and tx thread operations while the device is in exported state. - While the device is exported, device status is marked used and socket, sockfd, and thread pointers are valid. Export sequence (stub-up) includes validating the socket and creating receive (rx) and transmit (tx) threads to talk to the client to provide access to the exported device. rx and tx threads depends on local and shared state to be correct and in sync. Unexport (stub-down) sequence shuts the socket down and stops the rx and tx threads. Stub-down sequence relies on local and shared states to be in sync. There are races in updating the local and shared status in the current stub-up sequence resulting in crashes. These stem from starting rx and tx threads before local and global state is updated correctly to be in sync. 1. Doesn't handle kthread_create() error and saves invalid ptr in local state that drives rx and tx threads. 2. Updates tcp_socket and sockfd, starts stub_rx and stub_tx threads before updating usbip_device status to SDEV_ST_USED. This opens up a race condition between the threads and usbip_sockfd_store() stub up and down handling. Fix the above problems: - Stop using kthread_get_run() macro to create/start threads. - Create threads and get task struct reference. - Add kthread_create() failure handling and bail out. - Hold usbip_device lock to update local and shared states after creating rx and tx threads. - Update usbip_device status to SDEV_ST_USED. - Update usbip_device tcp_socket, sockfd, tcp_rx, and tcp_tx - Start threads after usbip_device (tcp_socket, sockfd, tcp_rx, tcp_tx, and status) is complete. Credit goes to syzbot and Tetsuo Handa for finding and root-causing the kthread_get_run() improper error handling problem and others. This is a hard problem to find and debug since the races aren't seen in a normal case. Fuzzing forces the race window to be small enough for the kthread_get_run() error path bug and starting threads before updating the local and shared state bug in the stub-up sequence. Tested with syzbot reproducer: - https://syzkaller.appspot.com/text?tag=ReproC&x=14801034d00000 Reported-by: syzbot <syzbot+a93fba6d384346a761e3@syzkaller.appspotmail.com> Reported-by: syzbot <syzbot+bf1a360e305ee719e364@syzkaller.appspotmail.com> Reported-by: syzbot <syzbot+95ce4b142579611ef0a9@syzkaller.appspotmail.com> Reported-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Fixes: 9720b4bc76a83807 ("staging/usbip: convert to kthread") Cc: stable@vger.kernel.org Signed-off-by: Shuah Khan <skhan@linuxfoundation.org> --- drivers/usb/usbip/stub_dev.c | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/drivers/usb/usbip/stub_dev.c b/drivers/usb/usbip/stub_dev.c index 90c105469a07..8f1de1fbbeed 100644 --- a/drivers/usb/usbip/stub_dev.c +++ b/drivers/usb/usbip/stub_dev.c @@ -46,6 +46,8 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a int sockfd = 0; struct socket *socket; int rv; + struct task_struct *tcp_rx = NULL; + struct task_struct *tcp_tx = NULL; if (!sdev) { dev_err(dev, "sdev is null\n"); @@ -80,20 +82,36 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a goto sock_err; } - sdev->ud.tcp_socket = socket; - sdev->ud.sockfd = sockfd; - + /* unlock and create threads and get tasks */ spin_unlock_irq(&sdev->ud.lock); + tcp_rx = kthread_create(stub_rx_loop, &sdev->ud, "stub_rx"); + if (IS_ERR(tcp_rx)) { + sockfd_put(socket); + return -EINVAL; + } + 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; + } - 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"); + /* get task structs now */ + get_task_struct(tcp_rx); + get_task_struct(tcp_tx); + /* lock and update sdev->ud state */ spin_lock_irq(&sdev->ud.lock); + sdev->ud.tcp_socket = socket; + sdev->ud.sockfd = sockfd; + sdev->ud.tcp_rx = tcp_rx; + sdev->ud.tcp_tx = 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"); -- 2.27.0 ^ permalink raw reply related [flat|nested] 34+ messages in thread
* Re: [PATCH 4/6] usbip: fix stub_dev usbip_sockfd_store() races leading to gpf 2021-03-08 3:53 ` [PATCH 4/6] usbip: fix stub_dev usbip_sockfd_store() races leading to gpf Shuah Khan @ 2021-03-08 7:35 ` Tetsuo Handa 2021-03-08 10:10 ` Tetsuo Handa 0 siblings, 1 reply; 34+ messages in thread From: Tetsuo Handa @ 2021-03-08 7:35 UTC (permalink / raw) To: Shuah Khan, shuah, valentina.manea.m, gregkh; +Cc: linux-usb, linux-kernel On 2021/03/08 12:53, Shuah Khan wrote: > Fix the above problems: > - Stop using kthread_get_run() macro to create/start threads. > - Create threads and get task struct reference. > - Add kthread_create() failure handling and bail out. > - Hold usbip_device lock to update local and shared states after > creating rx and tx threads. > - Update usbip_device status to SDEV_ST_USED. > - Update usbip_device tcp_socket, sockfd, tcp_rx, and tcp_tx > - Start threads after usbip_device (tcp_socket, sockfd, tcp_rx, tcp_tx, > and status) is complete. No, the whole usbip_sockfd_store() etc. should be serialized using a mutex, for two different threads can open same file and write the same content at the same moment. This results in seeing SDEV_ST_AVAILABLE and creating two threads and overwiting global variables and setting SDEV_ST_USED and starting two threads by each of two thread, which will later fail to call kthread_stop() on one of two thread because global variables are overwritten. kthread_crate() (which involves GFP_KERNEL allocation) can take long time enough to hit usbip_sockfd_store() must perform if (sdev->ud.status != SDEV_ST_AVAILABLE) { /* misc assignments for attach operation */ sdev->ud.status = SDEV_ST_USED; } under a lock, or multiple ud->tcp_{tx,rx} are created (which will later cause a crash like [1]) and refcount on ud->tcp_socket is leaked when usbip_sockfd_store() is concurrently called. problem. That's why my patch introduced usbip_event_mutex lock. ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 4/6] usbip: fix stub_dev usbip_sockfd_store() races leading to gpf 2021-03-08 7:35 ` Tetsuo Handa @ 2021-03-08 10:10 ` Tetsuo Handa 2021-03-08 16:27 ` Shuah Khan 0 siblings, 1 reply; 34+ messages in thread From: Tetsuo Handa @ 2021-03-08 10:10 UTC (permalink / raw) To: Shuah Khan, shuah, valentina.manea.m, gregkh; +Cc: linux-usb, linux-kernel On 2021/03/08 16:35, Tetsuo Handa wrote: > On 2021/03/08 12:53, Shuah Khan wrote: >> Fix the above problems: >> - Stop using kthread_get_run() macro to create/start threads. >> - Create threads and get task struct reference. >> - Add kthread_create() failure handling and bail out. >> - Hold usbip_device lock to update local and shared states after >> creating rx and tx threads. >> - Update usbip_device status to SDEV_ST_USED. >> - Update usbip_device tcp_socket, sockfd, tcp_rx, and tcp_tx >> - Start threads after usbip_device (tcp_socket, sockfd, tcp_rx, tcp_tx, >> and status) is complete. > > No, the whole usbip_sockfd_store() etc. should be serialized using a mutex, > for two different threads can open same file and write the same content at > the same moment. This results in seeing SDEV_ST_AVAILABLE and creating two > threads and overwiting global variables and setting SDEV_ST_USED and starting > two threads by each of two thread, which will later fail to call kthread_stop() > on one of two thread because global variables are overwritten. > > kthread_crate() (which involves GFP_KERNEL allocation) can take long time > enough to hit > > usbip_sockfd_store() must perform > > if (sdev->ud.status != SDEV_ST_AVAILABLE) { Oops. This is if (sdev->ud.status == SDEV_ST_AVAILABLE) { of course. > /* misc assignments for attach operation */ > sdev->ud.status = SDEV_ST_USED; > } > > under a lock, or multiple ud->tcp_{tx,rx} are created (which will later > cause a crash like [1]) and refcount on ud->tcp_socket is leaked when > usbip_sockfd_store() is concurrently called. > > problem. That's why my patch introduced usbip_event_mutex lock. > And I think that same serialization is required between "rh_port_connect() from attach_store()" and "rh_port_disconnect() from vhci_shutdown_connection() via usbip_event_add(&vdev->ud, VDEV_EVENT_DOWN) from vhci_port_disconnect() from detach_store()", for both vhci_rx_pdu() from vhci_rx_loop() and vhci_port_disconnect() from detach_store() can queue VDEV_EVENT_DOWN event which can be processed without waiting for attach_store() to complete. ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 4/6] usbip: fix stub_dev usbip_sockfd_store() races leading to gpf 2021-03-08 10:10 ` Tetsuo Handa @ 2021-03-08 16:27 ` Shuah Khan 2021-03-09 11:04 ` Tetsuo Handa 2021-03-09 15:22 ` Shuah Khan 0 siblings, 2 replies; 34+ messages in thread From: Shuah Khan @ 2021-03-08 16:27 UTC (permalink / raw) To: Tetsuo Handa, shuah, valentina.manea.m, gregkh Cc: linux-usb, linux-kernel, Shuah Khan On 3/8/21 3:10 AM, Tetsuo Handa wrote: > On 2021/03/08 16:35, Tetsuo Handa wrote: >> On 2021/03/08 12:53, Shuah Khan wrote: >>> Fix the above problems: >>> - Stop using kthread_get_run() macro to create/start threads. >>> - Create threads and get task struct reference. >>> - Add kthread_create() failure handling and bail out. >>> - Hold usbip_device lock to update local and shared states after >>> creating rx and tx threads. >>> - Update usbip_device status to SDEV_ST_USED. >>> - Update usbip_device tcp_socket, sockfd, tcp_rx, and tcp_tx >>> - Start threads after usbip_device (tcp_socket, sockfd, tcp_rx, tcp_tx, >>> and status) is complete. >> >> No, the whole usbip_sockfd_store() etc. should be serialized using a mutex, >> for two different threads can open same file and write the same content at >> the same moment. This results in seeing SDEV_ST_AVAILABLE and creating two >> threads and overwiting global variables and setting SDEV_ST_USED and starting >> two threads by each of two thread, which will later fail to call kthread_stop() >> on one of two thread because global variables are overwritten. >> >> kthread_crate() (which involves GFP_KERNEL allocation) can take long time >> enough to hit >> >> usbip_sockfd_store() must perform >> >> if (sdev->ud.status != SDEV_ST_AVAILABLE) { > > Oops. This is > > if (sdev->ud.status == SDEV_ST_AVAILABLE) { > > of course. > >> /* misc assignments for attach operation */ >> sdev->ud.status = SDEV_ST_USED; >> } >> >> under a lock, or multiple ud->tcp_{tx,rx} are created (which will later >> cause a crash like [1]) and refcount on ud->tcp_socket is leaked when >> usbip_sockfd_store() is concurrently called. >> >> problem. That's why my patch introduced usbip_event_mutex lock. >> > > And I think that same serialization is required between "rh_port_connect() from attach_store()" and > "rh_port_disconnect() from vhci_shutdown_connection() via usbip_event_add(&vdev->ud, VDEV_EVENT_DOWN) > from vhci_port_disconnect() from detach_store()", for both vhci_rx_pdu() from vhci_rx_loop() and > vhci_port_disconnect() from detach_store() can queue VDEV_EVENT_DOWN event which can be processed > without waiting for attach_store() to complete. > Yes. We might need synchronization between events, threads, and shutdown in usbip_host side and in connection polling and threads in vhci. I am also looking at the shutdown sequences closely as well since the local state is referenced without usbip_device lock in these paths. I am approaching these problems as peeling the onion an expression so we can limit the changes and take a spot fix approach. We have the goal to address these crashes and not introduce regressions. I don't seem to be able to reproduce these problems consistently in my env. with the reproducer. I couldn't reproduce them in normal case at all. Hence, the this cautious approach that reduces the chance of regressions and if we see regressions, they can fixed easily. https://syzkaller.appspot.com/text?tag=ReproC&x=14801034d00000 If this patch series fixes the problems you are seeing, I would like get these fixes in and address the other two potential race conditions in another round of patches. I also want to soak these in the next for a few weeks. Please let me know if these patches fix the problems you are seeing in your env. thanks, -- Shuah ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 4/6] usbip: fix stub_dev usbip_sockfd_store() races leading to gpf 2021-03-08 16:27 ` Shuah Khan @ 2021-03-09 11:04 ` Tetsuo Handa 2021-03-09 13:56 ` Tetsuo Handa 2021-03-09 19:50 ` Shuah Khan 2021-03-09 15:22 ` Shuah Khan 1 sibling, 2 replies; 34+ messages in thread From: Tetsuo Handa @ 2021-03-09 11:04 UTC (permalink / raw) To: Shuah Khan, shuah, valentina.manea.m, gregkh; +Cc: linux-usb, linux-kernel On 2021/03/09 1:27, Shuah Khan wrote: > Yes. We might need synchronization between events, threads, and shutdown > in usbip_host side and in connection polling and threads in vhci. > > I am also looking at the shutdown sequences closely as well since the > local state is referenced without usbip_device lock in these paths. > > I am approaching these problems as peeling the onion an expression so > we can limit the changes and take a spot fix approach. We have the > goal to address these crashes and not introduce regressions. I think my [PATCH v4 01/12]-[PATCH v4 06/12] simplify your further changes without introducing regressions. While ud->lock is held when checking ud->status, current attach/detach code is racy about read/update of ud->status . I think we can close race in attach/detach code via a simple usbip_event_mutex serialization. ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 4/6] usbip: fix stub_dev usbip_sockfd_store() races leading to gpf 2021-03-09 11:04 ` Tetsuo Handa @ 2021-03-09 13:56 ` Tetsuo Handa 2021-03-09 19:50 ` Shuah Khan 1 sibling, 0 replies; 34+ messages in thread From: Tetsuo Handa @ 2021-03-09 13:56 UTC (permalink / raw) To: Shuah Khan, shuah, valentina.manea.m, gregkh; +Cc: linux-usb, linux-kernel On 2021/03/09 20:04, Tetsuo Handa wrote: > On 2021/03/09 1:27, Shuah Khan wrote: >> Yes. We might need synchronization between events, threads, and shutdown >> in usbip_host side and in connection polling and threads in vhci. >> >> I am also looking at the shutdown sequences closely as well since the >> local state is referenced without usbip_device lock in these paths. >> >> I am approaching these problems as peeling the onion an expression so >> we can limit the changes and take a spot fix approach. We have the >> goal to address these crashes and not introduce regressions. > > I think my [PATCH v4 01/12]-[PATCH v4 06/12] simplify your further changes > without introducing regressions. While ud->lock is held when checking ud->status, > current attach/detach code is racy about read/update of ud->status . I think we > can close race in attach/detach code via a simple usbip_event_mutex serialization. > Commit 04679b3489e048cd ("Staging: USB/IP: add client driver") says /* * The important thing is that only one context begins cleanup. * This is why error handling and cleanup become simple. * We do not want to consider race condition as possible. */ static void vhci_shutdown_connection(struct usbip_device *ud) but why are we allowing multiple contexts to begin startup? That's where a subtle race window syzbot is reporting happened. This driver has never thought the possibility that multiple userspace processes can concurrently begin startup. Then, it is quite natural that we make startup simple and safe, by enforcing that only one context begins startup. Without serialization between startup/cleanup/event_handler(), "Fix the above problems:" in your changelog cannot become true. First step should be closing time-of-check to time-of-use bug via entire serialization as if "nonpreemptible UP kernel". ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 4/6] usbip: fix stub_dev usbip_sockfd_store() races leading to gpf 2021-03-09 11:04 ` Tetsuo Handa 2021-03-09 13:56 ` Tetsuo Handa @ 2021-03-09 19:50 ` Shuah Khan 2021-03-09 23:40 ` Tetsuo Handa 1 sibling, 1 reply; 34+ messages in thread From: Shuah Khan @ 2021-03-09 19:50 UTC (permalink / raw) To: Tetsuo Handa, shuah, valentina.manea.m, gregkh Cc: linux-usb, linux-kernel, Shuah Khan On 3/9/21 4:04 AM, Tetsuo Handa wrote: > On 2021/03/09 1:27, Shuah Khan wrote: >> Yes. We might need synchronization between events, threads, and shutdown >> in usbip_host side and in connection polling and threads in vhci. >> >> I am also looking at the shutdown sequences closely as well since the >> local state is referenced without usbip_device lock in these paths. >> >> I am approaching these problems as peeling the onion an expression so >> we can limit the changes and take a spot fix approach. We have the >> goal to address these crashes and not introduce regressions. > > I think my [PATCH v4 01/12]-[PATCH v4 06/12] simplify your further changes > without introducing regressions. While ud->lock is held when checking ud->status, > current attach/detach code is racy about read/update of ud->status . I think we > can close race in attach/detach code via a simple usbip_event_mutex serialization. > Do you mean patches 1,2,3,3,4,5,6? thanks, -- Shuah ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 4/6] usbip: fix stub_dev usbip_sockfd_store() races leading to gpf 2021-03-09 19:50 ` Shuah Khan @ 2021-03-09 23:40 ` Tetsuo Handa 2021-03-09 23:52 ` Shuah Khan 0 siblings, 1 reply; 34+ messages in thread From: Tetsuo Handa @ 2021-03-09 23:40 UTC (permalink / raw) To: Shuah Khan, shuah, valentina.manea.m, gregkh; +Cc: linux-usb, linux-kernel On 2021/03/10 4:50, Shuah Khan wrote: > On 3/9/21 4:04 AM, Tetsuo Handa wrote: >> On 2021/03/09 1:27, Shuah Khan wrote: >>> Yes. We might need synchronization between events, threads, and shutdown >>> in usbip_host side and in connection polling and threads in vhci. >>> >>> I am also looking at the shutdown sequences closely as well since the >>> local state is referenced without usbip_device lock in these paths. >>> >>> I am approaching these problems as peeling the onion an expression so >>> we can limit the changes and take a spot fix approach. We have the >>> goal to address these crashes and not introduce regressions. >> >> I think my [PATCH v4 01/12]-[PATCH v4 06/12] simplify your further changes >> without introducing regressions. While ud->lock is held when checking ud->status, >> current attach/detach code is racy about read/update of ud->status . I think we >> can close race in attach/detach code via a simple usbip_event_mutex serialization. >> > > Do you mean patches 1,2,3,3,4,5,6? Yes, my 1,2,3,4,5,6. Since you think that usbip_prepare_threads() does not worth introducing, I'm fine with replacing my 7,8,9,10,11,12 with your "[PATCH 0/6] usbip fixes to crashes found by syzbot". ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 4/6] usbip: fix stub_dev usbip_sockfd_store() races leading to gpf 2021-03-09 23:40 ` Tetsuo Handa @ 2021-03-09 23:52 ` Shuah Khan 2021-03-10 0:03 ` Tetsuo Handa 0 siblings, 1 reply; 34+ messages in thread From: Shuah Khan @ 2021-03-09 23:52 UTC (permalink / raw) To: Tetsuo Handa, shuah, valentina.manea.m, gregkh Cc: linux-usb, linux-kernel, Shuah Khan On 3/9/21 4:40 PM, Tetsuo Handa wrote: > On 2021/03/10 4:50, Shuah Khan wrote: >> On 3/9/21 4:04 AM, Tetsuo Handa wrote: >>> On 2021/03/09 1:27, Shuah Khan wrote: >>>> Yes. We might need synchronization between events, threads, and shutdown >>>> in usbip_host side and in connection polling and threads in vhci. >>>> >>>> I am also looking at the shutdown sequences closely as well since the >>>> local state is referenced without usbip_device lock in these paths. >>>> >>>> I am approaching these problems as peeling the onion an expression so >>>> we can limit the changes and take a spot fix approach. We have the >>>> goal to address these crashes and not introduce regressions. >>> >>> I think my [PATCH v4 01/12]-[PATCH v4 06/12] simplify your further changes >>> without introducing regressions. While ud->lock is held when checking ud->status, >>> current attach/detach code is racy about read/update of ud->status . I think we >>> can close race in attach/detach code via a simple usbip_event_mutex serialization. >>> >> >> Do you mean patches 1,2,3,3,4,5,6? > > Yes, my 1,2,3,4,5,6. > > Since you think that usbip_prepare_threads() does not worth introducing, I'm fine with > replacing my 7,8,9,10,11,12 with your "[PATCH 0/6] usbip fixes to crashes found by syzbot". > Using event lock isn't the right approach to solve the race. It is a large grain lock. I am not looking to replace patches. I still haven't seen any response from you about if you were able to verify the fixes I sent in fix the problem you are seeing. thanks, -- Shuah ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 4/6] usbip: fix stub_dev usbip_sockfd_store() races leading to gpf 2021-03-09 23:52 ` Shuah Khan @ 2021-03-10 0:03 ` Tetsuo Handa 2021-03-10 0:29 ` Shuah Khan 0 siblings, 1 reply; 34+ messages in thread From: Tetsuo Handa @ 2021-03-10 0:03 UTC (permalink / raw) To: Shuah Khan, shuah, valentina.manea.m, gregkh; +Cc: linux-usb, linux-kernel On 2021/03/10 8:52, Shuah Khan wrote: > On 3/9/21 4:40 PM, Tetsuo Handa wrote: >> On 2021/03/10 4:50, Shuah Khan wrote: >>> On 3/9/21 4:04 AM, Tetsuo Handa wrote: >>>> On 2021/03/09 1:27, Shuah Khan wrote: >>>>> Yes. We might need synchronization between events, threads, and shutdown >>>>> in usbip_host side and in connection polling and threads in vhci. >>>>> >>>>> I am also looking at the shutdown sequences closely as well since the >>>>> local state is referenced without usbip_device lock in these paths. >>>>> >>>>> I am approaching these problems as peeling the onion an expression so >>>>> we can limit the changes and take a spot fix approach. We have the >>>>> goal to address these crashes and not introduce regressions. >>>> >>>> I think my [PATCH v4 01/12]-[PATCH v4 06/12] simplify your further changes >>>> without introducing regressions. While ud->lock is held when checking ud->status, >>>> current attach/detach code is racy about read/update of ud->status . I think we >>>> can close race in attach/detach code via a simple usbip_event_mutex serialization. >>>> >>> >>> Do you mean patches 1,2,3,3,4,5,6? >> >> Yes, my 1,2,3,4,5,6. >> >> Since you think that usbip_prepare_threads() does not worth introducing, I'm fine with >> replacing my 7,8,9,10,11,12 with your "[PATCH 0/6] usbip fixes to crashes found by syzbot". >> > > Using event lock isn't the right approach to solve the race. It is a > large grain lock. I am not looking to replace patches. It is not a large grain lock. Since event_handler() is exclusively executed, this lock does _NOT_ block event_handler() unless attach/detach operations run concurrently. > > I still haven't seen any response from you about if you were able to > verify the fixes I sent in fix the problem you are seeing. I won't be able to verify your fixes, for it is syzbot who is seeing the problem. But I can see that your patch description is wrong because you are ignoring what I'm commenting. Global serialization had better come first. Your patch description depends on global serialization. ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 4/6] usbip: fix stub_dev usbip_sockfd_store() races leading to gpf 2021-03-10 0:03 ` Tetsuo Handa @ 2021-03-10 0:29 ` Shuah Khan 2021-03-10 1:02 ` Tetsuo Handa 0 siblings, 1 reply; 34+ messages in thread From: Shuah Khan @ 2021-03-10 0:29 UTC (permalink / raw) To: Tetsuo Handa, shuah, valentina.manea.m, gregkh Cc: linux-usb, linux-kernel, Shuah Khan On 3/9/21 5:03 PM, Tetsuo Handa wrote: > On 2021/03/10 8:52, Shuah Khan wrote: >> On 3/9/21 4:40 PM, Tetsuo Handa wrote: >>> On 2021/03/10 4:50, Shuah Khan wrote: >>>> On 3/9/21 4:04 AM, Tetsuo Handa wrote: >>>>> On 2021/03/09 1:27, Shuah Khan wrote: >>>>>> Yes. We might need synchronization between events, threads, and shutdown >>>>>> in usbip_host side and in connection polling and threads in vhci. >>>>>> >>>>>> I am also looking at the shutdown sequences closely as well since the >>>>>> local state is referenced without usbip_device lock in these paths. >>>>>> >>>>>> I am approaching these problems as peeling the onion an expression so >>>>>> we can limit the changes and take a spot fix approach. We have the >>>>>> goal to address these crashes and not introduce regressions. >>>>> >>>>> I think my [PATCH v4 01/12]-[PATCH v4 06/12] simplify your further changes >>>>> without introducing regressions. While ud->lock is held when checking ud->status, >>>>> current attach/detach code is racy about read/update of ud->status . I think we >>>>> can close race in attach/detach code via a simple usbip_event_mutex serialization. >>>>> >>>> >>>> Do you mean patches 1,2,3,3,4,5,6? >>> >>> Yes, my 1,2,3,4,5,6. >>> >>> Since you think that usbip_prepare_threads() does not worth introducing, I'm fine with >>> replacing my 7,8,9,10,11,12 with your "[PATCH 0/6] usbip fixes to crashes found by syzbot". >>> >> >> Using event lock isn't the right approach to solve the race. It is a >> large grain lock. I am not looking to replace patches. > > It is not a large grain lock. Since event_handler() is exclusively executed, this lock > does _NOT_ block event_handler() unless attach/detach operations run concurrently. > >> event handler queues the events. It shouldn't be blocked by attach and detach. The events could originate for various reasons during the host and vhci operations. I don't like using this lock for attach and detach. >> I still haven't seen any response from you about if you were able to >> verify the fixes I sent in fix the problem you are seeing. > > I won't be able to verify your fixes, for it is syzbot who is seeing the problem. Thank you for letting me know. thanks, -- Shuah ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 4/6] usbip: fix stub_dev usbip_sockfd_store() races leading to gpf 2021-03-10 0:29 ` Shuah Khan @ 2021-03-10 1:02 ` Tetsuo Handa 2021-03-10 2:07 ` Shuah Khan 0 siblings, 1 reply; 34+ messages in thread From: Tetsuo Handa @ 2021-03-10 1:02 UTC (permalink / raw) To: Shuah Khan, shuah, valentina.manea.m, gregkh; +Cc: linux-usb, linux-kernel On 2021/03/10 9:29, Shuah Khan wrote: >> It is not a large grain lock. Since event_handler() is exclusively executed, this lock >> does _NOT_ block event_handler() unless attach/detach operations run concurrently. >> >>> > > event handler queues the events. It shouldn't be blocked by attach > and detach. The events could originate for various reasons during > the host and vhci operations. I don't like using this lock for > attach and detach. How can attach/detach deadlock event_handler()? event_handler() calls e.g. vhci_shutdown_connection() via ud->eh_ops.shutdown(ud). vhci_shutdown_connection() e.g. waits for termination of tx/rx threads via kthread_stop_put(). event_handler() is already blocked by detach operation. How it can make situation worse to wait for creation of tx/rx threads in attach operation? ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 4/6] usbip: fix stub_dev usbip_sockfd_store() races leading to gpf 2021-03-10 1:02 ` Tetsuo Handa @ 2021-03-10 2:07 ` Shuah Khan 2021-03-10 10:38 ` Tetsuo Handa 0 siblings, 1 reply; 34+ messages in thread From: Shuah Khan @ 2021-03-10 2:07 UTC (permalink / raw) To: Tetsuo Handa, shuah, valentina.manea.m, gregkh Cc: linux-usb, linux-kernel, Shuah Khan On 3/9/21 6:02 PM, Tetsuo Handa wrote: > On 2021/03/10 9:29, Shuah Khan wrote: >>> It is not a large grain lock. Since event_handler() is exclusively executed, this lock >>> does _NOT_ block event_handler() unless attach/detach operations run concurrently. >>> >>>> >> >> event handler queues the events. It shouldn't be blocked by attach >> and detach. The events could originate for various reasons during >> the host and vhci operations. I don't like using this lock for >> attach and detach. > > How can attach/detach deadlock event_handler()? > event_handler() calls e.g. vhci_shutdown_connection() via ud->eh_ops.shutdown(ud). > vhci_shutdown_connection() e.g. waits for termination of tx/rx threads via kthread_stop_put(). > event_handler() is already blocked by detach operation. > How it can make situation worse to wait for creation of tx/rx threads in attach operation? > event_lock shouldn't be held during event ops. usbip_event_add() uses it to add events. Protecting shutdown path needs a different approach. In any case, do you have comments on this patch which doesn't even touch vhci driver? I understand you are identifying additional race condition that the vhci patches in this series might not fix. That doesn't mean that these patches aren't valid. Do you have any comments specific to the patches in this series? thanks, -- Shuah ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 4/6] usbip: fix stub_dev usbip_sockfd_store() races leading to gpf 2021-03-10 2:07 ` Shuah Khan @ 2021-03-10 10:38 ` Tetsuo Handa 0 siblings, 0 replies; 34+ messages in thread From: Tetsuo Handa @ 2021-03-10 10:38 UTC (permalink / raw) To: Shuah Khan, shuah, valentina.manea.m, gregkh; +Cc: linux-usb, linux-kernel On 2021/03/10 11:07, Shuah Khan wrote: > On 3/9/21 6:02 PM, Tetsuo Handa wrote: >> On 2021/03/10 9:29, Shuah Khan wrote: >>>> It is not a large grain lock. Since event_handler() is exclusively executed, this lock >>>> does _NOT_ block event_handler() unless attach/detach operations run concurrently. >>>> >>> >>> event handler queues the events. It shouldn't be blocked by attach >>> and detach. The events could originate for various reasons during >>> the host and vhci operations. I don't like using this lock for >>> attach and detach. >> >> How can attach/detach deadlock event_handler()? >> event_handler() calls e.g. vhci_shutdown_connection() via ud->eh_ops.shutdown(ud). >> vhci_shutdown_connection() e.g. waits for termination of tx/rx threads via kthread_stop_put(). >> event_handler() is already blocked by detach operation. >> How it can make situation worse to wait for creation of tx/rx threads in attach operation? >> > > event_lock shouldn't be held during event ops. usbip_event_add() > uses it to add events. Protecting shutdown path needs a different > approach. I can't understand what you are talking about. event_lock is defined as static DEFINE_SPINLOCK(event_lock); in drivers/usb/usbip/usbip_event.c and usbip_event_add() uses it like spin_lock_irqsave(&event_lock, flags); spin_unlock_irqrestore(&event_lock, flags); , but so what? I know event_lock spinlock cannot be taken when calling ud->eh_ops.shutdown(ud); ud->eh_ops.reset(ud); ud->eh_ops.unusable(ud); in event_handler() because e.g. vhci_shutdown_connection() can sleep. What my [PATCH v4 01/12] is suggesting is usbip_event_mutex which is defined as static DEFINE_MUTEX(usbip_event_mutex); in drivers/usb/usbip/usbip_event.c and held when calling ud->eh_ops.shutdown(ud); ud->eh_ops.reset(ud); ud->eh_ops.unusable(ud); in event_handler(). Since event_handler() is executed exclusively via singlethreaded workqueue, "event_handler() holds usbip_event_mutex" itself does not introduce a new lock dependency. My question is, how holding usbip_event_mutex can cause deadlock if usbip_sockfd_store()/attach_store()/detach_store() also hold usbip_event_mutex . kthread_create() is essentially several kmalloc(GFP_KERNEL) where event_handler() cannot interfere unless event_handler() serves as a memory reclaiming function. My question again. What functions might sleep and hold locks other than kthread_create() for tx/rx threads? Your answer to my question (if you identified such dependency) will go into patch shown bottom which replaces my [PATCH v4 01/12]-[PATCH v4 04/12] patches. > > In any case, do you have comments on this patch which doesn't even > touch vhci driver? I'm just replying to your [PATCH 4/6] because all your [PATCH 4/6]-[PATCH 6/6] patches have the same oversight. > > I understand you are identifying additional race condition that > the vhci patches in this series might not fix. That doesn't mean > that these patches aren't valid. > > Do you have any comments specific to the patches in this series? Your [PATCH 5/6] is still racy regarding rh_port_connect() versus rh_port_disconnect(). As soon as you call wake_up_process(), rh_port_disconnect() can be called before rh_port_connect() is called. Since you don't like serializing event_handler() and usbip_sockfd_store()/attach_store()/detach_store() using usbip_event_mutex, my patch shown below which uses attach_detach_lock mutex cannot close such race window. Ideally, wake_up_process() should be deferred to after releasing attach_detach_lock, but please answer to my question first. From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Date: Wed, 10 Mar 2021 18:31:54 +0900 syzbot is reporting a NULL pointer dereference at sock_sendmsg() [1], for lack of serialization between attach_store() and event_handler() causes vhci_shutdown_connection() to observe vdev->ud.tcp_tx == NULL while vdev->ud.tcp_socket != NULL. Please read the reference link for details of this race window. While usbip module exclusively runs event_handler(), usbip module has never thought the possibility that multiple userspace processes can concurrently call usbip_sockfd_store()/attach_store()/detach_store(). As a result, there is a TOCTTOU bug in these functions regarding ud->status value which can result in similar crashes like [1]. Simplest way would be to run all of event_handler()/usbip_sockfd_store()/attach_store()/detach_store() functions exclusively using a global mutex. But Shuah Khan does not want to share a global mutex between these functions, for ...[please fill in this part]... . Therefore, this patch introduces a per-submodule local mutex which closes race window within usbip_sockfd_store() and attach_store()/detach_store(). This local mutex cannot close race window between event_handler() and usbip_sockfd_store()/attach_store()/detach_store(), for calling wake_up_process() allows kernel thread to call usbip_event_add(VDEV_EVENT_DOWN) and event_handler() will start detach operation before this local mutex is released. The race window via usbip_event_add(VDEV_EVENT_DOWN) from kernel thread will be addressed by subsequent patches in this series, by splitting kthread_get_run() into kthread_create() and wake_up_process(), and deferring wake_up_process() to immediately before releasing this local mutex. [1] https://syzkaller.appspot.com/bug?extid=95ce4b142579611ef0a9 References: https://lkml.kernel.org/r/676d4518-0faa-9fab-15db-0db8d216d7fb@i-love.sakura.ne.jp --- drivers/usb/usbip/stub_dev.c | 16 ++++++++++++++-- drivers/usb/usbip/vhci_sysfs.c | 31 +++++++++++++++++++++++++++---- drivers/usb/usbip/vudc_sysfs.c | 16 ++++++++++++++-- 3 files changed, 55 insertions(+), 8 deletions(-) diff --git a/drivers/usb/usbip/stub_dev.c b/drivers/usb/usbip/stub_dev.c index 2305d425e6c9..66c8f2385f3a 100644 --- a/drivers/usb/usbip/stub_dev.c +++ b/drivers/usb/usbip/stub_dev.c @@ -39,8 +39,8 @@ static DEVICE_ATTR_RO(usbip_status); * is used to transfer usbip requests by kernel threads. -1 is a magic number * by which usbip connection is finished. */ -static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t __usbip_sockfd_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct stub_device *sdev = dev_get_drvdata(dev); int sockfd = 0; @@ -104,6 +104,18 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a spin_unlock_irq(&sdev->ud.lock); return -EINVAL; } +static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + static DEFINE_MUTEX(attach_detach_lock); + ssize_t ret = mutex_lock_killable(&attach_detach_lock); + + if (ret) + return ret; + ret = __usbip_sockfd_store(dev, attr, buf, count); + mutex_unlock(&attach_detach_lock); + return ret; +} static DEVICE_ATTR_WO(usbip_sockfd); static struct attribute *usbip_attrs[] = { diff --git a/drivers/usb/usbip/vhci_sysfs.c b/drivers/usb/usbip/vhci_sysfs.c index 96e5371dc335..777aba9b9115 100644 --- a/drivers/usb/usbip/vhci_sysfs.c +++ b/drivers/usb/usbip/vhci_sysfs.c @@ -17,6 +17,7 @@ #include "vhci.h" /* TODO: refine locking ?*/ +static DEFINE_MUTEX(attach_detach_lock); /* * output example: @@ -225,8 +226,8 @@ static int valid_port(__u32 *pdev_nr, __u32 *rhport) return 1; } -static ssize_t detach_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t __detach_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { __u32 port = 0, pdev_nr = 0, rhport = 0; struct usb_hcd *hcd; @@ -263,6 +264,17 @@ static ssize_t detach_store(struct device *dev, struct device_attribute *attr, return count; } +static ssize_t detach_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + ssize_t ret = mutex_lock_killable(&attach_detach_lock); + + if (ret) + return ret; + ret = __detach_store(dev, attr, buf, count); + mutex_unlock(&attach_detach_lock); + return ret; +} static DEVICE_ATTR_WO(detach); static int valid_args(__u32 *pdev_nr, __u32 *rhport, @@ -300,8 +312,8 @@ static int valid_args(__u32 *pdev_nr, __u32 *rhport, * * write() returns 0 on success, else negative errno. */ -static ssize_t attach_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t __attach_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct socket *socket; int sockfd = 0; @@ -396,6 +408,17 @@ static ssize_t attach_store(struct device *dev, struct device_attribute *attr, return count; } +static ssize_t attach_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + ssize_t ret = mutex_lock_killable(&attach_detach_lock); + + if (ret) + return ret; + ret = __attach_store(dev, attr, buf, count); + mutex_unlock(&attach_detach_lock); + return ret; +} static DEVICE_ATTR_WO(attach); #define MAX_STATUS_NAME 16 diff --git a/drivers/usb/usbip/vudc_sysfs.c b/drivers/usb/usbip/vudc_sysfs.c index 100f680c572a..b14876dd2c0c 100644 --- a/drivers/usb/usbip/vudc_sysfs.c +++ b/drivers/usb/usbip/vudc_sysfs.c @@ -90,8 +90,8 @@ static ssize_t dev_desc_read(struct file *file, struct kobject *kobj, } static BIN_ATTR_RO(dev_desc, sizeof(struct usb_device_descriptor)); -static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *attr, - const char *in, size_t count) +static ssize_t __usbip_sockfd_store(struct device *dev, struct device_attribute *attr, + const char *in, size_t count) { struct vudc *udc = (struct vudc *) dev_get_drvdata(dev); int rv; @@ -184,6 +184,18 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a return ret; } +static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *attr, + const char *in, size_t count) +{ + static DEFINE_MUTEX(attach_detach_lock); + ssize_t ret = mutex_lock_killable(&attach_detach_lock); + + if (ret) + return ret; + ret = __usbip_sockfd_store(dev, attr, in, count); + mutex_unlock(&attach_detach_lock); + return ret; +} static DEVICE_ATTR_WO(usbip_sockfd); static ssize_t usbip_status_show(struct device *dev, -- 2.18.4 ^ permalink raw reply related [flat|nested] 34+ messages in thread
* Re: [PATCH 4/6] usbip: fix stub_dev usbip_sockfd_store() races leading to gpf 2021-03-08 16:27 ` Shuah Khan 2021-03-09 11:04 ` Tetsuo Handa @ 2021-03-09 15:22 ` Shuah Khan 1 sibling, 0 replies; 34+ messages in thread From: Shuah Khan @ 2021-03-09 15:22 UTC (permalink / raw) To: Tetsuo Handa, shuah, valentina.manea.m, gregkh Cc: linux-usb, linux-kernel, Shuah Khan On 3/8/21 9:27 AM, Shuah Khan wrote: > On 3/8/21 3:10 AM, Tetsuo Handa wrote: >> On 2021/03/08 16:35, Tetsuo Handa wrote: >>> On 2021/03/08 12:53, Shuah Khan wrote: >>>> Fix the above problems: >>>> - Stop using kthread_get_run() macro to create/start threads. >>>> - Create threads and get task struct reference. >>>> - Add kthread_create() failure handling and bail out. >>>> - Hold usbip_device lock to update local and shared states after >>>> creating rx and tx threads. >>>> - Update usbip_device status to SDEV_ST_USED. >>>> - Update usbip_device tcp_socket, sockfd, tcp_rx, and tcp_tx >>>> - Start threads after usbip_device (tcp_socket, sockfd, tcp_rx, tcp_tx, >>>> and status) is complete. >>> >>> No, the whole usbip_sockfd_store() etc. should be serialized using a >>> mutex, >>> for two different threads can open same file and write the same >>> content at >>> the same moment. This results in seeing SDEV_ST_AVAILABLE and >>> creating two >>> threads and overwiting global variables and setting SDEV_ST_USED and >>> starting >>> two threads by each of two thread, which will later fail to call >>> kthread_stop() >>> on one of two thread because global variables are overwritten. >>> >>> kthread_crate() (which involves GFP_KERNEL allocation) can take long >>> time >>> enough to hit >>> >>> usbip_sockfd_store() must perform >>> >>> if (sdev->ud.status != SDEV_ST_AVAILABLE) { >> >> Oops. This is >> >> if (sdev->ud.status == SDEV_ST_AVAILABLE) { >> >> of course. >> >>> /* misc assignments for attach operation */ >>> sdev->ud.status = SDEV_ST_USED; >>> } >>> >>> under a lock, or multiple ud->tcp_{tx,rx} are created (which will >>> later >>> cause a crash like [1]) and refcount on ud->tcp_socket is leaked when >>> usbip_sockfd_store() is concurrently called. >>> >>> problem. That's why my patch introduced usbip_event_mutex lock. >>> >> >> And I think that same serialization is required between >> "rh_port_connect() from attach_store()" and >> "rh_port_disconnect() from vhci_shutdown_connection() via >> usbip_event_add(&vdev->ud, VDEV_EVENT_DOWN) >> from vhci_port_disconnect() from detach_store()", for both >> vhci_rx_pdu() from vhci_rx_loop() and >> vhci_port_disconnect() from detach_store() can queue VDEV_EVENT_DOWN >> event which can be processed >> without waiting for attach_store() to complete. >> > > Yes. We might need synchronization between events, threads, and shutdown > in usbip_host side and in connection polling and threads in vhci. > > I am also looking at the shutdown sequences closely as well since the > local state is referenced without usbip_device lock in these paths. > > I am approaching these problems as peeling the onion an expression so > we can limit the changes and take a spot fix approach. We have the > goal to address these crashes and not introduce regressions. > > I don't seem to be able to reproduce these problems consistently in my > env. with the reproducer. I couldn't reproduce them in normal case at > all. Hence, the this cautious approach that reduces the chance of > regressions and if we see regressions, they can fixed easily. > > https://syzkaller.appspot.com/text?tag=ReproC&x=14801034d00000 > > If this patch series fixes the problems you are seeing, I would like > get these fixes in and address the other two potential race conditions > in another round of patches. I also want to soak these in the next > for a few weeks. > > Please let me know if these patches fix the problems you are seeing in > your env. > Can you verify these patches in your environment and see if you are seeing any problems? I want to first see where we are with these fixes. thanks, -- Shuah ^ permalink raw reply [flat|nested] 34+ messages in thread
* [PATCH 5/6] usbip: fix vhci_hcd attach_store() races leading to gpf 2021-03-08 3:53 [PATCH 0/6] usbip fixes to crashes found by syzbot Shuah Khan ` (3 preceding siblings ...) 2021-03-08 3:53 ` [PATCH 4/6] usbip: fix stub_dev usbip_sockfd_store() races leading to gpf Shuah Khan @ 2021-03-08 3:53 ` Shuah Khan 2021-03-08 3:53 ` [PATCH 6/6] usbip: fix vudc usbip_sockfd_store " Shuah Khan 2021-03-10 18:33 ` [PATCH 0/6] usbip fixes to crashes found by syzbot Greg KH 6 siblings, 0 replies; 34+ messages in thread From: Shuah Khan @ 2021-03-08 3:53 UTC (permalink / raw) To: shuah, valentina.manea.m, gregkh Cc: Shuah Khan, linux-usb, linux-kernel, penguin-kernel, syzbot, syzbot, syzbot, stable attach_store() is invoked when user requests import (attach) a device from usbip host. Attach and detach are governed by local state and shared state - Shared state (usbip device status) - Device status is used to manage the attach and detach operations on import-able devices. - Local state (tcp_socket, rx and tx thread task_struct ptrs) A valid tcp_socket controls rx and tx thread operations while the device is in exported state. - Device has to be in the right state to be attached and detached. Attach sequence includes validating the socket and creating receive (rx) and transmit (tx) threads to talk to the host to get access to the imported device. rx and tx threads depends on local and shared state to be correct and in sync. Detach sequence shuts the socket down and stops the rx and tx threads. Detach sequence relies on local and shared states to be in sync. There are races in updating the local and shared status in the current attach sequence resulting in crashes. These stem from starting rx and tx threads before local and global state is updated correctly to be in sync. 1. Doesn't handle kthread_create() error and saves invalid ptr in local state that drives rx and tx threads. 2. Updates tcp_socket and sockfd, starts stub_rx and stub_tx threads before updating usbip_device status to VDEV_ST_NOTASSIGNED. This opens up a race condition between the threads, port connect, and detach handling. Fix the above problems: - Stop using kthread_get_run() macro to create/start threads. - Create threads and get task struct reference. - Add kthread_create() failure handling and bail out. - Hold vhci and usbip_device locks to update local and shared states after creating rx and tx threads. - Update usbip_device status to VDEV_ST_NOTASSIGNED. - Update usbip_device tcp_socket, sockfd, tcp_rx, and tcp_tx - Start threads after usbip_device (tcp_socket, sockfd, tcp_rx, tcp_tx, and status) is complete. Credit goes to syzbot and Tetsuo Handa for finding and root-causing the kthread_get_run() improper error handling problem and others. This is hard problem to find and debug since the races aren't seen in a normal case. Fuzzing forces the race window to be small enough for the kthread_get_run() error path bug and starting threads before updating the local and shared state bug in the attach sequence. - Update usbip_device tcp_rx and tcp_tx pointers holding vhci and usbip_device locks. Tested with syzbot reproducer: - https://syzkaller.appspot.com/text?tag=ReproC&x=14801034d00000 Reported-by: syzbot <syzbot+a93fba6d384346a761e3@syzkaller.appspotmail.com> Reported-by: syzbot <syzbot+bf1a360e305ee719e364@syzkaller.appspotmail.com> Reported-by: syzbot <syzbot+95ce4b142579611ef0a9@syzkaller.appspotmail.com> Reported-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Fixes: 9720b4bc76a83807 ("staging/usbip: convert to kthread") Cc: stable@vger.kernel.org Signed-off-by: Shuah Khan <skhan@linuxfoundation.org> --- drivers/usb/usbip/vhci_sysfs.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/drivers/usb/usbip/vhci_sysfs.c b/drivers/usb/usbip/vhci_sysfs.c index 1e1ae9bd06ab..c4b4256e5dad 100644 --- a/drivers/usb/usbip/vhci_sysfs.c +++ b/drivers/usb/usbip/vhci_sysfs.c @@ -312,6 +312,8 @@ static ssize_t attach_store(struct device *dev, struct device_attribute *attr, struct vhci *vhci; int err; unsigned long flags; + struct task_struct *tcp_rx = NULL; + struct task_struct *tcp_tx = NULL; /* * @rhport: port number of vhci_hcd @@ -360,9 +362,24 @@ static ssize_t attach_store(struct device *dev, struct device_attribute *attr, return -EINVAL; } - /* now need lock until setting vdev status as used */ + /* create threads before locking */ + tcp_rx = kthread_create(vhci_rx_loop, &vdev->ud, "vhci_rx"); + if (IS_ERR(tcp_rx)) { + sockfd_put(socket); + return -EINVAL; + } + tcp_tx = kthread_create(vhci_tx_loop, &vdev->ud, "vhci_tx"); + if (IS_ERR(tcp_tx)) { + kthread_stop(tcp_rx); + sockfd_put(socket); + return -EINVAL; + } + + /* get task structs now */ + get_task_struct(tcp_rx); + get_task_struct(tcp_tx); - /* begin a lock */ + /* now begin lock until setting vdev status set */ spin_lock_irqsave(&vhci->lock, flags); spin_lock(&vdev->ud.lock); @@ -372,6 +389,8 @@ static ssize_t attach_store(struct device *dev, struct device_attribute *attr, spin_unlock_irqrestore(&vhci->lock, flags); sockfd_put(socket); + kthread_stop_put(tcp_rx); + kthread_stop_put(tcp_tx); dev_err(dev, "port %d already used\n", rhport); /* @@ -390,6 +409,8 @@ static ssize_t attach_store(struct device *dev, struct device_attribute *attr, vdev->speed = speed; vdev->ud.sockfd = sockfd; vdev->ud.tcp_socket = socket; + vdev->ud.tcp_rx = tcp_rx; + vdev->ud.tcp_tx = tcp_tx; vdev->ud.status = VDEV_ST_NOTASSIGNED; usbip_kcov_handle_init(&vdev->ud); @@ -397,8 +418,8 @@ static ssize_t attach_store(struct device *dev, struct device_attribute *attr, spin_unlock_irqrestore(&vhci->lock, flags); /* end the lock */ - vdev->ud.tcp_rx = kthread_get_run(vhci_rx_loop, &vdev->ud, "vhci_rx"); - vdev->ud.tcp_tx = kthread_get_run(vhci_tx_loop, &vdev->ud, "vhci_tx"); + wake_up_process(vdev->ud.tcp_rx); + wake_up_process(vdev->ud.tcp_tx); rh_port_connect(vdev, speed); -- 2.27.0 ^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 6/6] usbip: fix vudc usbip_sockfd_store races leading to gpf 2021-03-08 3:53 [PATCH 0/6] usbip fixes to crashes found by syzbot Shuah Khan ` (4 preceding siblings ...) 2021-03-08 3:53 ` [PATCH 5/6] usbip: fix vhci_hcd attach_store() " Shuah Khan @ 2021-03-08 3:53 ` Shuah Khan 2021-03-10 18:33 ` [PATCH 0/6] usbip fixes to crashes found by syzbot Greg KH 6 siblings, 0 replies; 34+ messages in thread From: Shuah Khan @ 2021-03-08 3:53 UTC (permalink / raw) To: shuah, valentina.manea.m, gregkh Cc: Shuah Khan, linux-usb, linux-kernel, penguin-kernel, syzbot, syzbot, syzbot, stable usbip_sockfd_store() is invoked when user requests attach (import) detach (unimport) usb gadget device from usbip host. vhci_hcd sends import request and usbip_sockfd_store() exports the device if it is free for export. Export and unexport are governed by local state and shared state - Shared state (usbip device status, sockfd) - sockfd and Device status are used to determine if stub should be brought up or shut down. Device status is shared between host and client. - Local state (tcp_socket, rx and tx thread task_struct ptrs) A valid tcp_socket controls rx and tx thread operations while the device is in exported state. - While the device is exported, device status is marked used and socket, sockfd, and thread pointers are valid. Export sequence (stub-up) includes validating the socket and creating receive (rx) and transmit (tx) threads to talk to the client to provide access to the exported device. rx and tx threads depends on local and shared state to be correct and in sync. Unexport (stub-down) sequence shuts the socket down and stops the rx and tx threads. Stub-down sequence relies on local and shared states to be in sync. There are races in updating the local and shared status in the current stub-up sequence resulting in crashes. These stem from starting rx and tx threads before local and global state is updated correctly to be in sync. 1. Doesn't handle kthread_create() error and saves invalid ptr in local state that drives rx and tx threads. 2. Updates tcp_socket and sockfd, starts stub_rx and stub_tx threads before updating usbip_device status to SDEV_ST_USED. This opens up a race condition between the threads and usbip_sockfd_store() stub up and down handling. Fix the above problems: - Stop using kthread_get_run() macro to create/start threads. - Create threads and get task struct reference. - Add kthread_create() failure handling and bail out. - Hold usbip_device lock to update local and shared states after creating rx and tx threads. - Update usbip_device status to SDEV_ST_USED. - Update usbip_device tcp_socket, sockfd, tcp_rx, and tcp_tx - Start threads after usbip_device (tcp_socket, sockfd, tcp_rx, tcp_tx, and status) is complete. Credit goes to syzbot and Tetsuo Handa for finding and root-causing the kthread_get_run() improper error handling problem and others. This is a hard problem to find and debug since the races aren't seen in a normal case. Fuzzing forces the race window to be small enough for the kthread_get_run() error path bug and starting threads before updating the local and shared state bug in the stub-up sequence. Reported-by: syzbot <syzbot+a93fba6d384346a761e3@syzkaller.appspotmail.com> Reported-by: syzbot <syzbot+bf1a360e305ee719e364@syzkaller.appspotmail.com> Reported-by: syzbot <syzbot+95ce4b142579611ef0a9@syzkaller.appspotmail.com> Reported-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Fixes: 9720b4bc76a83807 ("staging/usbip: convert to kthread") Cc: stable@vger.kernel.org Signed-off-by: Shuah Khan <skhan@linuxfoundation.org> --- drivers/usb/usbip/vudc_sysfs.c | 42 +++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/drivers/usb/usbip/vudc_sysfs.c b/drivers/usb/usbip/vudc_sysfs.c index 83a0c59a3de8..a3ec39fc6177 100644 --- a/drivers/usb/usbip/vudc_sysfs.c +++ b/drivers/usb/usbip/vudc_sysfs.c @@ -90,8 +90,9 @@ static ssize_t dev_desc_read(struct file *file, struct kobject *kobj, } static BIN_ATTR_RO(dev_desc, sizeof(struct usb_device_descriptor)); -static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *attr, - const char *in, size_t count) +static ssize_t usbip_sockfd_store(struct device *dev, + struct device_attribute *attr, + const char *in, size_t count) { struct vudc *udc = (struct vudc *) dev_get_drvdata(dev); int rv; @@ -100,6 +101,8 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a struct socket *socket; unsigned long flags; int ret; + struct task_struct *tcp_rx = NULL; + struct task_struct *tcp_tx = NULL; rv = kstrtoint(in, 0, &sockfd); if (rv != 0) @@ -145,24 +148,47 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a goto sock_err; } - udc->ud.tcp_socket = socket; - + /* unlock and create threads and get tasks */ 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"); + tcp_rx = kthread_create(&v_rx_loop, &udc->ud, "vudc_rx"); + if (IS_ERR(tcp_rx)) { + sockfd_put(socket); + return -EINVAL; + } + tcp_tx = kthread_create(&v_tx_loop, &udc->ud, "vudc_tx"); + if (IS_ERR(tcp_tx)) { + kthread_stop(tcp_rx); + sockfd_put(socket); + return -EINVAL; + } + + /* get task structs now */ + get_task_struct(tcp_rx); + get_task_struct(tcp_tx); + /* lock and update udc->ud state */ spin_lock_irqsave(&udc->lock, flags); spin_lock_irq(&udc->ud.lock); + + udc->ud.tcp_socket = socket; + udc->ud.tcp_rx = tcp_rx; + udc->ud.tcp_rx = tcp_tx; udc->ud.status = SDEV_ST_USED; + spin_unlock_irq(&udc->ud.lock); ktime_get_ts64(&udc->start_time); v_start_timer(udc); udc->connected = 1; + + spin_unlock_irqrestore(&udc->lock, flags); + + wake_up_process(udc->ud.tcp_rx); + wake_up_process(udc->ud.tcp_tx); + return count; + } else { if (!udc->connected) { dev_err(dev, "Device not connected"); -- 2.27.0 ^ permalink raw reply related [flat|nested] 34+ messages in thread
* Re: [PATCH 0/6] usbip fixes to crashes found by syzbot 2021-03-08 3:53 [PATCH 0/6] usbip fixes to crashes found by syzbot Shuah Khan ` (5 preceding siblings ...) 2021-03-08 3:53 ` [PATCH 6/6] usbip: fix vudc usbip_sockfd_store " Shuah Khan @ 2021-03-10 18:33 ` Greg KH 2021-03-11 12:34 ` Tetsuo Handa 6 siblings, 1 reply; 34+ messages in thread From: Greg KH @ 2021-03-10 18:33 UTC (permalink / raw) To: Shuah Khan Cc: shuah, valentina.manea.m, linux-usb, linux-kernel, penguin-kernel On Sun, Mar 07, 2021 at 08:53:25PM -0700, Shuah Khan wrote: > This patch series fixes the following problems founds in syzbot > fuzzing. Thanks for these, all now queued up. greg k-h ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 0/6] usbip fixes to crashes found by syzbot 2021-03-10 18:33 ` [PATCH 0/6] usbip fixes to crashes found by syzbot Greg KH @ 2021-03-11 12:34 ` Tetsuo Handa 2021-03-11 12:57 ` Greg KH 0 siblings, 1 reply; 34+ messages in thread From: Tetsuo Handa @ 2021-03-11 12:34 UTC (permalink / raw) To: Greg KH, Shuah Khan; +Cc: shuah, valentina.manea.m, linux-usb, linux-kernel On 2021/03/11 3:33, Greg KH wrote: > On Sun, Mar 07, 2021 at 08:53:25PM -0700, Shuah Khan wrote: >> This patch series fixes the following problems founds in syzbot >> fuzzing. > > Thanks for these, all now queued up. I send SIGSTOP to [PATCH 4/6] usbip: fix stub_dev usbip_sockfd_store() races leading to gpf [PATCH 5/6] usbip: fix vhci_hcd attach_store() races leading to gpf [PATCH 6/6] usbip: fix vudc usbip_sockfd_store races leading to gpf because these patches merely converted NULL pointer dererefence bug to use-after-free bug by breaking kthread_get_run() into kthread_create()/get_task_struct()/wake_up_process(). ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 0/6] usbip fixes to crashes found by syzbot 2021-03-11 12:34 ` Tetsuo Handa @ 2021-03-11 12:57 ` Greg KH 2021-03-11 13:24 ` Tetsuo Handa 0 siblings, 1 reply; 34+ messages in thread From: Greg KH @ 2021-03-11 12:57 UTC (permalink / raw) To: Tetsuo Handa Cc: Shuah Khan, shuah, valentina.manea.m, linux-usb, linux-kernel On Thu, Mar 11, 2021 at 09:34:38PM +0900, Tetsuo Handa wrote: > On 2021/03/11 3:33, Greg KH wrote: > > On Sun, Mar 07, 2021 at 08:53:25PM -0700, Shuah Khan wrote: > >> This patch series fixes the following problems founds in syzbot > >> fuzzing. > > > > Thanks for these, all now queued up. > > I send SIGSTOP to > > [PATCH 4/6] usbip: fix stub_dev usbip_sockfd_store() races leading to gpf > [PATCH 5/6] usbip: fix vhci_hcd attach_store() races leading to gpf > [PATCH 6/6] usbip: fix vudc usbip_sockfd_store races leading to gpf > > because these patches merely converted NULL pointer dererefence bug to use-after-free bug > by breaking kthread_get_run() into kthread_create()/get_task_struct()/wake_up_process(). I'll take follow-on patches to fix that other issue, if it's proven to be valid. It's nice to fix up NULL dereference issues as soon as possible :) thanks, greg k-h ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 0/6] usbip fixes to crashes found by syzbot 2021-03-11 12:57 ` Greg KH @ 2021-03-11 13:24 ` Tetsuo Handa 2021-03-12 5:44 ` Tetsuo Handa 0 siblings, 1 reply; 34+ messages in thread From: Tetsuo Handa @ 2021-03-11 13:24 UTC (permalink / raw) To: Greg KH; +Cc: Shuah Khan, shuah, valentina.manea.m, linux-usb, linux-kernel On 2021/03/11 21:57, Greg KH wrote: > On Thu, Mar 11, 2021 at 09:34:38PM +0900, Tetsuo Handa wrote: >> On 2021/03/11 3:33, Greg KH wrote: >>> On Sun, Mar 07, 2021 at 08:53:25PM -0700, Shuah Khan wrote: >>>> This patch series fixes the following problems founds in syzbot >>>> fuzzing. >>> >>> Thanks for these, all now queued up. >> >> I send SIGSTOP to >> >> [PATCH 4/6] usbip: fix stub_dev usbip_sockfd_store() races leading to gpf >> [PATCH 5/6] usbip: fix vhci_hcd attach_store() races leading to gpf >> [PATCH 6/6] usbip: fix vudc usbip_sockfd_store races leading to gpf >> >> because these patches merely converted NULL pointer dererefence bug to use-after-free bug >> by breaking kthread_get_run() into kthread_create()/get_task_struct()/wake_up_process(). > > I'll take follow-on patches to fix that other issue, if it's proven to > be valid. It's nice to fix up NULL dereference issues as soon as > possible :) Not an "other issue". Shuah's [PATCH 4,5,6/6] is failing to fix NULL pointer dereference issue. These patches simply replaces NULL pointer dereference issue (caused by preemption) with use after free issue (caused by exactly same preemption) issue. Shuah has to understand the consequence of calling wake_up_process() on rx thread in order to fix this NULL pointer dereference issue. The only fix we can safely apply now is https://lkml.kernel.org/r/20210205135707.4574-1-penguin-kernel@I-love.SAKURA.ne.jp . Since I and Shuah agreed that we will remove kthread_get_run(), it is nice to fix up frequently happening -EINTR pointer dereference issue as soon as possible. ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 0/6] usbip fixes to crashes found by syzbot 2021-03-11 13:24 ` Tetsuo Handa @ 2021-03-12 5:44 ` Tetsuo Handa 2021-03-13 0:48 ` Tetsuo Handa 0 siblings, 1 reply; 34+ messages in thread From: Tetsuo Handa @ 2021-03-12 5:44 UTC (permalink / raw) To: Shuah Khan, shuah; +Cc: valentina.manea.m, linux-usb, linux-kernel, Greg KH I cloned git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux.git as you are testing changes there. > commit 09e4522c87ff54c655c09f318a68b012eda8eb01 (HEAD -> usbip_test, origin/usbip_test) > Author: Shuah Khan <skhan@linuxfoundation.org> > Date: Thu Mar 11 11:18:25 2021 -0700 > > usbip: fix vhci races in connection tear down > > - Change vhci_device_reset() to reset tcp_socket and sockfd. > if !in_disconnect How it can happen? vhci_device_reset() can be called only after vhci_shutdown_connection() completed, and vhci_shutdown_connection() from subsequent requests cannot be called until vhci_device_reset() completes. I consider it as a dead code which should be removed by my "[PATCH v4 05/12] usb: usbip: don't reset tcp_socket at vhci_device_reset()". And what you are missing in your [PATCH 4,5,6/6] is diff --git a/drivers/usb/usbip/vhci_sysfs.c b/drivers/usb/usbip/vhci_sysfs.c index c4457026d5ad..3c64bd06ab53 100644 --- a/drivers/usb/usbip/vhci_sysfs.c +++ b/drivers/usb/usbip/vhci_sysfs.c @@ -423,6 +423,7 @@ static ssize_t attach_store(struct device *dev, struct device_attribute *attr, /* end the lock */ wake_up_process(vdev->ud.tcp_rx); + schedule_timeout_uninterruptible(HZ); // Consider being preempted here. wake_up_process(vdev->ud.tcp_tx); rh_port_connect(vdev, speed); . wake_up_process(tcp_tx) can call vhci_shutdown_connection() before wake_up_process(tcp_tx) is called. Since vhci_shutdown_connection() destroys tcp_tx thread and releases tcp_tx memory via kthread_stop_put(tcp_tx), wake_up_process(tcp_tx) will access already freed memory. Your patch converted "NULL pointer dereference caused by failing to call kthread_stop_put(tcp_tx)" into "use after free caused by succeeding to call kthread_stop_put(tcp_tx)". ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 0/6] usbip fixes to crashes found by syzbot 2021-03-12 5:44 ` Tetsuo Handa @ 2021-03-13 0:48 ` Tetsuo Handa 2021-03-14 11:38 ` Tetsuo Handa 0 siblings, 1 reply; 34+ messages in thread From: Tetsuo Handa @ 2021-03-13 0:48 UTC (permalink / raw) To: Shuah Khan, shuah; +Cc: valentina.manea.m, linux-usb, linux-kernel, Greg KH On 2021/03/12 14:44, Tetsuo Handa wrote: > And what you are missing in your [PATCH 4,5,6/6] is > > diff --git a/drivers/usb/usbip/vhci_sysfs.c b/drivers/usb/usbip/vhci_sysfs.c > index c4457026d5ad..3c64bd06ab53 100644 > --- a/drivers/usb/usbip/vhci_sysfs.c > +++ b/drivers/usb/usbip/vhci_sysfs.c > @@ -423,6 +423,7 @@ static ssize_t attach_store(struct device *dev, struct device_attribute *attr, > /* end the lock */ > > wake_up_process(vdev->ud.tcp_rx); > + schedule_timeout_uninterruptible(HZ); // Consider being preempted here. > wake_up_process(vdev->ud.tcp_tx); > > rh_port_connect(vdev, speed); > > . wake_up_process(tcp_tx) can call vhci_shutdown_connection() before wake_up_process(tcp_tx) is called. wake_up_process(tcp_rx) can call vhci_shutdown_connection() before wake_up_process(tcp_tx) is called. > Since vhci_shutdown_connection() destroys tcp_tx thread and releases tcp_tx memory via kthread_stop_put(tcp_tx), > wake_up_process(tcp_tx) will access already freed memory. Your patch converted "NULL pointer dereference caused by > failing to call kthread_stop_put(tcp_tx)" into "use after free caused by succeeding to call kthread_stop_put(tcp_tx)". > And note that diff --git a/drivers/usb/usbip/vhci_sysfs.c b/drivers/usb/usbip/vhci_sysfs.c index c4457026d5ad..0e1a81d4632c 100644 --- a/drivers/usb/usbip/vhci_sysfs.c +++ b/drivers/usb/usbip/vhci_sysfs.c @@ -422,11 +422,11 @@ static ssize_t attach_store(struct device *dev, struct device_attribute *attr, spin_unlock_irqrestore(&vhci->lock, flags); /* end the lock */ - wake_up_process(vdev->ud.tcp_rx); - wake_up_process(vdev->ud.tcp_tx); - rh_port_connect(vdev, speed); + wake_up_process(vdev->ud.tcp_tx); + wake_up_process(vdev->ud.tcp_rx); + return count; } static DEVICE_ATTR_WO(attach); is as well not sufficient, for you are still missing diff --git a/drivers/usb/usbip/vhci_sysfs.c b/drivers/usb/usbip/vhci_sysfs.c index c4457026d5ad..c958f89a9196 100644 --- a/drivers/usb/usbip/vhci_sysfs.c +++ b/drivers/usb/usbip/vhci_sysfs.c @@ -422,11 +422,13 @@ static ssize_t attach_store(struct device *dev, struct device_attribute *attr, spin_unlock_irqrestore(&vhci->lock, flags); /* end the lock */ - wake_up_process(vdev->ud.tcp_rx); - wake_up_process(vdev->ud.tcp_tx); + schedule_timeout_uninterruptible(HZ); // Consider being preempted here. rh_port_connect(vdev, speed); + wake_up_process(vdev->ud.tcp_tx); + wake_up_process(vdev->ud.tcp_rx); + return count; } static DEVICE_ATTR_WO(attach); because vhci_port_disconnect() from detach_store() can call usbip_event_add(&vdev->ud, VDEV_EVENT_DOWN) (same use after free bug regarding tcp_tx and tcp_rx) as soon as all shared states are set up and spinlocks are released. What you had better consider first is how to protect event_handler()/usbip_sockfd_store()/attach_store()/detach_store() functions from concurrent calls. Please respond to https://lkml.kernel.org/r/3dab66dc-2981-bc88-a370-4b3178dfd390@i-love.sakura.ne.jp before you try to make further changes. ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 0/6] usbip fixes to crashes found by syzbot 2021-03-13 0:48 ` Tetsuo Handa @ 2021-03-14 11:38 ` Tetsuo Handa 2021-03-17 6:21 ` Tetsuo Handa 0 siblings, 1 reply; 34+ messages in thread From: Tetsuo Handa @ 2021-03-14 11:38 UTC (permalink / raw) To: Shuah Khan, shuah, Greg KH; +Cc: valentina.manea.m, linux-usb, linux-kernel On 2021/03/13 9:48, Tetsuo Handa wrote: > On 2021/03/12 14:44, Tetsuo Handa wrote: >> And what you are missing in your [PATCH 4,5,6/6] is >> >> diff --git a/drivers/usb/usbip/vhci_sysfs.c b/drivers/usb/usbip/vhci_sysfs.c >> index c4457026d5ad..3c64bd06ab53 100644 >> --- a/drivers/usb/usbip/vhci_sysfs.c >> +++ b/drivers/usb/usbip/vhci_sysfs.c >> @@ -423,6 +423,7 @@ static ssize_t attach_store(struct device *dev, struct device_attribute *attr, >> /* end the lock */ >> >> wake_up_process(vdev->ud.tcp_rx); >> + schedule_timeout_uninterruptible(HZ); // Consider being preempted here. >> wake_up_process(vdev->ud.tcp_tx); >> >> rh_port_connect(vdev, speed); >> >> . wake_up_process(tcp_tx) can call vhci_shutdown_connection() before wake_up_process(tcp_tx) is called. > > wake_up_process(tcp_rx) can call vhci_shutdown_connection() before wake_up_process(tcp_tx) is called. > >> Since vhci_shutdown_connection() destroys tcp_tx thread and releases tcp_tx memory via kthread_stop_put(tcp_tx), >> wake_up_process(tcp_tx) will access already freed memory. Your patch converted "NULL pointer dereference caused by >> failing to call kthread_stop_put(tcp_tx)" into "use after free caused by succeeding to call kthread_stop_put(tcp_tx)". >> > > And note that > > diff --git a/drivers/usb/usbip/vhci_sysfs.c b/drivers/usb/usbip/vhci_sysfs.c > index c4457026d5ad..0e1a81d4632c 100644 > --- a/drivers/usb/usbip/vhci_sysfs.c > +++ b/drivers/usb/usbip/vhci_sysfs.c > @@ -422,11 +422,11 @@ static ssize_t attach_store(struct device *dev, struct device_attribute *attr, > spin_unlock_irqrestore(&vhci->lock, flags); > /* end the lock */ > > - wake_up_process(vdev->ud.tcp_rx); > - wake_up_process(vdev->ud.tcp_tx); > - > rh_port_connect(vdev, speed); > > + wake_up_process(vdev->ud.tcp_tx); > + wake_up_process(vdev->ud.tcp_rx); > + > return count; > } > static DEVICE_ATTR_WO(attach); > > is as well not sufficient, for you are still missing Well, since tx thread can as well call usbip_event_add(USBIP_EH_SHUTDOWN), reversing the order of wake_up_process(tcp_tx) and wake_up_process(tcp_rx) will not help. > > diff --git a/drivers/usb/usbip/vhci_sysfs.c b/drivers/usb/usbip/vhci_sysfs.c > index c4457026d5ad..c958f89a9196 100644 > --- a/drivers/usb/usbip/vhci_sysfs.c > +++ b/drivers/usb/usbip/vhci_sysfs.c > @@ -422,11 +422,13 @@ static ssize_t attach_store(struct device *dev, struct device_attribute *attr, > spin_unlock_irqrestore(&vhci->lock, flags); > /* end the lock */ > > - wake_up_process(vdev->ud.tcp_rx); > - wake_up_process(vdev->ud.tcp_tx); > + schedule_timeout_uninterruptible(HZ); // Consider being preempted here. > > rh_port_connect(vdev, speed); > > + wake_up_process(vdev->ud.tcp_tx); > + wake_up_process(vdev->ud.tcp_rx); > + > return count; > } > static DEVICE_ATTR_WO(attach); > > because vhci_port_disconnect() from detach_store() can call usbip_event_add(&vdev->ud, VDEV_EVENT_DOWN) > (same use after free bug regarding tcp_tx and tcp_rx) as soon as all shared states are set up and > spinlocks are released. > > What you had better consider first is how to protect event_handler()/usbip_sockfd_store()/attach_store()/detach_store() functions > from concurrent calls. Please respond to https://lkml.kernel.org/r/3dab66dc-2981-bc88-a370-4b3178dfd390@i-love.sakura.ne.jp > before you try to make further changes. > After all, I believe that there is no choice but introduce a mutex for serialization. Greg, please pick up https://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux.git/commit/?h=usbip_test&id=f345de0d2e51a20a2a1c30fc22fa1527670d2095 and below patch. From e0579aa776e4a3568c06f767c193d2204b64679d Mon Sep 17 00:00:00 2001 From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Date: Sun, 14 Mar 2021 20:24:16 +0900 Subject: [PATCH v5] usb: usbip: serialize attach/detach operations The root problem syzbot has found [1] is that usbip module is not using serialization between attach/detach operations and event_handler(). This results in the following race windows. (1) two userspace processes can perform attach operation on the same device by writing the same content to the same attach interface file (2) one userspace process can perform detach operation on a device by writing to detach interface file while the other userspace process is performing attach operation on that device by writing to attach interface file (3) event_handler() kernel workqueue thread can perform detach operation on a device while some userspace process is still performing attach operation on that device What syzbot is reporting is (3), and what commits 46613c9dfa964c0c, 718ad9693e365612 and 9380afd6df70e24e did not take into account is As soon as one side of {tx,rx} kernel threads starts from attach operation, that kernel thread is allowed to call usbip_event_add(USBIP_EH_SHUTDOWN) which in turn allows event_handler() to call kthread_stop_put() on both {tx,rx} kernel threads via ud->eh_ops.shutdown(ud), before the other side of {tx,rx} kernel threads starts from attach operation. which will be reported as either NULL pointer dereference or use-after-free bug on the other side of {tx,rx} kernel threads. Since this race window cannot be closed without introducing serialization, this patch introduces usbip_event_mutex for serializing attach/detach operations and event_handler(). [1] https://syzkaller.appspot.com/bug?extid=95ce4b142579611ef0a9 Reported-by: syzbot <syzbot+95ce4b142579611ef0a9@syzkaller.appspotmail.com> Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Fixes: 46613c9dfa964c0c ("usbip: fix vudc usbip_sockfd_store races leading to gpf") Fixes: 718ad9693e365612 ("usbip: fix vhci_hcd attach_store() races leading to gpf") Fixes: 9380afd6df70e24e ("usbip: fix stub_dev usbip_sockfd_store() races leading to gpf") --- drivers/usb/usbip/stub_dev.c | 15 +++++++++++++-- drivers/usb/usbip/usbip_common.h | 2 ++ drivers/usb/usbip/usbip_event.c | 15 +++++++++++++++ drivers/usb/usbip/vhci_sysfs.c | 30 ++++++++++++++++++++++++++---- drivers/usb/usbip/vudc_sysfs.c | 16 +++++++++++++--- 5 files changed, 69 insertions(+), 9 deletions(-) diff --git a/drivers/usb/usbip/stub_dev.c b/drivers/usb/usbip/stub_dev.c index 8f1de1fbbeed..79ebc9795b4a 100644 --- a/drivers/usb/usbip/stub_dev.c +++ b/drivers/usb/usbip/stub_dev.c @@ -39,8 +39,8 @@ static DEVICE_ATTR_RO(usbip_status); * is used to transfer usbip requests by kernel threads. -1 is a magic number * by which usbip connection is finished. */ -static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t __usbip_sockfd_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct stub_device *sdev = dev_get_drvdata(dev); int sockfd = 0; @@ -132,6 +132,17 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a spin_unlock_irq(&sdev->ud.lock); return -EINVAL; } +static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + ssize_t ret = usbip_event_lock_killable(); + + if (ret) + return ret; + ret = __usbip_sockfd_store(dev, attr, buf, count); + usbip_event_unlock(); + return ret; +} static DEVICE_ATTR_WO(usbip_sockfd); static struct attribute *usbip_attrs[] = { diff --git a/drivers/usb/usbip/usbip_common.h b/drivers/usb/usbip/usbip_common.h index d60ce17d3dd2..ad7de3773e06 100644 --- a/drivers/usb/usbip/usbip_common.h +++ b/drivers/usb/usbip/usbip_common.h @@ -326,6 +326,8 @@ void usbip_stop_eh(struct usbip_device *ud); void usbip_event_add(struct usbip_device *ud, unsigned long event); int usbip_event_happened(struct usbip_device *ud); int usbip_in_eh(struct task_struct *task); +int usbip_event_lock_killable(void); +void usbip_event_unlock(void); static inline int interface_to_busnum(struct usb_interface *interface) { diff --git a/drivers/usb/usbip/usbip_event.c b/drivers/usb/usbip/usbip_event.c index 5d88917c9631..e05b858f346d 100644 --- a/drivers/usb/usbip/usbip_event.c +++ b/drivers/usb/usbip/usbip_event.c @@ -58,6 +58,19 @@ static struct usbip_device *get_event(void) } static struct task_struct *worker_context; +static DEFINE_MUTEX(usbip_event_mutex); + +int usbip_event_lock_killable(void) +{ + return mutex_lock_killable(&usbip_event_mutex); +} +EXPORT_SYMBOL_GPL(usbip_event_lock_killable); + +void usbip_event_unlock(void) +{ + mutex_unlock(&usbip_event_mutex); +} +EXPORT_SYMBOL_GPL(usbip_event_unlock); static void event_handler(struct work_struct *work) { @@ -68,6 +81,7 @@ static void event_handler(struct work_struct *work) } while ((ud = get_event()) != NULL) { + mutex_lock(&usbip_event_mutex); usbip_dbg_eh("pending event %lx\n", ud->event); /* @@ -91,6 +105,7 @@ static void event_handler(struct work_struct *work) unset_event(ud, USBIP_EH_UNUSABLE); } + mutex_unlock(&usbip_event_mutex); wake_up(&ud->eh_waitq); } } diff --git a/drivers/usb/usbip/vhci_sysfs.c b/drivers/usb/usbip/vhci_sysfs.c index c4b4256e5dad..d06087e4e29b 100644 --- a/drivers/usb/usbip/vhci_sysfs.c +++ b/drivers/usb/usbip/vhci_sysfs.c @@ -225,8 +225,8 @@ static int valid_port(__u32 *pdev_nr, __u32 *rhport) return 1; } -static ssize_t detach_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t __detach_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { __u32 port = 0, pdev_nr = 0, rhport = 0; struct usb_hcd *hcd; @@ -263,6 +263,17 @@ static ssize_t detach_store(struct device *dev, struct device_attribute *attr, return count; } +static ssize_t detach_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + ssize_t ret = usbip_event_lock_killable(); + + if (ret) + return ret; + ret = __detach_store(dev, attr, buf, count); + usbip_event_unlock(); + return ret; +} static DEVICE_ATTR_WO(detach); static int valid_args(__u32 *pdev_nr, __u32 *rhport, @@ -300,8 +311,8 @@ static int valid_args(__u32 *pdev_nr, __u32 *rhport, * * write() returns 0 on success, else negative errno. */ -static ssize_t attach_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t __attach_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct socket *socket; int sockfd = 0; @@ -425,6 +436,17 @@ static ssize_t attach_store(struct device *dev, struct device_attribute *attr, return count; } +static ssize_t attach_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + ssize_t ret = usbip_event_lock_killable(); + + if (ret) + return ret; + ret = __attach_store(dev, attr, buf, count); + usbip_event_unlock(); + return ret; +} static DEVICE_ATTR_WO(attach); #define MAX_STATUS_NAME 16 diff --git a/drivers/usb/usbip/vudc_sysfs.c b/drivers/usb/usbip/vudc_sysfs.c index a3ec39fc6177..3e3e4ef298d2 100644 --- a/drivers/usb/usbip/vudc_sysfs.c +++ b/drivers/usb/usbip/vudc_sysfs.c @@ -90,9 +90,8 @@ static ssize_t dev_desc_read(struct file *file, struct kobject *kobj, } static BIN_ATTR_RO(dev_desc, sizeof(struct usb_device_descriptor)); -static ssize_t usbip_sockfd_store(struct device *dev, - struct device_attribute *attr, - const char *in, size_t count) +static ssize_t __usbip_sockfd_store(struct device *dev, struct device_attribute *attr, + const char *in, size_t count) { struct vudc *udc = (struct vudc *) dev_get_drvdata(dev); int rv; @@ -219,6 +218,17 @@ static ssize_t usbip_sockfd_store(struct device *dev, return ret; } +static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *attr, + const char *in, size_t count) +{ + ssize_t ret = usbip_event_lock_killable(); + + if (ret) + return ret; + ret = __usbip_sockfd_store(dev, attr, in, count); + usbip_event_unlock(); + return ret; +} static DEVICE_ATTR_WO(usbip_sockfd); static ssize_t usbip_status_show(struct device *dev, -- 2.18.4 ^ permalink raw reply related [flat|nested] 34+ messages in thread
* Re: [PATCH 0/6] usbip fixes to crashes found by syzbot 2021-03-14 11:38 ` Tetsuo Handa @ 2021-03-17 6:21 ` Tetsuo Handa 2021-03-17 15:06 ` Shuah Khan 0 siblings, 1 reply; 34+ messages in thread From: Tetsuo Handa @ 2021-03-17 6:21 UTC (permalink / raw) To: Shuah Khan, shuah; +Cc: valentina.manea.m, linux-usb, linux-kernel, Greg KH Shuah, this driver is getting more and more cryptic and buggy. Please explain the strategy for serialization before you write patches. > - Fix attach_store() to check usbip_event_happened() before > waking up threads. No, this helps nothing. > diff --git a/drivers/usb/usbip/vhci_sysfs.c b/drivers/usb/usbip/vhci_sysfs.c > index c4b4256e5dad3..f0a770adebd97 100644 > --- a/drivers/usb/usbip/vhci_sysfs.c > +++ b/drivers/usb/usbip/vhci_sysfs.c > @@ -418,6 +418,15 @@ static ssize_t attach_store(struct device *dev, struct device_attribute *attr, > spin_unlock_irqrestore(&vhci->lock, flags); > /* end the lock */ > > + if (usbip_event_happened(&vdev->ud)) { > + /* > + * something went wrong - event handler shutting > + * the connection and doing reset - bail out > + */ > + dev_err(dev, "Event happended - handler is active\n"); > + return -EAGAIN; > + } > + detach_store() can queue shutdown event as soon as reaching "/* end the lock */" line but attach_store() might be preempted immediately after verifying that usbip_event_happened() was false (i.e. at this location) in order to wait for shutdown event posted by detach_store() to be processed. > wake_up_process(vdev->ud.tcp_rx); > wake_up_process(vdev->ud.tcp_tx); > ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 0/6] usbip fixes to crashes found by syzbot 2021-03-17 6:21 ` Tetsuo Handa @ 2021-03-17 15:06 ` Shuah Khan 2021-03-17 15:38 ` Tetsuo Handa 2021-03-18 13:13 ` Shuah Khan 0 siblings, 2 replies; 34+ messages in thread From: Shuah Khan @ 2021-03-17 15:06 UTC (permalink / raw) To: Tetsuo Handa, shuah Cc: valentina.manea.m, linux-usb, linux-kernel, Greg KH, Shuah Khan On 3/17/21 12:21 AM, Tetsuo Handa wrote: > Shuah, this driver is getting more and more cryptic and buggy. > Please explain the strategy for serialization before you write patches. > >> - Fix attach_store() to check usbip_event_happened() before >> waking up threads. > > No, this helps nothing. > >> diff --git a/drivers/usb/usbip/vhci_sysfs.c b/drivers/usb/usbip/vhci_sysfs.c >> index c4b4256e5dad3..f0a770adebd97 100644 >> --- a/drivers/usb/usbip/vhci_sysfs.c >> +++ b/drivers/usb/usbip/vhci_sysfs.c >> @@ -418,6 +418,15 @@ static ssize_t attach_store(struct device *dev, struct device_attribute *attr, >> spin_unlock_irqrestore(&vhci->lock, flags); >> /* end the lock */ >> >> + if (usbip_event_happened(&vdev->ud)) { >> + /* >> + * something went wrong - event handler shutting >> + * the connection and doing reset - bail out >> + */ >> + dev_err(dev, "Event happended - handler is active\n"); >> + return -EAGAIN; >> + } >> + > > detach_store() can queue shutdown event as soon as reaching "/* end the lock */" line > but attach_store() might be preempted immediately after verifying that > usbip_event_happened() was false (i.e. at this location) in order to wait for > shutdown event posted by detach_store() to be processed. > Yes. I haven't sent the patch for that reason. I am trying to test a solution. I haven't come up with a solution yet. Holding event_lock isn't the right solution. I am not going to accept that. This is a window that gets triggered by syzbot injecting errors in a sequence. Fixing this should be done taking other moving parts of the driver into account. thanks, -- Shuah ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 0/6] usbip fixes to crashes found by syzbot 2021-03-17 15:06 ` Shuah Khan @ 2021-03-17 15:38 ` Tetsuo Handa 2021-03-17 17:09 ` Shuah Khan 2021-03-18 13:13 ` Shuah Khan 1 sibling, 1 reply; 34+ messages in thread From: Tetsuo Handa @ 2021-03-17 15:38 UTC (permalink / raw) To: Shuah Khan, shuah; +Cc: valentina.manea.m, linux-usb, linux-kernel, Greg KH On 2021/03/18 0:06, Shuah Khan wrote: > Yes. I haven't sent the patch for that reason. I am trying to test a > solution. I haven't come up with a solution yet. > > Holding event_lock isn't the right solution. I am not going to accept > that. This is a window that gets triggered by syzbot injecting errors > in a sequence. Fixing this should be done taking other moving parts of > the driver into account. What is event_lock ? I questioned you what the event_lock is at https://lkml.kernel.org/r/3dab66dc-2981-bc88-a370-4b3178dfd390@i-love.sakura.ne.jp , but you haven't responded to that post. Also, you need to send https://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux.git/commit/?h=usbip_test&id=f345de0d2e51a20a2a1c30fc22fa1527670d2095 because Greg already sent this regression into upstream and stable kernels. ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 0/6] usbip fixes to crashes found by syzbot 2021-03-17 15:38 ` Tetsuo Handa @ 2021-03-17 17:09 ` Shuah Khan 0 siblings, 0 replies; 34+ messages in thread From: Shuah Khan @ 2021-03-17 17:09 UTC (permalink / raw) To: Tetsuo Handa, shuah Cc: valentina.manea.m, linux-usb, linux-kernel, Greg KH, Shuah Khan On 3/17/21 9:38 AM, Tetsuo Handa wrote: > On 2021/03/18 0:06, Shuah Khan wrote: >> Yes. I haven't sent the patch for that reason. I am trying to test a >> solution. I haven't come up with a solution yet. >> >> Holding event_lock isn't the right solution. I am not going to accept >> that. This is a window that gets triggered by syzbot injecting errors >> in a sequence. Fixing this should be done taking other moving parts of >> the driver into account. > > What is event_lock ? I questioned you what the event_lock is at > https://lkml.kernel.org/r/3dab66dc-2981-bc88-a370-4b3178dfd390@i-love.sakura.ne.jp , > but you haven't responded to that post. > > Also, you need to send https://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux.git/commit/?h=usbip_test&id=f345de0d2e51a20a2a1c30fc22fa1527670d2095 > because Greg already sent this regression into upstream and stable kernels. > I acked it when it came in and it will be picked up. thanks, -- Shuah ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 0/6] usbip fixes to crashes found by syzbot 2021-03-17 15:06 ` Shuah Khan 2021-03-17 15:38 ` Tetsuo Handa @ 2021-03-18 13:13 ` Shuah Khan 2021-03-18 13:39 ` Tetsuo Handa 1 sibling, 1 reply; 34+ messages in thread From: Shuah Khan @ 2021-03-18 13:13 UTC (permalink / raw) To: Tetsuo Handa, shuah Cc: valentina.manea.m, linux-usb, linux-kernel, Greg KH, Shuah Khan On 3/17/21 9:06 AM, Shuah Khan wrote: > On 3/17/21 12:21 AM, Tetsuo Handa wrote: >> Shuah, this driver is getting more and more cryptic and buggy. >> Please explain the strategy for serialization before you write patches. >> >>> - Fix attach_store() to check usbip_event_happened() before >>> waking up threads. >> >> No, this helps nothing. >> >>> diff --git a/drivers/usb/usbip/vhci_sysfs.c >>> b/drivers/usb/usbip/vhci_sysfs.c >>> index c4b4256e5dad3..f0a770adebd97 100644 >>> --- a/drivers/usb/usbip/vhci_sysfs.c >>> +++ b/drivers/usb/usbip/vhci_sysfs.c >>> @@ -418,6 +418,15 @@ static ssize_t attach_store(struct device *dev, >>> struct device_attribute *attr, >>> spin_unlock_irqrestore(&vhci->lock, flags); >>> /* end the lock */ >>> + if (usbip_event_happened(&vdev->ud)) { >>> + /* >>> + * something went wrong - event handler shutting >>> + * the connection and doing reset - bail out >>> + */ >>> + dev_err(dev, "Event happended - handler is active\n"); >>> + return -EAGAIN; >>> + } >>> + >> >> detach_store() can queue shutdown event as soon as reaching "/* end >> the lock */" line >> but attach_store() might be preempted immediately after verifying that >> usbip_event_happened() was false (i.e. at this location) in order to >> wait for >> shutdown event posted by detach_store() to be processed. >> > Please don't review code that isn't sent upstream. This repo you are looking at is a private branch created just to verify fixes on syzbot. I understand the race window you are talking about. I have my way of working to resolve it. thanks, -- Shuah ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 0/6] usbip fixes to crashes found by syzbot 2021-03-18 13:13 ` Shuah Khan @ 2021-03-18 13:39 ` Tetsuo Handa 0 siblings, 0 replies; 34+ messages in thread From: Tetsuo Handa @ 2021-03-18 13:39 UTC (permalink / raw) To: Shuah Khan, shuah; +Cc: valentina.manea.m, linux-usb, linux-kernel, Greg KH On 2021/03/18 22:13, Shuah Khan wrote: > Please don't review code that isn't sent upstream. This repo you are > looking at is a private branch created just to verify fixes on syzbot. But nobody was able to review this series when sent to ML (except you simply ignored my questions), and this series was merged to upstream and stable kernels despite there was an obvious assignment error which results in NULL pointer dereference. > > I understand the race window you are talking about. I have my way of > working to resolve it. Without an effort to share your understanding/idea and my understanding/idea, nobody can test/review what you call a solution. ^ permalink raw reply [flat|nested] 34+ messages in thread
end of thread, other threads:[~2021-03-18 13:40 UTC | newest] Thread overview: 34+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2021-03-08 3:53 [PATCH 0/6] usbip fixes to crashes found by syzbot Shuah Khan 2021-03-08 3:53 ` [PATCH 1/6] usbip: fix stub_dev to check for stream socket Shuah Khan 2021-03-08 3:53 ` [PATCH 2/6] usbip: fix vhci_hcd " Shuah Khan 2021-03-08 3:53 ` [PATCH 3/6] usbip: fix vudc " Shuah Khan 2021-03-08 3:53 ` [PATCH 4/6] usbip: fix stub_dev usbip_sockfd_store() races leading to gpf Shuah Khan 2021-03-08 7:35 ` Tetsuo Handa 2021-03-08 10:10 ` Tetsuo Handa 2021-03-08 16:27 ` Shuah Khan 2021-03-09 11:04 ` Tetsuo Handa 2021-03-09 13:56 ` Tetsuo Handa 2021-03-09 19:50 ` Shuah Khan 2021-03-09 23:40 ` Tetsuo Handa 2021-03-09 23:52 ` Shuah Khan 2021-03-10 0:03 ` Tetsuo Handa 2021-03-10 0:29 ` Shuah Khan 2021-03-10 1:02 ` Tetsuo Handa 2021-03-10 2:07 ` Shuah Khan 2021-03-10 10:38 ` Tetsuo Handa 2021-03-09 15:22 ` Shuah Khan 2021-03-08 3:53 ` [PATCH 5/6] usbip: fix vhci_hcd attach_store() " Shuah Khan 2021-03-08 3:53 ` [PATCH 6/6] usbip: fix vudc usbip_sockfd_store " Shuah Khan 2021-03-10 18:33 ` [PATCH 0/6] usbip fixes to crashes found by syzbot Greg KH 2021-03-11 12:34 ` Tetsuo Handa 2021-03-11 12:57 ` Greg KH 2021-03-11 13:24 ` Tetsuo Handa 2021-03-12 5:44 ` Tetsuo Handa 2021-03-13 0:48 ` Tetsuo Handa 2021-03-14 11:38 ` Tetsuo Handa 2021-03-17 6:21 ` Tetsuo Handa 2021-03-17 15:06 ` Shuah Khan 2021-03-17 15:38 ` Tetsuo Handa 2021-03-17 17:09 ` Shuah Khan 2021-03-18 13:13 ` Shuah Khan 2021-03-18 13:39 ` Tetsuo Handa
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).