mirror of
https://dev.lirent.ru/Vatrog/vm-introspection-engine.git
synced 2026-07-09 00:46:36 +03:00
Drop the user-half top-level NX bit when deriving VR_X
Under KVA shadow (KPTI) the kernel CR3 marks user-half PML4Es NX as hardening, so OR-ing that top-level NX down the walk made every user region non-executable - even live code (ntdll .text read back r--u). Ring 3 executes those pages via the user/shadow CR3, which reaches the same shared lower tables through an NX-clear PML4E, so the kernel table's user-half PML4E NX is not what enforces user execution. Ignore it on the user half; sub-PML4E NX (shared between both CR3s) stays authoritative.
This commit is contained in:
+5
-1
@@ -125,7 +125,11 @@ typedef struct {
|
||||
* x86-64 has no read bit: a present page is readable, so VR_R is always set on a
|
||||
* returned region. Write/execute/user are the EFFECTIVE rights along the whole
|
||||
* page-table path (RW & US are AND-ed across levels, NX is OR-ed), not just the
|
||||
* leaf entry, so they reflect what the guest CPU actually enforces. */
|
||||
* leaf entry, so they reflect what the guest CPU actually enforces. One
|
||||
* exception keeps VR_X honest under KVA shadow (KPTI): the kernel CR3 marks
|
||||
* user-half PML4Es NX as hardening, but ring 3 executes those pages via the
|
||||
* user/shadow CR3 (same shared lower tables, NX-clear PML4E), so the user-half
|
||||
* top-level NX bit is ignored when deriving VR_X. */
|
||||
#ifndef VMIE_VREGION_DEFINED
|
||||
#define VMIE_VREGION_DEFINED
|
||||
#define VR_R 0x1u /* readable (present => always set) */
|
||||
|
||||
Reference in New Issue
Block a user