refactor syscall ABI and FAT32 driver to use request structs and string views natively, enforce handle access rights on object lookup, add scheduler statistics tracking, fix KiSchedule to prevent 50% idle throttling on CPU-bound threads, better document x64 initial user stack alignment, fix process teardown to properly signal exit events and manage thread counts, optimize doom file I/O with a custom handle struct to internally track position and size, add SubsystemData to TEB for generic thread-local state, apply PAGE_NX to non-executable PE sections in the loader, update native apps, tests, and shells to match new APIs, update kernel32 directory retrieval.
This commit is contained in:
1 parent
603fbdfab1
commit
e1248f4afe
43 files changed
+2892
-1857
No files matched your search
+65
-24
@@ -290,29 +290,6 @@ __declspec(dllexport) KSTATUS CopyToUser(void* userDst, const void* kernelSrc, s
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
__declspec(dllexport) KSTATUS CopyStringFromUser(char* kernelDst,
|
||||
size_t kernelDstSize,
|
||||
const char* userSrc) {
|
||||
if (!kernelDst || kernelDstSize == 0 || !userSrc)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
for (size_t i = 0; i < kernelDstSize; i++) {
|
||||
KSTATUS s = MmProbeUserRead(userSrc + i, 1);
|
||||
if (!KSUCCESS(s)) {
|
||||
kernelDst[0] = '\0';
|
||||
return s;
|
||||
}
|
||||
|
||||
char ch = userSrc[i];
|
||||
kernelDst[i] = ch;
|
||||
if (ch == '\0')
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
kernelDst[kernelDstSize - 1] = '\0';
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Boundary-tag allocator (used for both pool and user heap)
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -595,6 +572,9 @@ static HEAP gPoolHeap;
|
||||
// User heap
|
||||
// ---------------------------------------------------------------------------
|
||||
static HEAP gUserHeap;
|
||||
__declspec(dllexport) void MmFreeUserImage(void* ptr, size_t size);
|
||||
static SPINLOCK gUserImageLock = SPINLOCK_INIT;
|
||||
static uintptr_t gUserImageNext = USER_LIMIT;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Module init
|
||||
@@ -621,8 +601,15 @@ void MmInitializeVirtual(PHYSICAL_ADDRESS bootPml4Phys, size_t poolSize) {
|
||||
gUserHeap.Start = USER_BASE;
|
||||
gUserHeap.Brk = USER_BASE;
|
||||
gUserHeap.Limit = USER_LIMIT;
|
||||
gUserHeap.MapFlags = PAGE_PRESENT | PAGE_WRITE | PAGE_USER;
|
||||
gUserHeap.MapFlags = PAGE_PRESENT | PAGE_WRITE | PAGE_USER | PAGE_NX;
|
||||
gUserHeap.Lock = (SPINLOCK)SPINLOCK_INIT;
|
||||
|
||||
// Executable image mappings grow downward from the top of user space.
|
||||
// The regular user heap grows upward from USER_BASE. Keeping them in
|
||||
// separate page-aligned regions prevents W^X section protection from
|
||||
// changing heap metadata or adjacent allocations.
|
||||
gUserImageLock = (SPINLOCK)SPINLOCK_INIT;
|
||||
gUserImageNext = USER_LIMIT;
|
||||
}
|
||||
|
||||
void MmActivate(void) {
|
||||
@@ -654,6 +641,60 @@ __declspec(dllexport) void* MmReallocateUserMemory(void* ptr, size_t newSize) {
|
||||
return KiHeapRealloc(&gUserHeap, ptr, newSize);
|
||||
}
|
||||
|
||||
|
||||
__declspec(dllexport) void* MmAllocateUserImage(size_t size) {
|
||||
KeAssertIrql(PASSIVE_LEVEL);
|
||||
if (!size) return (void*)0;
|
||||
|
||||
size_t pagesSize = (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
|
||||
if (pagesSize < size) return (void*)0;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gUserImageLock);
|
||||
|
||||
if (pagesSize > gUserImageNext || gUserImageNext - pagesSize < gUserHeap.Brk) {
|
||||
KeReleaseSpinlock(&gUserImageLock, flags);
|
||||
return (void*)0;
|
||||
}
|
||||
|
||||
uintptr_t base = gUserImageNext - pagesSize;
|
||||
gUserImageNext = base;
|
||||
KeReleaseSpinlock(&gUserImageLock, flags);
|
||||
|
||||
for (uintptr_t va = base; va < base + pagesSize; va += PAGE_SIZE) {
|
||||
PHYSICAL_ADDRESS frame = MmAllocateFrame();
|
||||
if (!frame) {
|
||||
MmFreeUserImage((void*)base, va - base);
|
||||
return (void*)0;
|
||||
}
|
||||
KSTATUS s = MmMapPage(va, frame, PAGE_PRESENT | PAGE_WRITE | PAGE_USER | PAGE_NX);
|
||||
if (!KSUCCESS(s)) {
|
||||
MmFreeFrame(frame);
|
||||
MmFreeUserImage((void*)base, va - base);
|
||||
return (void*)0;
|
||||
}
|
||||
}
|
||||
|
||||
memset((void*)base, 0, pagesSize);
|
||||
return (void*)base;
|
||||
}
|
||||
|
||||
__declspec(dllexport) void MmFreeUserImage(void* ptr, size_t size) {
|
||||
KeAssertIrql(PASSIVE_LEVEL);
|
||||
if (!ptr || !size) return;
|
||||
|
||||
uintptr_t base = (uintptr_t)ptr & PAGE_MASK;
|
||||
size_t pagesSize = (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
|
||||
if (pagesSize < size) return;
|
||||
|
||||
for (uintptr_t va = base; va < base + pagesSize; va += PAGE_SIZE) {
|
||||
PHYSICAL_ADDRESS phys = MmGetPhysicalAddress(va);
|
||||
if (!phys) continue;
|
||||
if (KSUCCESS(MmUnmapPage(va))) {
|
||||
MmFreeFrame(phys);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t MmGetKernelPoolUsage(void) {
|
||||
// Returns bytes committed to the kernel pool
|
||||
return (size_t)(gPoolHeap.Brk - gPoolHeap.Start);
|
||||
|
||||
Reference in new issue
Block a user