Repository navigation
Cygwin: Guard XSAVE allocation against broken CPUID emulation - #378
Open
LarsDammannCoherent wants to merge 1 commit into
Open
LarsDammannCoherent wants to merge 1 commit into
LarsDammannCoherent wants to merge 1 commit into
Conversation
CPUID(0xD, 0) returns the XSAVE area size in the low 32 bits of RBX. A conforming implementation clears the upper 32 bits, but broken CPUID emulation may leave the upper half of the register stale. This was observed when TwinCAT eXtended Automation Runtime (XAR) was running. Its kernel-level real-time component appears to intercept CPUID and restore only the lower half of a saved register, allowing stale upper bits to leak into unrelated processes. MSYS2's sigdelayed uses the full-width RBX value both for XSAVE stack allocation and, after copying it to RCX, for clearing the XSAVE buffer. Stale upper bits can therefore turn a small allocation into a multi-gigabyte stack adjustment and cause an access violation. Zero-extend EBX immediately after CPUID, before using RBX as a 64-bit value. This has no effect on conforming implementations and protects against broken CPUID emulation. Addresses: msys2#363 Signed-off-by: Lars Dammann <[email protected]>
LarsDammannCoherent
marked this pull request as ready for review
October 7, 2026 08:06
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Protect
sigdelayedfromCPUIDemulation that leaves the upper 32 bits ofRBXstale when querying theXSAVEarea size.If the upper half of
RBXcontains stale bits afterCPUID,sigdelayeduses the full-width value ofRBXand attempts a multi-gigabyte stack adjustment, causing an access violation. This was reproduced on a system with TwinCAT eXtended Automation Runtime (XAR) in RUN mode. The problem does not reproduce when TwinCAT XAR is in CONFIG mode.The suspected cause is a TwinCAT
CPUIDvirtualization handler that writes only the lower 32 bits of a saved register, leaving stale data in the upper half ofRBX.Reproduction
On an affected system, in powershell:
With TwinCAT RUN mode enabled, the unpatched runtime exits with
0xC0000005before producing output.With TwinCAT in CONFIG mode, it prints
Helloand exits with0.Change
Zero-extend
EBXimmediately afterCPUID(0xD, 0)and before usingRBXas a 64-bit value. This protects both theXSAVEstack adjustment and the subsequentXSAVE-buffer clearing operation. For conformingCPUIDimplementations, the upper 32 bits are already zero, so this change does not alter the result.As supporting context, consider that Microsoft鈥檚
CPUIDwrappers likewise expose each result only as a 32-bit value:Tests
msys-2.0.dlland TwinCAT RUN modemsys-2.0.dllfrom this PR and replaced the one from my local git 2.54 and Visual Studio 2026 embedded MinGit 2.54git submodulecommands work in git bash, both in TwinCAT RUN and CONFIG mode