Skip to content

v.0.9.8.1

Vadym edited this page Sep 23, 2026 · 1 revision

USBip v.0.9.8.1 Release Notes


1. libdrv

Critical

  • WSK Socket Teardown Race Condition & Rundown Protection: Replaced a custom atomic invocation counter and event wait with the Windows kernel EX_RUNDOWN_REF rundown protection (ExInitializeRundownProtection, ExAcquireRundownProtection, ExReleaseRundownProtection, ExWaitForRundownProtectionRelease) in wsk_cpp.cpp. This eliminates race conditions between socket teardown/close and active socket transfer/event callbacks, preventing use-after-free conditions and kernel crashes during socket destruction.
  • Informational Status Code Misinterpretation in WSK Provider Capture: Fixed status validation in GetProviderNPI within wsk_cpp.cpp. WskCaptureProviderNPI returns STATUS_TIMEOUT (0x00000102) on timeout. Because STATUS_TIMEOUT has severity 01 (informational), the macro NT_SUCCESS(STATUS_TIMEOUT) evaluates to TRUE. The driver previously treated capture timeouts as success, attempting calls against an uncaptured provider dispatch table and risking null pointer dereferences. Changed to strictly check status == STATUS_SUCCESS.
  • Transfers with bare TransferBuffer at DISPATCH_LEVEL (#190): In Mdl::lock (mdl_cpp.cpp) and Mdl::prepare_paged (mdl_cpp.h), relaxed the assertion and SAL contract from APC_LEVEL to _IRQL_requires_max_(DISPATCH_LEVEL). Per USB contract specifications and WDK guidelines, URB TransferBuffer pointers are contractually non-pageable (resident), making MmProbeAndLockPages valid up to DISPATCH_LEVEL.

High

  • Audit and Fix NT_ERROR vs. !NT_SUCCESS Status Handling: Audited all driver code to replace improper NT_ERROR(status) checks with !NT_SUCCESS(status) in wsk_cpp.cpp, pdu.cpp, and dbgcommon.cpp. NT_ERROR only evaluates severity 11, silently ignoring warning codes (severity 10) such as STATUS_BUFFER_OVERFLOW (0x80000005) returned by string formatting routines and registry queries. In wsk::control_client and wsk::control, allowed STATUS_BUFFER_OVERFLOW to update OutputSize with the required buffer size.
  • Select Configuration and Interface Descriptors Bounds Verification: Added strict validation and bounds checks when allocating, cloning, and formatting _URB_SELECT_CONFIGURATION and _URB_SELECT_INTERFACE requests in select_configuration (select.cpp, select.h), preventing out-of-bounds reads on truncated configuration descriptors.

Medium

  • Removal of Legacy Concurrency Check Counters in WSK: Removed unused debug counters and the ConcurrencyCheck helper in wsk_cpp.cpp.

2. ude_filter driver

Critical

  • Bounded Retry for BusRelations Cloning to Prevent Unfiltered Child Starts: Added usbip::clone_relations_retry in device.cpp, device.h, and pnp.cpp. Retries cloning DEVICE_RELATIONS synchronously up to a bounded limit with delays at PASSIVE_LEVEL. Under transient memory pressure, a failure to clone BusRelations could cause child PDOs to start without their upper filter (FiDO) attached, completely bypassing filtering logic. Added detailed diagnostic logging for relation allocation and FiDO attachment failures.
  • URB Length Validation in Internal Device Control: Implemented is_valid_urb_length in int_dev_ctrl.cpp for IOCTL_INTERNAL_USB_SUBMIT_URB. Rejects malformed requests for URB_FUNCTION_SELECT_INTERFACE, URB_FUNCTION_SYNC_RESET_PIPE, URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL, and URB_FUNCTION_SYNC_CLEAR_STALL with STATUS_INVALID_PARAMETER, preventing buffer over-reads and out-of-bounds writes.

High

  • Device Relations Integer Overflow Protection & Characteristics Inheritance: Hardened SizeOf_DEVICE_RELATIONS in device.cpp against 32-bit integer overflows when calculating allocation sizes (max_extra = (MAXULONG - sizeof(DEVICE_RELATIONS)) / sizeof(PDEVICE_OBJECT)). In addition, properly propagated the FILE_DEVICE_SECURE_OPEN characteristic bit from the lower device object to the FiDO (fido->Characteristics), ensuring security descriptors are consistently enforced on file open requests.
  • Remove Lock Adoption in Asynchronous Request Completion: Modernized internal device control IRP completion in request_complete (int_dev_ctrl.cpp) to adopt the remove lock (libdrv::remove_lock_guard), guaranteeing safe lock release on scope exit and eliminating potential remove lock leaks or premature device teardowns during asynchronous completion.
  • Audit and Fix NTSTATUS Warning Handling: Replaced improper NT_ERROR checks with !NT_SUCCESS across PnP dispatch (pnp.cpp), internal control (int_dev_ctrl.cpp), and interface queries (query_interface.cpp).

Medium

  • Null URB Pointer Guard: Added null checks for URB pointers extracted from incoming IRPs in int_dev_ctrl.cpp, safely completing requests with STATUS_INVALID_PARAMETER instead of crashing on invalid submissions.
  • Parent Remove Lock Synchronization on Child Device Creation: Acquired and released the parent filter's remove lock (IoAcquireRemoveLock / IoReleaseRemoveLock) while adding child filter device objects in device.cpp, ensuring the parent is not torn down concurrently during child attachment.

3. UDE driver

Critical

  • Fresh Work Item per Attach Attempt Phase: Fixed a concurrency race in vhci_ioctl.cpp. Previously, reusing a single work item allowed address-resolution and socket connection callbacks to overlap; a departing callback could clear the thread marker while its successor was running, causing deletion to block waiting on that successor. Moved request and allocation ownership to a fresh work item for each connection attempt while holding the extended context reference until predecessor completion.
  • Strict Multi-String and Semantic Validation for Persistent Devices: Added validate_persistent_devices in persistent.cpp, persistent.h, and vhci_ioctl.cpp for IOCTL_USBIP_VHCI_SET_PERSISTENT. Enforces wide-character alignment, 64 KB maximum buffer limit, null and double-null termination, device count bounding by controller port capacity (ctx.devices_cnt), and full semantic parsing of each entry (parse_device_str and fill_location). Rejects malformed or hostile input with STATUS_INVALID_PARAMETER before modifying the HKLM registry.
  • Transfer Failures with bare TransferBuffer at DISPATCH_LEVEL (#190): In make_transfer_buffer_mdl (network.cpp), removed the KeGetCurrentIrql() > APC_LEVEL check that returned STATUS_MUTANT_NOT_OWNED when processing URBs with bare TransferBuffer at DISPATCH_LEVEL.

High

  • URB Completion Byte Accounting, IRQL Contracts, and 64-bit Counter: Added missing UdecxUrbSetBytesCompleted calls in ret_submit_urb (wsk_receive.cpp) and fill_usb_device_serial (device_ioctl.cpp), ensuring the USB stack accurately receives the count of transferred bytes. Corrected IRQL annotations and paging rules in context.cpp, and expanded sent_requests to LONG64 using InterlockedIncrement64 in context.h to prevent 32-bit counter overflow under sustained network traffic.
  • Severing Chained MDL Next Pointers to Prevent Double-Free/Corruption: Introduced and integrated clear_mdl_next in wsk_context.h, wsk_context.cpp, and wsk_receive_irp.cpp to explicitly unchain all MDL pointers (mdl_hdr, mdl_buf, mdl_buf_tail, mdl_isoc), avoiding memory corruption, invalid page unlocking, and double-free hazards when freeing compound MDL chains.
  • Ground-Truth State Replay for Newly Connected Subscribers: Implemented replay_plugged_devices in vhci.cpp, vhci.h, and vhci_ioctl.cpp to inject state::plugged events for all currently active imported devices on a client's initial device_read IOCTL, preventing race conditions where newly launched userspace managers or GUIs missed previously attached devices.
  • Dynamic Event Queue Sizing and Redundant Event Sweeping with Location Hash: Replaced fixed event buffer limits with dynamic sizing (get_max_events), allocating 4 events per port with a 64-event floor in vhci.cpp. Implemented sweep_redundant_events to purge obsolete state events when capacity is reached, and added driver-computed location_hash to imported_device_location in vhci.h to replace costly string parsing with $O(1)$ integer comparisons.
  • Audit and Correction of NTSTATUS Checks: Replaced NT_ERROR with !NT_SUCCESS across VHCI IOCTLs and registry operations in persistent.cpp and vhci_ioctl.cpp, and asserted status == STATUS_SUCCESS for WdfRequestUnmarkCancelable in request_list.cpp.

Medium

  • Documentation of Device ACL and IOCTL Security Boundaries: Added extensive security documentation in vhci.cpp and vhci_ioctl.cpp analyzing VHCI device ACL trade-offs (World RW access), Server-Side Request Forgery (SSRF) risks via kernel-mode outbound sockets (plugin_hardware), and HKLM persistence security boundaries.
  • Ring Buffer Optimization: Removed redundant peek_hdr logic and streamlined ring buffer access in ring_buffer.h and ring_buffer.cpp.

4. libusbip

Critical

  • Overlapped DNS Resolution Cancellation Stack and Handle Hazard Fix: Fixed a critical stack corruption and handle lifetime bug in wait_for_resolve (remote.cpp). If GetAddrInfoExCancel() returned an error or completed asynchronously, the function previously exited while the Windows networking subsystem still held pointers to the stack-allocated OVERLAPPED structure. Fixed by unconditionally waiting on ovlp.hEvent and calling GetAddrInfoExOverlappedResult(&ovlp) upon cancellation before stack unwinding.
  • Unified Asynchronous Cancellation API: Designed and introduced a comprehensive cancellation architecture across remote.h, remote.cpp, vhci.h, and vhci.cpp. Allows non-blocking interruption of hostname resolution, socket connection attempts, import queries, and VHCI device I/O via cancellation tokens and native Win32 event handles without thread or resource leakage.

High

  • Modern Error Propagation via std::expected and Clean SetLastError Boundary: Overhauled networking error handling to use std::expected<T, DWORD> internally in do_connect (remote.cpp), win_socket.cpp, and last_error.h. Win32 SetLastError() is now invoked strictly at the public API boundary and only upon failure after resource cleanup is complete, guaranteeing that GetLastError() remains unpolluted on success and error codes are not overwritten during intermediate socket closes.
  • Buffer Bounds and Integer Overflow Guards in Device Enumeration: Added a hard cap (max_devices = 1024) and retry bounds to get_imported_devices (vhci.cpp) and get_persistent_devices (persistent.cpp) to prevent unbounded heap allocations and signed integer overflow when the driver returns repetitive ERROR_INSUFFICIENT_BUFFER. In attach(), immediate failure is returned if BytesReturned != outlen.
  • String Conversion Boundary and MULTI_SZ Safety: Prevented ERROR_INVALID_PARAMETER from MultiByteToWideChar / WideCharToMultiByte by returning empty strings immediately on empty input in utf8_to_wchar (strconv.cpp, strconv.h). Ensured make_multi_sz outputs a valid double null-terminated string (\0\0) on empty collections. Fixed VerQueryValue in file_ver.cpp to return nullptr instead of throwing on missing version entries.

Medium

  • USB ID Database Parser Performance and Safety Overhaul: Redesigned the UsbIds database parser with string views, documented explicit buffer lifetime contracts, and streamlined binary search lookups for vendor, product, and class IDs in usb_ids.h and usb_ids.cpp.
  • Winsock Initialization and Network Edge Case Fixes: Verified Winsock version negotiation bytes in init_wsa() (win_socket.cpp), handled missing FD_CONNECT notification flags in Release builds on fast loopback interfaces in remote.cpp, and resolved strict-aliasing issues in enum_exportable_devices.
  • Public C++17 API Verification: Updated compile-time validation test cases in libusbip_check/main.cpp to verify C++17 API compatibility of the new cancellation interfaces for external consumers.

5. usbip utility

High

  • Signal Handler Crash Fix and Lifecycle Guard in ctrl_c_guard: Cached the std::stop_token internally in ctrl_c_guard (ctrl_c_guard.h, ctrl_c_guard.cpp) to prevent null pointer dereferences and crashes when Ctrl+C is received during or after token transitions. Documented and asserted single-instance invariants to eliminate concurrent or nested console handler conflicts.
  • Graceful Cancellation Support Across CLI Commands: Integrated ctrl_c_guard into attach (attach.cpp), detach (detach.cpp), and list (list.cpp), enabling responsive cancellation of long-running network requests and VHCI operations without corrupting driver or socket state.

Medium

  • Replacement of spdlog with Zero-Dependency C++23 Print Logger: Dropped the external spdlog vcpkg dependency, replacing it with a clean, header-only C++23 logging implementation in usbip::log (log.h, usbip.vcxproj) based on std::print / std::println, significantly reducing build overhead and package footprint.
  • CLI Parser Usability and Cleanups: Removed always_capture_default() in usbip.cpp to fix misleading [{}] and [-1] defaults in CLI --help output, migrated mutable static argument structures to std::make_shared, provided non-empty fallback validation messages in serial_validator, and improved socket status reporting on detach -a closeonly (strings.cpp).

6. GUI (wusbip)

High

  • Preservation of Persistent Devices on Disconnect and Failed Attach: Added a check for !is_checked(dev, COL_PERSISTENT) on state::disconnected before calling remove_device(dev) in wusbip.cpp. Previously, when an attach attempt failed or a device disconnected, the GUI inadvertently purged persistent devices from the tree list instead of retaining them.
  • Worker Thread Safety and Deterministic Shutdown via std::jthread: Migrated background monitoring threads to std::jthread (m_read_thread) in wusbip.h and wusbip.cpp, guaranteeing scoped cancellation and joining on window destruction, and explicitly cancelling pending I/O via vhci::cancel_io to prevent hung UI shutdowns.

Medium

  • UI Update Locking and Startup Toast Suppression: Used wxWindowUpdateLocker during mass device tree refreshes to eliminate visual flickering, and introduced a 2-second startup grace period (m_start_time) in wusbip.cpp to suppress spurious balloon notifications during initial tree synchronization.

7. devnode utility

High

  • Infinite Loop Prevention in Device Property Retrieval: Added bounded retry count (max_attempts = 3) and buffer growth verification (actual > prop.size()) in get_device_property (main.cpp). Prevents an infinite loop if SetupDiGetDeviceProperty repeatedly returns ERROR_INSUFFICIENT_BUFFER without reporting an increased required size.
  • Resilient Driver Installation on Non-Fatal Property Query Failures: Made failures in SetupDiGetDeviceInstallParams non-fatal in install_devnode_and_driver (main.cpp), allowing driver installation to proceed even if querying optional reboot flags fails.
  • Null Pointer Dereference Guard in Error Logging: Guarded the str pointer in errmsg (main.cpp) (if (str && *str)) to prevent crashing on null strings, and formatted error messages directly using format_message().

Medium

  • Deprecation Fix via PathMatchSpecEx: Replaced the deprecated PathMatchSpec API with PathMatchSpecEx(..., PMSF_NORMAL) in main.cpp.
  • Enhanced Diagnostics and Argument Management: Reported the specific device instance ID when DiUninstallDevice() fails in main.cpp, eliminated always_capture_default() to fix CLI help text formatting, and migrated CLI argument structures to std::make_shared.

8. Installer

High

  • Elimination of Third-Party Binary DLL (UninsIS.dll): Removed the precompiled binary dependency UninsIS.dll. Re-implemented all previous uninstallation management, process checks, and cleanup natively using Inno Setup Pascal Script in setup.iss, eliminating binary supply-chain risks.
  • Unquoted Uninstaller Path Parsing and Directory Spoofing Mitigation: Hardened previous uninstaller path resolution in GetInstalledUninstallString (setup.iss). For unquoted registry paths with command arguments, searches backward for .exe and verifies file existence to prevent misidentifying directories containing .exe as executables or launching unauthorized executables.
  • Thorough Dual-Pass Driver Removal: Implemented a sequential dual-pass uninstallation mechanism using pnputil in setup.iss to query both registry entries and OEM driver files, ensuring that stale driver store packages and test certificates are completely removed.

Medium

  • Silent Upgrade Execution and Dialog Suppression: Passed /VERYSILENT /NORESTART /SUPPRESSMSGBOXES to child uninstaller instances and added bounded polling loops with sleep intervals in setup.iss to ensure old uninstaller files are removed before installing updated binaries.
  • Native Test-Signing Verification: Verified kernel test signing using NtQuerySystemInformation(SystemCodeIntegrityInformation) and alerted users if test-signed drivers are not enabled in setup.iss.
  • Native Task Scheduler COM Automation: Replaced external static XML task templates with native COM automation (Schedule.Service) in setup.iss, correctly configuring multiple instance policies (MultipleInstances := 2).