forked from cezanne/usbip-win
-
-
Notifications
You must be signed in to change notification settings - Fork 136
v.0.9.8.1
Vadym edited this page Sep 23, 2026
·
1 revision
-
WSK Socket Teardown Race Condition & Rundown Protection:
Replaced a custom atomic invocation counter and event wait with the Windows kernel
EX_RUNDOWN_REFrundown protection (ExInitializeRundownProtection,ExAcquireRundownProtection,ExReleaseRundownProtection,ExWaitForRundownProtectionRelease) inwsk_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
GetProviderNPIwithinwsk_cpp.cpp.WskCaptureProviderNPIreturnsSTATUS_TIMEOUT(0x00000102) on timeout. BecauseSTATUS_TIMEOUThas severity01(informational), the macroNT_SUCCESS(STATUS_TIMEOUT)evaluates toTRUE. The driver previously treated capture timeouts as success, attempting calls against an uncaptured provider dispatch table and risking null pointer dereferences. Changed to strictly checkstatus == STATUS_SUCCESS. -
Transfers with bare TransferBuffer at DISPATCH_LEVEL (#190):
In
Mdl::lock(mdl_cpp.cpp) andMdl::prepare_paged(mdl_cpp.h), relaxed the assertion and SAL contract fromAPC_LEVELto_IRQL_requires_max_(DISPATCH_LEVEL). Per USB contract specifications and WDK guidelines, URBTransferBufferpointers are contractually non-pageable (resident), makingMmProbeAndLockPagesvalid up toDISPATCH_LEVEL.
-
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)inwsk_cpp.cpp,pdu.cpp, anddbgcommon.cpp.NT_ERRORonly evaluates severity11, silently ignoring warning codes (severity10) such asSTATUS_BUFFER_OVERFLOW(0x80000005) returned by string formatting routines and registry queries. Inwsk::control_clientandwsk::control, allowedSTATUS_BUFFER_OVERFLOWto updateOutputSizewith the required buffer size. -
Select Configuration and Interface Descriptors Bounds Verification:
Added strict validation and bounds checks when allocating, cloning, and formatting
_URB_SELECT_CONFIGURATIONand_URB_SELECT_INTERFACErequests inselect_configuration(select.cpp,select.h), preventing out-of-bounds reads on truncated configuration descriptors.
-
Removal of Legacy Concurrency Check Counters in WSK:
Removed unused debug counters and the
ConcurrencyCheckhelper inwsk_cpp.cpp.
-
Bounded Retry for BusRelations Cloning to Prevent Unfiltered Child Starts:
Added
usbip::clone_relations_retryindevice.cpp,device.h, andpnp.cpp. Retries cloningDEVICE_RELATIONSsynchronously up to a bounded limit with delays atPASSIVE_LEVEL. Under transient memory pressure, a failure to cloneBusRelationscould 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_lengthinint_dev_ctrl.cppforIOCTL_INTERNAL_USB_SUBMIT_URB. Rejects malformed requests forURB_FUNCTION_SELECT_INTERFACE,URB_FUNCTION_SYNC_RESET_PIPE,URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL, andURB_FUNCTION_SYNC_CLEAR_STALLwithSTATUS_INVALID_PARAMETER, preventing buffer over-reads and out-of-bounds writes.
-
Device Relations Integer Overflow Protection & Characteristics Inheritance:
Hardened
SizeOf_DEVICE_RELATIONSindevice.cppagainst 32-bit integer overflows when calculating allocation sizes (max_extra = (MAXULONG - sizeof(DEVICE_RELATIONS)) / sizeof(PDEVICE_OBJECT)). In addition, properly propagated theFILE_DEVICE_SECURE_OPENcharacteristic 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_ERRORchecks with!NT_SUCCESSacross PnP dispatch (pnp.cpp), internal control (int_dev_ctrl.cpp), and interface queries (query_interface.cpp).
-
Null URB Pointer Guard:
Added null checks for URB pointers extracted from incoming IRPs in
int_dev_ctrl.cpp, safely completing requests withSTATUS_INVALID_PARAMETERinstead 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 indevice.cpp, ensuring the parent is not torn down concurrently during child attachment.
-
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_devicesinpersistent.cpp,persistent.h, andvhci_ioctl.cppforIOCTL_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_strandfill_location). Rejects malformed or hostile input withSTATUS_INVALID_PARAMETERbefore modifying the HKLM registry. -
Transfer Failures with bare TransferBuffer at DISPATCH_LEVEL (#190):
In
make_transfer_buffer_mdl(network.cpp), removed theKeGetCurrentIrql() > APC_LEVELcheck that returnedSTATUS_MUTANT_NOT_OWNEDwhen processing URBs with bareTransferBufferatDISPATCH_LEVEL.
-
URB Completion Byte Accounting, IRQL Contracts, and 64-bit Counter:
Added missing
UdecxUrbSetBytesCompletedcalls inret_submit_urb(wsk_receive.cpp) andfill_usb_device_serial(device_ioctl.cpp), ensuring the USB stack accurately receives the count of transferred bytes. Corrected IRQL annotations and paging rules incontext.cpp, and expandedsent_requeststoLONG64usingInterlockedIncrement64incontext.hto prevent 32-bit counter overflow under sustained network traffic. -
Severing Chained MDL Next Pointers to Prevent Double-Free/Corruption:
Introduced and integrated
clear_mdl_nextinwsk_context.h,wsk_context.cpp, andwsk_receive_irp.cppto 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_devicesinvhci.cpp,vhci.h, andvhci_ioctl.cppto injectstate::pluggedevents for all currently active imported devices on a client's initialdevice_readIOCTL, 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 invhci.cpp. Implementedsweep_redundant_eventsto purge obsolete state events when capacity is reached, and added driver-computedlocation_hashtoimported_device_locationinvhci.hto replace costly string parsing with$O(1)$ integer comparisons. -
Audit and Correction of NTSTATUS Checks:
Replaced
NT_ERRORwith!NT_SUCCESSacross VHCI IOCTLs and registry operations inpersistent.cppandvhci_ioctl.cpp, and assertedstatus == STATUS_SUCCESSforWdfRequestUnmarkCancelableinrequest_list.cpp.
-
Documentation of Device ACL and IOCTL Security Boundaries:
Added extensive security documentation in
vhci.cppandvhci_ioctl.cppanalyzing 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_hdrlogic and streamlined ring buffer access inring_buffer.handring_buffer.cpp.
-
Overlapped DNS Resolution Cancellation Stack and Handle Hazard Fix:
Fixed a critical stack corruption and handle lifetime bug in
wait_for_resolve(remote.cpp). IfGetAddrInfoExCancel()returned an error or completed asynchronously, the function previously exited while the Windows networking subsystem still held pointers to the stack-allocatedOVERLAPPEDstructure. Fixed by unconditionally waiting onovlp.hEventand callingGetAddrInfoExOverlappedResult(&ovlp)upon cancellation before stack unwinding. -
Unified Asynchronous Cancellation API:
Designed and introduced a comprehensive cancellation architecture across
remote.h,remote.cpp,vhci.h, andvhci.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.
-
Modern Error Propagation via
std::expectedand CleanSetLastErrorBoundary: Overhauled networking error handling to usestd::expected<T, DWORD>internally indo_connect(remote.cpp),win_socket.cpp, andlast_error.h. Win32SetLastError()is now invoked strictly at the public API boundary and only upon failure after resource cleanup is complete, guaranteeing thatGetLastError()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 toget_imported_devices(vhci.cpp) andget_persistent_devices(persistent.cpp) to prevent unbounded heap allocations and signed integer overflow when the driver returns repetitiveERROR_INSUFFICIENT_BUFFER. Inattach(), immediate failure is returned ifBytesReturned != outlen. -
String Conversion Boundary and MULTI_SZ Safety:
Prevented
ERROR_INVALID_PARAMETERfromMultiByteToWideChar/WideCharToMultiByteby returning empty strings immediately on empty input inutf8_to_wchar(strconv.cpp,strconv.h). Ensuredmake_multi_szoutputs a valid double null-terminated string (\0\0) on empty collections. FixedVerQueryValueinfile_ver.cppto returnnullptrinstead of throwing on missing version entries.
-
USB ID Database Parser Performance and Safety Overhaul:
Redesigned the
UsbIdsdatabase parser with string views, documented explicit buffer lifetime contracts, and streamlined binary search lookups for vendor, product, and class IDs inusb_ids.handusb_ids.cpp. -
Winsock Initialization and Network Edge Case Fixes:
Verified Winsock version negotiation bytes in
init_wsa()(win_socket.cpp), handled missingFD_CONNECTnotification flags in Release builds on fast loopback interfaces inremote.cpp, and resolved strict-aliasing issues inenum_exportable_devices. -
Public C++17 API Verification:
Updated compile-time validation test cases in
libusbip_check/main.cppto verify C++17 API compatibility of the new cancellation interfaces for external consumers.
-
Signal Handler Crash Fix and Lifecycle Guard in
ctrl_c_guard: Cached thestd::stop_tokeninternally inctrl_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_guardintoattach(attach.cpp),detach(detach.cpp), andlist(list.cpp), enabling responsive cancellation of long-running network requests and VHCI operations without corrupting driver or socket state.
-
Replacement of
spdlogwith Zero-Dependency C++23 Print Logger: Dropped the externalspdlogvcpkg dependency, replacing it with a clean, header-only C++23 logging implementation inusbip::log(log.h,usbip.vcxproj) based onstd::print/std::println, significantly reducing build overhead and package footprint. -
CLI Parser Usability and Cleanups:
Removed
always_capture_default()inusbip.cppto fix misleading[{}]and[-1]defaults in CLI--helpoutput, migrated mutable static argument structures tostd::make_shared, provided non-empty fallback validation messages inserial_validator, and improved socket status reporting ondetach -a closeonly(strings.cpp).
-
Preservation of Persistent Devices on Disconnect and Failed Attach:
Added a check for
!is_checked(dev, COL_PERSISTENT)onstate::disconnectedbefore callingremove_device(dev)inwusbip.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 tostd::jthread(m_read_thread) inwusbip.handwusbip.cpp, guaranteeing scoped cancellation and joining on window destruction, and explicitly cancelling pending I/O viavhci::cancel_ioto prevent hung UI shutdowns.
-
UI Update Locking and Startup Toast Suppression:
Used
wxWindowUpdateLockerduring mass device tree refreshes to eliminate visual flickering, and introduced a 2-second startup grace period (m_start_time) inwusbip.cppto suppress spurious balloon notifications during initial tree synchronization.
-
Infinite Loop Prevention in Device Property Retrieval:
Added bounded retry count (
max_attempts = 3) and buffer growth verification (actual > prop.size()) inget_device_property(main.cpp). Prevents an infinite loop ifSetupDiGetDevicePropertyrepeatedly returnsERROR_INSUFFICIENT_BUFFERwithout reporting an increased required size. -
Resilient Driver Installation on Non-Fatal Property Query Failures:
Made failures in
SetupDiGetDeviceInstallParamsnon-fatal ininstall_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
strpointer inerrmsg(main.cpp) (if (str && *str)) to prevent crashing on null strings, and formatted error messages directly usingformat_message().
-
Deprecation Fix via
PathMatchSpecEx: Replaced the deprecatedPathMatchSpecAPI withPathMatchSpecEx(..., PMSF_NORMAL)inmain.cpp. -
Enhanced Diagnostics and Argument Management:
Reported the specific device instance ID when
DiUninstallDevice()fails inmain.cpp, eliminatedalways_capture_default()to fix CLI help text formatting, and migrated CLI argument structures tostd::make_shared.
-
Elimination of Third-Party Binary DLL (
UninsIS.dll): Removed the precompiled binary dependencyUninsIS.dll. Re-implemented all previous uninstallation management, process checks, and cleanup natively using Inno Setup Pascal Script insetup.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.exeand verifies file existence to prevent misidentifying directories containing.exeas executables or launching unauthorized executables. -
Thorough Dual-Pass Driver Removal:
Implemented a sequential dual-pass uninstallation mechanism using
pnputilinsetup.issto query both registry entries and OEM driver files, ensuring that stale driver store packages and test certificates are completely removed.
-
Silent Upgrade Execution and Dialog Suppression:
Passed
/VERYSILENT /NORESTART /SUPPRESSMSGBOXESto child uninstaller instances and added bounded polling loops with sleep intervals insetup.issto 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 insetup.iss. -
Native Task Scheduler COM Automation:
Replaced external static XML task templates with native COM automation (
Schedule.Service) insetup.iss, correctly configuring multiple instance policies (MultipleInstances := 2).