feat: multi-user system, bug fixes, security & performance fixes, and more

This commit is contained in:
2026-03-14 13:28:46 +01:00
parent 576ad34f95
commit 261b536041
389 changed files with 231853 additions and 591 deletions
+72 -4
View File
@@ -38,6 +38,23 @@ extern "C" void SyscallEntry();
namespace Montauk {
// ---- User pointer validation ----
// Reject pointers that fall in the kernel-half of the address space
// (canonical high addresses, i.e. >= 0x0000800000000000).
// This prevents userspace from tricking the kernel into reading/writing
// kernel memory via syscall arguments.
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 ----
extern "C" int64_t SyscallDispatch(SyscallFrame* frame) {
@@ -59,14 +76,17 @@ namespace Montauk {
case SYS_GETPID:
return (int64_t)Sys_GetPid();
case SYS_PRINT:
if (!ValidUserPtr(frame->arg1)) return -1;
Sys_Print((const char*)frame->arg1);
return 0;
case SYS_PUTCHAR:
Sys_Putchar((char)frame->arg1);
return 0;
case SYS_OPEN:
if (!ValidUserPtr(frame->arg1)) return -1;
return (int64_t)Sys_Open((const char*)frame->arg1);
case SYS_READ:
if (!ValidUserPtr(frame->arg2)) return -1;
return (int64_t)Sys_Read((int)frame->arg1, (uint8_t*)frame->arg2,
frame->arg3, frame->arg4);
case SYS_GETSIZE:
@@ -75,6 +95,7 @@ namespace Montauk {
Sys_Close((int)frame->arg1);
return 0;
case SYS_READDIR:
if (!ValidUserPtr(frame->arg1) || !ValidUserPtr(frame->arg2)) return -1;
return (int64_t)Sys_ReadDir((const char*)frame->arg1,
(const char**)frame->arg2,
(int)frame->arg3);
@@ -88,11 +109,13 @@ namespace Montauk {
case SYS_GETMILLISECONDS:
return (int64_t)Sys_GetMilliseconds();
case SYS_GETINFO:
if (!ValidUserPtr(frame->arg1)) return -1;
Sys_GetInfo((SysInfo*)frame->arg1);
return 0;
case SYS_ISKEYAVAILABLE:
return (int64_t)Sys_IsKeyAvailable();
case SYS_GETKEY:
if (!ValidUserPtr(frame->arg1)) return -1;
Sys_GetKey((KeyEvent*)frame->arg1);
return 0;
case SYS_GETCHAR:
@@ -100,11 +123,14 @@ namespace Montauk {
case SYS_PING:
return (int64_t)Sys_Ping((uint32_t)frame->arg1, (uint32_t)frame->arg2);
case SYS_SPAWN:
return (int64_t)Sys_Spawn((const char*)frame->arg1, (const char*)frame->arg2);
if (!ValidUserPtr(frame->arg1)) return -1;
return (int64_t)Sys_Spawn((const char*)frame->arg1,
IsUserPtr(frame->arg2) ? (const char*)frame->arg2 : nullptr);
case SYS_WAITPID:
Sys_WaitPid((int)frame->arg1);
return 0;
case SYS_FBINFO:
if (!ValidUserPtr(frame->arg1)) return -1;
Sys_FbInfo((FbInfo*)frame->arg1);
return 0;
case SYS_FBMAP:
@@ -112,6 +138,7 @@ namespace Montauk {
case SYS_TERMSIZE:
return (int64_t)Sys_TermSize();
case SYS_GETARGS:
if (!ValidUserPtr(frame->arg1)) return -1;
return (int64_t)Sys_GetArgs((char*)frame->arg1, frame->arg2);
case SYS_RESET:
Sys_Reset();
@@ -120,6 +147,7 @@ namespace Montauk {
Sys_Shutdown();
return 0;
case SYS_GETTIME:
if (!ValidUserPtr(frame->arg1)) return -1;
Sys_GetTime((DateTime*)frame->arg1);
return 0;
case SYS_SOCKET:
@@ -133,61 +161,83 @@ namespace Montauk {
case SYS_ACCEPT:
return (int64_t)Sys_Accept((int)frame->arg1);
case SYS_SEND:
if (!ValidUserPtr(frame->arg2)) return -1;
return (int64_t)Sys_Send((int)frame->arg1, (const uint8_t*)frame->arg2, (uint32_t)frame->arg3);
case SYS_RECV:
if (!ValidUserPtr(frame->arg2)) return -1;
return (int64_t)Sys_Recv((int)frame->arg1, (uint8_t*)frame->arg2, (uint32_t)frame->arg3);
case SYS_CLOSESOCK:
Sys_CloseSock((int)frame->arg1);
return 0;
case SYS_GETNETCFG:
if (!ValidUserPtr(frame->arg1)) return -1;
Sys_GetNetCfg((NetCfg*)frame->arg1);
return 0;
case SYS_SETNETCFG:
if (!ValidUserPtr(frame->arg1)) return -1;
return (int64_t)Sys_SetNetCfg((const NetCfg*)frame->arg1);
case SYS_SENDTO:
if (!ValidUserPtr(frame->arg2)) return -1;
return (int64_t)Sys_SendTo((int)frame->arg1, (const uint8_t*)frame->arg2,
(uint32_t)frame->arg3, (uint32_t)frame->arg4,
(uint16_t)frame->arg5);
case SYS_RECVFROM:
if (!ValidUserPtr(frame->arg2)) return -1;
return (int64_t)Sys_RecvFrom((int)frame->arg1, (uint8_t*)frame->arg2,
(uint32_t)frame->arg3, (uint32_t*)frame->arg4,
(uint16_t*)frame->arg5);
(uint32_t)frame->arg3,
IsUserPtr(frame->arg4) ? (uint32_t*)frame->arg4 : nullptr,
IsUserPtr(frame->arg5) ? (uint16_t*)frame->arg5 : nullptr);
case SYS_FWRITE:
if (!ValidUserPtr(frame->arg2)) return -1;
return (int64_t)Sys_FWrite((int)frame->arg1, (const uint8_t*)frame->arg2,
frame->arg3, frame->arg4);
case SYS_FCREATE:
if (!ValidUserPtr(frame->arg1)) return -1;
return (int64_t)Sys_FCreate((const char*)frame->arg1);
case SYS_FDELETE:
if (!ValidUserPtr(frame->arg1)) return -1;
return (int64_t)Sys_FDelete((const char*)frame->arg1);
case SYS_FMKDIR:
if (!ValidUserPtr(frame->arg1)) return -1;
return (int64_t)Sys_FMkdir((const char*)frame->arg1);
case SYS_DRIVELIST:
if (!ValidUserPtr(frame->arg1)) return -1;
return (int64_t)Sys_DriveList((int*)frame->arg1, (int)frame->arg2);
case SYS_TERMSCALE:
return Sys_TermScale(frame->arg1, frame->arg2);
case SYS_RESOLVE:
if (!ValidUserPtr(frame->arg1)) return -1;
return Sys_Resolve((const char*)frame->arg1);
case SYS_GETRANDOM:
if (!ValidUserPtr(frame->arg1)) return -1;
return Sys_GetRandom((uint8_t*)frame->arg1, frame->arg2);
case SYS_KLOG:
if (!ValidUserPtr(frame->arg1)) return -1;
return Kt::ReadKernelLog((char*)frame->arg1, frame->arg2);
case SYS_MOUSESTATE:
if (!ValidUserPtr(frame->arg1)) return -1;
Sys_MouseState((MouseState*)frame->arg1);
return 0;
case SYS_SETMOUSEBOUNDS:
Sys_SetMouseBounds((int32_t)frame->arg1, (int32_t)frame->arg2);
return 0;
case SYS_SPAWN_REDIR:
return (int64_t)Sys_SpawnRedir((const char*)frame->arg1, (const char*)frame->arg2);
if (!ValidUserPtr(frame->arg1)) return -1;
return (int64_t)Sys_SpawnRedir((const char*)frame->arg1,
IsUserPtr(frame->arg2) ? (const char*)frame->arg2 : nullptr);
case SYS_CHILDIO_READ:
if (!ValidUserPtr(frame->arg2)) return -1;
return (int64_t)Sys_ChildIoRead((int)frame->arg1, (char*)frame->arg2, (int)frame->arg3);
case SYS_CHILDIO_WRITE:
if (!ValidUserPtr(frame->arg2)) return -1;
return (int64_t)Sys_ChildIoWrite((int)frame->arg1, (const char*)frame->arg2, (int)frame->arg3);
case SYS_CHILDIO_WRITEKEY:
if (!ValidUserPtr(frame->arg2)) return -1;
return (int64_t)Sys_ChildIoWriteKey((int)frame->arg1, (const KeyEvent*)frame->arg2);
case SYS_CHILDIO_SETTERMSZ:
return (int64_t)Sys_ChildIoSetTermsz((int)frame->arg1, (int)frame->arg2, (int)frame->arg3);
case SYS_WINCREATE:
if (!ValidUserPtr(frame->arg1) || !ValidUserPtr(frame->arg4)) return -1;
return (int64_t)Sys_WinCreate((const char*)frame->arg1, (int)frame->arg2,
(int)frame->arg3, (WinCreateResult*)frame->arg4);
case SYS_WINDESTROY:
@@ -195,16 +245,20 @@ namespace Montauk {
case SYS_WINPRESENT:
return (int64_t)Sys_WinPresent((int)frame->arg1);
case SYS_WINPOLL:
if (!ValidUserPtr(frame->arg2)) return -1;
return (int64_t)Sys_WinPoll((int)frame->arg1, (WinEvent*)frame->arg2);
case SYS_WINENUM:
if (!ValidUserPtr(frame->arg1)) return -1;
return (int64_t)Sys_WinEnum((WinInfo*)frame->arg1, (int)frame->arg2);
case SYS_WINMAP:
return (int64_t)Sys_WinMap((int)frame->arg1);
case SYS_WINSENDEVENT:
if (!ValidUserPtr(frame->arg2)) return -1;
return (int64_t)Sys_WinSendEvent((int)frame->arg1, (const WinEvent*)frame->arg2);
case SYS_WINRESIZE:
return (int64_t)Sys_WinResize((int)frame->arg1, (int)frame->arg2, (int)frame->arg3);
case SYS_PROCLIST:
if (!ValidUserPtr(frame->arg1)) return -1;
return (int64_t)Sys_ProcList((ProcInfo*)frame->arg1, (int)frame->arg2);
case SYS_KILL: {
// Free heap allocations for the target process before killing it
@@ -217,8 +271,10 @@ namespace Montauk {
return (int64_t)Sys_Kill((int)frame->arg1);
}
case SYS_DEVLIST:
if (!ValidUserPtr(frame->arg1)) return -1;
return (int64_t)Sys_DevList((DevInfo*)frame->arg1, (int)frame->arg2);
case SYS_DISKINFO:
if (!ValidUserPtr(frame->arg1)) return -1;
return (int64_t)Sys_DiskInfo((DiskInfo*)frame->arg1, (int)frame->arg2);
case SYS_WINSETSCALE:
return (int64_t)Sys_WinSetScale((int)frame->arg1);
@@ -227,41 +283,53 @@ namespace Montauk {
case SYS_WINSETCURSOR:
return (int64_t)Sys_WinSetCursor((int)frame->arg1, (int)frame->arg2);
case SYS_MEMSTATS:
if (!ValidUserPtr(frame->arg1)) return -1;
Sys_MemStats((MemStats*)frame->arg1);
return 0;
case SYS_PARTLIST:
if (!ValidUserPtr(frame->arg1)) return -1;
return (int64_t)Sys_PartList((PartInfo*)frame->arg1, (int)frame->arg2);
case SYS_DISKREAD:
if (!ValidUserPtr(frame->arg4)) return -1;
return (int64_t)Sys_DiskRead((int)frame->arg1, frame->arg2,
(uint32_t)frame->arg3, (void*)frame->arg4);
case SYS_DISKWRITE:
if (!ValidUserPtr(frame->arg4)) return -1;
return (int64_t)Sys_DiskWrite((int)frame->arg1, frame->arg2,
(uint32_t)frame->arg3, (const void*)frame->arg4);
case SYS_GPTINIT:
return (int64_t)Sys_GptInit((int)frame->arg1);
case SYS_GPTADD:
if (!ValidUserPtr(frame->arg1)) return -1;
return (int64_t)Sys_GptAdd((const GptAddParams*)frame->arg1);
case SYS_FSMOUNT:
return (int64_t)Sys_FsMount((int)frame->arg1, (int)frame->arg2);
case SYS_FSFORMAT:
if (!ValidUserPtr(frame->arg1)) return -1;
return (int64_t)Sys_FsFormat((const FsFormatParams*)frame->arg1);
case SYS_AUDIOOPEN:
return Sys_AudioOpen((uint32_t)frame->arg1, (uint8_t)frame->arg2, (uint8_t)frame->arg3);
case SYS_AUDIOCLOSE:
return Sys_AudioClose((int)frame->arg1);
case SYS_AUDIOWRITE:
if (!ValidUserPtr(frame->arg2)) return -1;
return Sys_AudioWrite((int)frame->arg1, (const uint8_t*)frame->arg2, (uint32_t)frame->arg3);
case SYS_AUDIOCTL:
return Sys_AudioCtl((int)frame->arg1, (int)frame->arg2, (int)frame->arg3);
case SYS_BTSCAN:
if (!ValidUserPtr(frame->arg1)) return -1;
return Sys_BtScan((BtScanResult*)frame->arg1, (int)frame->arg2, (uint32_t)frame->arg3);
case SYS_BTCONNECT:
if (!ValidUserPtr(frame->arg1)) return -1;
return Sys_BtConnect((const uint8_t*)frame->arg1);
case SYS_BTDISCONNECT:
if (!ValidUserPtr(frame->arg1)) return -1;
return Sys_BtDisconnect((const uint8_t*)frame->arg1);
case SYS_BTLIST:
if (!ValidUserPtr(frame->arg1)) return -1;
return Sys_BtList((BtDevInfo*)frame->arg1, (int)frame->arg2);
case SYS_BTINFO:
if (!ValidUserPtr(frame->arg1)) return -1;
return Sys_BtInfo((BtAdapterInfo*)frame->arg1);
default:
return -1;