Add LA57 (5-level paging) support for Linux & Windows Intel layers#1991
Open
ricardojrdez wants to merge 4 commits into
Open
Add LA57 (5-level paging) support for Linux & Windows Intel layers#1991ricardojrdez wants to merge 4 commits into
ricardojrdez wants to merge 4 commits into
Conversation
Five-level paging (LA57) widens the linear address space to 57 bits by adding a fifth page map level (PML5). The existing Intel32e layer is hardwired to 48-bit virtual addresses and a 4-entry page-table walk, so on LA57 images the 48-bit address_mask truncates canonical kernel pointers and the page walk treats the PML5 as a PML4. The visible symptom is that physical scanning (psscan) works while virtual list-following (pslist, check_syscall, ...) silently returns nothing. Add Intel32e_LA57 with _maxvirtaddr=57 and a 5-entry _structure; all derived values (maximum_address, address_mask, canonicalization, translation walk) follow from those two constants. Add the matching WindowsIntel32e_LA57 (transition-PFN workaround) and LinuxIntel32e_LA57 (_maxphyaddr=52, as 5-level kernels always use a 52-bit physical mask). Detect LA57 at runtime in the Linux automagic: read __pgtable_l5_enabled from the physical layer in the banner stacker, and use NUMBER(pgtable_l5_enabled) in the VMCOREINFO stacker. Detection is runtime, not build-time, since a CONFIG_X86_5LEVEL kernel still boots in 4-level mode on non-LA57 hardware. Add synthetic-page-table unit tests in test/layers/test_intel.py covering the 5-level walk (4K/2M/1G), 57-bit canonicalization, the pointer-masking regression, and the Windows/Linux entry variants. Validated against a real LA57 LiME capture (Ubuntu 24.04, 6.8.0-117, Diamorphine rootkit): pslist now lists processes, hidden_modules reveals the rootkit and check_syscall recovers the hijacked entries. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add WindowsIntel32e_LA57 selection to the Windows automagic. A self-referential PML5 is indistinguishable from a PML4 during the DTB scan, so the 64-bit choice is refined by reading CR4 from the x64 Low Stub (_PROCESSOR_START_BLOCK->...->SpecialRegisters->Cr4): bit 12 (LA57) is the authoritative runtime indicator of 5-level paging. The new _la57_from_low_stub helper validates the stub's CR3 against the discovered DTB before trusting its CR4, and returns None when no Low Stub is present so 4-level behaviour is unchanged. Replace hardwired 48-bit constants that broke on LA57: - pdbscan: optimized scan start derived from _maxvirtaddr (0x1F0 << (maxvirtaddr - 9)); kernel hint/base masked with vlayer.address_mask instead of 0xFFFFFFFFFFFF. - modules.get_kernel_space_start: the 64-bit MmSystemRangeStart fallback default is derived from the layer (0xFFFF800000000000 for 4-level, 0xFF00000000000000 for LA57) instead of being hardcoded. Add new CR4 Low Stub constants and synthetic-stub unit tests in test/automagic/test_windows.py. Note: detection still relies on the Low Stub, which is absent on some virtualized snapshots; a probe-based fallback for that case is left for a follow-up (no Windows LA57 image was available to validate it). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
With 5-level paging now supported, resolve the FIXME in _intel_vmemmap_start: for the !CONFIG_DYNAMIC_MEMORY_LAYOUT SPARSEMEM case, use __VMEMMAP_BASE_L5 (0xFFD4000000000000) when the layer is LA57 instead of raising "5-level paging is not yet supported". KASLR kernels (>= 4.9) keep using the vmemmap_base symbol, so this branch only affects non-KASLR 5-level kernels. The surrounding page -> physical machinery (canonicalize + page objects) was validated on a real LA57 capture via linux.pagecache. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Build a synthetic Windows physical image with a self-referential x64 DTB and an x64 Low Stub, then drive the real WindowsIntelStacker.stack() to confirm it selects WindowsIntel32e_LA57 iff CR4.LA57 is set, and falls back to WindowsIntel32e when the bit is clear or no Low Stub is present. This exercises the self-referential scan path plus the CR4 refinement end-to-end, complementing the existing _la57_from_low_stub unit tests. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Member
|
#1939 might also be related. My concern is that it only supports linux at the moment, and it will need carefully checking to ensure it's extensible enough to support Windows if/when windows eventually moves to 5-level paging. |
Author
|
I've already extended to Windows in a related commit. For testing I used a synthetic dump as Windows is not yet supporting LA57 |
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.
Five-level paging (LA57) widens the linear address space to 57 bits by adding a fifth page map level (PML5). The existing Intel32e layer is hardwired to 48-bit virtual addresses and a 4-entry page-table walk, so on LA57 images the 48-bit address_mask truncates canonical kernel pointers and the page walk treats the PML5 as a PML4. The visible symptom is that physical scanning (psscan) works while virtual list-following (pslist, check_syscall, ...) silently returns nothing.
Add Intel32e_LA57 with _maxvirtaddr=57 and a 5-entry _structure; all derived values (maximum_address, address_mask, canonicalization, translation walk) follow from those two constants. Add the matching WindowsIntel32e_LA57 (transition-PFN workaround) and LinuxIntel32e_LA57 (_maxphyaddr=52, as 5-level kernels always use a 52-bit physical mask).
Detect LA57 at runtime in the Linux automagic: read __pgtable_l5_enabled from the physical layer in the banner stacker, and use NUMBER(pgtable_l5_enabled) in the VMCOREINFO stacker. Detection is runtime, not build-time, since a CONFIG_X86_5LEVEL kernel still boots in 4-level mode on non-LA57 hardware.
Add synthetic-page-table unit tests in test/layers/test_intel.py covering the 5-level walk (4K/2M/1G), 57-bit canonicalization, the pointer-masking regression, and the Windows/Linux entry variants.
Validated against a real LA57 LiME capture (Ubuntu 24.04, 6.8.0-117, Diamorphine rootkit): pslist now lists processes, hidden_modules reveals the rootkit and check_syscall recovers the hijacked entries.