fix: various kernel bug fixes
This commit is contained in:
+35
-12
@@ -20,11 +20,11 @@ namespace Montauk {
|
|||||||
|
|
||||||
static constexpr int MaxHeapAllocs = 512;
|
static constexpr int MaxHeapAllocs = 512;
|
||||||
|
|
||||||
static HeapAlloc g_heapAllocs[Sched::MaxProcesses][MaxHeapAllocs];
|
inline HeapAlloc g_heapAllocs[Sched::MaxProcesses][MaxHeapAllocs] = {};
|
||||||
static int g_heapAllocCount[Sched::MaxProcesses];
|
inline int g_heapAllocCount[Sched::MaxProcesses] = {};
|
||||||
|
|
||||||
// Get the process table slot index for the current process
|
// Get the process table slot index for the current process
|
||||||
static int GetCurrentSlot() {
|
inline int GetCurrentSlot() {
|
||||||
auto* proc = Sched::GetCurrentProcessPtr();
|
auto* proc = Sched::GetCurrentProcessPtr();
|
||||||
if (proc == nullptr) return -1;
|
if (proc == nullptr) return -1;
|
||||||
// Process slot index = pointer offset from slot 0
|
// Process slot index = pointer offset from slot 0
|
||||||
@@ -32,9 +32,11 @@ namespace Montauk {
|
|||||||
return (int)(proc - slot0);
|
return (int)(proc - slot0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t Sys_Alloc(uint64_t size) {
|
inline uint64_t Sys_Alloc(uint64_t size) {
|
||||||
auto* proc = Sched::GetCurrentProcessPtr();
|
auto* proc = Sched::GetCurrentProcessPtr();
|
||||||
if (proc == nullptr) return 0;
|
if (proc == nullptr) return 0;
|
||||||
|
int slot = GetCurrentSlot();
|
||||||
|
if (slot < 0) return 0;
|
||||||
|
|
||||||
// Guard against overflow before rounding
|
// Guard against overflow before rounding
|
||||||
static constexpr uint64_t USER_SPACE_END = 0x0000800000000000ULL;
|
static constexpr uint64_t USER_SPACE_END = 0x0000800000000000ULL;
|
||||||
@@ -50,36 +52,57 @@ namespace Montauk {
|
|||||||
if (userVa + size < userVa || userVa + size > USER_SPACE_END) return 0;
|
if (userVa + size < userVa || userVa + size > USER_SPACE_END) return 0;
|
||||||
|
|
||||||
uint64_t numPages = size / 0x1000;
|
uint64_t numPages = size / 0x1000;
|
||||||
|
if (g_heapAllocCount[slot] >= MaxHeapAllocs) return 0;
|
||||||
|
|
||||||
// Allocate physical pages and map them into the process
|
// Allocate physical pages and map them into the process
|
||||||
|
uint64_t mappedPages = 0;
|
||||||
for (uint64_t i = 0; i < numPages; i++) {
|
for (uint64_t i = 0; i < numPages; i++) {
|
||||||
void* page = Memory::g_pfa->AllocateZeroed();
|
void* page = Memory::g_pfa->AllocateZeroed();
|
||||||
if (page == nullptr) return 0;
|
if (page == nullptr) {
|
||||||
|
for (uint64_t j = 0; j < mappedPages; j++) {
|
||||||
|
uint64_t pageVa = userVa + j * 0x1000;
|
||||||
|
uint64_t physAddr = Memory::VMM::Paging::GetPhysAddr(proc->pml4Phys, pageVa);
|
||||||
|
if (physAddr != 0) {
|
||||||
|
Memory::g_pfa->Free((void*)Memory::HHDM(physAddr));
|
||||||
|
}
|
||||||
|
Memory::VMM::Paging::UnmapUserIn(proc->pml4Phys, pageVa);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
uint64_t physAddr = Memory::SubHHDM((uint64_t)page);
|
uint64_t physAddr = Memory::SubHHDM((uint64_t)page);
|
||||||
if (!Memory::VMM::Paging::MapUserIn(proc->pml4Phys, physAddr, userVa + i * 0x1000)) return 0;
|
if (!Memory::VMM::Paging::MapUserIn(proc->pml4Phys, physAddr, userVa + i * 0x1000)) {
|
||||||
|
Memory::g_pfa->Free(page);
|
||||||
|
for (uint64_t j = 0; j < mappedPages; j++) {
|
||||||
|
uint64_t pageVa = userVa + j * 0x1000;
|
||||||
|
uint64_t mappedPhys = Memory::VMM::Paging::GetPhysAddr(proc->pml4Phys, pageVa);
|
||||||
|
if (mappedPhys != 0) {
|
||||||
|
Memory::g_pfa->Free((void*)Memory::HHDM(mappedPhys));
|
||||||
|
}
|
||||||
|
Memory::VMM::Paging::UnmapUserIn(proc->pml4Phys, pageVa);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
mappedPages++;
|
||||||
}
|
}
|
||||||
|
|
||||||
proc->heapNext += size;
|
proc->heapNext += size;
|
||||||
|
|
||||||
// Track the allocation so Sys_Free can release it
|
// Track the allocation so Sys_Free can release it
|
||||||
int slot = GetCurrentSlot();
|
Sched::g_allocatedPages[slot] += numPages;
|
||||||
if (slot >= 0) Sched::g_allocatedPages[slot] += numPages;
|
|
||||||
if (slot >= 0 && g_heapAllocCount[slot] < MaxHeapAllocs) {
|
|
||||||
g_heapAllocs[slot][g_heapAllocCount[slot]++] = { userVa, numPages };
|
g_heapAllocs[slot][g_heapAllocCount[slot]++] = { userVa, numPages };
|
||||||
}
|
|
||||||
|
|
||||||
return userVa;
|
return userVa;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset heap allocation tracking for a process slot.
|
// Reset heap allocation tracking for a process slot.
|
||||||
// The actual physical pages are freed by Paging::FreeUserHalf() during process cleanup.
|
// The actual physical pages are freed by Paging::FreeUserHalf() during process cleanup.
|
||||||
static void CleanupHeapForSlot(int slot, uint64_t /*pml4Phys*/) {
|
inline void CleanupHeapForSlot(int slot, uint64_t /*pml4Phys*/) {
|
||||||
if (slot < 0 || slot >= Sched::MaxProcesses) return;
|
if (slot < 0 || slot >= Sched::MaxProcesses) return;
|
||||||
g_heapAllocCount[slot] = 0;
|
g_heapAllocCount[slot] = 0;
|
||||||
Sched::g_allocatedPages[slot] = 0;
|
Sched::g_allocatedPages[slot] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Sys_Free(uint64_t addr) {
|
inline void Sys_Free(uint64_t addr) {
|
||||||
auto* proc = Sched::GetCurrentProcessPtr();
|
auto* proc = Sched::GetCurrentProcessPtr();
|
||||||
if (proc == nullptr) return;
|
if (proc == nullptr) return;
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace Montauk {
|
|||||||
|
|
||||||
// Maximum libraries per process
|
// Maximum libraries per process
|
||||||
static constexpr int MaxLibsPerProcess = 8;
|
static constexpr int MaxLibsPerProcess = 8;
|
||||||
static constexpr int MaxProcesses = 64;
|
static constexpr int MaxProcesses = Sched::MaxProcesses;
|
||||||
|
|
||||||
// Library entry tracking
|
// Library entry tracking
|
||||||
struct LibEntry {
|
struct LibEntry {
|
||||||
@@ -28,15 +28,15 @@ namespace Montauk {
|
|||||||
bool inUse;
|
bool inUse;
|
||||||
};
|
};
|
||||||
|
|
||||||
static uint64_t GetLibSlotBase(int libSlot) {
|
inline uint64_t GetLibSlotBase(int libSlot) {
|
||||||
return Sched::LIB_BASE + (uint64_t(libSlot) * Sched::LIB_MAX_SIZE);
|
return Sched::LIB_BASE + (uint64_t(libSlot) * Sched::LIB_MAX_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Per-process library table
|
// Per-process library table
|
||||||
static LibEntry g_libTable[MaxProcesses][MaxLibsPerProcess];
|
inline LibEntry g_libTable[MaxProcesses][MaxLibsPerProcess] = {};
|
||||||
|
|
||||||
// Initialize library table for a process slot
|
// Initialize library table for a process slot
|
||||||
static void InitLibTable(int slot) {
|
inline void InitLibTable(int slot) {
|
||||||
if (slot < 0 || slot >= MaxProcesses) return;
|
if (slot < 0 || slot >= MaxProcesses) return;
|
||||||
for (int i = 0; i < MaxLibsPerProcess; i++) {
|
for (int i = 0; i < MaxLibsPerProcess; i++) {
|
||||||
g_libTable[slot][i].inUse = false;
|
g_libTable[slot][i].inUse = false;
|
||||||
@@ -49,7 +49,7 @@ namespace Montauk {
|
|||||||
// Load a shared library into the current process's address space.
|
// Load a shared library into the current process's address space.
|
||||||
// Returns a library handle (slot index + 1) on success, or 0 on failure.
|
// Returns a library handle (slot index + 1) on success, or 0 on failure.
|
||||||
// The library is loaded at a fixed address based on the slot.
|
// The library is loaded at a fixed address based on the slot.
|
||||||
static uint64_t Sys_LoadLib(const char* path) {
|
inline uint64_t Sys_LoadLib(const char* path) {
|
||||||
int slot = GetCurrentSlot();
|
int slot = GetCurrentSlot();
|
||||||
if (slot < 0) return 0;
|
if (slot < 0) return 0;
|
||||||
|
|
||||||
@@ -100,7 +100,7 @@ namespace Montauk {
|
|||||||
|
|
||||||
// Unload a shared library.
|
// Unload a shared library.
|
||||||
// Decrements refcount; actually unmaps when refcount reaches 0.
|
// Decrements refcount; actually unmaps when refcount reaches 0.
|
||||||
static int Sys_UnloadLib(uint64_t handle) {
|
inline int Sys_UnloadLib(uint64_t handle) {
|
||||||
int slot = GetCurrentSlot();
|
int slot = GetCurrentSlot();
|
||||||
if (slot < 0) return -1;
|
if (slot < 0) return -1;
|
||||||
|
|
||||||
@@ -139,7 +139,7 @@ namespace Montauk {
|
|||||||
// handle = library handle from LoadLib
|
// handle = library handle from LoadLib
|
||||||
// symbolOffset = ELF symbol value from the library's symbol table
|
// symbolOffset = ELF symbol value from the library's symbol table
|
||||||
// Returns the virtual address of the symbol, or 0 if not found.
|
// Returns the virtual address of the symbol, or 0 if not found.
|
||||||
static uint64_t Sys_DLSym(uint64_t handle, uint64_t symbolOffset) {
|
inline uint64_t Sys_DLSym(uint64_t handle, uint64_t symbolOffset) {
|
||||||
int slot = GetCurrentSlot();
|
int slot = GetCurrentSlot();
|
||||||
if (slot < 0) return 0;
|
if (slot < 0) return 0;
|
||||||
|
|
||||||
@@ -153,7 +153,7 @@ namespace Montauk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get library relocation base / load bias (for userspace symbol resolution)
|
// Get library relocation base / load bias (for userspace symbol resolution)
|
||||||
static uint64_t Sys_GetLibBase(uint64_t handle) {
|
inline uint64_t Sys_GetLibBase(uint64_t handle) {
|
||||||
int slot = GetCurrentSlot();
|
int slot = GetCurrentSlot();
|
||||||
if (slot < 0) return 0;
|
if (slot < 0) return 0;
|
||||||
|
|
||||||
@@ -166,7 +166,7 @@ namespace Montauk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Cleanup library table for a process slot
|
// Cleanup library table for a process slot
|
||||||
static void CleanupLibTable(int slot) {
|
inline void CleanupLibTable(int slot) {
|
||||||
if (slot < 0 || slot >= MaxProcesses) return;
|
if (slot < 0 || slot >= MaxProcesses) return;
|
||||||
|
|
||||||
auto* proc = Sched::GetProcessSlot(slot);
|
auto* proc = Sched::GetProcessSlot(slot);
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include <Fs/FsProbe.hpp>
|
#include <Fs/FsProbe.hpp>
|
||||||
#include <Fs/Fat32.hpp>
|
#include <Fs/Fat32.hpp>
|
||||||
#include <Fs/Ext2.hpp>
|
#include <Fs/Ext2.hpp>
|
||||||
|
#include <Api/UserMemory.hpp>
|
||||||
|
|
||||||
#include "Syscall.hpp"
|
#include "Syscall.hpp"
|
||||||
|
|
||||||
@@ -25,6 +26,7 @@ namespace Montauk {
|
|||||||
// Fill a user buffer with partition info. Returns the number of entries written.
|
// Fill a user buffer with partition info. Returns the number of entries written.
|
||||||
static int Sys_PartList(PartInfo* buf, int maxCount) {
|
static int Sys_PartList(PartInfo* buf, int maxCount) {
|
||||||
if (buf == nullptr || maxCount <= 0) return 0;
|
if (buf == nullptr || maxCount <= 0) return 0;
|
||||||
|
if (!UserMemory::Range((uint64_t)buf, (uint64_t)maxCount * sizeof(PartInfo), true)) return -1;
|
||||||
|
|
||||||
int total = Drivers::Storage::Gpt::GetPartitionCount();
|
int total = Drivers::Storage::Gpt::GetPartitionCount();
|
||||||
int count = total < maxCount ? total : maxCount;
|
int count = total < maxCount ? total : maxCount;
|
||||||
@@ -61,6 +63,7 @@ namespace Montauk {
|
|||||||
if (!dev) return -1;
|
if (!dev) return -1;
|
||||||
|
|
||||||
if (lba + count > dev->SectorCount) return -1;
|
if (lba + count > dev->SectorCount) return -1;
|
||||||
|
if (!UserMemory::Range((uint64_t)buffer, (uint64_t)count * dev->SectorSize, true)) return -1;
|
||||||
|
|
||||||
if (!dev->ReadSectors(dev->Ctx, lba, count, buffer)) return -1;
|
if (!dev->ReadSectors(dev->Ctx, lba, count, buffer)) return -1;
|
||||||
|
|
||||||
@@ -76,6 +79,7 @@ namespace Montauk {
|
|||||||
if (!dev) return -1;
|
if (!dev) return -1;
|
||||||
|
|
||||||
if (lba + count > dev->SectorCount) return -1;
|
if (lba + count > dev->SectorCount) return -1;
|
||||||
|
if (!UserMemory::Range((uint64_t)buffer, (uint64_t)count * dev->SectorSize, false)) return -1;
|
||||||
|
|
||||||
if (!dev->WriteSectors(dev->Ctx, lba, count, buffer)) return -1;
|
if (!dev->WriteSectors(dev->Ctx, lba, count, buffer)) return -1;
|
||||||
|
|
||||||
|
|||||||
+112
-112
@@ -36,40 +36,25 @@
|
|||||||
#include "LibSyscall.hpp" // SYS_LOAD_LIB, SYS_UNLOAD_LIB, SYS_DLSYM
|
#include "LibSyscall.hpp" // SYS_LOAD_LIB, SYS_UNLOAD_LIB, SYS_DLSYM
|
||||||
#include "CrashReportSyscall.hpp" // SYS_CRASH_REPORT
|
#include "CrashReportSyscall.hpp" // SYS_CRASH_REPORT
|
||||||
#include "Clipboard.hpp" // SYS_CLIPBOARD_*
|
#include "Clipboard.hpp" // SYS_CLIPBOARD_*
|
||||||
|
#include "UserMemory.hpp"
|
||||||
|
|
||||||
// Assembly entry point
|
// Assembly entry point
|
||||||
extern "C" void SyscallEntry();
|
extern "C" void SyscallEntry();
|
||||||
|
|
||||||
namespace Montauk {
|
namespace Montauk {
|
||||||
|
|
||||||
// ---- User pointer validation ----
|
static constexpr uint64_t kMaxPrintableStringBytes = 4096;
|
||||||
// Reject pointers that fall in the kernel-half of the address space
|
static constexpr uint64_t kMaxPathBytes = 256;
|
||||||
// (canonical high addresses, i.e. >= 0x0000800000000000).
|
static constexpr uint64_t kMaxArgsBytes = 256;
|
||||||
// This prevents userspace from tricking the kernel into reading/writing
|
static constexpr uint64_t kMaxWindowTitleBytes = 256;
|
||||||
// kernel memory via syscall arguments.
|
static constexpr uint64_t kMaxHostnameBytes = 256;
|
||||||
|
static constexpr uint64_t kMaxUserNameBytes = 32;
|
||||||
static constexpr uint64_t USER_SPACE_END = 0x0000800000000000ULL;
|
|
||||||
|
|
||||||
static bool IsUserPtr(uint64_t addr) {
|
|
||||||
return addr == 0 || addr < USER_SPACE_END;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate that a pointer is non-null and in user space
|
|
||||||
static bool ValidUserPtr(uint64_t addr) {
|
|
||||||
return addr != 0 && addr < USER_SPACE_END;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---- Dispatch ----
|
// ---- Dispatch ----
|
||||||
|
|
||||||
extern "C" int64_t SyscallDispatch(SyscallFrame* frame) {
|
extern "C" int64_t SyscallDispatch(SyscallFrame* frame) {
|
||||||
switch (frame->syscall_nr) {
|
switch (frame->syscall_nr) {
|
||||||
case SYS_EXIT: {
|
case SYS_EXIT: {
|
||||||
int slot = GetCurrentSlot();
|
|
||||||
auto* proc = Sched::GetCurrentProcessPtr();
|
|
||||||
if (slot >= 0 && proc)
|
|
||||||
CleanupHeapForSlot(slot, proc->pml4Phys);
|
|
||||||
if (slot >= 0)
|
|
||||||
CleanupLibTable(slot);
|
|
||||||
Sys_Exit((int)frame->arg1);
|
Sys_Exit((int)frame->arg1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -82,17 +67,17 @@ namespace Montauk {
|
|||||||
case SYS_GETPID:
|
case SYS_GETPID:
|
||||||
return (int64_t)Sys_GetPid();
|
return (int64_t)Sys_GetPid();
|
||||||
case SYS_PRINT:
|
case SYS_PRINT:
|
||||||
if (!ValidUserPtr(frame->arg1)) return -1;
|
if (!UserMemory::String(frame->arg1, kMaxPrintableStringBytes)) return -1;
|
||||||
Sys_Print((const char*)frame->arg1);
|
Sys_Print((const char*)frame->arg1);
|
||||||
return 0;
|
return 0;
|
||||||
case SYS_PUTCHAR:
|
case SYS_PUTCHAR:
|
||||||
Sys_Putchar((char)frame->arg1);
|
Sys_Putchar((char)frame->arg1);
|
||||||
return 0;
|
return 0;
|
||||||
case SYS_OPEN:
|
case SYS_OPEN:
|
||||||
if (!ValidUserPtr(frame->arg1)) return -1;
|
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return -1;
|
||||||
return (int64_t)Sys_Open((const char*)frame->arg1);
|
return (int64_t)Sys_Open((const char*)frame->arg1);
|
||||||
case SYS_READ:
|
case SYS_READ:
|
||||||
if (!ValidUserPtr(frame->arg2)) return -1;
|
if (!UserMemory::Range(frame->arg2, frame->arg4, true)) return -1;
|
||||||
return (int64_t)Sys_Read((int)frame->arg1, (uint8_t*)frame->arg2,
|
return (int64_t)Sys_Read((int)frame->arg1, (uint8_t*)frame->arg2,
|
||||||
frame->arg3, frame->arg4);
|
frame->arg3, frame->arg4);
|
||||||
case SYS_GETSIZE:
|
case SYS_GETSIZE:
|
||||||
@@ -101,7 +86,13 @@ namespace Montauk {
|
|||||||
Sys_Close((int)frame->arg1);
|
Sys_Close((int)frame->arg1);
|
||||||
return 0;
|
return 0;
|
||||||
case SYS_READDIR:
|
case SYS_READDIR:
|
||||||
if (!ValidUserPtr(frame->arg1) || !ValidUserPtr(frame->arg2)) return -1;
|
if ((int64_t)frame->arg3 < 0) return -1;
|
||||||
|
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return -1;
|
||||||
|
if (!UserMemory::Range(frame->arg2,
|
||||||
|
(uint64_t)((frame->arg3 > 256) ? 256 : frame->arg3) * sizeof(const char*),
|
||||||
|
true)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
return (int64_t)Sys_ReadDir((const char*)frame->arg1,
|
return (int64_t)Sys_ReadDir((const char*)frame->arg1,
|
||||||
(const char**)frame->arg2,
|
(const char**)frame->arg2,
|
||||||
(int)frame->arg3);
|
(int)frame->arg3);
|
||||||
@@ -115,13 +106,13 @@ namespace Montauk {
|
|||||||
case SYS_GETMILLISECONDS:
|
case SYS_GETMILLISECONDS:
|
||||||
return (int64_t)Sys_GetMilliseconds();
|
return (int64_t)Sys_GetMilliseconds();
|
||||||
case SYS_GETINFO:
|
case SYS_GETINFO:
|
||||||
if (!ValidUserPtr(frame->arg1)) return -1;
|
if (!UserMemory::Writable<SysInfo>(frame->arg1)) return -1;
|
||||||
Sys_GetInfo((SysInfo*)frame->arg1);
|
Sys_GetInfo((SysInfo*)frame->arg1);
|
||||||
return 0;
|
return 0;
|
||||||
case SYS_ISKEYAVAILABLE:
|
case SYS_ISKEYAVAILABLE:
|
||||||
return (int64_t)Sys_IsKeyAvailable();
|
return (int64_t)Sys_IsKeyAvailable();
|
||||||
case SYS_GETKEY:
|
case SYS_GETKEY:
|
||||||
if (!ValidUserPtr(frame->arg1)) return -1;
|
if (!UserMemory::Writable<KeyEvent>(frame->arg1)) return -1;
|
||||||
Sys_GetKey((KeyEvent*)frame->arg1);
|
Sys_GetKey((KeyEvent*)frame->arg1);
|
||||||
return 0;
|
return 0;
|
||||||
case SYS_GETCHAR:
|
case SYS_GETCHAR:
|
||||||
@@ -129,14 +120,15 @@ namespace Montauk {
|
|||||||
case SYS_PING:
|
case SYS_PING:
|
||||||
return (int64_t)Sys_Ping((uint32_t)frame->arg1, (uint32_t)frame->arg2);
|
return (int64_t)Sys_Ping((uint32_t)frame->arg1, (uint32_t)frame->arg2);
|
||||||
case SYS_SPAWN:
|
case SYS_SPAWN:
|
||||||
if (!ValidUserPtr(frame->arg1)) return -1;
|
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return -1;
|
||||||
|
if (frame->arg2 != 0 && !UserMemory::String(frame->arg2, kMaxArgsBytes)) return -1;
|
||||||
return (int64_t)Sys_Spawn((const char*)frame->arg1,
|
return (int64_t)Sys_Spawn((const char*)frame->arg1,
|
||||||
IsUserPtr(frame->arg2) ? (const char*)frame->arg2 : nullptr);
|
UserMemory::IsUserPtr(frame->arg2) ? (const char*)frame->arg2 : nullptr);
|
||||||
case SYS_WAITPID:
|
case SYS_WAITPID:
|
||||||
Sys_WaitPid((int)frame->arg1);
|
Sys_WaitPid((int)frame->arg1);
|
||||||
return 0;
|
return 0;
|
||||||
case SYS_FBINFO:
|
case SYS_FBINFO:
|
||||||
if (!ValidUserPtr(frame->arg1)) return -1;
|
if (!UserMemory::Writable<FbInfo>(frame->arg1)) return -1;
|
||||||
Sys_FbInfo((FbInfo*)frame->arg1);
|
Sys_FbInfo((FbInfo*)frame->arg1);
|
||||||
return 0;
|
return 0;
|
||||||
case SYS_FBMAP:
|
case SYS_FBMAP:
|
||||||
@@ -144,7 +136,7 @@ namespace Montauk {
|
|||||||
case SYS_TERMSIZE:
|
case SYS_TERMSIZE:
|
||||||
return (int64_t)Sys_TermSize();
|
return (int64_t)Sys_TermSize();
|
||||||
case SYS_GETARGS:
|
case SYS_GETARGS:
|
||||||
if (!ValidUserPtr(frame->arg1)) return -1;
|
if (!UserMemory::Range(frame->arg1, frame->arg2, true)) return -1;
|
||||||
return (int64_t)Sys_GetArgs((char*)frame->arg1, frame->arg2);
|
return (int64_t)Sys_GetArgs((char*)frame->arg1, frame->arg2);
|
||||||
case SYS_RESET:
|
case SYS_RESET:
|
||||||
Sys_Reset();
|
Sys_Reset();
|
||||||
@@ -153,7 +145,7 @@ namespace Montauk {
|
|||||||
Sys_Shutdown();
|
Sys_Shutdown();
|
||||||
return 0;
|
return 0;
|
||||||
case SYS_GETTIME:
|
case SYS_GETTIME:
|
||||||
if (!ValidUserPtr(frame->arg1)) return -1;
|
if (!UserMemory::Writable<DateTime>(frame->arg1)) return -1;
|
||||||
Sys_GetTime((DateTime*)frame->arg1);
|
Sys_GetTime((DateTime*)frame->arg1);
|
||||||
return 0;
|
return 0;
|
||||||
case SYS_SOCKET:
|
case SYS_SOCKET:
|
||||||
@@ -167,87 +159,94 @@ namespace Montauk {
|
|||||||
case SYS_ACCEPT:
|
case SYS_ACCEPT:
|
||||||
return (int64_t)Sys_Accept((int)frame->arg1);
|
return (int64_t)Sys_Accept((int)frame->arg1);
|
||||||
case SYS_SEND:
|
case SYS_SEND:
|
||||||
if (!ValidUserPtr(frame->arg2)) return -1;
|
if (!UserMemory::Range(frame->arg2, frame->arg3, false)) return -1;
|
||||||
return (int64_t)Sys_Send((int)frame->arg1, (const uint8_t*)frame->arg2, (uint32_t)frame->arg3);
|
return (int64_t)Sys_Send((int)frame->arg1, (const uint8_t*)frame->arg2, (uint32_t)frame->arg3);
|
||||||
case SYS_RECV:
|
case SYS_RECV:
|
||||||
if (!ValidUserPtr(frame->arg2)) return -1;
|
if (!UserMemory::Range(frame->arg2, frame->arg3, true)) return -1;
|
||||||
return (int64_t)Sys_Recv((int)frame->arg1, (uint8_t*)frame->arg2, (uint32_t)frame->arg3);
|
return (int64_t)Sys_Recv((int)frame->arg1, (uint8_t*)frame->arg2, (uint32_t)frame->arg3);
|
||||||
case SYS_CLOSESOCK:
|
case SYS_CLOSESOCK:
|
||||||
Sys_CloseSock((int)frame->arg1);
|
Sys_CloseSock((int)frame->arg1);
|
||||||
return 0;
|
return 0;
|
||||||
case SYS_GETNETCFG:
|
case SYS_GETNETCFG:
|
||||||
if (!ValidUserPtr(frame->arg1)) return -1;
|
if (!UserMemory::Writable<NetCfg>(frame->arg1)) return -1;
|
||||||
Sys_GetNetCfg((NetCfg*)frame->arg1);
|
Sys_GetNetCfg((NetCfg*)frame->arg1);
|
||||||
return 0;
|
return 0;
|
||||||
case SYS_SETNETCFG:
|
case SYS_SETNETCFG:
|
||||||
if (!ValidUserPtr(frame->arg1)) return -1;
|
if (!UserMemory::Readable<NetCfg>(frame->arg1)) return -1;
|
||||||
return (int64_t)Sys_SetNetCfg((const NetCfg*)frame->arg1);
|
return (int64_t)Sys_SetNetCfg((const NetCfg*)frame->arg1);
|
||||||
case SYS_SENDTO:
|
case SYS_SENDTO:
|
||||||
if (!ValidUserPtr(frame->arg2)) return -1;
|
if (!UserMemory::Range(frame->arg2, frame->arg3, false)) return -1;
|
||||||
return (int64_t)Sys_SendTo((int)frame->arg1, (const uint8_t*)frame->arg2,
|
return (int64_t)Sys_SendTo((int)frame->arg1, (const uint8_t*)frame->arg2,
|
||||||
(uint32_t)frame->arg3, (uint32_t)frame->arg4,
|
(uint32_t)frame->arg3, (uint32_t)frame->arg4,
|
||||||
(uint16_t)frame->arg5);
|
(uint16_t)frame->arg5);
|
||||||
case SYS_RECVFROM:
|
case SYS_RECVFROM:
|
||||||
if (!ValidUserPtr(frame->arg2)) return -1;
|
if (!UserMemory::Range(frame->arg2, frame->arg3, true)) return -1;
|
||||||
|
if (!UserMemory::OptionalRange(frame->arg4, sizeof(uint32_t), true)) return -1;
|
||||||
|
if (!UserMemory::OptionalRange(frame->arg5, sizeof(uint16_t), true)) return -1;
|
||||||
return (int64_t)Sys_RecvFrom((int)frame->arg1, (uint8_t*)frame->arg2,
|
return (int64_t)Sys_RecvFrom((int)frame->arg1, (uint8_t*)frame->arg2,
|
||||||
(uint32_t)frame->arg3,
|
(uint32_t)frame->arg3,
|
||||||
IsUserPtr(frame->arg4) ? (uint32_t*)frame->arg4 : nullptr,
|
UserMemory::IsUserPtr(frame->arg4) ? (uint32_t*)frame->arg4 : nullptr,
|
||||||
IsUserPtr(frame->arg5) ? (uint16_t*)frame->arg5 : nullptr);
|
UserMemory::IsUserPtr(frame->arg5) ? (uint16_t*)frame->arg5 : nullptr);
|
||||||
case SYS_FWRITE:
|
case SYS_FWRITE:
|
||||||
if (!ValidUserPtr(frame->arg2)) return -1;
|
if (!UserMemory::Range(frame->arg2, frame->arg4, false)) return -1;
|
||||||
return (int64_t)Sys_FWrite((int)frame->arg1, (const uint8_t*)frame->arg2,
|
return (int64_t)Sys_FWrite((int)frame->arg1, (const uint8_t*)frame->arg2,
|
||||||
frame->arg3, frame->arg4);
|
frame->arg3, frame->arg4);
|
||||||
case SYS_FCREATE:
|
case SYS_FCREATE:
|
||||||
if (!ValidUserPtr(frame->arg1)) return -1;
|
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return -1;
|
||||||
return (int64_t)Sys_FCreate((const char*)frame->arg1);
|
return (int64_t)Sys_FCreate((const char*)frame->arg1);
|
||||||
case SYS_FDELETE:
|
case SYS_FDELETE:
|
||||||
if (!ValidUserPtr(frame->arg1)) return -1;
|
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return -1;
|
||||||
return (int64_t)Sys_FDelete((const char*)frame->arg1);
|
return (int64_t)Sys_FDelete((const char*)frame->arg1);
|
||||||
case SYS_FMKDIR:
|
case SYS_FMKDIR:
|
||||||
if (!ValidUserPtr(frame->arg1)) return -1;
|
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return -1;
|
||||||
return (int64_t)Sys_FMkdir((const char*)frame->arg1);
|
return (int64_t)Sys_FMkdir((const char*)frame->arg1);
|
||||||
case SYS_FRENAME:
|
case SYS_FRENAME:
|
||||||
if (!ValidUserPtr(frame->arg1)) return -1;
|
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return -1;
|
||||||
if (!ValidUserPtr(frame->arg2)) return -1;
|
if (!UserMemory::String(frame->arg2, kMaxPathBytes)) return -1;
|
||||||
return (int64_t)Sys_FRename((const char*)frame->arg1, (const char*)frame->arg2);
|
return (int64_t)Sys_FRename((const char*)frame->arg1, (const char*)frame->arg2);
|
||||||
case SYS_DRIVELIST:
|
case SYS_DRIVELIST:
|
||||||
if (!ValidUserPtr(frame->arg1)) return -1;
|
if ((int64_t)frame->arg2 < 0) return -1;
|
||||||
|
if (!UserMemory::Range(frame->arg1, (uint64_t)frame->arg2 * sizeof(int), true)) return -1;
|
||||||
return (int64_t)Sys_DriveList((int*)frame->arg1, (int)frame->arg2);
|
return (int64_t)Sys_DriveList((int*)frame->arg1, (int)frame->arg2);
|
||||||
case SYS_TERMSCALE:
|
case SYS_TERMSCALE:
|
||||||
return Sys_TermScale(frame->arg1, frame->arg2);
|
return Sys_TermScale(frame->arg1, frame->arg2);
|
||||||
case SYS_RESOLVE:
|
case SYS_RESOLVE:
|
||||||
if (!ValidUserPtr(frame->arg1)) return -1;
|
if (!UserMemory::String(frame->arg1, kMaxHostnameBytes)) return -1;
|
||||||
return Sys_Resolve((const char*)frame->arg1);
|
return Sys_Resolve((const char*)frame->arg1);
|
||||||
case SYS_GETRANDOM:
|
case SYS_GETRANDOM:
|
||||||
if (!ValidUserPtr(frame->arg1)) return -1;
|
if (!UserMemory::Range(frame->arg1, frame->arg2, true)) return -1;
|
||||||
return Sys_GetRandom((uint8_t*)frame->arg1, frame->arg2);
|
return Sys_GetRandom((uint8_t*)frame->arg1, frame->arg2);
|
||||||
case SYS_KLOG:
|
case SYS_KLOG:
|
||||||
if (!ValidUserPtr(frame->arg1)) return -1;
|
if (!UserMemory::Range(frame->arg1, frame->arg2, true)) return -1;
|
||||||
return Kt::ReadKernelLog((char*)frame->arg1, frame->arg2);
|
return Kt::ReadKernelLog((char*)frame->arg1, frame->arg2);
|
||||||
case SYS_MOUSESTATE:
|
case SYS_MOUSESTATE:
|
||||||
if (!ValidUserPtr(frame->arg1)) return -1;
|
if (!UserMemory::Writable<MouseState>(frame->arg1)) return -1;
|
||||||
Sys_MouseState((MouseState*)frame->arg1);
|
Sys_MouseState((MouseState*)frame->arg1);
|
||||||
return 0;
|
return 0;
|
||||||
case SYS_SETMOUSEBOUNDS:
|
case SYS_SETMOUSEBOUNDS:
|
||||||
Sys_SetMouseBounds((int32_t)frame->arg1, (int32_t)frame->arg2);
|
Sys_SetMouseBounds((int32_t)frame->arg1, (int32_t)frame->arg2);
|
||||||
return 0;
|
return 0;
|
||||||
case SYS_SPAWN_REDIR:
|
case SYS_SPAWN_REDIR:
|
||||||
if (!ValidUserPtr(frame->arg1)) return -1;
|
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return -1;
|
||||||
|
if (frame->arg2 != 0 && !UserMemory::String(frame->arg2, kMaxArgsBytes)) return -1;
|
||||||
return (int64_t)Sys_SpawnRedir((const char*)frame->arg1,
|
return (int64_t)Sys_SpawnRedir((const char*)frame->arg1,
|
||||||
IsUserPtr(frame->arg2) ? (const char*)frame->arg2 : nullptr);
|
UserMemory::IsUserPtr(frame->arg2) ? (const char*)frame->arg2 : nullptr);
|
||||||
case SYS_CHILDIO_READ:
|
case SYS_CHILDIO_READ:
|
||||||
if (!ValidUserPtr(frame->arg2)) return -1;
|
if ((int64_t)frame->arg3 < 0) return -1;
|
||||||
|
if (!UserMemory::Range(frame->arg2, (uint64_t)frame->arg3, true)) return -1;
|
||||||
return (int64_t)Sys_ChildIoRead((int)frame->arg1, (char*)frame->arg2, (int)frame->arg3);
|
return (int64_t)Sys_ChildIoRead((int)frame->arg1, (char*)frame->arg2, (int)frame->arg3);
|
||||||
case SYS_CHILDIO_WRITE:
|
case SYS_CHILDIO_WRITE:
|
||||||
if (!ValidUserPtr(frame->arg2)) return -1;
|
if ((int64_t)frame->arg3 < 0) return -1;
|
||||||
|
if (!UserMemory::Range(frame->arg2, (uint64_t)frame->arg3, false)) return -1;
|
||||||
return (int64_t)Sys_ChildIoWrite((int)frame->arg1, (const char*)frame->arg2, (int)frame->arg3);
|
return (int64_t)Sys_ChildIoWrite((int)frame->arg1, (const char*)frame->arg2, (int)frame->arg3);
|
||||||
case SYS_CHILDIO_WRITEKEY:
|
case SYS_CHILDIO_WRITEKEY:
|
||||||
if (!ValidUserPtr(frame->arg2)) return -1;
|
if (!UserMemory::Readable<KeyEvent>(frame->arg2)) return -1;
|
||||||
return (int64_t)Sys_ChildIoWriteKey((int)frame->arg1, (const KeyEvent*)frame->arg2);
|
return (int64_t)Sys_ChildIoWriteKey((int)frame->arg1, (const KeyEvent*)frame->arg2);
|
||||||
case SYS_CHILDIO_SETTERMSZ:
|
case SYS_CHILDIO_SETTERMSZ:
|
||||||
return (int64_t)Sys_ChildIoSetTermsz((int)frame->arg1, (int)frame->arg2, (int)frame->arg3);
|
return (int64_t)Sys_ChildIoSetTermsz((int)frame->arg1, (int)frame->arg2, (int)frame->arg3);
|
||||||
case SYS_WINCREATE:
|
case SYS_WINCREATE:
|
||||||
if (!ValidUserPtr(frame->arg1) || !ValidUserPtr(frame->arg4)) return -1;
|
if (!UserMemory::String(frame->arg1, kMaxWindowTitleBytes)) return -1;
|
||||||
|
if (!UserMemory::Writable<WinCreateResult>(frame->arg4)) return -1;
|
||||||
return (int64_t)Sys_WinCreate((const char*)frame->arg1, (int)frame->arg2,
|
return (int64_t)Sys_WinCreate((const char*)frame->arg1, (int)frame->arg2,
|
||||||
(int)frame->arg3, (WinCreateResult*)frame->arg4);
|
(int)frame->arg3, (WinCreateResult*)frame->arg4);
|
||||||
case SYS_WINDESTROY:
|
case SYS_WINDESTROY:
|
||||||
@@ -255,39 +254,33 @@ namespace Montauk {
|
|||||||
case SYS_WINPRESENT:
|
case SYS_WINPRESENT:
|
||||||
return (int64_t)Sys_WinPresent((int)frame->arg1);
|
return (int64_t)Sys_WinPresent((int)frame->arg1);
|
||||||
case SYS_WINPOLL:
|
case SYS_WINPOLL:
|
||||||
if (!ValidUserPtr(frame->arg2)) return -1;
|
if (!UserMemory::Writable<WinEvent>(frame->arg2)) return -1;
|
||||||
return (int64_t)Sys_WinPoll((int)frame->arg1, (WinEvent*)frame->arg2);
|
return (int64_t)Sys_WinPoll((int)frame->arg1, (WinEvent*)frame->arg2);
|
||||||
case SYS_WINENUM:
|
case SYS_WINENUM:
|
||||||
if (!ValidUserPtr(frame->arg1)) return -1;
|
if ((int64_t)frame->arg2 < 0) return -1;
|
||||||
|
if (!UserMemory::Range(frame->arg1, (uint64_t)frame->arg2 * sizeof(WinInfo), true)) return -1;
|
||||||
return (int64_t)Sys_WinEnum((WinInfo*)frame->arg1, (int)frame->arg2);
|
return (int64_t)Sys_WinEnum((WinInfo*)frame->arg1, (int)frame->arg2);
|
||||||
case SYS_WINMAP:
|
case SYS_WINMAP:
|
||||||
return (int64_t)Sys_WinMap((int)frame->arg1);
|
return (int64_t)Sys_WinMap((int)frame->arg1);
|
||||||
case SYS_WINUNMAP:
|
case SYS_WINUNMAP:
|
||||||
return (int64_t)Sys_WinUnmap((int)frame->arg1);
|
return (int64_t)Sys_WinUnmap((int)frame->arg1);
|
||||||
case SYS_WINSENDEVENT:
|
case SYS_WINSENDEVENT:
|
||||||
if (!ValidUserPtr(frame->arg2)) return -1;
|
if (!UserMemory::Readable<WinEvent>(frame->arg2)) return -1;
|
||||||
return (int64_t)Sys_WinSendEvent((int)frame->arg1, (const WinEvent*)frame->arg2);
|
return (int64_t)Sys_WinSendEvent((int)frame->arg1, (const WinEvent*)frame->arg2);
|
||||||
case SYS_WINRESIZE:
|
case SYS_WINRESIZE:
|
||||||
return (int64_t)Sys_WinResize((int)frame->arg1, (int)frame->arg2, (int)frame->arg3);
|
return (int64_t)Sys_WinResize((int)frame->arg1, (int)frame->arg2, (int)frame->arg3);
|
||||||
case SYS_PROCLIST:
|
case SYS_PROCLIST:
|
||||||
if (!ValidUserPtr(frame->arg1)) return -1;
|
if ((int64_t)frame->arg2 < 0) return -1;
|
||||||
|
if (!UserMemory::Range(frame->arg1, (uint64_t)frame->arg2 * sizeof(ProcInfo), true)) return -1;
|
||||||
return (int64_t)Sys_ProcList((ProcInfo*)frame->arg1, (int)frame->arg2);
|
return (int64_t)Sys_ProcList((ProcInfo*)frame->arg1, (int)frame->arg2);
|
||||||
case SYS_KILL: {
|
case SYS_KILL:
|
||||||
// Free heap allocations for the target process before killing it
|
|
||||||
auto* target = Sched::GetProcessByPid((int)frame->arg1);
|
|
||||||
if (target) {
|
|
||||||
auto* slot0 = Sched::GetProcessSlot(0);
|
|
||||||
int targetSlot = (int)(target - slot0);
|
|
||||||
CleanupHeapForSlot(targetSlot, target->pml4Phys);
|
|
||||||
CleanupLibTable(targetSlot);
|
|
||||||
}
|
|
||||||
return (int64_t)Sys_Kill((int)frame->arg1);
|
return (int64_t)Sys_Kill((int)frame->arg1);
|
||||||
}
|
|
||||||
case SYS_DEVLIST:
|
case SYS_DEVLIST:
|
||||||
if (!ValidUserPtr(frame->arg1)) return -1;
|
if ((int64_t)frame->arg2 < 0) return -1;
|
||||||
|
if (!UserMemory::Range(frame->arg1, (uint64_t)frame->arg2 * sizeof(DevInfo), true)) return -1;
|
||||||
return (int64_t)Sys_DevList((DevInfo*)frame->arg1, (int)frame->arg2);
|
return (int64_t)Sys_DevList((DevInfo*)frame->arg1, (int)frame->arg2);
|
||||||
case SYS_DISKINFO:
|
case SYS_DISKINFO:
|
||||||
if (!ValidUserPtr(frame->arg1)) return -1;
|
if (!UserMemory::Writable<DiskInfo>(frame->arg1)) return -1;
|
||||||
return (int64_t)Sys_DiskInfo((DiskInfo*)frame->arg1, (int)frame->arg2);
|
return (int64_t)Sys_DiskInfo((DiskInfo*)frame->arg1, (int)frame->arg2);
|
||||||
case SYS_WINSETSCALE:
|
case SYS_WINSETSCALE:
|
||||||
return (int64_t)Sys_WinSetScale((int)frame->arg1);
|
return (int64_t)Sys_WinSetScale((int)frame->arg1);
|
||||||
@@ -296,53 +289,54 @@ namespace Montauk {
|
|||||||
case SYS_WINSETCURSOR:
|
case SYS_WINSETCURSOR:
|
||||||
return (int64_t)Sys_WinSetCursor((int)frame->arg1, (int)frame->arg2);
|
return (int64_t)Sys_WinSetCursor((int)frame->arg1, (int)frame->arg2);
|
||||||
case SYS_MEMSTATS:
|
case SYS_MEMSTATS:
|
||||||
if (!ValidUserPtr(frame->arg1)) return -1;
|
if (!UserMemory::Writable<MemStats>(frame->arg1)) return -1;
|
||||||
Sys_MemStats((MemStats*)frame->arg1);
|
Sys_MemStats((MemStats*)frame->arg1);
|
||||||
return 0;
|
return 0;
|
||||||
case SYS_PARTLIST:
|
case SYS_PARTLIST:
|
||||||
if (!ValidUserPtr(frame->arg1)) return -1;
|
if ((int64_t)frame->arg2 < 0) return -1;
|
||||||
|
if (!UserMemory::Range(frame->arg1, (uint64_t)frame->arg2 * sizeof(PartInfo), true)) return -1;
|
||||||
return (int64_t)Sys_PartList((PartInfo*)frame->arg1, (int)frame->arg2);
|
return (int64_t)Sys_PartList((PartInfo*)frame->arg1, (int)frame->arg2);
|
||||||
case SYS_DISKREAD:
|
case SYS_DISKREAD:
|
||||||
if (!ValidUserPtr(frame->arg4)) return -1;
|
|
||||||
return (int64_t)Sys_DiskRead((int)frame->arg1, frame->arg2,
|
return (int64_t)Sys_DiskRead((int)frame->arg1, frame->arg2,
|
||||||
(uint32_t)frame->arg3, (void*)frame->arg4);
|
(uint32_t)frame->arg3, (void*)frame->arg4);
|
||||||
case SYS_DISKWRITE:
|
case SYS_DISKWRITE:
|
||||||
if (!ValidUserPtr(frame->arg4)) return -1;
|
|
||||||
return (int64_t)Sys_DiskWrite((int)frame->arg1, frame->arg2,
|
return (int64_t)Sys_DiskWrite((int)frame->arg1, frame->arg2,
|
||||||
(uint32_t)frame->arg3, (const void*)frame->arg4);
|
(uint32_t)frame->arg3, (const void*)frame->arg4);
|
||||||
case SYS_GPTINIT:
|
case SYS_GPTINIT:
|
||||||
return (int64_t)Sys_GptInit((int)frame->arg1);
|
return (int64_t)Sys_GptInit((int)frame->arg1);
|
||||||
case SYS_GPTADD:
|
case SYS_GPTADD:
|
||||||
if (!ValidUserPtr(frame->arg1)) return -1;
|
if (!UserMemory::Readable<GptAddParams>(frame->arg1)) return -1;
|
||||||
return (int64_t)Sys_GptAdd((const GptAddParams*)frame->arg1);
|
return (int64_t)Sys_GptAdd((const GptAddParams*)frame->arg1);
|
||||||
case SYS_FSMOUNT:
|
case SYS_FSMOUNT:
|
||||||
return (int64_t)Sys_FsMount((int)frame->arg1, (int)frame->arg2);
|
return (int64_t)Sys_FsMount((int)frame->arg1, (int)frame->arg2);
|
||||||
case SYS_FSFORMAT:
|
case SYS_FSFORMAT:
|
||||||
if (!ValidUserPtr(frame->arg1)) return -1;
|
if (!UserMemory::Readable<FsFormatParams>(frame->arg1)) return -1;
|
||||||
return (int64_t)Sys_FsFormat((const FsFormatParams*)frame->arg1);
|
return (int64_t)Sys_FsFormat((const FsFormatParams*)frame->arg1);
|
||||||
case SYS_AUDIOOPEN:
|
case SYS_AUDIOOPEN:
|
||||||
return Sys_AudioOpen((uint32_t)frame->arg1, (uint8_t)frame->arg2, (uint8_t)frame->arg3);
|
return Sys_AudioOpen((uint32_t)frame->arg1, (uint8_t)frame->arg2, (uint8_t)frame->arg3);
|
||||||
case SYS_AUDIOCLOSE:
|
case SYS_AUDIOCLOSE:
|
||||||
return Sys_AudioClose((int)frame->arg1);
|
return Sys_AudioClose((int)frame->arg1);
|
||||||
case SYS_AUDIOWRITE:
|
case SYS_AUDIOWRITE:
|
||||||
if (!ValidUserPtr(frame->arg2)) return -1;
|
if (!UserMemory::Range(frame->arg2, frame->arg3, false)) return -1;
|
||||||
return Sys_AudioWrite((int)frame->arg1, (const uint8_t*)frame->arg2, (uint32_t)frame->arg3);
|
return Sys_AudioWrite((int)frame->arg1, (const uint8_t*)frame->arg2, (uint32_t)frame->arg3);
|
||||||
case SYS_AUDIOCTL:
|
case SYS_AUDIOCTL:
|
||||||
return Sys_AudioCtl((int)frame->arg1, (int)frame->arg2, (int)frame->arg3);
|
return Sys_AudioCtl((int)frame->arg1, (int)frame->arg2, (int)frame->arg3);
|
||||||
case SYS_BTSCAN:
|
case SYS_BTSCAN:
|
||||||
if (!ValidUserPtr(frame->arg1)) return -1;
|
if ((int64_t)frame->arg2 < 0) return -1;
|
||||||
|
if (!UserMemory::Range(frame->arg1, (uint64_t)frame->arg2 * sizeof(BtScanResult), true)) return -1;
|
||||||
return Sys_BtScan((BtScanResult*)frame->arg1, (int)frame->arg2, (uint32_t)frame->arg3);
|
return Sys_BtScan((BtScanResult*)frame->arg1, (int)frame->arg2, (uint32_t)frame->arg3);
|
||||||
case SYS_BTCONNECT:
|
case SYS_BTCONNECT:
|
||||||
if (!ValidUserPtr(frame->arg1)) return -1;
|
if (!UserMemory::Range(frame->arg1, 6, false)) return -1;
|
||||||
return Sys_BtConnect((const uint8_t*)frame->arg1);
|
return Sys_BtConnect((const uint8_t*)frame->arg1);
|
||||||
case SYS_BTDISCONNECT:
|
case SYS_BTDISCONNECT:
|
||||||
if (!ValidUserPtr(frame->arg1)) return -1;
|
if (!UserMemory::Range(frame->arg1, 6, false)) return -1;
|
||||||
return Sys_BtDisconnect((const uint8_t*)frame->arg1);
|
return Sys_BtDisconnect((const uint8_t*)frame->arg1);
|
||||||
case SYS_BTLIST:
|
case SYS_BTLIST:
|
||||||
if (!ValidUserPtr(frame->arg1)) return -1;
|
if ((int64_t)frame->arg2 < 0) return -1;
|
||||||
|
if (!UserMemory::Range(frame->arg1, (uint64_t)frame->arg2 * sizeof(BtDevInfo), true)) return -1;
|
||||||
return Sys_BtList((BtDevInfo*)frame->arg1, (int)frame->arg2);
|
return Sys_BtList((BtDevInfo*)frame->arg1, (int)frame->arg2);
|
||||||
case SYS_BTINFO:
|
case SYS_BTINFO:
|
||||||
if (!ValidUserPtr(frame->arg1)) return -1;
|
if (!UserMemory::Writable<BtAdapterInfo>(frame->arg1)) return -1;
|
||||||
return Sys_BtInfo((BtAdapterInfo*)frame->arg1);
|
return Sys_BtInfo((BtAdapterInfo*)frame->arg1);
|
||||||
case SYS_SUSPEND:
|
case SYS_SUSPEND:
|
||||||
return Sys_Suspend();
|
return Sys_Suspend();
|
||||||
@@ -351,48 +345,53 @@ namespace Montauk {
|
|||||||
case SYS_GETTZ:
|
case SYS_GETTZ:
|
||||||
return Sys_GetTZ();
|
return Sys_GetTZ();
|
||||||
case SYS_SETUSER:
|
case SYS_SETUSER:
|
||||||
if (!ValidUserPtr(frame->arg2)) return -1;
|
if (!UserMemory::String(frame->arg2, kMaxUserNameBytes)) return -1;
|
||||||
return Sys_SetUser((int)frame->arg1, (const char*)frame->arg2);
|
return Sys_SetUser((int)frame->arg1, (const char*)frame->arg2);
|
||||||
case SYS_GETUSER:
|
case SYS_GETUSER:
|
||||||
if (!ValidUserPtr(frame->arg1)) return -1;
|
if (!UserMemory::Range(frame->arg1, frame->arg2, true)) return -1;
|
||||||
return Sys_GetUser((char*)frame->arg1, frame->arg2);
|
return Sys_GetUser((char*)frame->arg1, frame->arg2);
|
||||||
case SYS_GETCWD:
|
case SYS_GETCWD:
|
||||||
if (!ValidUserPtr(frame->arg1)) return -1;
|
if (!UserMemory::Range(frame->arg1, frame->arg2, true)) return -1;
|
||||||
return Sys_GetCwd((char*)frame->arg1, frame->arg2);
|
return Sys_GetCwd((char*)frame->arg1, frame->arg2);
|
||||||
case SYS_CHDIR:
|
case SYS_CHDIR:
|
||||||
if (!ValidUserPtr(frame->arg1)) return -1;
|
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return -1;
|
||||||
return Sys_Chdir((const char*)frame->arg1);
|
return Sys_Chdir((const char*)frame->arg1);
|
||||||
case SYS_DUPHANDLE:
|
case SYS_DUPHANDLE:
|
||||||
return Sys_DupHandle((int)frame->arg1);
|
return Sys_DupHandle((int)frame->arg1);
|
||||||
case SYS_WAIT_HANDLE:
|
case SYS_WAIT_HANDLE:
|
||||||
return (int64_t)Sys_WaitHandle((int)frame->arg1, (uint32_t)frame->arg2, frame->arg3);
|
return (int64_t)Sys_WaitHandle((int)frame->arg1, (uint32_t)frame->arg2, frame->arg3);
|
||||||
case SYS_STREAM_CREATE:
|
case SYS_STREAM_CREATE:
|
||||||
if (!ValidUserPtr(frame->arg1) || !ValidUserPtr(frame->arg2)) return -1;
|
if (!UserMemory::Writable<int>(frame->arg1) || !UserMemory::Writable<int>(frame->arg2)) return -1;
|
||||||
return Sys_StreamCreate((int*)frame->arg1, (int*)frame->arg2, (uint32_t)frame->arg3);
|
return Sys_StreamCreate((int*)frame->arg1, (int*)frame->arg2, (uint32_t)frame->arg3);
|
||||||
case SYS_STREAM_READ:
|
case SYS_STREAM_READ:
|
||||||
if (!ValidUserPtr(frame->arg2)) return -1;
|
if ((int64_t)frame->arg3 < 0) return -1;
|
||||||
|
if (!UserMemory::Range(frame->arg2, (uint64_t)frame->arg3, true)) return -1;
|
||||||
return Sys_StreamRead((int)frame->arg1, (uint8_t*)frame->arg2, (int)frame->arg3);
|
return Sys_StreamRead((int)frame->arg1, (uint8_t*)frame->arg2, (int)frame->arg3);
|
||||||
case SYS_STREAM_WRITE:
|
case SYS_STREAM_WRITE:
|
||||||
if (!ValidUserPtr(frame->arg2)) return -1;
|
if ((int64_t)frame->arg3 < 0) return -1;
|
||||||
|
if (!UserMemory::Range(frame->arg2, (uint64_t)frame->arg3, false)) return -1;
|
||||||
return Sys_StreamWrite((int)frame->arg1, (const uint8_t*)frame->arg2, (int)frame->arg3);
|
return Sys_StreamWrite((int)frame->arg1, (const uint8_t*)frame->arg2, (int)frame->arg3);
|
||||||
case SYS_MAILBOX_CREATE:
|
case SYS_MAILBOX_CREATE:
|
||||||
if (!ValidUserPtr(frame->arg1) || !ValidUserPtr(frame->arg2)) return -1;
|
if (!UserMemory::Writable<int>(frame->arg1) || !UserMemory::Writable<int>(frame->arg2)) return -1;
|
||||||
return Sys_MailboxCreate((int*)frame->arg1, (int*)frame->arg2);
|
return Sys_MailboxCreate((int*)frame->arg1, (int*)frame->arg2);
|
||||||
case SYS_MAILBOX_SEND:
|
case SYS_MAILBOX_SEND:
|
||||||
if (frame->arg3 != 0 && !ValidUserPtr(frame->arg3)) return -1;
|
if (frame->arg4 > 0 && !UserMemory::Range(frame->arg3, frame->arg4, false)) return -1;
|
||||||
return Sys_MailboxSend((int)frame->arg1, (uint32_t)frame->arg2,
|
return Sys_MailboxSend((int)frame->arg1, (uint32_t)frame->arg2,
|
||||||
(const void*)frame->arg3, (uint16_t)frame->arg4,
|
(const void*)frame->arg3, (uint16_t)frame->arg4,
|
||||||
(int)frame->arg5);
|
(int)frame->arg5);
|
||||||
case SYS_MAILBOX_RECV:
|
case SYS_MAILBOX_RECV:
|
||||||
if (frame->arg2 != 0 && !IsUserPtr(frame->arg2)) return -1;
|
if (!UserMemory::Writable<uint16_t>(frame->arg4)) return -1;
|
||||||
if (frame->arg3 != 0 && !IsUserPtr(frame->arg3)) return -1;
|
if (frame->arg2 != 0 && !UserMemory::Writable<uint32_t>(frame->arg2)) return -1;
|
||||||
if (!ValidUserPtr(frame->arg4)) return -1;
|
if (frame->arg3 != 0) {
|
||||||
if (frame->arg5 != 0 && !IsUserPtr(frame->arg5)) return -1;
|
uint16_t maxCopy = *(uint16_t*)frame->arg4;
|
||||||
|
if (!UserMemory::Range(frame->arg3, maxCopy, true)) return -1;
|
||||||
|
}
|
||||||
|
if (frame->arg5 != 0 && !UserMemory::Writable<int>(frame->arg5)) return -1;
|
||||||
return Sys_MailboxRecv((int)frame->arg1,
|
return Sys_MailboxRecv((int)frame->arg1,
|
||||||
IsUserPtr(frame->arg2) ? (uint32_t*)frame->arg2 : nullptr,
|
UserMemory::IsUserPtr(frame->arg2) ? (uint32_t*)frame->arg2 : nullptr,
|
||||||
IsUserPtr(frame->arg3) ? (void*)frame->arg3 : nullptr,
|
UserMemory::IsUserPtr(frame->arg3) ? (void*)frame->arg3 : nullptr,
|
||||||
(uint16_t*)frame->arg4,
|
(uint16_t*)frame->arg4,
|
||||||
IsUserPtr(frame->arg5) ? (int*)frame->arg5 : nullptr);
|
UserMemory::IsUserPtr(frame->arg5) ? (int*)frame->arg5 : nullptr);
|
||||||
case SYS_WAITSET_CREATE:
|
case SYS_WAITSET_CREATE:
|
||||||
return Sys_WaitsetCreate();
|
return Sys_WaitsetCreate();
|
||||||
case SYS_WAITSET_ADD:
|
case SYS_WAITSET_ADD:
|
||||||
@@ -400,9 +399,9 @@ namespace Montauk {
|
|||||||
case SYS_WAITSET_REMOVE:
|
case SYS_WAITSET_REMOVE:
|
||||||
return Sys_WaitsetRemove((int)frame->arg1, (int)frame->arg2);
|
return Sys_WaitsetRemove((int)frame->arg1, (int)frame->arg2);
|
||||||
case SYS_WAITSET_WAIT:
|
case SYS_WAITSET_WAIT:
|
||||||
if (frame->arg2 != 0 && !ValidUserPtr(frame->arg2)) return -1;
|
if (frame->arg2 != 0 && !UserMemory::Writable<IpcWaitResult>(frame->arg2)) return -1;
|
||||||
return Sys_WaitsetWait((int)frame->arg1,
|
return Sys_WaitsetWait((int)frame->arg1,
|
||||||
IsUserPtr(frame->arg2) ? (IpcWaitResult*)frame->arg2 : nullptr,
|
UserMemory::IsUserPtr(frame->arg2) ? (IpcWaitResult*)frame->arg2 : nullptr,
|
||||||
frame->arg3);
|
frame->arg3);
|
||||||
case SYS_PROC_OPEN:
|
case SYS_PROC_OPEN:
|
||||||
return Sys_ProcOpen((int)frame->arg1);
|
return Sys_ProcOpen((int)frame->arg1);
|
||||||
@@ -413,7 +412,7 @@ namespace Montauk {
|
|||||||
case SYS_SURFACE_RESIZE:
|
case SYS_SURFACE_RESIZE:
|
||||||
return Sys_SurfaceResize((int)frame->arg1, frame->arg2);
|
return Sys_SurfaceResize((int)frame->arg1, frame->arg2);
|
||||||
case SYS_LOAD_LIB:
|
case SYS_LOAD_LIB:
|
||||||
if (!ValidUserPtr(frame->arg1)) return 0;
|
if (!UserMemory::String(frame->arg1, 128)) return 0;
|
||||||
return (int64_t)Sys_LoadLib((const char*)frame->arg1);
|
return (int64_t)Sys_LoadLib((const char*)frame->arg1);
|
||||||
case SYS_UNLOAD_LIB:
|
case SYS_UNLOAD_LIB:
|
||||||
return Sys_UnloadLib(frame->arg1);
|
return Sys_UnloadLib(frame->arg1);
|
||||||
@@ -422,21 +421,22 @@ namespace Montauk {
|
|||||||
case SYS_GETLIBBASE:
|
case SYS_GETLIBBASE:
|
||||||
return (int64_t)Sys_GetLibBase(frame->arg1);
|
return (int64_t)Sys_GetLibBase(frame->arg1);
|
||||||
case SYS_CRASH_REPORT:
|
case SYS_CRASH_REPORT:
|
||||||
|
if (!UserMemory::Writable<CrashReportInfo>(frame->arg1)) return -1;
|
||||||
return Sys_CrashReport((CrashReportInfo*)frame->arg1);
|
return Sys_CrashReport((CrashReportInfo*)frame->arg1);
|
||||||
case SYS_CLIPBOARD_SET_TEXT:
|
case SYS_CLIPBOARD_SET_TEXT:
|
||||||
if (frame->arg2 > 0 && !ValidUserPtr(frame->arg1)) return -1;
|
if (frame->arg2 > 0 && !UserMemory::Range(frame->arg1, frame->arg2, false)) return -1;
|
||||||
return Sys_ClipboardSetText((const char*)frame->arg1, (uint32_t)frame->arg2);
|
return Sys_ClipboardSetText((const char*)frame->arg1, (uint32_t)frame->arg2);
|
||||||
case SYS_CLIPBOARD_GET_INFO:
|
case SYS_CLIPBOARD_GET_INFO:
|
||||||
if (!ValidUserPtr(frame->arg1)) return -1;
|
if (!UserMemory::Writable<ClipboardInfo>(frame->arg1)) return -1;
|
||||||
return Sys_ClipboardGetInfo((ClipboardInfo*)frame->arg1);
|
return Sys_ClipboardGetInfo((ClipboardInfo*)frame->arg1);
|
||||||
case SYS_CLIPBOARD_GET_TEXT:
|
case SYS_CLIPBOARD_GET_TEXT:
|
||||||
if (frame->arg2 > 0 && !ValidUserPtr(frame->arg1)) return -1;
|
if (frame->arg2 > 0 && !UserMemory::Range(frame->arg1, frame->arg2, true)) return -1;
|
||||||
if (!ValidUserPtr(frame->arg3)) return -1;
|
if (!UserMemory::Writable<uint32_t>(frame->arg3)) return -1;
|
||||||
if (frame->arg4 != 0 && !IsUserPtr(frame->arg4)) return -1;
|
if (frame->arg4 != 0 && !UserMemory::Writable<uint64_t>(frame->arg4)) return -1;
|
||||||
return Sys_ClipboardGetText(IsUserPtr(frame->arg1) ? (char*)frame->arg1 : nullptr,
|
return Sys_ClipboardGetText(UserMemory::IsUserPtr(frame->arg1) ? (char*)frame->arg1 : nullptr,
|
||||||
(uint32_t)frame->arg2,
|
(uint32_t)frame->arg2,
|
||||||
(uint32_t*)frame->arg3,
|
(uint32_t*)frame->arg3,
|
||||||
IsUserPtr(frame->arg4) ? (uint64_t*)frame->arg4 : nullptr);
|
UserMemory::IsUserPtr(frame->arg4) ? (uint64_t*)frame->arg4 : nullptr);
|
||||||
case SYS_CLIPBOARD_CLEAR:
|
case SYS_CLIPBOARD_CLEAR:
|
||||||
return Sys_ClipboardClear();
|
return Sys_ClipboardClear();
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -24,10 +24,15 @@ void operator delete(void* block)
|
|||||||
|
|
||||||
void operator delete[](void* block)
|
void operator delete[](void* block)
|
||||||
{
|
{
|
||||||
delete block;
|
Memory::g_heap->Free(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator delete(void* block, long unsigned int)
|
void operator delete(void* block, long unsigned int)
|
||||||
{
|
{
|
||||||
Memory::g_heap->Free(block);
|
Memory::g_heap->Free(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void operator delete[](void* block, long unsigned int)
|
||||||
|
{
|
||||||
|
Memory::g_heap->Free(block);
|
||||||
|
}
|
||||||
|
|||||||
@@ -20,21 +20,14 @@ namespace kcp
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
class vector {
|
class vector {
|
||||||
protected:
|
protected:
|
||||||
T* array;
|
T* array = nullptr;
|
||||||
std::size_t sz;
|
std::size_t sz = 0;
|
||||||
std::size_t capacity;
|
std::size_t capacity = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
vector()
|
vector() = default;
|
||||||
{
|
|
||||||
sz = 0;
|
|
||||||
array = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
vector(std::initializer_list<T> initList) {
|
vector(std::initializer_list<T> initList) {
|
||||||
sz = 0;
|
|
||||||
array = nullptr;
|
|
||||||
|
|
||||||
for (auto itr = initList.begin(); itr != initList.end(); itr++) {
|
for (auto itr = initList.begin(); itr != initList.end(); itr++) {
|
||||||
T item = *itr;
|
T item = *itr;
|
||||||
push_back(item);
|
push_back(item);
|
||||||
@@ -43,16 +36,13 @@ namespace kcp
|
|||||||
|
|
||||||
T& operator[](std::size_t position)
|
T& operator[](std::size_t position)
|
||||||
{
|
{
|
||||||
if (position > (capacity - 1)) {
|
if (position >= sz || array == nullptr) {
|
||||||
kerr << "Vector out of bounds caught!" << Kt::newline;
|
Panic("Vector out of bounds caught!", nullptr);
|
||||||
|
__builtin_unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
return at(0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return array[position];
|
return array[position];
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
T& at(std::int64_t position) {
|
T& at(std::int64_t position) {
|
||||||
return this->operator[](position);
|
return this->operator[](position);
|
||||||
@@ -62,8 +52,14 @@ namespace kcp
|
|||||||
size_t _sz = sz;
|
size_t _sz = sz;
|
||||||
|
|
||||||
if (capacity < sz + 1) {
|
if (capacity < sz + 1) {
|
||||||
array = (T *)Memory::g_heap->Realloc(array, sizeof(T) * (sz + 1));
|
size_t newCapacity = (capacity == 0) ? 4 : (capacity * 2);
|
||||||
capacity++;
|
T* newArray = (T*)Memory::g_heap->Realloc(array, sizeof(T) * newCapacity);
|
||||||
|
if (newArray == nullptr) {
|
||||||
|
Panic("Vector allocation failed!", nullptr);
|
||||||
|
__builtin_unreachable();
|
||||||
|
}
|
||||||
|
array = newArray;
|
||||||
|
capacity = newCapacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
array[sz++] = value;
|
array[sz++] = value;
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
|
|
||||||
namespace Hal {
|
namespace Hal {
|
||||||
constexpr auto InterruptGate = 0x8E;
|
constexpr auto InterruptGate = 0x8E;
|
||||||
constexpr auto TrapGate = 0x8F;
|
|
||||||
|
|
||||||
InterruptDescriptor* IDT;
|
InterruptDescriptor* IDT;
|
||||||
IDTRStruct IDTR{};
|
IDTRStruct IDTR{};
|
||||||
@@ -53,6 +52,7 @@ namespace Hal {
|
|||||||
"Hypervisor Injection Exception",
|
"Hypervisor Injection Exception",
|
||||||
"VMM Communication Exception",
|
"VMM Communication Exception",
|
||||||
"Security Exception",
|
"Security Exception",
|
||||||
|
"Reserved",
|
||||||
"Reserved"
|
"Reserved"
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -196,7 +196,7 @@ namespace Hal {
|
|||||||
// Use IST1 for NMI (2) and Double Fault (8) so they get a
|
// Use IST1 for NMI (2) and Double Fault (8) so they get a
|
||||||
// known-good stack even if the kernel stack has overflowed.
|
// known-good stack even if the kernel stack has overflowed.
|
||||||
uint8_t ist = (I == 2 || I == 8) ? 1 : 0;
|
uint8_t ist = (I == 2 || I == 8) ? 1 : 0;
|
||||||
IDTEncodeInterrupt(I, (void*)ExceptionHandler<I>, TrapGate, ist);
|
IDTEncodeInterrupt(I, (void*)ExceptionHandler<I>, InterruptGate, ist);
|
||||||
SetHandler<I+1,N>::run();
|
SetHandler<I+1,N>::run();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -211,7 +211,7 @@ namespace Hal {
|
|||||||
IDTR.Base = (uint64_t)IDT;
|
IDTR.Base = (uint64_t)IDT;
|
||||||
Kt::KernelLogStream(Kt::DEBUG, "IDT") << "Set IDTR Base to " << base::hex << IDTR.Base << " and Limit to " << base::hex << IDTR.Limit;
|
Kt::KernelLogStream(Kt::DEBUG, "IDT") << "Set IDTR Base to " << base::hex << IDTR.Base << " and Limit to " << base::hex << IDTR.Limit;
|
||||||
|
|
||||||
SetHandler<0, 31>::run();
|
SetHandler<0, 32>::run();
|
||||||
|
|
||||||
Kt::KernelLogStream(Kt::OK, "Hal") << "Created exception interrupt vectors";
|
Kt::KernelLogStream(Kt::OK, "Hal") << "Created exception interrupt vectors";
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include <CppLib/Spinlock.hpp>
|
#include <CppLib/Spinlock.hpp>
|
||||||
#include <Timekeeping/ApicTimer.hpp>
|
#include <Timekeeping/ApicTimer.hpp>
|
||||||
#include <Terminal/Terminal.hpp>
|
#include <Terminal/Terminal.hpp>
|
||||||
|
#include <Api/UserMemory.hpp>
|
||||||
|
|
||||||
namespace Ipc {
|
namespace Ipc {
|
||||||
|
|
||||||
@@ -697,6 +698,7 @@ namespace Ipc {
|
|||||||
|
|
||||||
int StreamReadHandle(int handle, uint8_t* out, int maxLen) {
|
int StreamReadHandle(int handle, uint8_t* out, int maxLen) {
|
||||||
if (out == nullptr) return -1;
|
if (out == nullptr) return -1;
|
||||||
|
if (maxLen > 0 && !Montauk::UserMemory::Range((uint64_t)out, (uint64_t)maxLen, true)) return -1;
|
||||||
|
|
||||||
HandleType type = HandleType::None;
|
HandleType type = HandleType::None;
|
||||||
Object* object = nullptr;
|
Object* object = nullptr;
|
||||||
@@ -708,6 +710,7 @@ namespace Ipc {
|
|||||||
|
|
||||||
int StreamWriteHandle(int handle, const uint8_t* data, int len) {
|
int StreamWriteHandle(int handle, const uint8_t* data, int len) {
|
||||||
if (data == nullptr) return -1;
|
if (data == nullptr) return -1;
|
||||||
|
if (len > 0 && !Montauk::UserMemory::Range((uint64_t)data, (uint64_t)len, false)) return -1;
|
||||||
|
|
||||||
HandleType type = HandleType::None;
|
HandleType type = HandleType::None;
|
||||||
Object* object = nullptr;
|
Object* object = nullptr;
|
||||||
@@ -908,6 +911,8 @@ namespace Ipc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int MailboxSendHandle(int handle, uint32_t msgType, const void* data, uint16_t len, int attachHandle) {
|
int MailboxSendHandle(int handle, uint32_t msgType, const void* data, uint16_t len, int attachHandle) {
|
||||||
|
if (len > 0 && (data == nullptr || !Montauk::UserMemory::Range((uint64_t)data, len, false))) return -1;
|
||||||
|
|
||||||
HandleType type = HandleType::None;
|
HandleType type = HandleType::None;
|
||||||
Object* object = nullptr;
|
Object* object = nullptr;
|
||||||
uint32_t rights = 0;
|
uint32_t rights = 0;
|
||||||
@@ -918,6 +923,13 @@ namespace Ipc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int MailboxRecvHandle(int handle, uint32_t* msgType, void* data, uint16_t* inOutLen, int* outAttachHandle) {
|
int MailboxRecvHandle(int handle, uint32_t* msgType, void* data, uint16_t* inOutLen, int* outAttachHandle) {
|
||||||
|
if (inOutLen == nullptr || !Montauk::UserMemory::Writable<uint16_t>((uint64_t)inOutLen)) return -1;
|
||||||
|
|
||||||
|
uint16_t requestedLen = *inOutLen;
|
||||||
|
if (msgType != nullptr && !Montauk::UserMemory::Writable<uint32_t>((uint64_t)msgType)) return -1;
|
||||||
|
if (requestedLen > 0 && (data == nullptr || !Montauk::UserMemory::Range((uint64_t)data, requestedLen, true))) return -1;
|
||||||
|
if (outAttachHandle != nullptr && !Montauk::UserMemory::Writable<int>((uint64_t)outAttachHandle)) return -1;
|
||||||
|
|
||||||
HandleType type = HandleType::None;
|
HandleType type = HandleType::None;
|
||||||
Object* object = nullptr;
|
Object* object = nullptr;
|
||||||
uint32_t rights = 0;
|
uint32_t rights = 0;
|
||||||
@@ -978,6 +990,7 @@ namespace Ipc {
|
|||||||
|
|
||||||
int FileReadHandle(int handle, uint8_t* buffer, uint64_t offset, uint64_t size) {
|
int FileReadHandle(int handle, uint8_t* buffer, uint64_t offset, uint64_t size) {
|
||||||
if (buffer == nullptr) return -1;
|
if (buffer == nullptr) return -1;
|
||||||
|
if (size > 0 && !Montauk::UserMemory::Range((uint64_t)buffer, size, true)) return -1;
|
||||||
|
|
||||||
HandleType type = HandleType::None;
|
HandleType type = HandleType::None;
|
||||||
Object* object = nullptr;
|
Object* object = nullptr;
|
||||||
@@ -989,6 +1002,7 @@ namespace Ipc {
|
|||||||
|
|
||||||
int FileWriteHandle(int handle, const uint8_t* buffer, uint64_t offset, uint64_t size) {
|
int FileWriteHandle(int handle, const uint8_t* buffer, uint64_t offset, uint64_t size) {
|
||||||
if (buffer == nullptr) return -1;
|
if (buffer == nullptr) return -1;
|
||||||
|
if (size > 0 && !Montauk::UserMemory::Range((uint64_t)buffer, size, false)) return -1;
|
||||||
|
|
||||||
HandleType type = HandleType::None;
|
HandleType type = HandleType::None;
|
||||||
Object* object = nullptr;
|
Object* object = nullptr;
|
||||||
@@ -1208,6 +1222,7 @@ namespace Ipc {
|
|||||||
|
|
||||||
int SocketSendHandle(int handle, const uint8_t* data, uint32_t len) {
|
int SocketSendHandle(int handle, const uint8_t* data, uint32_t len) {
|
||||||
if (data == nullptr) return -1;
|
if (data == nullptr) return -1;
|
||||||
|
if (len > 0 && !Montauk::UserMemory::Range((uint64_t)data, len, false)) return -1;
|
||||||
|
|
||||||
Socket* socket = nullptr;
|
Socket* socket = nullptr;
|
||||||
uint32_t rights = 0;
|
uint32_t rights = 0;
|
||||||
@@ -1223,6 +1238,7 @@ namespace Ipc {
|
|||||||
|
|
||||||
int SocketRecvHandle(int handle, uint8_t* buffer, uint32_t maxLen) {
|
int SocketRecvHandle(int handle, uint8_t* buffer, uint32_t maxLen) {
|
||||||
if (buffer == nullptr) return -1;
|
if (buffer == nullptr) return -1;
|
||||||
|
if (maxLen > 0 && !Montauk::UserMemory::Range((uint64_t)buffer, maxLen, true)) return -1;
|
||||||
|
|
||||||
Socket* socket = nullptr;
|
Socket* socket = nullptr;
|
||||||
uint32_t rights = 0;
|
uint32_t rights = 0;
|
||||||
@@ -1241,6 +1257,7 @@ namespace Ipc {
|
|||||||
|
|
||||||
int SocketSendToHandle(int handle, const uint8_t* data, uint32_t len, uint32_t destIp, uint16_t destPort) {
|
int SocketSendToHandle(int handle, const uint8_t* data, uint32_t len, uint32_t destIp, uint16_t destPort) {
|
||||||
if (data == nullptr) return -1;
|
if (data == nullptr) return -1;
|
||||||
|
if (len > 0 && !Montauk::UserMemory::Range((uint64_t)data, len, false)) return -1;
|
||||||
|
|
||||||
Socket* socket = nullptr;
|
Socket* socket = nullptr;
|
||||||
uint32_t rights = 0;
|
uint32_t rights = 0;
|
||||||
@@ -1271,6 +1288,9 @@ namespace Ipc {
|
|||||||
|
|
||||||
int SocketRecvFromHandle(int handle, uint8_t* buffer, uint32_t maxLen, uint32_t* srcIp, uint16_t* srcPort) {
|
int SocketRecvFromHandle(int handle, uint8_t* buffer, uint32_t maxLen, uint32_t* srcIp, uint16_t* srcPort) {
|
||||||
if (buffer == nullptr) return -1;
|
if (buffer == nullptr) return -1;
|
||||||
|
if (maxLen > 0 && !Montauk::UserMemory::Range((uint64_t)buffer, maxLen, true)) return -1;
|
||||||
|
if (srcIp != nullptr && !Montauk::UserMemory::Writable<uint32_t>((uint64_t)srcIp)) return -1;
|
||||||
|
if (srcPort != nullptr && !Montauk::UserMemory::Writable<uint16_t>((uint64_t)srcPort)) return -1;
|
||||||
|
|
||||||
Socket* socket = nullptr;
|
Socket* socket = nullptr;
|
||||||
uint32_t rights = 0;
|
uint32_t rights = 0;
|
||||||
|
|||||||
@@ -363,6 +363,53 @@ namespace Memory::VMM {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Paging::IsUserRangeAccessible(std::uint64_t pml4Phys, std::uint64_t virtualAddress,
|
||||||
|
std::uint64_t size, bool requireWrite) {
|
||||||
|
static constexpr uint64_t USER_SPACE_END = 0x0000800000000000ULL;
|
||||||
|
|
||||||
|
if (size == 0) return true;
|
||||||
|
if (virtualAddress >= USER_SPACE_END) return false;
|
||||||
|
if (virtualAddress + size < virtualAddress) return false;
|
||||||
|
if (virtualAddress + size > USER_SPACE_END) return false;
|
||||||
|
|
||||||
|
auto pageAccessible = [&](uint64_t pageVa) -> bool {
|
||||||
|
VirtualAddress va(pageVa);
|
||||||
|
PageTable* pml4 = (PageTable*)pml4Phys;
|
||||||
|
|
||||||
|
PageTableEntry* pml4e = (PageTableEntry*)Memory::HHDM(&pml4->entries[va.GetL4Index()]);
|
||||||
|
if (!pml4e->Present || !pml4e->Supervisor) return false;
|
||||||
|
if (requireWrite && !pml4e->Writable) return false;
|
||||||
|
|
||||||
|
PageTable* pml3 = (PageTable*)(pml4e->Address << 12);
|
||||||
|
PageTableEntry* pml3e = (PageTableEntry*)Memory::HHDM(&pml3->entries[va.GetL3Index()]);
|
||||||
|
if (!pml3e->Present || !pml3e->Supervisor) return false;
|
||||||
|
if (requireWrite && !pml3e->Writable) return false;
|
||||||
|
if (pml3e->LargerPages) return true;
|
||||||
|
|
||||||
|
PageTable* pml2 = (PageTable*)(pml3e->Address << 12);
|
||||||
|
PageTableEntry* pml2e = (PageTableEntry*)Memory::HHDM(&pml2->entries[va.GetL2Index()]);
|
||||||
|
if (!pml2e->Present || !pml2e->Supervisor) return false;
|
||||||
|
if (requireWrite && !pml2e->Writable) return false;
|
||||||
|
if (pml2e->LargerPages) return true;
|
||||||
|
|
||||||
|
PageTable* pml1 = (PageTable*)(pml2e->Address << 12);
|
||||||
|
PageTableEntry* pte = (PageTableEntry*)Memory::HHDM(&pml1->entries[va.GetPageIndex()]);
|
||||||
|
if (!pte->Present || !pte->Supervisor) return false;
|
||||||
|
if (requireWrite && !pte->Writable) return false;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
uint64_t page = virtualAddress & ~0xFFFULL;
|
||||||
|
uint64_t lastPage = (virtualAddress + size - 1) & ~0xFFFULL;
|
||||||
|
for (;;) {
|
||||||
|
if (!pageAccessible(page)) return false;
|
||||||
|
if (page == lastPage) break;
|
||||||
|
page += 0x1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Mask to extract only the 40-bit physical address from a PTE Address field
|
// Mask to extract only the 40-bit physical address from a PTE Address field
|
||||||
// (bits 12-51 of the PTE). The PageTableEntry::Address field is 52 bits wide
|
// (bits 12-51 of the PTE). The PageTableEntry::Address field is 52 bits wide
|
||||||
// and includes NX, PK, and software-available bits that must be stripped.
|
// and includes NX, PK, and software-available bits that must be stripped.
|
||||||
|
|||||||
@@ -117,6 +117,12 @@ public:
|
|||||||
// Skips MMIO/WC pages (WriteThrough or CacheDisabled set in PTE).
|
// Skips MMIO/WC pages (WriteThrough or CacheDisabled set in PTE).
|
||||||
static void FreeUserHalf(std::uint64_t pml4Phys);
|
static void FreeUserHalf(std::uint64_t pml4Phys);
|
||||||
|
|
||||||
|
// Validate that every page in the given user range is mapped with
|
||||||
|
// user permissions. If requireWrite is true, all pages must also be
|
||||||
|
// writable.
|
||||||
|
static bool IsUserRangeAccessible(std::uint64_t pml4Phys, std::uint64_t virtualAddress,
|
||||||
|
std::uint64_t size, bool requireWrite = false);
|
||||||
|
|
||||||
// Identity-map EFI runtime service regions so firmware code can
|
// Identity-map EFI runtime service regions so firmware code can
|
||||||
// reference its own data at physical addresses.
|
// reference its own data at physical addresses.
|
||||||
void MapEfiRuntime(limine_efi_memmap_response* efiMemmap);
|
void MapEfiRuntime(limine_efi_memmap_response* efiMemmap);
|
||||||
|
|||||||
@@ -18,6 +18,8 @@
|
|||||||
#include <Hal/SmpBoot.hpp>
|
#include <Hal/SmpBoot.hpp>
|
||||||
#include <Timekeeping/ApicTimer.hpp>
|
#include <Timekeeping/ApicTimer.hpp>
|
||||||
#include <Api/WinServer.hpp>
|
#include <Api/WinServer.hpp>
|
||||||
|
#include <Api/Heap.hpp>
|
||||||
|
#include <Api/LibSyscall.hpp>
|
||||||
#include <Ipc/Ipc.hpp>
|
#include <Ipc/Ipc.hpp>
|
||||||
|
|
||||||
// Assembly: context switch with CR3 and FPU state parameters
|
// Assembly: context switch with CR3 and FPU state parameters
|
||||||
@@ -135,6 +137,7 @@ namespace Sched {
|
|||||||
processTable[i].cwd[0] = '\0';
|
processTable[i].cwd[0] = '\0';
|
||||||
processTable[i].runningOnCpu = -1;
|
processTable[i].runningOnCpu = -1;
|
||||||
processTable[i].killPending = false;
|
processTable[i].killPending = false;
|
||||||
|
processTable[i].reapReady = false;
|
||||||
processTable[i].waitingForPid = -1;
|
processTable[i].waitingForPid = -1;
|
||||||
processTable[i].sleepUntilTick = 0;
|
processTable[i].sleepUntilTick = 0;
|
||||||
processTable[i].waitingOnObject = nullptr;
|
processTable[i].waitingOnObject = nullptr;
|
||||||
@@ -184,6 +187,7 @@ namespace Sched {
|
|||||||
// dispatch this half-initialized process.
|
// dispatch this half-initialized process.
|
||||||
processTable[slot].state = ProcessState::Running;
|
processTable[slot].state = ProcessState::Running;
|
||||||
processTable[slot].runningOnCpu = -1;
|
processTable[slot].runningOnCpu = -1;
|
||||||
|
processTable[slot].reapReady = false;
|
||||||
schedLock.Release();
|
schedLock.Release();
|
||||||
|
|
||||||
// Create per-process PML4 with kernel-half copied
|
// Create per-process PML4 with kernel-half copied
|
||||||
@@ -319,6 +323,7 @@ namespace Sched {
|
|||||||
proc.readdirCursor = 0;
|
proc.readdirCursor = 0;
|
||||||
proc.runningOnCpu = -1;
|
proc.runningOnCpu = -1;
|
||||||
proc.killPending = false;
|
proc.killPending = false;
|
||||||
|
proc.reapReady = false;
|
||||||
proc.waitingForPid = -1;
|
proc.waitingForPid = -1;
|
||||||
proc.sleepUntilTick = 0;
|
proc.sleepUntilTick = 0;
|
||||||
proc.waitingOnObject = nullptr;
|
proc.waitingOnObject = nullptr;
|
||||||
@@ -417,7 +422,7 @@ namespace Sched {
|
|||||||
static void ReclaimTerminated() {
|
static void ReclaimTerminated() {
|
||||||
schedLock.Acquire();
|
schedLock.Acquire();
|
||||||
for (int i = 0; i < MaxProcesses; i++) {
|
for (int i = 0; i < MaxProcesses; i++) {
|
||||||
if (processTable[i].state == ProcessState::Terminated) {
|
if (processTable[i].state == ProcessState::Terminated && processTable[i].reapReady) {
|
||||||
// Grab the pointers, mark Free, then free memory after releasing lock
|
// Grab the pointers, mark Free, then free memory after releasing lock
|
||||||
void* stackBase = (processTable[i].stackBase != 0)
|
void* stackBase = (processTable[i].stackBase != 0)
|
||||||
? (void*)processTable[i].stackBase : nullptr;
|
? (void*)processTable[i].stackBase : nullptr;
|
||||||
@@ -425,6 +430,7 @@ namespace Sched {
|
|||||||
? (void*)Memory::HHDM(processTable[i].pml4Phys) : nullptr;
|
? (void*)Memory::HHDM(processTable[i].pml4Phys) : nullptr;
|
||||||
processTable[i].stackBase = 0;
|
processTable[i].stackBase = 0;
|
||||||
processTable[i].pml4Phys = 0;
|
processTable[i].pml4Phys = 0;
|
||||||
|
processTable[i].reapReady = false;
|
||||||
processTable[i].state = ProcessState::Free;
|
processTable[i].state = ProcessState::Free;
|
||||||
|
|
||||||
// Release lock during PFA::Free to minimize hold time
|
// Release lock during PFA::Free to minimize hold time
|
||||||
@@ -610,6 +616,8 @@ namespace Sched {
|
|||||||
|
|
||||||
// Release process-scoped IPC handles/mappings before tearing down the address space.
|
// Release process-scoped IPC handles/mappings before tearing down the address space.
|
||||||
Ipc::CleanupProcessSlot(slot, exitingPid, proc.pml4Phys);
|
Ipc::CleanupProcessSlot(slot, exitingPid, proc.pml4Phys);
|
||||||
|
Montauk::CleanupHeapForSlot(slot, proc.pml4Phys);
|
||||||
|
Montauk::CleanupLibTable(slot);
|
||||||
|
|
||||||
proc.waitingForPid = -1;
|
proc.waitingForPid = -1;
|
||||||
proc.sleepUntilTick = 0;
|
proc.sleepUntilTick = 0;
|
||||||
@@ -640,6 +648,7 @@ namespace Sched {
|
|||||||
|
|
||||||
proc.state = ProcessState::Terminated;
|
proc.state = ProcessState::Terminated;
|
||||||
proc.runningOnCpu = -1;
|
proc.runningOnCpu = -1;
|
||||||
|
proc.reapReady = true;
|
||||||
|
|
||||||
// Wake any processes blocked on this PID
|
// Wake any processes blocked on this PID
|
||||||
for (int i = 0; i < MaxProcesses; i++) {
|
for (int i = 0; i < MaxProcesses; i++) {
|
||||||
@@ -729,12 +738,14 @@ namespace Sched {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Process is Ready or Blocked (not running on any CPU).
|
// Process is Ready or Blocked (not running on any CPU).
|
||||||
// Mark it Terminated so the scheduler won't pick it up.
|
// Mark it non-runnable so the scheduler won't pick it up, but do not
|
||||||
|
// expose it to the BSP reaper until teardown is complete.
|
||||||
int killedPid = proc.pid;
|
int killedPid = proc.pid;
|
||||||
if (proc.state == ProcessState::Ready)
|
if (proc.state == ProcessState::Ready)
|
||||||
readyCount--;
|
readyCount--;
|
||||||
proc.state = ProcessState::Terminated;
|
proc.state = ProcessState::Terminated;
|
||||||
proc.killPending = false;
|
proc.killPending = false;
|
||||||
|
proc.reapReady = false;
|
||||||
proc.waitingForPid = -1;
|
proc.waitingForPid = -1;
|
||||||
proc.sleepUntilTick = 0;
|
proc.sleepUntilTick = 0;
|
||||||
proc.waitingOnObject = nullptr;
|
proc.waitingOnObject = nullptr;
|
||||||
@@ -756,6 +767,8 @@ namespace Sched {
|
|||||||
// Safe to clean up resources now -- process is not running anywhere.
|
// Safe to clean up resources now -- process is not running anywhere.
|
||||||
WinServer::CleanupProcess(killedPid);
|
WinServer::CleanupProcess(killedPid);
|
||||||
Ipc::CleanupProcessSlot(slot, killedPid, proc.pml4Phys);
|
Ipc::CleanupProcessSlot(slot, killedPid, proc.pml4Phys);
|
||||||
|
Montauk::CleanupHeapForSlot(slot, proc.pml4Phys);
|
||||||
|
Montauk::CleanupLibTable(slot);
|
||||||
|
|
||||||
proc.redirected = false;
|
proc.redirected = false;
|
||||||
proc.parentPid = -1;
|
proc.parentPid = -1;
|
||||||
@@ -778,6 +791,10 @@ namespace Sched {
|
|||||||
|
|
||||||
Memory::VMM::Paging::FreeUserHalf(proc.pml4Phys);
|
Memory::VMM::Paging::FreeUserHalf(proc.pml4Phys);
|
||||||
|
|
||||||
|
schedLock.Acquire();
|
||||||
|
proc.reapReady = true;
|
||||||
|
schedLock.Release();
|
||||||
|
|
||||||
// Kernel stack and PML4 freed by ReclaimTerminated on BSP tick.
|
// Kernel stack and PML4 freed by ReclaimTerminated on BSP tick.
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ namespace Sched {
|
|||||||
|
|
||||||
int runningOnCpu; // CPU index running this process (-1 if not running)
|
int runningOnCpu; // CPU index running this process (-1 if not running)
|
||||||
bool killPending = false; // Set by Sys_Kill when target is running on another CPU
|
bool killPending = false; // Set by Sys_Kill when target is running on another CPU
|
||||||
|
bool reapReady = false; // Set once teardown is complete and BSP may free slot resources
|
||||||
|
|
||||||
// I/O redirection for GUI terminal
|
// I/O redirection for GUI terminal
|
||||||
bool redirected = false;
|
bool redirected = false;
|
||||||
|
|||||||
Reference in New Issue
Block a user