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:
maksw committed 2026-05-26 14:46:49 +02:00
1 parent 603fbdfab1
commit e1248f4afe
43 files changed
+2892 -1857

No files matched your search

+65 -24
View File
@@ -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);