From b1d980a0102adef243ee90235124302d85d93a38 Mon Sep 17 00:00:00 2001 From: KyungWoon Cho Date: Sun, 3 Jan 2021 14:21:39 +0900 Subject: [PATCH] a more safe way to detach an actively running vusb When a device is actively running with iso transfer, detach process is used to be freezed. This is due to that iso transfers are requested to the plugged-out device. Therefore, let an invalidated vusb deny a subsequent request. --- driver/vhci_ude/vhci_ep.c | 21 ++------------------- driver/vhci_ude/vhci_plugout.c | 8 +++++++- driver/vhci_ude/vhci_queue_ep.c | 6 +++++- 3 files changed, 14 insertions(+), 21 deletions(-) diff --git a/driver/vhci_ude/vhci_ep.c b/driver/vhci_ude/vhci_ep.c index d28f1a3b..8509553b 100644 --- a/driver/vhci_ude/vhci_ep.c +++ b/driver/vhci_ude/vhci_ep.c @@ -159,18 +159,6 @@ ep_add(_In_ UDECXUSBDEVICE udev, _In_ PUDECX_USB_ENDPOINT_INIT_AND_METADATA epcr return status; } -static VOID -release_ep(PUDECX_ENDPOINTS_CONFIGURE_PARAMS params) -{ - TRD(VUSB, "Enter: ReleasedEndpointsCount=%d", params->ReleasedEndpointsCount); - - for (ULONG i = 0; i < params->ReleasedEndpointsCount; i++) { - pctx_ep_t ep = TO_EP(params->ReleasedEndpoints[i]); - WdfIoQueuePurgeSynchronously(ep->queue); - TRD(VUSB, "Released ep->addr=0x%x!", ep->addr); - } -} - static NTSTATUS set_intf_for_ep(pctx_vusb_t vusb, WDFREQUEST req, PUDECX_ENDPOINTS_CONFIGURE_PARAMS params) { @@ -215,13 +203,6 @@ ep_configure(_In_ UDECXUSBDEVICE udev, _In_ WDFREQUEST req, _In_ PUDECX_ENDPOINT TRD(VUSB, "Enter: %!epconf!", params->ConfigureType); - release_ep(params); - if ((params->ConfigureType == UdecxEndpointsConfigureTypeEndpointsReleasedOnly) || (vusb->invalid == TRUE)) { - WdfRequestComplete(req, status); - TRD(VUSB, "Leave: %!STATUS!", status); - return; - } - switch (params->ConfigureType) { case UdecxEndpointsConfigureTypeDeviceInitialize: /* FIXME: UDE framework seems to not call SET CONFIGURATION if a USB has multiple interfaces. @@ -236,6 +217,8 @@ ep_configure(_In_ UDECXUSBDEVICE udev, _In_ WDFREQUEST req, _In_ PUDECX_ENDPOINT case UdecxEndpointsConfigureTypeInterfaceSettingChange: status = set_intf_for_ep(vusb, req, params); break; + case UdecxEndpointsConfigureTypeEndpointsReleasedOnly: + break; default: TRE(VUSB, "unhandled configure type: %!epconf!", params->ConfigureType); break; diff --git a/driver/vhci_ude/vhci_plugout.c b/driver/vhci_ude/vhci_plugout.c index 22a70a3d..db95d299 100644 --- a/driver/vhci_ude/vhci_plugout.c +++ b/driver/vhci_ude/vhci_plugout.c @@ -55,15 +55,21 @@ vusb_plugout(pctx_vusb_t vusb) { NTSTATUS status; + /* + * invalidate first to prevent requests from an upper layer. + * If requests are consistently fed into a vusb about to be plugged out, + * a live deadlock may occur where vusb aborts pending urbs indefinately. + */ + vusb->invalid = TRUE; abort_pending_req_read(vusb); abort_all_pending_urbrs(vusb); status = UdecxUsbDevicePlugOutAndDelete(vusb->ude_usbdev); if (NT_ERROR(status)) { + vusb->invalid = FALSE; TRD(PLUGIN, "failed to plug out: %!STATUS!", status); return status; } - vusb->invalid = TRUE; return STATUS_SUCCESS; } diff --git a/driver/vhci_ude/vhci_queue_ep.c b/driver/vhci_ude/vhci_queue_ep.c index 1cb27b79..11af752f 100644 --- a/driver/vhci_ude/vhci_queue_ep.c +++ b/driver/vhci_ude/vhci_queue_ep.c @@ -16,7 +16,11 @@ internal_device_control(_In_ WDFQUEUE queue, _In_ WDFREQUEST req, TRE(EP, "unexpected ioctl: %!IOCTL!", ioctl_code); } else { - status = submit_req_urb(*TO_PEP(queue), req); + pctx_ep_t ep = *TO_PEP(queue); + if (ep->vusb->invalid) + status = STATUS_DEVICE_DOES_NOT_EXIST; + else + status = submit_req_urb(*TO_PEP(queue), req); } if (status != STATUS_PENDING)