Windows IOCP lifetime bugs can corrupt memory during cancellation or shutdown
Reseau releases before 1.3.3 contain related lifetime defects in the Windows I/O completion port (IOCP) backend. During cancellation or event-loop shutdown, the package can stop retaining memory that the Windows kernel still owns. A remote peer that can time or stall I/O around application-driven deadlines, concurrent closes, or event-loop shutdown may be able to trigger these races. Linux, macOS, and FreeBSD use different polling backends and are not affected.
Impact
Depending on the interleaving, the kernel can write network data or completion status into reclaimed Julia heap memory. The resulting memory corruption can crash the process and may also cause information disclosure or code execution, although no reliable exploit was demonstrated.
Exploitation is timing-dependent. The most direct raw-buffer corruption path also requires a read or write deadline to race with a concurrent close or eviction of the same file descriptor.
Technical details
This advisory consolidates two variants of the same kernel-ownership failure:
WSARecvandWSASendreceived pointers into caller-owned buffers that were preserved only for the dynamic extent of the Julia call. A cancellation wake could be consumed before the kernel's completion packet, allowing the call to unwind and the buffer to be collected while the kernel still owned its address. Direct overlapped reads and writes, including this path, first shipped in Reseau 1.1.3.Event-loop shutdown closed the completion port and discarded the objects that rooted pending
OVERLAPPEDstructures without first canceling and draining all kernel-owned operations.
Reseau 1.3.2 added roots for object-backed reads and writes and implemented synchronous shutdown draining, but pointer-only operations still supplied no retained buffer root. During shutdown, their cancellation wait could lose access to the registration and return before the backend drain finished. That release could also treat CancelIoEx returning ERROR_NOT_FOUND as terminal while the completion packet was queued or had been dequeued by the poller but not yet consumed. Clearing the operation's active state at that point permitted live OVERLAPPED storage to be reset or reused. Separately, a finish path could observe a terminal WSAGetOverlappedResult after the poller dequeued a packet and reset the storage before the poller retired the old operation. Consequently, 1.3.2 is still included in the affected range.
Patches
Upgrade to Reseau 1.3.3 or later. The complete fix:
uses bounded, operation-owned buffers for raw reads and writes and retains buffer roots until completion consumption;
synchronously cancels and drains every outstanding operation before dropping backend roots; and
permits only the completion consumer to clear an active operation, preventing premature
OVERLAPPEDreuse.
Workarounds
There is no complete Windows workaround that preserves use of the vulnerable IOCP backend. Running the service on a non-Windows backend avoids these defects. Avoiding concurrent close/deadline operations reduces exposure to the raw-buffer race but does not address the shutdown variant.
Reported to the JuliaLang security team through Anthropic's Coordinated Vulnerability Disclosure program.
References
- https://github.com/JuliaServices/Reseau.jl/commit/9add20c1f39ecba430c9aa1dcd399191ccaeb76b
- https://github.com/JuliaServices/Reseau.jl/commit/ea95f091baaf7386267fd633742768121dfe20ff
- https://github.com/JuliaServices/Reseau.jl/pull/132
- https://github.com/JuliaServices/Reseau.jl/pull/135
- https://github.com/JuliaServices/Reseau.jl/releases/tag/v1.3.3