Fix Linux madvise() advice values incorrectly combined via bitwise OR in GCToOSInterface::VirtualReset#126966
Open
Fix Linux madvise() advice values incorrectly combined via bitwise OR in GCToOSInterface::VirtualReset#126966
Conversation
…bitwise OR Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/0cc0572d-b79f-46a0-bae2-6159c6d9ca19 Co-authored-by: janvorli <10758568+janvorli@users.noreply.github.com>
…bitwise OR Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/0cc0572d-b79f-46a0-bae2-6159c6d9ca19 Co-authored-by: janvorli <10758568+janvorli@users.noreply.github.com>
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/0cc0572d-b79f-46a0-bae2-6159c6d9ca19 Co-authored-by: janvorli <10758568+janvorli@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Fix madvise() advice values combined via bitwise OR
Fix Linux madvise() advice values incorrectly combined via bitwise OR in GCToOSInterface::VirtualReset
Apr 15, 2026
Contributor
|
Tagging subscribers to this area: @agocke |
janvorli
reviewed
Apr 15, 2026
…is not available Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/d656ac8b-2ae6-4625-a13b-ae63c5075c53 Co-authored-by: janvorli <10758568+janvorli@users.noreply.github.com>
jkotas
approved these changes
Apr 15, 2026
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes Linux GCToOSInterface::VirtualReset to avoid passing an invalid/incorrectly-combined advice value to madvise(), ensuring the GC’s “reset pages” hint behaves correctly across kernel versions.
Changes:
- Replace the single
madvise()call (with OR-combined advice values) with separate calls forMADV_DONTDUMPand the reclaim hint (MADV_FREEor POSIX fallback). - Restructure the POSIX fallback as a proper
#elifso it is only used when theMADV_FREEpath is unavailable.
…ndition Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/b398a17b-ed44-4a7e-b722-eaa9dff11424 Co-authored-by: janvorli <10758568+janvorli@users.noreply.github.com>
janvorli
approved these changes
Apr 16, 2026
This was referenced Apr 16, 2026
Open
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.
main PR
Description
VirtualResetwas combiningMADV_FREE(8) andMADV_DONTDUMP(16) via bitwise OR and passing the result (24) to a singlemadvise()call.madvise()takes a single advice constant — not a bitmask — so this was either rejected asEINVAL(kernels < 5.18) or silently matchedMADV_DONTNEED_LOCKED(kernels ≥ 5.18), a completely different operation.Fix: Issue two separate
madvise()calls, and useposix_madvise(POSIX_MADV_DONTNEED)as a proper fallback only whenMADV_FREEis not available:The
posix_madvise(POSIX_MADV_DONTNEED)path is an#elifchained to#ifdef MADV_FREE, making it a proper fallback that only executes whenMADV_FREEis unavailable. The guard usesMADV_FREEdirectly (the kernel header constant) rather thanHAVE_MADV_FREE, which was never defined by the GC unix CMake build system. The previous#if defined(HAVE_POSIX_MADVISE) && !defined(MADV_DONTDUMP)condition was semantically unrelated to that fallback decision. This matches the pattern already used byVirtualReserveInnerandVirtualCommitInnerin the same file. Introduced by #95643.Customer Impact
On all Linux builds where both
MADV_DONTDUMPandMADV_FREEare defined (i.e., all modern glibc/x86-64 Linux):MADV_DONTDUMPis never applied (reset memory appears in coredumps).MADV_DONTNEED_LOCKEDis invoked instead — immediately discarding pages including locked pages, which is semantically incorrect and potentially dangerous.Additionally, because
HAVE_MADV_FREEwas never defined by the build system, theMADV_FREEreclaim path was silently compiled out on all platforms, falling through toposix_madvise(POSIX_MADV_DONTNEED)instead. UsingMADV_FREEdirectly as the preprocessor guard restores the intended behavior.Regression
Yes — introduced in .NET 9 by #95643 (an optimization to reduce syscall count).
Testing
The bug is a straightforward misuse of a syscall interface. The fix has been manually verified against the Linux
madvise(2)man page and kernel headers. No existing automated test infrastructure coversmadvise()advice values directly.Risk
Low. The change is a minimal, targeted fix: replace one combined
madvise()call with two separate calls, restructure theposix_madvisefallback as a proper#elif, and use theMADV_FREEkernel constant directly as the preprocessor guard. No logic changes, no new APIs, no structural changes.Package authoring no longer needed in .NET 9
IMPORTANT: Starting with .NET 9, you no longer need to edit a NuGet package's csproj to enable building and bump the version.
Keep in mind that we still need package authoring in .NET 8 and older versions.