Skip to content

gh-144319: Fix huge page leak in datastack chunk allocator#147963

Merged
pablogsal merged 1 commit intopython:mainfrom
pablogsal:fixes
Apr 5, 2026
Merged

gh-144319: Fix huge page leak in datastack chunk allocator#147963
pablogsal merged 1 commit intopython:mainfrom
pablogsal:fixes

Conversation

@pablogsal
Copy link
Copy Markdown
Member

@pablogsal pablogsal commented Apr 1, 2026

The datastack chunk allocator (allocate_chunk in pystate.c) and other
small virtual-memory users such as the JIT tracer allocate through
_PyObject_VirtualAlloc() using the logical requested size. When huge pages
are enabled, the arena allocator may round those mappings up to the platform
huge page size, so freeing with the smaller requested size can make
munmap() fail with EINVAL and leak the mapping.

This change moves the rounding logic into _PyObject_VirtualAlloc() /
_PyObject_VirtualFree() so allocation and free always agree on the full
mapped size. Keeping it in the allocator layer also avoids a hardcoded 2 MB
assumption in pystate.c and fixes the JIT tracer allocation path at the
same time.

@pablogsal pablogsal requested a review from nascheme April 1, 2026 11:50
@pablogsal pablogsal changed the title Fix huge page leak in datastack chunk allocator gh-144319: Fix huge page leak in datastack chunk allocator Apr 1, 2026
@pablogsal
Copy link
Copy Markdown
Member Author

CC: @Fidget-Spinner

Copy link
Copy Markdown
Member

@Fidget-Spinner Fidget-Spinner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other than the stylistic stuff @maurycy pointed out, I think this looks fine.

The original fix rounded datastack chunk allocations in pystate.c so that
_PyObject_VirtualFree() would receive the full huge page mapping size.

Change direction and move that logic into _PyObject_VirtualAlloc() and
_PyObject_VirtualFree() instead. The key invariant is that munmap() must see
the full mapped size, so alloc and free now apply the same platform-specific
rounding in the allocator layer.

This keeps _PyStackChunk bookkeeping in requested-size units, avoids a
hardcoded 2 MB assumption, and also covers other small virtual-memory users
such as the JIT tracer state allocation in optimizer.c.
Copy link
Copy Markdown
Member Author

I changed direction from the pystate.c-local roundup to an allocator-level fix. The important invariant here is that munmap() must always see the full mapped size, so I moved the rounding into _PyObject_VirtualAlloc() / _PyObject_VirtualFree() to keep alloc/free symmetric. That also covers the JIT tracer path instead of fixing only the datastack caller.

@pablogsal pablogsal merged commit 77fc2f5 into python:main Apr 5, 2026
54 checks passed
@pablogsal pablogsal deleted the fixes branch April 5, 2026 15:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants