feat: unify system status codes
This commit is contained in:
1 parent
93894b8fe5
commit
8a3ffb2be1
46 files changed
+1499
-489
No files matched your search
@@ -36,12 +36,12 @@ namespace montauk::abi {
|
||||
bitsPerSample, pid, name);
|
||||
}
|
||||
|
||||
return -1;
|
||||
return NoDevice;
|
||||
}
|
||||
|
||||
static int64_t Sys_AudioClose(int handle) {
|
||||
Drivers::Audio::Mixer::Close(handle);
|
||||
return 0;
|
||||
return Success;
|
||||
}
|
||||
|
||||
static int64_t Sys_AudioWrite(int handle, const uint8_t* data, uint32_t size) {
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
namespace montauk::abi {
|
||||
|
||||
static int64_t Sys_BtScan(BtScanResult* buf, int maxCount, uint32_t timeoutMs) {
|
||||
if (!buf || maxCount <= 0) return -1;
|
||||
if (!Drivers::USB::Bluetooth::IsInitialized()) return -1;
|
||||
if (!buf || maxCount <= 0) return InvalidArgument;
|
||||
if (!Drivers::USB::Bluetooth::IsInitialized()) return NoDevice;
|
||||
|
||||
// Use a stack buffer for kernel-side results (max 16)
|
||||
Drivers::USB::Bluetooth::Hci::InquiryDevice tmpBuf[16];
|
||||
@@ -46,15 +46,15 @@ namespace montauk::abi {
|
||||
}
|
||||
|
||||
static int64_t Sys_BtConnect(const uint8_t* bdAddr) {
|
||||
if (!bdAddr) return -1;
|
||||
if (!Drivers::USB::Bluetooth::IsInitialized()) return -1;
|
||||
if (!bdAddr) return InvalidArgument;
|
||||
if (!Drivers::USB::Bluetooth::IsInitialized()) return NoDevice;
|
||||
|
||||
return (int64_t)Drivers::USB::Bluetooth::Connect(bdAddr);
|
||||
}
|
||||
|
||||
static int64_t Sys_BtDisconnect(const uint8_t* bdAddr) {
|
||||
if (!bdAddr) return -1;
|
||||
if (!Drivers::USB::Bluetooth::IsInitialized()) return -1;
|
||||
if (!bdAddr) return InvalidArgument;
|
||||
if (!Drivers::USB::Bluetooth::IsInitialized()) return NoDevice;
|
||||
|
||||
Kt::KernelLogStream(Kt::INFO, "Power") << "pid " << kcp::dec
|
||||
<< (uint64_t)Sched::GetCurrentPid()
|
||||
@@ -63,11 +63,11 @@ namespace montauk::abi {
|
||||
}
|
||||
|
||||
static int64_t Sys_BtSetAddr(const uint8_t* bdAddr) {
|
||||
if (!bdAddr) return -1;
|
||||
if (!Drivers::USB::Bluetooth::IsInitialized()) return -1;
|
||||
if (!bdAddr) return InvalidArgument;
|
||||
if (!Drivers::USB::Bluetooth::IsInitialized()) return NoDevice;
|
||||
|
||||
// bdAddr is a 6-byte buffer, addr[0] = least-significant octet.
|
||||
return Drivers::USB::Bluetooth::SetAddress(bdAddr) ? 0 : -1;
|
||||
return Drivers::USB::Bluetooth::SetAddress(bdAddr) ? Success : GenericFailure;
|
||||
}
|
||||
|
||||
static int64_t Sys_BtBonds(BtBondInfo* buf, int maxCount) {
|
||||
@@ -90,8 +90,8 @@ namespace montauk::abi {
|
||||
}
|
||||
|
||||
static int64_t Sys_BtForget(const uint8_t* bdAddr) {
|
||||
if (!bdAddr) return -1;
|
||||
if (!Drivers::USB::Bluetooth::IsInitialized()) return -1;
|
||||
if (!bdAddr) return InvalidArgument;
|
||||
if (!Drivers::USB::Bluetooth::IsInitialized()) return NoDevice;
|
||||
|
||||
return (int64_t)Drivers::USB::Bluetooth::ForgetDevice(bdAddr);
|
||||
}
|
||||
@@ -119,13 +119,13 @@ namespace montauk::abi {
|
||||
}
|
||||
|
||||
static int64_t Sys_BtInfo(BtAdapterInfo* buf) {
|
||||
if (!buf) return -1;
|
||||
if (!buf) return InvalidArgument;
|
||||
|
||||
memset(buf, 0, sizeof(BtAdapterInfo));
|
||||
|
||||
if (!Drivers::USB::Bluetooth::IsInitialized()) {
|
||||
buf->initialized = 0;
|
||||
return -1;
|
||||
return NoDevice;
|
||||
}
|
||||
|
||||
buf->initialized = 1;
|
||||
@@ -138,7 +138,7 @@ namespace montauk::abi {
|
||||
for (; i < 63 && name[i]; i++) buf->name[i] = name[i];
|
||||
buf->name[i] = '\0';
|
||||
|
||||
return 0;
|
||||
return Success;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,4 +12,4 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define MONTAUK_BUILD_NUMBER 251
|
||||
#define MONTAUK_BUILD_NUMBER 254
|
||||
@@ -90,22 +90,24 @@ namespace montauk::abi {
|
||||
static int Sys_ClipboardSetText(const char* data, uint32_t len) {
|
||||
if (len == 0)
|
||||
return Sys_ClipboardClear();
|
||||
if (data == nullptr || len > CLIPBOARD_MAX_TEXT_BYTES || Memory::g_heap == nullptr)
|
||||
return -1;
|
||||
if (data == nullptr || len > CLIPBOARD_MAX_TEXT_BYTES)
|
||||
return InvalidArgument;
|
||||
if (Memory::g_heap == nullptr)
|
||||
return OutOfMemory;
|
||||
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
if (data[i] == '\0')
|
||||
return -1;
|
||||
return InvalidArgument;
|
||||
}
|
||||
|
||||
const char* currentUser = ClipboardCurrentUser();
|
||||
if (currentUser == nullptr) return -1;
|
||||
if (currentUser == nullptr) return GenericFailure;
|
||||
|
||||
char user[32];
|
||||
ClipboardCopyUser(user, currentUser);
|
||||
|
||||
char* newText = (char*)Memory::g_heap->Request(len + 1);
|
||||
if (newText == nullptr) return -1;
|
||||
if (newText == nullptr) return OutOfMemory;
|
||||
for (uint32_t i = 0; i < len; i++)
|
||||
newText[i] = data[i];
|
||||
newText[len] = '\0';
|
||||
@@ -129,18 +131,18 @@ namespace montauk::abi {
|
||||
if (oldText != nullptr)
|
||||
Memory::g_heap->Free(oldText);
|
||||
|
||||
return 0;
|
||||
return Success;
|
||||
}
|
||||
|
||||
static int Sys_ClipboardGetInfo(ClipboardInfo* out) {
|
||||
if (out == nullptr) return -1;
|
||||
if (out == nullptr) return InvalidArgument;
|
||||
|
||||
out->textBytes = 0;
|
||||
out->_pad = 0;
|
||||
out->serial = 0;
|
||||
|
||||
const char* currentUser = ClipboardCurrentUser();
|
||||
if (currentUser == nullptr) return -1;
|
||||
if (currentUser == nullptr) return GenericFailure;
|
||||
|
||||
char user[32];
|
||||
ClipboardCopyUser(user, currentUser);
|
||||
@@ -152,17 +154,17 @@ namespace montauk::abi {
|
||||
out->serial = slot->serial;
|
||||
}
|
||||
g_clipboardLock.Release();
|
||||
return 0;
|
||||
return Success;
|
||||
}
|
||||
|
||||
static int Sys_ClipboardGetText(char* buffer, uint32_t bufferLen, uint32_t* outLen, uint64_t* outSerial) {
|
||||
if (outLen == nullptr) return -1;
|
||||
if (outLen == nullptr) return InvalidArgument;
|
||||
|
||||
*outLen = 0;
|
||||
if (outSerial != nullptr) *outSerial = 0;
|
||||
|
||||
const char* currentUser = ClipboardCurrentUser();
|
||||
if (currentUser == nullptr) return -1;
|
||||
if (currentUser == nullptr) return GenericFailure;
|
||||
|
||||
char user[32];
|
||||
ClipboardCopyUser(user, currentUser);
|
||||
@@ -173,25 +175,25 @@ namespace montauk::abi {
|
||||
if (slot != nullptr && outSerial != nullptr)
|
||||
*outSerial = slot->serial;
|
||||
g_clipboardLock.Release();
|
||||
return 0;
|
||||
return Success;
|
||||
}
|
||||
|
||||
*outLen = slot->len;
|
||||
if (outSerial != nullptr) *outSerial = slot->serial;
|
||||
if (buffer == nullptr || bufferLen < slot->len) {
|
||||
g_clipboardLock.Release();
|
||||
return -1;
|
||||
return BufferTooSmall;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < slot->len; i++)
|
||||
buffer[i] = slot->text[i];
|
||||
g_clipboardLock.Release();
|
||||
return 0;
|
||||
return Success;
|
||||
}
|
||||
|
||||
static int Sys_ClipboardClear() {
|
||||
const char* currentUser = ClipboardCurrentUser();
|
||||
if (currentUser == nullptr) return -1;
|
||||
if (currentUser == nullptr) return GenericFailure;
|
||||
|
||||
char user[32];
|
||||
ClipboardCopyUser(user, currentUser);
|
||||
@@ -214,7 +216,7 @@ namespace montauk::abi {
|
||||
if (oldText != nullptr)
|
||||
Memory::g_heap->Free(oldText);
|
||||
|
||||
return 0;
|
||||
return Success;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -225,10 +225,10 @@ namespace montauk::abi {
|
||||
}
|
||||
|
||||
static int Sys_DiskInfo(DiskInfo* buf, int blockDevIndex) {
|
||||
if (buf == nullptr) return -1;
|
||||
if (buf == nullptr) return InvalidArgument;
|
||||
|
||||
auto* bdev = Drivers::Storage::GetBlockDevice(blockDevIndex);
|
||||
if (!bdev) return -1;
|
||||
if (!bdev) return NoDevice;
|
||||
|
||||
// Zero the struct first so SATA-specific fields default to 0
|
||||
for (unsigned i = 0; i < sizeof(DiskInfo); i++)
|
||||
@@ -303,8 +303,8 @@ namespace montauk::abi {
|
||||
}
|
||||
|
||||
// If type is still 0, this block device is not recognized
|
||||
if (buf->type == 0) return -1;
|
||||
if (buf->type == 0) return UnsupportedOp;
|
||||
|
||||
return 0;
|
||||
return Success;
|
||||
}
|
||||
};
|
||||
@@ -20,6 +20,8 @@
|
||||
#include <Fs/ProtectedPaths.hpp>
|
||||
|
||||
namespace montauk::abi {
|
||||
// Writes refused here return SystemIntegrityError: the path is protected
|
||||
// by Fs/ProtectedPaths, not merely gated on an ordinary capability.
|
||||
static bool CanModifyFilePath(const char* resolved) {
|
||||
uint64_t required = Fs::RequiredFileWriteCapability(resolved);
|
||||
return required == 0 || Sched::HasCapability(required);
|
||||
@@ -27,7 +29,7 @@ namespace montauk::abi {
|
||||
|
||||
static int Sys_Open(const char* path) {
|
||||
char resolved[256];
|
||||
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return -1;
|
||||
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return InvalidArgument;
|
||||
return Ipc::OpenFileHandle(resolved);
|
||||
}
|
||||
|
||||
@@ -53,8 +55,8 @@ namespace montauk::abi {
|
||||
static int Sys_ReadDirAt(const char* path, const char** outNames, int maxEntries,
|
||||
int startIndex) {
|
||||
char resolved[256];
|
||||
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return -1;
|
||||
if (startIndex < 0) return -1;
|
||||
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return InvalidArgument;
|
||||
if (startIndex < 0) return InvalidArgument;
|
||||
|
||||
// Get entries from VFS into a kernel-local array
|
||||
const char* kernelNames[256];
|
||||
@@ -65,7 +67,7 @@ namespace montauk::abi {
|
||||
|
||||
// Allocate a user-accessible page for string data via process heap
|
||||
auto* proc = Sched::GetCurrentProcessPtr();
|
||||
if (proc == nullptr) return -1;
|
||||
if (proc == nullptr) return GenericFailure;
|
||||
|
||||
// Use a rotating ring of scratch pages below the heap instead of
|
||||
// extending the heap high-water mark on every call. This keeps repeated
|
||||
@@ -80,11 +82,11 @@ namespace montauk::abi {
|
||||
|
||||
if (physAddr == 0) {
|
||||
void* page = Memory::g_pfa->AllocateZeroed();
|
||||
if (page == nullptr) return -1;
|
||||
if (page == nullptr) return OutOfMemory;
|
||||
physAddr = Memory::SubHHDM((uint64_t)page);
|
||||
if (!Memory::VMM::Paging::MapUserIn(proc->pml4Phys, physAddr, userVa)) {
|
||||
Memory::g_pfa->Free(page);
|
||||
return -1;
|
||||
return OutOfMemory;
|
||||
}
|
||||
pageBuf = (uint8_t*)page;
|
||||
} else {
|
||||
@@ -113,25 +115,25 @@ namespace montauk::abi {
|
||||
|
||||
static int Sys_FCreate(const char* path) {
|
||||
char resolved[256];
|
||||
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return -1;
|
||||
if (!CanModifyFilePath(resolved)) return SYS_ERR_PERMISSION;
|
||||
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return InvalidArgument;
|
||||
if (!CanModifyFilePath(resolved)) return SystemIntegrityError;
|
||||
return Ipc::CreateFileHandle(resolved);
|
||||
}
|
||||
|
||||
static int Sys_FDelete(const char* path) {
|
||||
char resolved[256];
|
||||
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return -1;
|
||||
if (!CanModifyFilePath(resolved)) return SYS_ERR_PERMISSION;
|
||||
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return InvalidArgument;
|
||||
if (!CanModifyFilePath(resolved)) return SystemIntegrityError;
|
||||
return Fs::Vfs::VfsDelete(resolved);
|
||||
}
|
||||
|
||||
static int Sys_Stat(const char* path, FileStat* out) {
|
||||
if (out == nullptr) return -1;
|
||||
if (out == nullptr) return InvalidArgument;
|
||||
char resolved[256];
|
||||
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return -1;
|
||||
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return InvalidArgument;
|
||||
|
||||
Fs::Vfs::StatInfo info;
|
||||
if (Fs::Vfs::VfsStat(resolved, info) != 0) return -1;
|
||||
if (Fs::Vfs::VfsStat(resolved, info) != 0) return NoSuchPath;
|
||||
|
||||
out->size = info.size;
|
||||
out->mtime = info.mtime;
|
||||
@@ -139,38 +141,46 @@ namespace montauk::abi {
|
||||
out->atime = info.atime;
|
||||
out->mode = info.mode;
|
||||
out->isDir = info.isDir ? 1u : 0u;
|
||||
return 0;
|
||||
return Success;
|
||||
}
|
||||
|
||||
static int Sys_Utime(const char* path, int64_t atime, int64_t mtime,
|
||||
bool useCurrent) {
|
||||
char resolved[256];
|
||||
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return -1;
|
||||
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return InvalidArgument;
|
||||
// Timestamps are file state like any other: a protected path must not
|
||||
// be mutable through a side door that skips the write check.
|
||||
if (!CanModifyFilePath(resolved)) return SYS_ERR_PERMISSION;
|
||||
if (!CanModifyFilePath(resolved)) return SystemIntegrityError;
|
||||
if (useCurrent) {
|
||||
int64_t now = Timekeeping::GetUnixTimestamp();
|
||||
atime = now;
|
||||
mtime = now;
|
||||
}
|
||||
return Fs::Vfs::VfsSetTimes(resolved, atime, mtime);
|
||||
// VfsSetTimes has its own codes: -1 not found, -2 unsupported by the
|
||||
// filesystem, -3 timestamp out of range, -4 I/O error.
|
||||
switch (Fs::Vfs::VfsSetTimes(resolved, atime, mtime)) {
|
||||
case 0: return Success;
|
||||
case -2: return UnsupportedOp;
|
||||
case -3: return InvalidArgument;
|
||||
case -4: return IoFailure;
|
||||
default: return NoSuchPath;
|
||||
}
|
||||
}
|
||||
|
||||
static int Sys_FMkdir(const char* path) {
|
||||
char resolved[256];
|
||||
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return -1;
|
||||
if (!CanModifyFilePath(resolved)) return SYS_ERR_PERMISSION;
|
||||
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return InvalidArgument;
|
||||
if (!CanModifyFilePath(resolved)) return SystemIntegrityError;
|
||||
return Fs::Vfs::VfsMkdir(resolved);
|
||||
}
|
||||
|
||||
static int Sys_FRename(const char* oldPath, const char* newPath) {
|
||||
char resolvedOld[256];
|
||||
char resolvedNew[256];
|
||||
if (!ResolveProcessPath(oldPath, resolvedOld, sizeof(resolvedOld))) return -1;
|
||||
if (!ResolveProcessPath(newPath, resolvedNew, sizeof(resolvedNew))) return -1;
|
||||
if (!ResolveProcessPath(oldPath, resolvedOld, sizeof(resolvedOld))) return InvalidArgument;
|
||||
if (!ResolveProcessPath(newPath, resolvedNew, sizeof(resolvedNew))) return InvalidArgument;
|
||||
if (!CanModifyFilePath(resolvedOld) || !CanModifyFilePath(resolvedNew))
|
||||
return SYS_ERR_PERMISSION;
|
||||
return SystemIntegrityError;
|
||||
return Fs::Vfs::VfsRename(resolvedOld, resolvedNew);
|
||||
}
|
||||
|
||||
|
||||
@@ -118,18 +118,18 @@ namespace montauk::abi {
|
||||
if ((int64_t)index == -1) {
|
||||
return GPU::FlipSupported() ? 1 : 0;
|
||||
}
|
||||
if (!GPU::FlipSupported()) return -1;
|
||||
if (!GPU::FlipSupported()) return UnsupportedOp;
|
||||
|
||||
auto* proc = Sched::GetCurrentProcessPtr();
|
||||
if ((int64_t)index == -2) {
|
||||
return proc != nullptr ? GPU::AcquireFlip(proc->pid) : -1;
|
||||
return proc != nullptr ? GPU::AcquireFlip(proc->pid) : GenericFailure;
|
||||
}
|
||||
if (proc == nullptr) return -1;
|
||||
if (proc == nullptr) return GenericFailure;
|
||||
return GPU::Flip((int)index, (flags & 1) != 0, proc->pid);
|
||||
}
|
||||
|
||||
static int64_t Sys_DisplayInfo(DisplayInfo* out) {
|
||||
return Drivers::Graphics::IntelGPU::GetDisplayInfo(out) ? 0 : -1;
|
||||
return Drivers::Graphics::IntelGPU::GetDisplayInfo(out) ? Success : NoDevice;
|
||||
}
|
||||
|
||||
static int64_t Sys_DisplayModes(DisplayModeInfo* out, int maxCount) {
|
||||
@@ -137,7 +137,12 @@ namespace montauk::abi {
|
||||
}
|
||||
|
||||
static int64_t Sys_DisplaySetMode(int modeIndex) {
|
||||
return Drivers::Graphics::IntelGPU::SetDisplayMode(modeIndex);
|
||||
// The driver answers -2 for a mode that would need link retraining
|
||||
// and -3 for a modeset that failed and was rolled back.
|
||||
int64_t rc = Drivers::Graphics::IntelGPU::SetDisplayMode(modeIndex);
|
||||
if (rc == -2) return UnsupportedOp;
|
||||
if (rc == -3) return IoFailure;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int64_t Sys_DisplayBrightness(int percent) {
|
||||
|
||||
@@ -211,9 +211,9 @@ namespace montauk::abi {
|
||||
auto* proc = Sched::GetCurrentProcessPtr();
|
||||
int slot = GetCurrentSlot();
|
||||
if (proc == nullptr || slot < 0 || size == 0 || (addr & 0xFFFULL) != 0 ||
|
||||
size > UINT64_MAX - 0xFFFULL) return -1;
|
||||
size > UINT64_MAX - 0xFFFULL) return InvalidArgument;
|
||||
size = (size + 0xFFFULL) & ~0xFFFULL;
|
||||
if (addr > UINT64_MAX - size) return -1;
|
||||
if (addr > UINT64_MAX - size) return InvalidArgument;
|
||||
|
||||
g_heapLocks[slot].Acquire();
|
||||
uint64_t firstPage = 0;
|
||||
@@ -229,7 +229,7 @@ namespace montauk::abi {
|
||||
}
|
||||
link = &area->next;
|
||||
}
|
||||
if (*link == nullptr) { g_heapLocks[slot].Release(); return -1; }
|
||||
if (*link == nullptr) { g_heapLocks[slot].Release(); return InvalidArgument; }
|
||||
|
||||
HeapAlloc* area = *link;
|
||||
uint64_t oldPages = area->numPages;
|
||||
@@ -262,7 +262,7 @@ namespace montauk::abi {
|
||||
g_heapLocks[slot].Acquire();
|
||||
Sched::g_allocatedPages[slot] -= resident;
|
||||
g_heapLocks[slot].Release();
|
||||
return 0;
|
||||
return Success;
|
||||
}
|
||||
|
||||
inline int64_t Sys_Protect(uint64_t addr, uint64_t size, uint64_t prot) {
|
||||
@@ -272,9 +272,9 @@ namespace montauk::abi {
|
||||
size > UINT64_MAX - 0xFFFULL ||
|
||||
(prot & ~(VmProtRead | VmProtWrite | VmProtExec)) != 0 ||
|
||||
(prot & VmProtRead) == 0 ||
|
||||
((prot & VmProtWrite) != 0 && (prot & VmProtExec) != 0)) return -1;
|
||||
((prot & VmProtWrite) != 0 && (prot & VmProtExec) != 0)) return InvalidArgument;
|
||||
size = (size + 0xFFFULL) & ~0xFFFULL;
|
||||
if (addr > UINT64_MAX - size) return -1;
|
||||
if (addr > UINT64_MAX - size) return InvalidArgument;
|
||||
|
||||
g_heapLocks[slot].Acquire();
|
||||
uint64_t pages = size / 0x1000ULL;
|
||||
@@ -293,7 +293,7 @@ namespace montauk::abi {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!covered) { g_heapLocks[slot].Release(); return -1; }
|
||||
if (!covered) { g_heapLocks[slot].Release(); return InvalidArgument; }
|
||||
}
|
||||
|
||||
uint64_t end = addr + size;
|
||||
@@ -343,12 +343,12 @@ namespace montauk::abi {
|
||||
addr + i * 0x1000ULL,
|
||||
writable, executable)) {
|
||||
g_heapLocks[slot].Release();
|
||||
return -1;
|
||||
return GenericFailure;
|
||||
}
|
||||
}
|
||||
g_heapLocks[slot].Release();
|
||||
Memory::ShootdownUserRange(proc->pml4Phys, addr, (uint32_t)pages);
|
||||
return 0;
|
||||
return Success;
|
||||
}
|
||||
|
||||
// Resolve a non-present access inside an anonymous VMA. This is used for
|
||||
|
||||
+20
-20
@@ -19,18 +19,18 @@ namespace montauk::abi {
|
||||
const char* path, const char* args,
|
||||
const SpawnCapabilities* capabilities) {
|
||||
char resolved[256];
|
||||
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return -1;
|
||||
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return InvalidArgument;
|
||||
|
||||
int parentSlot = Ipc::CurrentSlot();
|
||||
int childPid = Sched::Spawn(resolved, args, false, nullptr, 0,
|
||||
capabilities);
|
||||
if (childPid < 0) return -1;
|
||||
if (childPid < 0) return childPid;
|
||||
|
||||
auto* child = Sched::GetProcessByPid(childPid);
|
||||
int childSlot = Ipc::SlotForPid(childPid);
|
||||
if (child == nullptr || childSlot < 0 || parentSlot < 0) {
|
||||
Sched::KillProcess(childPid);
|
||||
return -1;
|
||||
return GenericFailure;
|
||||
}
|
||||
|
||||
Ipc::Stream* outStream = Ipc::CreateStream(RedirOutputStreamCapacity);
|
||||
@@ -41,7 +41,7 @@ namespace montauk::abi {
|
||||
if (inStream != nullptr) Ipc::ReleaseStream(inStream, false, false);
|
||||
if (keyMailbox != nullptr) Ipc::ReleaseMailbox(keyMailbox, false, false);
|
||||
Sched::KillProcess(childPid);
|
||||
return -1;
|
||||
return OutOfMemory;
|
||||
}
|
||||
|
||||
int parentOutHandle = Ipc::InstallHandleForSlot(
|
||||
@@ -71,7 +71,7 @@ namespace montauk::abi {
|
||||
if (child->ioInHandle < 0) Ipc::ReleaseStream(inStream, false, false);
|
||||
if (child->ioKeyHandle < 0) Ipc::ReleaseMailbox(keyMailbox, false, false);
|
||||
Sched::KillProcess(childPid);
|
||||
return -1;
|
||||
return GenericFailure;
|
||||
}
|
||||
|
||||
child->redirected = true;
|
||||
@@ -80,7 +80,7 @@ namespace montauk::abi {
|
||||
child->termRows = 25;
|
||||
if (Sched::StartProcess(childPid) < 0) {
|
||||
Sched::KillProcess(childPid);
|
||||
return -1;
|
||||
return GenericFailure;
|
||||
}
|
||||
|
||||
return childPid;
|
||||
@@ -93,11 +93,11 @@ namespace montauk::abi {
|
||||
static int Sys_SpawnRedirCaps(const char* path, const char* args,
|
||||
const SpawnCapabilities* requested) {
|
||||
auto* parent = Sched::GetCurrentProcessPtr();
|
||||
if (parent == nullptr || requested == nullptr) return -1;
|
||||
if (parent == nullptr || requested == nullptr) return InvalidArgument;
|
||||
|
||||
SpawnCapabilities copy = *requested;
|
||||
if (!ValidCapabilityDelegation(copy, parent->delegableCaps)) {
|
||||
return SYS_ERR_PERMISSION;
|
||||
return CapabilityDenied;
|
||||
}
|
||||
return Sys_SpawnRedirInternal(path, args, ©);
|
||||
}
|
||||
@@ -105,51 +105,51 @@ namespace montauk::abi {
|
||||
static int Sys_ChildIoRead(int childPid, char* buf, int maxLen) {
|
||||
auto* child = Sched::GetProcessByPid(childPid);
|
||||
if (child == nullptr || child->parentPid != Sched::GetCurrentPid())
|
||||
return SYS_ERR_PERMISSION;
|
||||
return PermissionDenied;
|
||||
Ipc::HandleSnapshot snapshot;
|
||||
Ipc::Stream* stream = GetRedirOutStream(child, snapshot);
|
||||
if (!child->redirected || stream == nullptr) return -1;
|
||||
if (!child->redirected || stream == nullptr) return InvalidArgument;
|
||||
return Ipc::StreamRead(stream, (uint8_t*)buf, maxLen, true);
|
||||
}
|
||||
|
||||
static int Sys_ChildIoWrite(int childPid, const char* data, int len) {
|
||||
auto* child = Sched::GetProcessByPid(childPid);
|
||||
if (child == nullptr || child->parentPid != Sched::GetCurrentPid())
|
||||
return SYS_ERR_PERMISSION;
|
||||
return PermissionDenied;
|
||||
Ipc::HandleSnapshot snapshot;
|
||||
Ipc::Stream* stream = GetRedirInStream(child, snapshot);
|
||||
if (!child->redirected || stream == nullptr) return -1;
|
||||
if (!child->redirected || stream == nullptr) return InvalidArgument;
|
||||
return WriteAllToStream(stream, (const uint8_t*)data, len);
|
||||
}
|
||||
|
||||
static int Sys_ChildIoWriteKey(int childPid, const KeyEvent* key) {
|
||||
if (key == nullptr) return -1;
|
||||
if (key == nullptr) return InvalidArgument;
|
||||
auto* child = Sched::GetProcessByPid(childPid);
|
||||
if (child == nullptr || child->parentPid != Sched::GetCurrentPid())
|
||||
return SYS_ERR_PERMISSION;
|
||||
return PermissionDenied;
|
||||
Ipc::HandleSnapshot snapshot;
|
||||
Ipc::Mailbox* mailbox = GetRedirKeyMailbox(child, snapshot);
|
||||
if (!child->redirected || mailbox == nullptr) return -1;
|
||||
if (!child->redirected || mailbox == nullptr) return InvalidArgument;
|
||||
|
||||
for (;;) {
|
||||
uint64_t observedWake = Sched::ObserveObjectWake(mailbox);
|
||||
int rc = Ipc::MailboxSend(mailbox, 0, key, sizeof(KeyEvent));
|
||||
if (rc < 0) return -1;
|
||||
if (rc < 0) return GenericFailure;
|
||||
if (rc == 0) {
|
||||
Sched::BlockOnObjectSince(mailbox, 0, observedWake);
|
||||
continue;
|
||||
}
|
||||
return 0;
|
||||
return Success;
|
||||
}
|
||||
}
|
||||
|
||||
static int Sys_ChildIoSetTermsz(int childPid, int cols, int rows) {
|
||||
auto* child = Sched::GetProcessByPid(childPid);
|
||||
if (child == nullptr || child->parentPid != Sched::GetCurrentPid())
|
||||
return SYS_ERR_PERMISSION;
|
||||
if (!child->redirected) return -1;
|
||||
return PermissionDenied;
|
||||
if (!child->redirected) return InvalidArgument;
|
||||
child->termCols = cols;
|
||||
child->termRows = rows;
|
||||
return 0;
|
||||
return Success;
|
||||
}
|
||||
};
|
||||
@@ -20,15 +20,15 @@ namespace montauk::abi {
|
||||
}
|
||||
|
||||
static int Sys_StreamCreate(int* outReadHandle, int* outWriteHandle, uint32_t capacity) {
|
||||
if (outReadHandle == nullptr || outWriteHandle == nullptr) return -1;
|
||||
if (outReadHandle == nullptr || outWriteHandle == nullptr) return InvalidArgument;
|
||||
|
||||
int readHandle = -1;
|
||||
int writeHandle = -1;
|
||||
if (Ipc::CreateStreamHandlePair(capacity, readHandle, writeHandle) < 0) return -1;
|
||||
if (Ipc::CreateStreamHandlePair(capacity, readHandle, writeHandle) < 0) return GenericFailure;
|
||||
|
||||
*outReadHandle = readHandle;
|
||||
*outWriteHandle = writeHandle;
|
||||
return 0;
|
||||
return Success;
|
||||
}
|
||||
|
||||
static int Sys_StreamRead(int handle, uint8_t* buffer, int maxLen) {
|
||||
@@ -40,15 +40,15 @@ namespace montauk::abi {
|
||||
}
|
||||
|
||||
static int Sys_MailboxCreate(int* outSendHandle, int* outRecvHandle) {
|
||||
if (outSendHandle == nullptr || outRecvHandle == nullptr) return -1;
|
||||
if (outSendHandle == nullptr || outRecvHandle == nullptr) return InvalidArgument;
|
||||
|
||||
int sendHandle = -1;
|
||||
int recvHandle = -1;
|
||||
if (Ipc::CreateMailboxHandlePair(sendHandle, recvHandle) < 0) return -1;
|
||||
if (Ipc::CreateMailboxHandlePair(sendHandle, recvHandle) < 0) return GenericFailure;
|
||||
|
||||
*outSendHandle = sendHandle;
|
||||
*outRecvHandle = recvHandle;
|
||||
return 0;
|
||||
return Success;
|
||||
}
|
||||
|
||||
static int Sys_MailboxSend(int handle, uint32_t msgType, const void* data, uint16_t len, int attachHandle) {
|
||||
|
||||
@@ -115,15 +115,15 @@ namespace montauk::abi {
|
||||
// Decrements refcount; actually unmaps when refcount reaches 0.
|
||||
inline int Sys_UnloadLib(uint64_t handle) {
|
||||
int slot = GetCurrentSlot();
|
||||
if (slot < 0) return -1;
|
||||
if (slot < 0) return GenericFailure;
|
||||
|
||||
int libSlot = (int)handle - 1;
|
||||
if (libSlot < 0 || libSlot >= MaxLibsPerProcess) return -1;
|
||||
if (libSlot < 0 || libSlot >= MaxLibsPerProcess) return InvalidArgument;
|
||||
|
||||
g_libLocks[slot].Acquire();
|
||||
if (!g_libTable[slot][libSlot].inUse) {
|
||||
g_libLocks[slot].Release();
|
||||
return -1;
|
||||
return InvalidArgument;
|
||||
}
|
||||
|
||||
g_libTable[slot][libSlot].refcount--;
|
||||
@@ -144,7 +144,7 @@ namespace montauk::abi {
|
||||
}
|
||||
|
||||
g_libLocks[slot].Release();
|
||||
return 0;
|
||||
return Success;
|
||||
}
|
||||
|
||||
// Resolve a symbol in a loaded library.
|
||||
|
||||
@@ -164,7 +164,7 @@ namespace montauk::abi {
|
||||
// wired and wireless status apart: the IP configuration is global, so the
|
||||
// only way to say which interface owns it is `active`.
|
||||
static int Sys_NetIfs(NetIfInfo* out, int maxCount) {
|
||||
if (out == nullptr || maxCount <= 0) return -1;
|
||||
if (out == nullptr || maxCount <= 0) return InvalidArgument;
|
||||
|
||||
const auto* active = ::Net::NetIf::Active();
|
||||
int count = ::Net::NetIf::Count();
|
||||
@@ -193,12 +193,12 @@ namespace montauk::abi {
|
||||
}
|
||||
|
||||
static int Sys_SetNetCfg(const NetCfg* in) {
|
||||
if (in == nullptr) return -1;
|
||||
if (in == nullptr) return InvalidArgument;
|
||||
Net::SetIpAddress(in->ipAddress);
|
||||
Net::SetSubnetMask(in->subnetMask);
|
||||
Net::SetGateway(in->gateway);
|
||||
Net::SetDnsServer(in->dnsServer);
|
||||
return 0;
|
||||
return Success;
|
||||
}
|
||||
|
||||
// ---- DNS resolve ----
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace montauk::abi {
|
||||
Kt::KernelLogStream(Kt::INFO, "Power") << "pid " << kcp::dec
|
||||
<< (uint64_t)Sched::GetCurrentPid()
|
||||
<< " posted graceful power request " << (uint64_t)action;
|
||||
return 0;
|
||||
return Success;
|
||||
}
|
||||
|
||||
static void Sys_Reset() {
|
||||
@@ -88,7 +88,7 @@ namespace montauk::abi {
|
||||
|
||||
static int64_t Sys_Suspend() {
|
||||
if (!Hal::AcpiSleep::IsS3Available()) {
|
||||
return -1; // S3 not supported
|
||||
return UnsupportedOp; // S3 not supported
|
||||
}
|
||||
return (int64_t)Hal::AcpiSleep::Suspend();
|
||||
}
|
||||
@@ -98,7 +98,7 @@ namespace montauk::abi {
|
||||
static int64_t Sys_PowerInfo(PowerInfo* out) {
|
||||
Hal::CpuPower::Snapshot s{};
|
||||
if (!Hal::CpuPower::GetSnapshot(s)) {
|
||||
return -1;
|
||||
return NoDevice;
|
||||
}
|
||||
|
||||
out->hwpActive = s.HwpActive ? 1 : 0;
|
||||
@@ -113,7 +113,7 @@ namespace montauk::abi {
|
||||
out->maxMHz = s.MaxMHz;
|
||||
out->effMHz = s.EffMHz;
|
||||
out->apIdleHint = Hal::CpuIdle::GetApIdleHint();
|
||||
return 0;
|
||||
return Success;
|
||||
}
|
||||
|
||||
// SYS_BATTERYINFO. Fills a battery snapshot. Returns -1 on a machine with
|
||||
@@ -122,7 +122,7 @@ namespace montauk::abi {
|
||||
static int64_t Sys_BatteryInfo(BatteryInfo* out) {
|
||||
Hal::Battery::Status s{};
|
||||
if (!Hal::Battery::GetStatus(s)) {
|
||||
return -1;
|
||||
return NoDevice;
|
||||
}
|
||||
|
||||
out->present = s.Present ? 1 : 0;
|
||||
@@ -139,6 +139,6 @@ namespace montauk::abi {
|
||||
out->presentRate = s.PresentRate;
|
||||
out->voltageMv = s.VoltageMv;
|
||||
out->minutesRemaining = s.MinutesRemaining;
|
||||
return 0;
|
||||
return Success;
|
||||
}
|
||||
};
|
||||
+30
-30
@@ -49,13 +49,13 @@ namespace montauk::abi {
|
||||
// stream, whether or not it also carries a capability grant. The child is
|
||||
// created suspended (startReady == false) so its first instruction cannot
|
||||
// run before the channels exist, and is started here once they do.
|
||||
// Returns childPid, or kills the child and returns -1 on failure.
|
||||
// Returns childPid, or kills the child and returns GenericFailure.
|
||||
static int InheritRedirection(int childPid, Sched::Process* parent, int parentSlot) {
|
||||
auto* child = Sched::GetProcessByPid(childPid);
|
||||
int childSlot = Ipc::SlotForPid(childPid);
|
||||
if (child == nullptr || childSlot < 0 || parentSlot < 0) {
|
||||
Sched::KillProcess(childPid);
|
||||
return -1;
|
||||
return GenericFailure;
|
||||
}
|
||||
|
||||
child->ioOutHandle = DuplicateHandleBetweenSlots(parentSlot, parent->ioOutHandle, childSlot);
|
||||
@@ -65,7 +65,7 @@ namespace montauk::abi {
|
||||
if (child->ioOutHandle < 0 || child->ioInHandle < 0 || child->ioKeyHandle < 0 ||
|
||||
!ConfigureRedirWaitsetForSlot(childSlot, child)) {
|
||||
Sched::KillProcess(childPid);
|
||||
return -1;
|
||||
return GenericFailure;
|
||||
}
|
||||
|
||||
child->redirected = true;
|
||||
@@ -74,7 +74,7 @@ namespace montauk::abi {
|
||||
child->termRows = parent->termRows;
|
||||
if (Sched::StartProcess(childPid) < 0) {
|
||||
Sched::KillProcess(childPid);
|
||||
return -1;
|
||||
return GenericFailure;
|
||||
}
|
||||
|
||||
return childPid;
|
||||
@@ -83,7 +83,7 @@ namespace montauk::abi {
|
||||
static int Sys_Spawn(const char* path, const char* args,
|
||||
const char* environment = nullptr, uint32_t environmentLength = 0) {
|
||||
char resolved[256];
|
||||
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return -1;
|
||||
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return InvalidArgument;
|
||||
|
||||
auto* parent = Sched::GetCurrentProcessPtr();
|
||||
int parentSlot = Ipc::CurrentSlot();
|
||||
@@ -101,7 +101,7 @@ namespace montauk::abi {
|
||||
static int Sys_SpawnCaps(const char* path, const char* args,
|
||||
const char* user, const SpawnCapabilities* requested) {
|
||||
auto* parent = Sched::GetCurrentProcessPtr();
|
||||
if (parent == nullptr || requested == nullptr) return -1;
|
||||
if (parent == nullptr || requested == nullptr) return InvalidArgument;
|
||||
|
||||
// Snapshot all security-sensitive userspace inputs before evaluating
|
||||
// them. This prevents another thread from changing a mask or owner
|
||||
@@ -111,7 +111,7 @@ namespace montauk::abi {
|
||||
const char* userOverride = nullptr;
|
||||
if (user != nullptr) {
|
||||
if (!Sched::HasCapability(CAP_USER_ADMIN))
|
||||
return SYS_ERR_PERMISSION;
|
||||
return CapabilityDenied;
|
||||
int i = 0;
|
||||
for (; i < 31 && user[i]; i++) childUser[i] = user[i];
|
||||
childUser[i] = '\0';
|
||||
@@ -122,11 +122,11 @@ namespace montauk::abi {
|
||||
// possessing a capability is insufficient to pass it: the parent must
|
||||
// also hold it in its delegable set.
|
||||
if (!ValidCapabilityDelegation(copy, parent->delegableCaps)) {
|
||||
return SYS_ERR_PERMISSION;
|
||||
return CapabilityDenied;
|
||||
}
|
||||
|
||||
char resolved[256];
|
||||
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return -1;
|
||||
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return InvalidArgument;
|
||||
|
||||
int parentSlot = Ipc::CurrentSlot();
|
||||
bool inheritRedirection = parent->redirected;
|
||||
@@ -143,16 +143,16 @@ namespace montauk::abi {
|
||||
// The calling process's own capability masks.
|
||||
static int Sys_GetCaps(SpawnCapabilities* out) {
|
||||
auto* proc = Sched::GetCurrentProcessPtr();
|
||||
if (proc == nullptr || out == nullptr) return -1;
|
||||
if (proc == nullptr || out == nullptr) return InvalidArgument;
|
||||
out->effective = proc->effectiveCaps;
|
||||
out->delegable = proc->delegableCaps;
|
||||
return 0;
|
||||
return Success;
|
||||
}
|
||||
|
||||
// Copy the absolute path this process was spawned from (argv[0]).
|
||||
static int Sys_GetExecPath(char* buf, uint64_t maxLen) {
|
||||
auto* proc = Sched::GetCurrentProcessPtr();
|
||||
if (proc == nullptr || buf == nullptr || maxLen == 0) return -1;
|
||||
if (proc == nullptr || buf == nullptr || maxLen == 0) return InvalidArgument;
|
||||
int i = 0;
|
||||
for (; i < (int)maxLen - 1 && proc->name[i]; i++) {
|
||||
buf[i] = proc->name[i];
|
||||
@@ -163,7 +163,7 @@ namespace montauk::abi {
|
||||
|
||||
static int Sys_GetArgs(char* buf, uint64_t maxLen) {
|
||||
auto* proc = Sched::GetCurrentProcessPtr();
|
||||
if (proc == nullptr || buf == nullptr || maxLen == 0) return -1;
|
||||
if (proc == nullptr || buf == nullptr || maxLen == 0) return InvalidArgument;
|
||||
int i = 0;
|
||||
for (; i < (int)maxLen - 1 && proc->args[i]; i++) {
|
||||
buf[i] = proc->args[i];
|
||||
@@ -174,8 +174,8 @@ namespace montauk::abi {
|
||||
|
||||
static int Sys_GetEnviron(char* buf, uint64_t maxLen) {
|
||||
auto* proc = Sched::GetCurrentProcessPtr();
|
||||
if (proc == nullptr || buf == nullptr || maxLen == 0) return -1;
|
||||
if (maxLen < proc->environmentLength) return -2;
|
||||
if (proc == nullptr || buf == nullptr || maxLen == 0) return InvalidArgument;
|
||||
if (maxLen < proc->environmentLength) return BufferTooSmall;
|
||||
for (uint32_t i = 0; i < proc->environmentLength; i++)
|
||||
buf[i] = proc->environment[i];
|
||||
return (int)proc->environmentLength;
|
||||
@@ -184,10 +184,10 @@ namespace montauk::abi {
|
||||
static int Sys_SetEnviron(const char* buf, uint64_t len) {
|
||||
auto* proc = Sched::GetCurrentProcessPtr();
|
||||
if (proc == nullptr || buf == nullptr || len == 0 ||
|
||||
len > Sched::Process::EnvironmentBytes || buf[len - 1] != '\0') return -1;
|
||||
len > Sched::Process::EnvironmentBytes || buf[len - 1] != '\0') return InvalidArgument;
|
||||
for (uint64_t i = 0; i < len; i++) proc->environment[i] = buf[i];
|
||||
proc->environmentLength = (uint32_t)len;
|
||||
return 0;
|
||||
return Success;
|
||||
}
|
||||
|
||||
static int Sys_ProcList(ProcInfo* buf, int maxCount) {
|
||||
@@ -233,7 +233,7 @@ namespace montauk::abi {
|
||||
}
|
||||
ancestor = target->parentPid;
|
||||
}
|
||||
if (!descendant) return SYS_ERR_PERMISSION;
|
||||
if (!descendant) return PermissionDenied;
|
||||
}
|
||||
return Sched::KillProcess(pid);
|
||||
}
|
||||
@@ -247,19 +247,19 @@ namespace montauk::abi {
|
||||
}
|
||||
|
||||
static int Sys_SetUser(int pid, const char* name) {
|
||||
if (name == nullptr) return -1;
|
||||
if (name == nullptr) return InvalidArgument;
|
||||
auto* target = Sched::GetProcessByPid(pid);
|
||||
if (target == nullptr) return -1;
|
||||
if (target == nullptr) return InvalidArgument;
|
||||
int i = 0;
|
||||
for (; i < 31 && name[i]; i++)
|
||||
target->user[i] = name[i];
|
||||
target->user[i] = '\0';
|
||||
return 0;
|
||||
return Success;
|
||||
}
|
||||
|
||||
static int Sys_GetUser(char* buf, uint64_t maxLen) {
|
||||
auto* proc = Sched::GetCurrentProcessPtr();
|
||||
if (proc == nullptr || buf == nullptr || maxLen == 0) return -1;
|
||||
if (proc == nullptr || buf == nullptr || maxLen == 0) return InvalidArgument;
|
||||
int i = 0;
|
||||
for (; i < (int)maxLen - 1 && proc->user[i]; i++)
|
||||
buf[i] = proc->user[i];
|
||||
@@ -269,15 +269,15 @@ namespace montauk::abi {
|
||||
|
||||
static int Sys_GetCwd(char* buf, uint64_t maxLen) {
|
||||
auto* proc = Sched::GetCurrentProcessPtr();
|
||||
if (proc == nullptr || buf == nullptr || maxLen == 0) return -1;
|
||||
if (proc == nullptr || buf == nullptr || maxLen == 0) return InvalidArgument;
|
||||
|
||||
const char* cwd = proc->cwd[0] ? proc->cwd : "0:/";
|
||||
uint64_t cwdLen = 0;
|
||||
while (cwd[cwdLen] != '\0') cwdLen++;
|
||||
|
||||
// Reserve -1 for non-size failures so libc can distinguish them
|
||||
// from a buffer that can be retried with a larger allocation.
|
||||
if (maxLen <= cwdLen) return -2;
|
||||
// BufferTooSmall tells libc the call can be retried with a larger
|
||||
// allocation (ERANGE), unlike the other failures.
|
||||
if (maxLen <= cwdLen) return BufferTooSmall;
|
||||
|
||||
for (uint64_t i = 0; i <= cwdLen; i++) buf[i] = cwd[i];
|
||||
return (int)cwdLen;
|
||||
@@ -304,10 +304,10 @@ namespace montauk::abi {
|
||||
|
||||
static int Sys_Chdir(const char* path) {
|
||||
auto* proc = Sched::GetCurrentProcessPtr();
|
||||
if (proc == nullptr || path == nullptr) return -1;
|
||||
if (proc == nullptr || path == nullptr) return InvalidArgument;
|
||||
|
||||
char resolved[256];
|
||||
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return -1;
|
||||
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return InvalidArgument;
|
||||
|
||||
// ReadDir doubles as the directory-existence probe: it fails
|
||||
// for nonexistent paths and for regular files (directories are
|
||||
@@ -315,12 +315,12 @@ namespace montauk::abi {
|
||||
// would reject every valid target).
|
||||
{
|
||||
const char* entries[1];
|
||||
if (Fs::Vfs::VfsReadDir(resolved, entries, 1) < 0) return -1;
|
||||
if (Fs::Vfs::VfsReadDir(resolved, entries, 1) < 0) return NoSuchPath;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
for (; i < 255 && resolved[i]; i++) proc->cwd[i] = resolved[i];
|
||||
proc->cwd[i] = '\0';
|
||||
return 0;
|
||||
return Success;
|
||||
}
|
||||
};
|
||||
+25
-25
@@ -29,7 +29,7 @@ namespace montauk::abi {
|
||||
// Fill a user buffer with partition info. Returns the number of entries written.
|
||||
static int Sys_PartList(PartInfo* buf, int maxCount) {
|
||||
if (buf == nullptr || maxCount <= 0) return 0;
|
||||
if (!UserMemory::Range((uint64_t)buf, (uint64_t)maxCount * sizeof(PartInfo), true)) return -1;
|
||||
if (!UserMemory::Range((uint64_t)buf, (uint64_t)maxCount * sizeof(PartInfo), true)) return BadPointer;
|
||||
|
||||
int total = Drivers::Storage::Gpt::GetPartitionCount();
|
||||
int count = total < maxCount ? total : maxCount;
|
||||
@@ -58,10 +58,10 @@ namespace montauk::abi {
|
||||
}
|
||||
|
||||
// Fill a user buffer with one entry per mounted volume. Returns the number
|
||||
// of entries written, or -1 for a bad buffer.
|
||||
// of entries written, or BadPointer for a bad buffer.
|
||||
static int Sys_VolInfo(VolInfo* buf, int maxCount) {
|
||||
if (buf == nullptr || maxCount <= 0) return 0;
|
||||
if (!UserMemory::Range((uint64_t)buf, (uint64_t)maxCount * sizeof(VolInfo), true)) return -1;
|
||||
if (!UserMemory::Range((uint64_t)buf, (uint64_t)maxCount * sizeof(VolInfo), true)) return BadPointer;
|
||||
|
||||
int drives[Fs::Vfs::MaxDrives];
|
||||
int n = Fs::Vfs::VfsDriveList(drives, Fs::Vfs::MaxDrives);
|
||||
@@ -99,47 +99,47 @@ namespace montauk::abi {
|
||||
return n;
|
||||
}
|
||||
|
||||
// Read sectors from a block device. Returns bytes read, or -1 on error.
|
||||
// Read sectors from a block device. Returns bytes read, or a status code.
|
||||
static int64_t Sys_DiskRead(int blockDev, uint64_t lba, uint32_t count, void* buffer) {
|
||||
if (buffer == nullptr || count == 0) return -1;
|
||||
if (count > 128) return -1; // same limit as AHCI
|
||||
if (buffer == nullptr || count == 0) return InvalidArgument;
|
||||
if (count > 128) return InvalidArgument; // same limit as AHCI
|
||||
|
||||
auto* dev = Drivers::Storage::GetBlockDevice(blockDev);
|
||||
if (!dev) return -1;
|
||||
if (!dev) return NoDevice;
|
||||
|
||||
if (lba >= dev->SectorCount || count > dev->SectorCount - lba) return -1;
|
||||
if (!UserMemory::Range((uint64_t)buffer, (uint64_t)count * dev->SectorSize, true)) return -1;
|
||||
if (lba >= dev->SectorCount || count > dev->SectorCount - lba) return InvalidArgument;
|
||||
if (!UserMemory::Range((uint64_t)buffer, (uint64_t)count * dev->SectorSize, true)) return BadPointer;
|
||||
|
||||
if (!dev->ReadSectors(dev->Ctx, lba, count, buffer)) return -1;
|
||||
if (!dev->ReadSectors(dev->Ctx, lba, count, buffer)) return IoFailure;
|
||||
|
||||
return (int64_t)(count * dev->SectorSize);
|
||||
}
|
||||
|
||||
// Write sectors to a block device. Returns bytes written, or -1 on error.
|
||||
// Write sectors to a block device. Returns bytes written, or a status code.
|
||||
static int64_t Sys_DiskWrite(int blockDev, uint64_t lba, uint32_t count, const void* buffer) {
|
||||
if (buffer == nullptr || count == 0) return -1;
|
||||
if (count > 128) return -1;
|
||||
if (buffer == nullptr || count == 0) return InvalidArgument;
|
||||
if (count > 128) return InvalidArgument;
|
||||
|
||||
auto* dev = Drivers::Storage::GetBlockDevice(blockDev);
|
||||
if (!dev) return -1;
|
||||
if (!dev) return NoDevice;
|
||||
|
||||
if (lba >= dev->SectorCount || count > dev->SectorCount - lba) return -1;
|
||||
if (!UserMemory::Range((uint64_t)buffer, (uint64_t)count * dev->SectorSize, false)) return -1;
|
||||
if (lba >= dev->SectorCount || count > dev->SectorCount - lba) return InvalidArgument;
|
||||
if (!UserMemory::Range((uint64_t)buffer, (uint64_t)count * dev->SectorSize, false)) return BadPointer;
|
||||
|
||||
if (!dev->WriteSectors(dev->Ctx, lba, count, buffer)) return -1;
|
||||
if (!dev->WriteSectors(dev->Ctx, lba, count, buffer)) return IoFailure;
|
||||
|
||||
return (int64_t)(count * dev->SectorSize);
|
||||
}
|
||||
|
||||
// Initialize a new GPT on a block device. Returns 0 on success, -1 on error.
|
||||
// Initialize a new GPT on a block device. Returns 0 on success, GenericFailure on error.
|
||||
static int64_t Sys_GptInit(int blockDev) {
|
||||
Fs::FsProbe::UnmountPartitionsForBlockDevice(blockDev);
|
||||
return (int64_t)Drivers::Storage::Gpt::InitializeGpt(blockDev);
|
||||
}
|
||||
|
||||
// Add a partition to an existing GPT. Returns partition index on success, -1 on error.
|
||||
// Add a partition to an existing GPT. Returns partition index on success, GenericFailure on error.
|
||||
static int64_t Sys_GptAdd(const GptAddParams* params) {
|
||||
if (params == nullptr) return -1;
|
||||
if (params == nullptr) return InvalidArgument;
|
||||
|
||||
Drivers::Storage::Gpt::Guid typeGuid;
|
||||
__builtin_memcpy(&typeGuid, ¶ms->typeGuid, sizeof(typeGuid));
|
||||
@@ -149,7 +149,7 @@ namespace montauk::abi {
|
||||
typeGuid, params->name);
|
||||
}
|
||||
|
||||
// Mount a partition as a VFS drive. Returns 0 on success, -1 on error.
|
||||
// Mount a partition as a VFS drive. Returns 0 on success, GenericFailure on error.
|
||||
static int64_t Sys_FsMount(int partIndex, int driveNum) {
|
||||
return (int64_t)Fs::FsProbe::MountPartition(partIndex, driveNum);
|
||||
}
|
||||
@@ -163,12 +163,12 @@ namespace montauk::abi {
|
||||
return (int64_t)Fs::FsProbe::SyncAndUnmountAll();
|
||||
}
|
||||
|
||||
// Format a partition with a filesystem. Returns 0 on success, -1 on error.
|
||||
// Format a partition with a filesystem. Returns 0 on success, GenericFailure on error.
|
||||
static int64_t Sys_FsFormat(const FsFormatParams* params) {
|
||||
if (params == nullptr) return -1;
|
||||
if (params == nullptr) return InvalidArgument;
|
||||
|
||||
auto* part = Drivers::Storage::Gpt::GetPartition(params->partIndex);
|
||||
if (!part) return -1;
|
||||
if (!part) return InvalidArgument;
|
||||
|
||||
switch (params->fsType) {
|
||||
case FS_TYPE_FAT32:
|
||||
@@ -180,7 +180,7 @@ namespace montauk::abi {
|
||||
part->BlockDevIndex, part->StartLba, part->SectorCount,
|
||||
params->label[0] ? params->label : nullptr);
|
||||
default:
|
||||
return -1; // unknown filesystem type
|
||||
return UnsupportedOp; // unknown filesystem type
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+182
-180
@@ -62,54 +62,54 @@ namespace montauk::abi {
|
||||
switch (frame->syscall_nr) {
|
||||
case SYS_EXIT: {
|
||||
Sys_Exit((int)frame->arg1);
|
||||
return 0;
|
||||
return Success;
|
||||
}
|
||||
case SYS_YIELD:
|
||||
Sys_Yield();
|
||||
return 0;
|
||||
return Success;
|
||||
case SYS_SLEEP_MS:
|
||||
Sys_SleepMs(frame->arg1);
|
||||
return 0;
|
||||
return Success;
|
||||
case SYS_GETPID:
|
||||
return (int64_t)Sys_GetPid();
|
||||
case SYS_PRINT:
|
||||
if (!UserMemory::String(frame->arg1, kMaxPrintableStringBytes)) return -1;
|
||||
if (!UserMemory::String(frame->arg1, kMaxPrintableStringBytes)) return BadPointer;
|
||||
Sys_Print((const char*)frame->arg1);
|
||||
return 0;
|
||||
return Success;
|
||||
case SYS_PUTCHAR:
|
||||
Sys_Putchar((char)frame->arg1);
|
||||
return 0;
|
||||
return Success;
|
||||
case SYS_OPEN:
|
||||
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return -1;
|
||||
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return BadPointer;
|
||||
return (int64_t)Sys_Open((const char*)frame->arg1);
|
||||
case SYS_READ:
|
||||
if (!UserMemory::Range(frame->arg2, frame->arg4, true)) return -1;
|
||||
if (!UserMemory::Range(frame->arg2, frame->arg4, true)) return BadPointer;
|
||||
return (int64_t)Sys_Read((int)frame->arg1, (uint8_t*)frame->arg2,
|
||||
frame->arg3, frame->arg4);
|
||||
case SYS_GETSIZE:
|
||||
return (int64_t)Sys_GetSize((int)frame->arg1);
|
||||
case SYS_CLOSE:
|
||||
Sys_Close((int)frame->arg1);
|
||||
return 0;
|
||||
return Success;
|
||||
case SYS_READDIR:
|
||||
if ((int64_t)frame->arg3 < 0) return -1;
|
||||
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return -1;
|
||||
if ((int64_t)frame->arg3 < 0) return InvalidArgument;
|
||||
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return BadPointer;
|
||||
if (!UserMemory::Range(frame->arg2,
|
||||
(uint64_t)((frame->arg3 > 256) ? 256 : frame->arg3) * sizeof(const char*),
|
||||
true)) {
|
||||
return -1;
|
||||
return BadPointer;
|
||||
}
|
||||
return (int64_t)Sys_ReadDir((const char*)frame->arg1,
|
||||
(const char**)frame->arg2,
|
||||
(int)frame->arg3);
|
||||
case SYS_READDIR_AT:
|
||||
if ((int64_t)frame->arg3 < 0) return -1;
|
||||
if ((int64_t)frame->arg4 < 0) return -1;
|
||||
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return -1;
|
||||
if ((int64_t)frame->arg3 < 0) return InvalidArgument;
|
||||
if ((int64_t)frame->arg4 < 0) return InvalidArgument;
|
||||
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return BadPointer;
|
||||
if (!UserMemory::Range(frame->arg2,
|
||||
(uint64_t)((frame->arg3 > 256) ? 256 : frame->arg3) * sizeof(const char*),
|
||||
true)) {
|
||||
return -1;
|
||||
return BadPointer;
|
||||
}
|
||||
return (int64_t)Sys_ReadDirAt((const char*)frame->arg1,
|
||||
(const char**)frame->arg2,
|
||||
@@ -121,7 +121,7 @@ namespace montauk::abi {
|
||||
return (int64_t)Sys_AllocEager(frame->arg1);
|
||||
case SYS_FREE:
|
||||
Sys_Free(frame->arg1);
|
||||
return 0;
|
||||
return Success;
|
||||
case SYS_MMAP_ANON:
|
||||
return (int64_t)Sys_MapAnonymous(frame->arg1, frame->arg2);
|
||||
case SYS_MUNMAP:
|
||||
@@ -133,15 +133,15 @@ namespace montauk::abi {
|
||||
case SYS_GETMILLISECONDS:
|
||||
return (int64_t)Sys_GetMilliseconds();
|
||||
case SYS_GETINFO:
|
||||
if (!UserMemory::Writable<SysInfo>(frame->arg1)) return -1;
|
||||
if (!UserMemory::Writable<SysInfo>(frame->arg1)) return BadPointer;
|
||||
Sys_GetInfo((SysInfo*)frame->arg1);
|
||||
return 0;
|
||||
return Success;
|
||||
case SYS_ISKEYAVAILABLE:
|
||||
return (int64_t)Sys_IsKeyAvailable();
|
||||
case SYS_GETKEY:
|
||||
if (!UserMemory::Writable<KeyEvent>(frame->arg1)) return -1;
|
||||
if (!UserMemory::Writable<KeyEvent>(frame->arg1)) return BadPointer;
|
||||
Sys_GetKey((KeyEvent*)frame->arg1);
|
||||
return 0;
|
||||
return Success;
|
||||
case SYS_GETCHAR:
|
||||
return (int64_t)Sys_GetChar();
|
||||
case SYS_GETCHAR_NB:
|
||||
@@ -149,73 +149,75 @@ namespace montauk::abi {
|
||||
case SYS_PING:
|
||||
return (int64_t)Sys_Ping((uint32_t)frame->arg1, (uint32_t)frame->arg2);
|
||||
case SYS_SPAWN:
|
||||
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return -1;
|
||||
if (frame->arg2 != 0 && !UserMemory::String(frame->arg2, kMaxArgsBytes)) return -1;
|
||||
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return BadPointer;
|
||||
if (frame->arg2 != 0 && !UserMemory::String(frame->arg2, kMaxArgsBytes)) return BadPointer;
|
||||
return (int64_t)Sys_Spawn((const char*)frame->arg1,
|
||||
UserMemory::IsUserPtr(frame->arg2) ? (const char*)frame->arg2 : nullptr);
|
||||
case SYS_SPAWN_CAPS:
|
||||
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return -1;
|
||||
if (frame->arg2 != 0 && !UserMemory::String(frame->arg2, kMaxArgsBytes)) return -1;
|
||||
if (frame->arg3 != 0 && !UserMemory::String(frame->arg3, 32)) return -1;
|
||||
if (!UserMemory::Readable<SpawnCapabilities>(frame->arg4)) return -1;
|
||||
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return BadPointer;
|
||||
if (frame->arg2 != 0 && !UserMemory::String(frame->arg2, kMaxArgsBytes)) return BadPointer;
|
||||
if (frame->arg3 != 0 && !UserMemory::String(frame->arg3, 32)) return BadPointer;
|
||||
if (!UserMemory::Readable<SpawnCapabilities>(frame->arg4)) return BadPointer;
|
||||
return (int64_t)Sys_SpawnCaps(
|
||||
(const char*)frame->arg1,
|
||||
frame->arg2 ? (const char*)frame->arg2 : nullptr,
|
||||
frame->arg3 ? (const char*)frame->arg3 : nullptr,
|
||||
(const SpawnCapabilities*)frame->arg4);
|
||||
case SYS_SPAWN_ENV:
|
||||
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return -1;
|
||||
if (frame->arg2 != 0 && !UserMemory::String(frame->arg2, kMaxArgsBytes)) return -1;
|
||||
if (frame->arg3 == 0 || frame->arg4 == 0 ||
|
||||
frame->arg4 > Sched::Process::EnvironmentBytes ||
|
||||
!UserMemory::Range(frame->arg3, frame->arg4, false) ||
|
||||
((const char*)frame->arg3)[frame->arg4 - 1] != '\0') return -1;
|
||||
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return BadPointer;
|
||||
if (frame->arg2 != 0 && !UserMemory::String(frame->arg2, kMaxArgsBytes)) return BadPointer;
|
||||
if (frame->arg4 == 0 || frame->arg4 > Sched::Process::EnvironmentBytes)
|
||||
return InvalidArgument;
|
||||
if (frame->arg3 == 0 || !UserMemory::Range(frame->arg3, frame->arg4, false))
|
||||
return BadPointer;
|
||||
if (((const char*)frame->arg3)[frame->arg4 - 1] != '\0') return InvalidArgument;
|
||||
return (int64_t)Sys_Spawn((const char*)frame->arg1,
|
||||
UserMemory::IsUserPtr(frame->arg2) ? (const char*)frame->arg2 : nullptr,
|
||||
(const char*)frame->arg3, (uint32_t)frame->arg4);
|
||||
case SYS_WAITPID:
|
||||
return Sys_WaitPid((int)frame->arg1);
|
||||
case SYS_GETENVIRON:
|
||||
if (!UserMemory::Range(frame->arg1, frame->arg2, true)) return -1;
|
||||
if (!UserMemory::Range(frame->arg1, frame->arg2, true)) return BadPointer;
|
||||
return Sys_GetEnviron((char*)frame->arg1, frame->arg2);
|
||||
case SYS_SETENVIRON:
|
||||
if (frame->arg2 == 0 || frame->arg2 > Sched::Process::EnvironmentBytes ||
|
||||
!UserMemory::Range(frame->arg1, frame->arg2, false)) return -1;
|
||||
if (frame->arg2 == 0 || frame->arg2 > Sched::Process::EnvironmentBytes)
|
||||
return InvalidArgument;
|
||||
if (!UserMemory::Range(frame->arg1, frame->arg2, false)) return BadPointer;
|
||||
return Sys_SetEnviron((const char*)frame->arg1, frame->arg2);
|
||||
case SYS_FBINFO:
|
||||
if (!UserMemory::Writable<FbInfo>(frame->arg1)) return -1;
|
||||
if (!UserMemory::Writable<FbInfo>(frame->arg1)) return BadPointer;
|
||||
Sys_FbInfo((FbInfo*)frame->arg1);
|
||||
return 0;
|
||||
return Success;
|
||||
case SYS_FBMAP:
|
||||
return (int64_t)Sys_FbMap();
|
||||
case SYS_FBFLIP:
|
||||
return Sys_FbFlip(frame->arg1, frame->arg2);
|
||||
case SYS_DISPLAYINFO:
|
||||
if (!UserMemory::Writable<DisplayInfo>(frame->arg1)) return -1;
|
||||
if (!UserMemory::Writable<DisplayInfo>(frame->arg1)) return BadPointer;
|
||||
return Sys_DisplayInfo((DisplayInfo*)frame->arg1);
|
||||
case SYS_DISPLAYMODES:
|
||||
// The Intel driver publishes at most 32 modes. Bounding this
|
||||
// here also keeps the userspace range calculation overflow-free.
|
||||
if ((int64_t)frame->arg2 < 0 || frame->arg2 > 32) return -1;
|
||||
if ((int64_t)frame->arg2 < 0 || frame->arg2 > 32) return InvalidArgument;
|
||||
if (!UserMemory::Range(frame->arg1,
|
||||
(uint64_t)frame->arg2 * sizeof(DisplayModeInfo), true)) return -1;
|
||||
(uint64_t)frame->arg2 * sizeof(DisplayModeInfo), true)) return BadPointer;
|
||||
return Sys_DisplayModes((DisplayModeInfo*)frame->arg1, (int)frame->arg2);
|
||||
case SYS_DISPLAYSETMODE:
|
||||
if (!Sched::Consent::Require(CAP_DISPLAY_ADMIN)) return SYS_ERR_PERMISSION;
|
||||
if (!Sched::Consent::Require(CAP_DISPLAY_ADMIN)) return CapabilityDenied;
|
||||
return Sys_DisplaySetMode((int)frame->arg1);
|
||||
case SYS_DISPLAYBRIGHTNESS:
|
||||
if ((int64_t)frame->arg1 >= 0 &&
|
||||
!Sched::Consent::Require(CAP_DISPLAY_ADMIN)) return SYS_ERR_PERMISSION;
|
||||
!Sched::Consent::Require(CAP_DISPLAY_ADMIN)) return CapabilityDenied;
|
||||
return Sys_DisplayBrightness((int)frame->arg1);
|
||||
case SYS_GETEXECPATH:
|
||||
if (!UserMemory::Range(frame->arg2 ? frame->arg1 : frame->arg1, frame->arg2, true)) return -1;
|
||||
if (!UserMemory::Range(frame->arg2 ? frame->arg1 : frame->arg1, frame->arg2, true)) return BadPointer;
|
||||
return Sys_GetExecPath((char*)frame->arg1, frame->arg2);
|
||||
case SYS_STAT:
|
||||
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return -1;
|
||||
if (!UserMemory::Writable<FileStat>(frame->arg2)) return -1;
|
||||
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return BadPointer;
|
||||
if (!UserMemory::Writable<FileStat>(frame->arg2)) return BadPointer;
|
||||
return (int64_t)Sys_Stat((const char*)frame->arg1, (FileStat*)frame->arg2);
|
||||
case SYS_UTIME:
|
||||
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return -1;
|
||||
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return BadPointer;
|
||||
return (int64_t)Sys_Utime((const char*)frame->arg1,
|
||||
(int64_t)frame->arg2,
|
||||
(int64_t)frame->arg3,
|
||||
@@ -223,33 +225,33 @@ namespace montauk::abi {
|
||||
case SYS_TERMSIZE:
|
||||
return (int64_t)Sys_TermSize();
|
||||
case SYS_GETARGS:
|
||||
if (!UserMemory::Range(frame->arg1, frame->arg2, true)) return -1;
|
||||
if (!UserMemory::Range(frame->arg1, frame->arg2, true)) return BadPointer;
|
||||
return (int64_t)Sys_GetArgs((char*)frame->arg1, frame->arg2);
|
||||
case SYS_RESET:
|
||||
if (!Sched::HasCapability(CAP_POWER_CONTROL)) return SYS_ERR_PERMISSION;
|
||||
if (!Sched::HasCapability(CAP_POWER_CONTROL)) return CapabilityDenied;
|
||||
Sys_Reset();
|
||||
return 0;
|
||||
return Success;
|
||||
case SYS_SHUTDOWN:
|
||||
if (!Sched::HasCapability(CAP_POWER_CONTROL)) return SYS_ERR_PERMISSION;
|
||||
if (!Sched::HasCapability(CAP_POWER_CONTROL)) return CapabilityDenied;
|
||||
Sys_Shutdown();
|
||||
return 0;
|
||||
return Success;
|
||||
case SYS_POWER_REQUEST:
|
||||
if (frame->arg1 != POWER_REQ_QUERY &&
|
||||
frame->arg1 != POWER_REQ_SHUTDOWN &&
|
||||
frame->arg1 != POWER_REQ_REBOOT &&
|
||||
frame->arg1 != POWER_REQ_PEEK) return -1;
|
||||
frame->arg1 != POWER_REQ_PEEK) return InvalidArgument;
|
||||
if (frame->arg1 == POWER_REQ_QUERY) {
|
||||
if (!Sched::HasCapability(CAP_POWER_CONTROL)) return SYS_ERR_PERMISSION;
|
||||
if (!Sched::HasCapability(CAP_POWER_CONTROL)) return CapabilityDenied;
|
||||
} else if (!Sched::HasCapability(CAP_POWER_REQUEST)) {
|
||||
return SYS_ERR_PERMISSION;
|
||||
return CapabilityDenied;
|
||||
}
|
||||
return Sys_PowerRequest((int)frame->arg1);
|
||||
case SYS_GETTIME:
|
||||
if (!UserMemory::Writable<DateTime>(frame->arg1)) return -1;
|
||||
if (!UserMemory::Writable<DateTime>(frame->arg1)) return BadPointer;
|
||||
Sys_GetTime((DateTime*)frame->arg1);
|
||||
return 0;
|
||||
return Success;
|
||||
case SYS_SETUNIXTIME:
|
||||
if (!Sched::Consent::Require(CAP_SET_TIME)) return SYS_ERR_PERMISSION;
|
||||
if (!Sched::Consent::Require(CAP_SET_TIME)) return CapabilityDenied;
|
||||
return Sys_SetUnixTime((int64_t)frame->arg1);
|
||||
case SYS_SOCKET:
|
||||
return (int64_t)Sys_Socket((int)frame->arg1);
|
||||
@@ -262,114 +264,114 @@ namespace montauk::abi {
|
||||
case SYS_ACCEPT:
|
||||
return (int64_t)Sys_Accept((int)frame->arg1);
|
||||
case SYS_SEND:
|
||||
if (!UserMemory::Range(frame->arg2, frame->arg3, false)) return -1;
|
||||
if (!UserMemory::Range(frame->arg2, frame->arg3, false)) return BadPointer;
|
||||
return (int64_t)Sys_Send((int)frame->arg1, (const uint8_t*)frame->arg2, (uint32_t)frame->arg3);
|
||||
case SYS_RECV:
|
||||
if (!UserMemory::Range(frame->arg2, frame->arg3, true)) return -1;
|
||||
if (!UserMemory::Range(frame->arg2, frame->arg3, true)) return BadPointer;
|
||||
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;
|
||||
return Success;
|
||||
case SYS_GETNETCFG:
|
||||
if (!UserMemory::Writable<NetCfg>(frame->arg1)) return -1;
|
||||
if (!UserMemory::Writable<NetCfg>(frame->arg1)) return BadPointer;
|
||||
Sys_GetNetCfg((NetCfg*)frame->arg1);
|
||||
return 0;
|
||||
return Success;
|
||||
case SYS_SETNETCFG:
|
||||
if (!Sched::Consent::Require(CAP_NETWORK_ADMIN)) return SYS_ERR_PERMISSION;
|
||||
if (!UserMemory::Readable<NetCfg>(frame->arg1)) return -1;
|
||||
if (!Sched::Consent::Require(CAP_NETWORK_ADMIN)) return CapabilityDenied;
|
||||
if (!UserMemory::Readable<NetCfg>(frame->arg1)) return BadPointer;
|
||||
return (int64_t)Sys_SetNetCfg((const NetCfg*)frame->arg1);
|
||||
case SYS_NETSTATUS:
|
||||
if (!UserMemory::Writable<NetStatus>(frame->arg1)) return -1;
|
||||
if (!UserMemory::Writable<NetStatus>(frame->arg1)) return BadPointer;
|
||||
Sys_NetStatus((NetStatus*)frame->arg1);
|
||||
return 0;
|
||||
return Success;
|
||||
case SYS_SENDTO:
|
||||
if (!UserMemory::Range(frame->arg2, frame->arg3, false)) return -1;
|
||||
if (!UserMemory::Range(frame->arg2, frame->arg3, false)) return BadPointer;
|
||||
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 (!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;
|
||||
if (!UserMemory::Range(frame->arg2, frame->arg3, true)) return BadPointer;
|
||||
if (!UserMemory::OptionalRange(frame->arg4, sizeof(uint32_t), true)) return BadPointer;
|
||||
if (!UserMemory::OptionalRange(frame->arg5, sizeof(uint16_t), true)) return BadPointer;
|
||||
return (int64_t)Sys_RecvFrom((int)frame->arg1, (uint8_t*)frame->arg2,
|
||||
(uint32_t)frame->arg3,
|
||||
UserMemory::IsUserPtr(frame->arg4) ? (uint32_t*)frame->arg4 : nullptr,
|
||||
UserMemory::IsUserPtr(frame->arg5) ? (uint16_t*)frame->arg5 : nullptr);
|
||||
case SYS_FWRITE:
|
||||
if (!UserMemory::Range(frame->arg2, frame->arg4, false)) return -1;
|
||||
if (!UserMemory::Range(frame->arg2, frame->arg4, false)) return BadPointer;
|
||||
return (int64_t)Sys_FWrite((int)frame->arg1, (const uint8_t*)frame->arg2,
|
||||
frame->arg3, frame->arg4);
|
||||
case SYS_FCREATE:
|
||||
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return -1;
|
||||
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return BadPointer;
|
||||
return (int64_t)Sys_FCreate((const char*)frame->arg1);
|
||||
case SYS_FDELETE:
|
||||
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return -1;
|
||||
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return BadPointer;
|
||||
return (int64_t)Sys_FDelete((const char*)frame->arg1);
|
||||
case SYS_FMKDIR:
|
||||
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return -1;
|
||||
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return BadPointer;
|
||||
return (int64_t)Sys_FMkdir((const char*)frame->arg1);
|
||||
case SYS_FRENAME:
|
||||
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return -1;
|
||||
if (!UserMemory::String(frame->arg2, kMaxPathBytes)) return -1;
|
||||
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return BadPointer;
|
||||
if (!UserMemory::String(frame->arg2, kMaxPathBytes)) return BadPointer;
|
||||
return (int64_t)Sys_FRename((const char*)frame->arg1, (const char*)frame->arg2);
|
||||
case SYS_DRIVELIST:
|
||||
if ((int64_t)frame->arg2 < 0) return -1;
|
||||
if (!UserMemory::Range(frame->arg1, (uint64_t)frame->arg2 * sizeof(int), true)) return -1;
|
||||
if ((int64_t)frame->arg2 < 0) return InvalidArgument;
|
||||
if (!UserMemory::Range(frame->arg1, (uint64_t)frame->arg2 * sizeof(int), true)) return BadPointer;
|
||||
return (int64_t)Sys_DriveList((int*)frame->arg1, (int)frame->arg2);
|
||||
case SYS_DRIVELABEL:
|
||||
if ((int64_t)frame->arg3 <= 0) return -1;
|
||||
if (!UserMemory::Range(frame->arg2, frame->arg3, true)) return -1;
|
||||
if ((int64_t)frame->arg3 <= 0) return InvalidArgument;
|
||||
if (!UserMemory::Range(frame->arg2, frame->arg3, true)) return BadPointer;
|
||||
return (int64_t)Sys_DriveLabel((int)frame->arg1, (char*)frame->arg2, (int)frame->arg3);
|
||||
case SYS_DRIVEKIND:
|
||||
return (int64_t)Sys_DriveKind((int)frame->arg1);
|
||||
case SYS_TERMSCALE:
|
||||
return Sys_TermScale(frame->arg1, frame->arg2);
|
||||
case SYS_RESOLVE:
|
||||
if (!UserMemory::String(frame->arg1, kMaxHostnameBytes)) return -1;
|
||||
if (!UserMemory::String(frame->arg1, kMaxHostnameBytes)) return BadPointer;
|
||||
return Sys_Resolve((const char*)frame->arg1);
|
||||
case SYS_GETRANDOM:
|
||||
if (!UserMemory::Range(frame->arg1, frame->arg2, true)) return -1;
|
||||
if (!UserMemory::Range(frame->arg1, frame->arg2, true)) return BadPointer;
|
||||
return Sys_GetRandom((uint8_t*)frame->arg1, frame->arg2);
|
||||
case SYS_LOG:
|
||||
if (!Sched::Consent::Require(CAP_LOG_READ)) return SYS_ERR_PERMISSION;
|
||||
if (!UserMemory::Range(frame->arg1, frame->arg2, true)) return -1;
|
||||
if (!Sched::Consent::Require(CAP_LOG_READ)) return CapabilityDenied;
|
||||
if (!UserMemory::Range(frame->arg1, frame->arg2, true)) return BadPointer;
|
||||
return Kt::ReadKernelLogBuffer((char*)frame->arg1, frame->arg2);
|
||||
case SYS_MOUSESTATE:
|
||||
if (!UserMemory::Writable<MouseState>(frame->arg1)) return -1;
|
||||
if (!UserMemory::Writable<MouseState>(frame->arg1)) return BadPointer;
|
||||
Sys_MouseState((MouseState*)frame->arg1);
|
||||
return 0;
|
||||
return Success;
|
||||
case SYS_SETMOUSEBOUNDS:
|
||||
Sys_SetMouseBounds((int32_t)frame->arg1, (int32_t)frame->arg2);
|
||||
return 0;
|
||||
return Success;
|
||||
case SYS_SPAWN_REDIR:
|
||||
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return -1;
|
||||
if (frame->arg2 != 0 && !UserMemory::String(frame->arg2, kMaxArgsBytes)) return -1;
|
||||
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return BadPointer;
|
||||
if (frame->arg2 != 0 && !UserMemory::String(frame->arg2, kMaxArgsBytes)) return BadPointer;
|
||||
return (int64_t)Sys_SpawnRedir((const char*)frame->arg1,
|
||||
UserMemory::IsUserPtr(frame->arg2) ? (const char*)frame->arg2 : nullptr);
|
||||
case SYS_SPAWN_REDIR_CAPS:
|
||||
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return -1;
|
||||
if (frame->arg2 != 0 && !UserMemory::String(frame->arg2, kMaxArgsBytes)) return -1;
|
||||
if (!UserMemory::Readable<SpawnCapabilities>(frame->arg3)) return -1;
|
||||
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return BadPointer;
|
||||
if (frame->arg2 != 0 && !UserMemory::String(frame->arg2, kMaxArgsBytes)) return BadPointer;
|
||||
if (!UserMemory::Readable<SpawnCapabilities>(frame->arg3)) return BadPointer;
|
||||
return (int64_t)Sys_SpawnRedirCaps(
|
||||
(const char*)frame->arg1,
|
||||
frame->arg2 ? (const char*)frame->arg2 : nullptr,
|
||||
(const SpawnCapabilities*)frame->arg3);
|
||||
case SYS_CHILDIO_READ:
|
||||
if ((int64_t)frame->arg3 < 0) return -1;
|
||||
if (!UserMemory::Range(frame->arg2, (uint64_t)frame->arg3, true)) return -1;
|
||||
if ((int64_t)frame->arg3 < 0) return InvalidArgument;
|
||||
if (!UserMemory::Range(frame->arg2, (uint64_t)frame->arg3, true)) return BadPointer;
|
||||
return (int64_t)Sys_ChildIoRead((int)frame->arg1, (char*)frame->arg2, (int)frame->arg3);
|
||||
case SYS_CHILDIO_WRITE:
|
||||
if ((int64_t)frame->arg3 < 0) return -1;
|
||||
if (!UserMemory::Range(frame->arg2, (uint64_t)frame->arg3, false)) return -1;
|
||||
if ((int64_t)frame->arg3 < 0) return InvalidArgument;
|
||||
if (!UserMemory::Range(frame->arg2, (uint64_t)frame->arg3, false)) return BadPointer;
|
||||
return (int64_t)Sys_ChildIoWrite((int)frame->arg1, (const char*)frame->arg2, (int)frame->arg3);
|
||||
case SYS_CHILDIO_WRITEKEY:
|
||||
if (!UserMemory::Readable<KeyEvent>(frame->arg2)) return -1;
|
||||
if (!UserMemory::Readable<KeyEvent>(frame->arg2)) return BadPointer;
|
||||
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 (!UserMemory::String(frame->arg1, kMaxWindowTitleBytes)) return -1;
|
||||
if (!UserMemory::Writable<WinCreateResult>(frame->arg4)) return -1;
|
||||
if (!UserMemory::String(frame->arg1, kMaxWindowTitleBytes)) return BadPointer;
|
||||
if (!UserMemory::Writable<WinCreateResult>(frame->arg4)) return BadPointer;
|
||||
return (int64_t)Sys_WinCreate((const char*)frame->arg1, (int)frame->arg2,
|
||||
(int)frame->arg3, (WinCreateResult*)frame->arg4);
|
||||
case SYS_WINDESTROY:
|
||||
@@ -377,38 +379,38 @@ namespace montauk::abi {
|
||||
case SYS_WINPRESENT:
|
||||
return (int64_t)Sys_WinPresent((int)frame->arg1);
|
||||
case SYS_WINPOLL:
|
||||
if (!UserMemory::Writable<WinEvent>(frame->arg2)) return -1;
|
||||
if (!UserMemory::Writable<WinEvent>(frame->arg2)) return BadPointer;
|
||||
return (int64_t)Sys_WinPoll((int)frame->arg1, (WinEvent*)frame->arg2);
|
||||
case SYS_WINENUM:
|
||||
if ((int64_t)frame->arg2 < 0) return -1;
|
||||
if (!UserMemory::Range(frame->arg1, (uint64_t)frame->arg2 * sizeof(WinInfo), true)) return -1;
|
||||
if ((int64_t)frame->arg2 < 0) return InvalidArgument;
|
||||
if (!UserMemory::Range(frame->arg1, (uint64_t)frame->arg2 * sizeof(WinInfo), true)) return BadPointer;
|
||||
return (int64_t)Sys_WinEnum((WinInfo*)frame->arg1, (int)frame->arg2);
|
||||
case SYS_WINMAP:
|
||||
return (int64_t)Sys_WinMap((int)frame->arg1);
|
||||
case SYS_WINUNMAP:
|
||||
return (int64_t)Sys_WinUnmap((int)frame->arg1);
|
||||
case SYS_WINSENDEVENT:
|
||||
if (!UserMemory::Readable<WinEvent>(frame->arg2)) return -1;
|
||||
if (!UserMemory::Readable<WinEvent>(frame->arg2)) return BadPointer;
|
||||
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 ((int64_t)frame->arg2 < 0) return -1;
|
||||
if (!UserMemory::Range(frame->arg1, (uint64_t)frame->arg2 * sizeof(ProcInfo), true)) return -1;
|
||||
if ((int64_t)frame->arg2 < 0) return InvalidArgument;
|
||||
if (!UserMemory::Range(frame->arg1, (uint64_t)frame->arg2 * sizeof(ProcInfo), true)) return BadPointer;
|
||||
return (int64_t)Sys_ProcList((ProcInfo*)frame->arg1, (int)frame->arg2);
|
||||
case SYS_KILL:
|
||||
return (int64_t)Sys_Kill((int)frame->arg1);
|
||||
case SYS_SETSESSION:
|
||||
return (int64_t)Sys_SetSession();
|
||||
case SYS_KILLSESSION:
|
||||
if (!Sched::HasCapability(CAP_PROCESS_ADMIN)) return SYS_ERR_PERMISSION;
|
||||
if (!Sched::HasCapability(CAP_PROCESS_ADMIN)) return CapabilityDenied;
|
||||
return (int64_t)Sys_KillSession((int)frame->arg1);
|
||||
case SYS_DEVLIST:
|
||||
if ((int64_t)frame->arg2 < 0) return -1;
|
||||
if (!UserMemory::Range(frame->arg1, (uint64_t)frame->arg2 * sizeof(DevInfo), true)) return -1;
|
||||
if ((int64_t)frame->arg2 < 0) return InvalidArgument;
|
||||
if (!UserMemory::Range(frame->arg1, (uint64_t)frame->arg2 * sizeof(DevInfo), true)) return BadPointer;
|
||||
return (int64_t)Sys_DevList((DevInfo*)frame->arg1, (int)frame->arg2);
|
||||
case SYS_DISKINFO:
|
||||
if (!UserMemory::Writable<DiskInfo>(frame->arg1)) return -1;
|
||||
if (!UserMemory::Writable<DiskInfo>(frame->arg1)) return BadPointer;
|
||||
return (int64_t)Sys_DiskInfo((DiskInfo*)frame->arg1, (int)frame->arg2);
|
||||
case SYS_WINSETSCALE:
|
||||
return (int64_t)Sys_WinSetScale((int)frame->arg1);
|
||||
@@ -419,54 +421,54 @@ namespace montauk::abi {
|
||||
case SYS_WINSETFLAGS:
|
||||
return (int64_t)Sys_WinSetFlags((int)frame->arg1, (uint32_t)frame->arg2);
|
||||
case SYS_MEMSTATS:
|
||||
if (!UserMemory::Writable<MemStats>(frame->arg1)) return -1;
|
||||
if (!UserMemory::Writable<MemStats>(frame->arg1)) return BadPointer;
|
||||
Sys_MemStats((MemStats*)frame->arg1);
|
||||
return 0;
|
||||
return Success;
|
||||
case SYS_PARTLIST:
|
||||
if ((int64_t)frame->arg2 < 0) return -1;
|
||||
if (!UserMemory::Range(frame->arg1, (uint64_t)frame->arg2 * sizeof(PartInfo), true)) return -1;
|
||||
if ((int64_t)frame->arg2 < 0) return InvalidArgument;
|
||||
if (!UserMemory::Range(frame->arg1, (uint64_t)frame->arg2 * sizeof(PartInfo), true)) return BadPointer;
|
||||
return (int64_t)Sys_PartList((PartInfo*)frame->arg1, (int)frame->arg2);
|
||||
case SYS_VOLINFO:
|
||||
if ((int64_t)frame->arg2 < 0) return -1;
|
||||
if (!UserMemory::Range(frame->arg1, (uint64_t)frame->arg2 * sizeof(VolInfo), true)) return -1;
|
||||
if ((int64_t)frame->arg2 < 0) return InvalidArgument;
|
||||
if (!UserMemory::Range(frame->arg1, (uint64_t)frame->arg2 * sizeof(VolInfo), true)) return BadPointer;
|
||||
return (int64_t)Sys_VolInfo((VolInfo*)frame->arg1, (int)frame->arg2);
|
||||
case SYS_DISKREAD:
|
||||
if (!Sched::HasCapability(CAP_RAW_STORAGE)) return SYS_ERR_PERMISSION;
|
||||
if (!Sched::HasCapability(CAP_RAW_STORAGE)) return CapabilityDenied;
|
||||
return (int64_t)Sys_DiskRead((int)frame->arg1, frame->arg2,
|
||||
(uint32_t)frame->arg3, (void*)frame->arg4);
|
||||
case SYS_DISKWRITE:
|
||||
if (!Sched::HasCapability(CAP_RAW_STORAGE)) return SYS_ERR_PERMISSION;
|
||||
if (!Sched::HasCapability(CAP_RAW_STORAGE)) return CapabilityDenied;
|
||||
return (int64_t)Sys_DiskWrite((int)frame->arg1, frame->arg2,
|
||||
(uint32_t)frame->arg3, (const void*)frame->arg4);
|
||||
case SYS_GPTINIT:
|
||||
if (!Sched::Consent::Require(CAP_STORAGE_ADMIN)) return SYS_ERR_PERMISSION;
|
||||
if (!Sched::Consent::Require(CAP_STORAGE_ADMIN)) return CapabilityDenied;
|
||||
return (int64_t)Sys_GptInit((int)frame->arg1);
|
||||
case SYS_GPTADD:
|
||||
if (!Sched::Consent::Require(CAP_STORAGE_ADMIN)) return SYS_ERR_PERMISSION;
|
||||
if (!UserMemory::Readable<GptAddParams>(frame->arg1)) return -1;
|
||||
if (!Sched::Consent::Require(CAP_STORAGE_ADMIN)) return CapabilityDenied;
|
||||
if (!UserMemory::Readable<GptAddParams>(frame->arg1)) return BadPointer;
|
||||
return (int64_t)Sys_GptAdd((const GptAddParams*)frame->arg1);
|
||||
case SYS_FSMOUNT:
|
||||
if (!Sched::Consent::Require(CAP_STORAGE_ADMIN)) return SYS_ERR_PERMISSION;
|
||||
if (!Sched::Consent::Require(CAP_STORAGE_ADMIN)) return CapabilityDenied;
|
||||
return (int64_t)Sys_FsMount((int)frame->arg1, (int)frame->arg2);
|
||||
case SYS_FS_SYNC:
|
||||
if (!Sched::Consent::Require(CAP_STORAGE_ADMIN)) return SYS_ERR_PERMISSION;
|
||||
if (!Sched::Consent::Require(CAP_STORAGE_ADMIN)) return CapabilityDenied;
|
||||
return Sys_FsSync();
|
||||
case SYS_FSFORMAT:
|
||||
if (!Sched::Consent::Require(CAP_STORAGE_ADMIN)) return SYS_ERR_PERMISSION;
|
||||
if (!UserMemory::Readable<FsFormatParams>(frame->arg1)) return -1;
|
||||
if (!Sched::Consent::Require(CAP_STORAGE_ADMIN)) return CapabilityDenied;
|
||||
if (!UserMemory::Readable<FsFormatParams>(frame->arg1)) return BadPointer;
|
||||
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 (!UserMemory::Range(frame->arg2, frame->arg3, false)) return -1;
|
||||
if (!UserMemory::Range(frame->arg2, frame->arg3, false)) return BadPointer;
|
||||
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_AUDIOLIST:
|
||||
if ((int64_t)frame->arg2 < 0) return -1;
|
||||
if (!UserMemory::Range(frame->arg1, (uint64_t)frame->arg2 * sizeof(AudioStreamInfo), true)) return -1;
|
||||
if ((int64_t)frame->arg2 < 0) return InvalidArgument;
|
||||
if (!UserMemory::Range(frame->arg1, (uint64_t)frame->arg2 * sizeof(AudioStreamInfo), true)) return BadPointer;
|
||||
return Sys_AudioList((AudioStreamInfo*)frame->arg1, (int)frame->arg2);
|
||||
case SYS_AUDIOWAIT:
|
||||
return Sys_AudioWait(frame->arg1, frame->arg2);
|
||||
@@ -507,21 +509,21 @@ namespace montauk::abi {
|
||||
return Sys_UsbBulkInRead((int)frame->arg1, (uint8_t*)frame->arg2,
|
||||
(uint32_t)frame->arg3);
|
||||
case SYS_POWERINFO:
|
||||
if (!UserMemory::Writable<PowerInfo>(frame->arg1)) return -1;
|
||||
if (!UserMemory::Writable<PowerInfo>(frame->arg1)) return BadPointer;
|
||||
return Sys_PowerInfo((PowerInfo*)frame->arg1);
|
||||
case SYS_BATTERYINFO:
|
||||
// Read-only power telemetry, ungated like SYS_POWERINFO: the
|
||||
// panel indicator has to work in an unprivileged session, which
|
||||
// holds no device capability to spend on it.
|
||||
if (!UserMemory::Writable<BatteryInfo>(frame->arg1)) return -1;
|
||||
if (!UserMemory::Writable<BatteryInfo>(frame->arg1)) return BadPointer;
|
||||
return Sys_BatteryInfo((BatteryInfo*)frame->arg1);
|
||||
case SYS_GETCAPS:
|
||||
if (!UserMemory::Writable<SpawnCapabilities>(frame->arg1)) return -1;
|
||||
if (!UserMemory::Writable<SpawnCapabilities>(frame->arg1)) return BadPointer;
|
||||
return Sys_GetCaps((SpawnCapabilities*)frame->arg1);
|
||||
case SYS_CONSENT_REGISTER:
|
||||
return Sched::Consent::Register();
|
||||
case SYS_CONSENT_NEXT:
|
||||
if (!UserMemory::Writable<ConsentRequest>(frame->arg1)) return -1;
|
||||
if (!UserMemory::Writable<ConsentRequest>(frame->arg1)) return BadPointer;
|
||||
return Sched::Consent::Next((ConsentRequest*)frame->arg1);
|
||||
case SYS_CONSENT_REPLY:
|
||||
return Sched::Consent::Reply(frame->arg1, (int)frame->arg2);
|
||||
@@ -529,43 +531,43 @@ namespace montauk::abi {
|
||||
return Sys_ThreadSpawn(frame->arg1, frame->arg2, frame->arg3);
|
||||
case SYS_THREAD_EXIT:
|
||||
Sys_ThreadExit((int)frame->arg1);
|
||||
return 0;
|
||||
return Success;
|
||||
case SYS_THREAD_JOIN:
|
||||
if (frame->arg2 != 0 && !UserMemory::Writable<int>(frame->arg2)) return -1;
|
||||
if (frame->arg2 != 0 && !UserMemory::Writable<int>(frame->arg2)) return BadPointer;
|
||||
return Sys_ThreadJoin((int)frame->arg1, (int*)frame->arg2);
|
||||
case SYS_THREAD_SELF:
|
||||
return Sys_ThreadSelf();
|
||||
case SYS_BTSCAN:
|
||||
if (!Sched::HasCapability(CAP_DEVICE_ADMIN)) return SYS_ERR_PERMISSION;
|
||||
if ((int64_t)frame->arg2 < 0) return -1;
|
||||
if (!UserMemory::Range(frame->arg1, (uint64_t)frame->arg2 * sizeof(BtScanResult), true)) return -1;
|
||||
if (!Sched::HasCapability(CAP_DEVICE_ADMIN)) return CapabilityDenied;
|
||||
if ((int64_t)frame->arg2 < 0) return InvalidArgument;
|
||||
if (!UserMemory::Range(frame->arg1, (uint64_t)frame->arg2 * sizeof(BtScanResult), true)) return BadPointer;
|
||||
return Sys_BtScan((BtScanResult*)frame->arg1, (int)frame->arg2, (uint32_t)frame->arg3);
|
||||
case SYS_BTCONNECT:
|
||||
if (!Sched::HasCapability(CAP_DEVICE_ADMIN)) return SYS_ERR_PERMISSION;
|
||||
if (!UserMemory::Range(frame->arg1, 6, false)) return -1;
|
||||
if (!Sched::HasCapability(CAP_DEVICE_ADMIN)) return CapabilityDenied;
|
||||
if (!UserMemory::Range(frame->arg1, 6, false)) return BadPointer;
|
||||
return Sys_BtConnect((const uint8_t*)frame->arg1);
|
||||
case SYS_BTDISCONNECT:
|
||||
if (!Sched::HasCapability(CAP_DEVICE_ADMIN)) return SYS_ERR_PERMISSION;
|
||||
if (!UserMemory::Range(frame->arg1, 6, false)) return -1;
|
||||
if (!Sched::HasCapability(CAP_DEVICE_ADMIN)) return CapabilityDenied;
|
||||
if (!UserMemory::Range(frame->arg1, 6, false)) return BadPointer;
|
||||
return Sys_BtDisconnect((const uint8_t*)frame->arg1);
|
||||
case SYS_BTSETADDR:
|
||||
if (!Sched::HasCapability(CAP_DEVICE_ADMIN)) return SYS_ERR_PERMISSION;
|
||||
if (!UserMemory::Range(frame->arg1, 6, false)) return -1;
|
||||
if (!Sched::HasCapability(CAP_DEVICE_ADMIN)) return CapabilityDenied;
|
||||
if (!UserMemory::Range(frame->arg1, 6, false)) return BadPointer;
|
||||
return Sys_BtSetAddr((const uint8_t*)frame->arg1);
|
||||
case SYS_BTBONDS:
|
||||
if ((int64_t)frame->arg2 < 0) return -1;
|
||||
if (!UserMemory::Range(frame->arg1, (uint64_t)frame->arg2 * sizeof(BtBondInfo), true)) return -1;
|
||||
if ((int64_t)frame->arg2 < 0) return InvalidArgument;
|
||||
if (!UserMemory::Range(frame->arg1, (uint64_t)frame->arg2 * sizeof(BtBondInfo), true)) return BadPointer;
|
||||
return Sys_BtBonds((BtBondInfo*)frame->arg1, (int)frame->arg2);
|
||||
case SYS_BTFORGET:
|
||||
if (!Sched::HasCapability(CAP_DEVICE_ADMIN)) return SYS_ERR_PERMISSION;
|
||||
if (!UserMemory::Range(frame->arg1, 6, false)) return -1;
|
||||
if (!Sched::HasCapability(CAP_DEVICE_ADMIN)) return CapabilityDenied;
|
||||
if (!UserMemory::Range(frame->arg1, 6, false)) return BadPointer;
|
||||
return Sys_BtForget((const uint8_t*)frame->arg1);
|
||||
case SYS_BTLIST:
|
||||
if ((int64_t)frame->arg2 < 0) return -1;
|
||||
if (!UserMemory::Range(frame->arg1, (uint64_t)frame->arg2 * sizeof(BtDevInfo), true)) return -1;
|
||||
if ((int64_t)frame->arg2 < 0) return InvalidArgument;
|
||||
if (!UserMemory::Range(frame->arg1, (uint64_t)frame->arg2 * sizeof(BtDevInfo), true)) return BadPointer;
|
||||
return Sys_BtList((BtDevInfo*)frame->arg1, (int)frame->arg2);
|
||||
case SYS_BTINFO:
|
||||
if (!UserMemory::Writable<BtAdapterInfo>(frame->arg1)) return -1;
|
||||
if (!UserMemory::Writable<BtAdapterInfo>(frame->arg1)) return BadPointer;
|
||||
return Sys_BtInfo((BtAdapterInfo*)frame->arg1);
|
||||
case SYS_WIFI_SCAN:
|
||||
if (!Sched::Consent::Require(CAP_NETWORK_ADMIN)) return SYS_ERR_PERMISSION;
|
||||
@@ -596,61 +598,61 @@ namespace montauk::abi {
|
||||
if (frame->arg2 != 0 && !UserMemory::String(frame->arg2, 128)) return -1;
|
||||
return Sys_WifiConnectAsync((const char*)frame->arg1, (const char*)frame->arg2);
|
||||
case SYS_NETIFS:
|
||||
if ((int64_t)frame->arg2 < 0) return -1;
|
||||
if (!UserMemory::Range(frame->arg1, (uint64_t)frame->arg2 * sizeof(NetIfInfo), true)) return -1;
|
||||
if ((int64_t)frame->arg2 < 0) return InvalidArgument;
|
||||
if (!UserMemory::Range(frame->arg1, (uint64_t)frame->arg2 * sizeof(NetIfInfo), true)) return BadPointer;
|
||||
return Sys_NetIfs((NetIfInfo*)frame->arg1, (int)frame->arg2);
|
||||
case SYS_SUSPEND:
|
||||
if (!Sched::HasCapability(CAP_SUSPEND)) return SYS_ERR_PERMISSION;
|
||||
if (!Sched::HasCapability(CAP_SUSPEND)) return CapabilityDenied;
|
||||
return Sys_Suspend();
|
||||
case SYS_SETTZ:
|
||||
if (!Sched::Consent::Require(CAP_SET_TIME)) return SYS_ERR_PERMISSION;
|
||||
if (!Sched::Consent::Require(CAP_SET_TIME)) return CapabilityDenied;
|
||||
return Sys_SetTZ((int32_t)frame->arg1);
|
||||
case SYS_GETTZ:
|
||||
return Sys_GetTZ();
|
||||
case SYS_SETUSER:
|
||||
if (!Sched::HasCapability(CAP_USER_ADMIN)) return SYS_ERR_PERMISSION;
|
||||
if (!UserMemory::String(frame->arg2, kMaxUserNameBytes)) return -1;
|
||||
if (!Sched::HasCapability(CAP_USER_ADMIN)) return CapabilityDenied;
|
||||
if (!UserMemory::String(frame->arg2, kMaxUserNameBytes)) return BadPointer;
|
||||
return Sys_SetUser((int)frame->arg1, (const char*)frame->arg2);
|
||||
case SYS_GETUSER:
|
||||
if (!UserMemory::Range(frame->arg1, frame->arg2, true)) return -1;
|
||||
if (!UserMemory::Range(frame->arg1, frame->arg2, true)) return BadPointer;
|
||||
return Sys_GetUser((char*)frame->arg1, frame->arg2);
|
||||
case SYS_GETCWD:
|
||||
if (!UserMemory::Range(frame->arg1, frame->arg2, true)) return -1;
|
||||
if (!UserMemory::Range(frame->arg1, frame->arg2, true)) return BadPointer;
|
||||
return Sys_GetCwd((char*)frame->arg1, frame->arg2);
|
||||
case SYS_CHDIR:
|
||||
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return -1;
|
||||
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return BadPointer;
|
||||
return Sys_Chdir((const char*)frame->arg1);
|
||||
case SYS_DUPHANDLE:
|
||||
return Sys_DupHandle((int)frame->arg1);
|
||||
case SYS_WAIT_HANDLE:
|
||||
return (int64_t)Sys_WaitHandle((int)frame->arg1, (uint32_t)frame->arg2, frame->arg3);
|
||||
case SYS_STREAM_CREATE:
|
||||
if (!UserMemory::Writable<int>(frame->arg1) || !UserMemory::Writable<int>(frame->arg2)) return -1;
|
||||
if (!UserMemory::Writable<int>(frame->arg1) || !UserMemory::Writable<int>(frame->arg2)) return BadPointer;
|
||||
return Sys_StreamCreate((int*)frame->arg1, (int*)frame->arg2, (uint32_t)frame->arg3);
|
||||
case SYS_STREAM_READ:
|
||||
if ((int64_t)frame->arg3 < 0) return -1;
|
||||
if (!UserMemory::Range(frame->arg2, (uint64_t)frame->arg3, true)) return -1;
|
||||
if ((int64_t)frame->arg3 < 0) return InvalidArgument;
|
||||
if (!UserMemory::Range(frame->arg2, (uint64_t)frame->arg3, true)) return BadPointer;
|
||||
return Sys_StreamRead((int)frame->arg1, (uint8_t*)frame->arg2, (int)frame->arg3);
|
||||
case SYS_STREAM_WRITE:
|
||||
if ((int64_t)frame->arg3 < 0) return -1;
|
||||
if (!UserMemory::Range(frame->arg2, (uint64_t)frame->arg3, false)) return -1;
|
||||
if ((int64_t)frame->arg3 < 0) return InvalidArgument;
|
||||
if (!UserMemory::Range(frame->arg2, (uint64_t)frame->arg3, false)) return BadPointer;
|
||||
return Sys_StreamWrite((int)frame->arg1, (const uint8_t*)frame->arg2, (int)frame->arg3);
|
||||
case SYS_MAILBOX_CREATE:
|
||||
if (!UserMemory::Writable<int>(frame->arg1) || !UserMemory::Writable<int>(frame->arg2)) return -1;
|
||||
if (!UserMemory::Writable<int>(frame->arg1) || !UserMemory::Writable<int>(frame->arg2)) return BadPointer;
|
||||
return Sys_MailboxCreate((int*)frame->arg1, (int*)frame->arg2);
|
||||
case SYS_MAILBOX_SEND:
|
||||
if (frame->arg4 > 0 && !UserMemory::Range(frame->arg3, frame->arg4, false)) return -1;
|
||||
if (frame->arg4 > 0 && !UserMemory::Range(frame->arg3, frame->arg4, false)) return BadPointer;
|
||||
return Sys_MailboxSend((int)frame->arg1, (uint32_t)frame->arg2,
|
||||
(const void*)frame->arg3, (uint16_t)frame->arg4,
|
||||
(int)frame->arg5);
|
||||
case SYS_MAILBOX_RECV:
|
||||
if (!UserMemory::Writable<uint16_t>(frame->arg4)) return -1;
|
||||
if (frame->arg2 != 0 && !UserMemory::Writable<uint32_t>(frame->arg2)) return -1;
|
||||
if (!UserMemory::Writable<uint16_t>(frame->arg4)) return BadPointer;
|
||||
if (frame->arg2 != 0 && !UserMemory::Writable<uint32_t>(frame->arg2)) return BadPointer;
|
||||
if (frame->arg3 != 0) {
|
||||
uint16_t maxCopy = *(uint16_t*)frame->arg4;
|
||||
if (!UserMemory::Range(frame->arg3, maxCopy, true)) return -1;
|
||||
if (!UserMemory::Range(frame->arg3, maxCopy, true)) return BadPointer;
|
||||
}
|
||||
if (frame->arg5 != 0 && !UserMemory::Writable<int>(frame->arg5)) return -1;
|
||||
if (frame->arg5 != 0 && !UserMemory::Writable<int>(frame->arg5)) return BadPointer;
|
||||
return Sys_MailboxRecv((int)frame->arg1,
|
||||
UserMemory::IsUserPtr(frame->arg2) ? (uint32_t*)frame->arg2 : nullptr,
|
||||
UserMemory::IsUserPtr(frame->arg3) ? (void*)frame->arg3 : nullptr,
|
||||
@@ -663,7 +665,7 @@ namespace montauk::abi {
|
||||
case SYS_WAITSET_REMOVE:
|
||||
return Sys_WaitsetRemove((int)frame->arg1, (int)frame->arg2);
|
||||
case SYS_WAITSET_WAIT:
|
||||
if (frame->arg2 != 0 && !UserMemory::Writable<IpcWaitResult>(frame->arg2)) return -1;
|
||||
if (frame->arg2 != 0 && !UserMemory::Writable<IpcWaitResult>(frame->arg2)) return BadPointer;
|
||||
return Sys_WaitsetWait((int)frame->arg1,
|
||||
UserMemory::IsUserPtr(frame->arg2) ? (IpcWaitResult*)frame->arg2 : nullptr,
|
||||
frame->arg3);
|
||||
@@ -685,18 +687,18 @@ namespace montauk::abi {
|
||||
case SYS_GETLIBBASE:
|
||||
return (int64_t)Sys_GetLibBase(frame->arg1);
|
||||
case SYS_CRASH_REPORT:
|
||||
if (!UserMemory::Writable<CrashReportInfo>(frame->arg1)) return -1;
|
||||
if (!UserMemory::Writable<CrashReportInfo>(frame->arg1)) return BadPointer;
|
||||
return Sys_CrashReport((CrashReportInfo*)frame->arg1);
|
||||
case SYS_CLIPBOARD_SET_TEXT:
|
||||
if (frame->arg2 > 0 && !UserMemory::Range(frame->arg1, frame->arg2, false)) return -1;
|
||||
if (frame->arg2 > 0 && !UserMemory::Range(frame->arg1, frame->arg2, false)) return BadPointer;
|
||||
return Sys_ClipboardSetText((const char*)frame->arg1, (uint32_t)frame->arg2);
|
||||
case SYS_CLIPBOARD_GET_INFO:
|
||||
if (!UserMemory::Writable<ClipboardInfo>(frame->arg1)) return -1;
|
||||
if (!UserMemory::Writable<ClipboardInfo>(frame->arg1)) return BadPointer;
|
||||
return Sys_ClipboardGetInfo((ClipboardInfo*)frame->arg1);
|
||||
case SYS_CLIPBOARD_GET_TEXT:
|
||||
if (frame->arg2 > 0 && !UserMemory::Range(frame->arg1, frame->arg2, true)) return -1;
|
||||
if (!UserMemory::Writable<uint32_t>(frame->arg3)) return -1;
|
||||
if (frame->arg4 != 0 && !UserMemory::Writable<uint64_t>(frame->arg4)) return -1;
|
||||
if (frame->arg2 > 0 && !UserMemory::Range(frame->arg1, frame->arg2, true)) return BadPointer;
|
||||
if (!UserMemory::Writable<uint32_t>(frame->arg3)) return BadPointer;
|
||||
if (frame->arg4 != 0 && !UserMemory::Writable<uint64_t>(frame->arg4)) return BadPointer;
|
||||
return Sys_ClipboardGetText(UserMemory::IsUserPtr(frame->arg1) ? (char*)frame->arg1 : nullptr,
|
||||
(uint32_t)frame->arg2,
|
||||
(uint32_t*)frame->arg3,
|
||||
@@ -706,7 +708,7 @@ namespace montauk::abi {
|
||||
case SYS_INPUT_WAIT:
|
||||
return (int64_t)Sys_InputWait(frame->arg1, frame->arg2);
|
||||
case SYS_LOG_WRITE: {
|
||||
if (!UserMemory::String(frame->arg1, kMaxUserspaceLogEntryBytes)) return -1;
|
||||
if (!UserMemory::String(frame->arg1, kMaxUserspaceLogEntryBytes)) return BadPointer;
|
||||
|
||||
auto* process = Sched::GetCurrentProcessPtr();
|
||||
const char* username = process != nullptr && process->user[0] != '\0'
|
||||
@@ -719,12 +721,12 @@ namespace montauk::abi {
|
||||
Kt::UserspaceLogStream(imageName, username)
|
||||
<< (const char*)frame->arg1;
|
||||
|
||||
return 0;
|
||||
return Success;
|
||||
}
|
||||
case SYS_TERMINAL_ATTACHED:
|
||||
return Sys_TerminalAttached();
|
||||
default:
|
||||
return -1;
|
||||
return BadInvocation;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <Common/StatusCodes.hpp>
|
||||
|
||||
namespace montauk::abi {
|
||||
|
||||
@@ -399,6 +400,9 @@ namespace montauk::abi {
|
||||
static_assert((CAP_ADMIN_SESSION & CAP_COMPOSITOR) == 0,
|
||||
"a session must not delegate the compositor's authority; "
|
||||
"login grants it to the desktop directly");
|
||||
// Capability denial for the Wi-Fi and USB syscalls only, which keep their
|
||||
// own WIFI_ERR_* / USB_ERR_* spaces; everything else returns
|
||||
// CapabilityDenied from StatusCodes.
|
||||
static constexpr int SYS_ERR_PERMISSION = -13;
|
||||
|
||||
// A process holds two independent sets: what it may use (effective) and
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace montauk::abi {
|
||||
|
||||
static int64_t Sys_SetTZ(int32_t offsetMinutes) {
|
||||
Timekeeping::SetTZOffset(offsetMinutes);
|
||||
return 0;
|
||||
return Success;
|
||||
}
|
||||
|
||||
static int64_t Sys_GetTZ() {
|
||||
@@ -40,6 +40,6 @@ namespace montauk::abi {
|
||||
}
|
||||
|
||||
static int64_t Sys_SetUnixTime(int64_t unixSeconds) {
|
||||
return Timekeeping::SetUnixTimestamp(unixSeconds) ? 0 : -1;
|
||||
return Timekeeping::SetUnixTimestamp(unixSeconds) ? Success : InvalidArgument;
|
||||
}
|
||||
};
|
||||
@@ -55,13 +55,13 @@ namespace WinServer {
|
||||
}
|
||||
|
||||
static int UnmapRetiredSnapshotsLocked(int windowId, int callerPid, uint64_t callerPml4) {
|
||||
int result = -1;
|
||||
int result = InvalidArgument;
|
||||
for (int i = 0; i < MaxRetiredSnapshots; i++) {
|
||||
if (!g_retiredSnapshots[i].used || g_retiredSnapshots[i].windowId != windowId) continue;
|
||||
|
||||
if (g_retiredSnapshots[i].surface != nullptr) {
|
||||
if (Ipc::UnmapSurfaceForPid(g_retiredSnapshots[i].surface, callerPid, callerPml4) == 0) {
|
||||
result = 0;
|
||||
result = Success;
|
||||
}
|
||||
Ipc::ReleaseSurface(g_retiredSnapshots[i].surface);
|
||||
}
|
||||
@@ -95,21 +95,22 @@ namespace WinServer {
|
||||
}
|
||||
|
||||
static int SendEventLocked(int windowId, const montauk::abi::WinEvent* event) {
|
||||
if (windowId < 0 || windowId >= MaxWindows || event == nullptr) return -1;
|
||||
if (windowId < 0 || windowId >= MaxWindows || event == nullptr) return InvalidArgument;
|
||||
WindowSlot& slot = g_slots[windowId];
|
||||
if (!slot.used || slot.eventMailbox == nullptr) return -1;
|
||||
if (!slot.used || slot.eventMailbox == nullptr) return InvalidArgument;
|
||||
|
||||
int rc = (event->type == 1)
|
||||
? Ipc::MailboxSendCoalescedMouse(slot.eventMailbox, 0, event, sizeof(*event))
|
||||
: Ipc::MailboxSend(slot.eventMailbox, 0, event, sizeof(*event));
|
||||
return rc > 0 ? 0 : -1;
|
||||
if (rc < 0) return GenericFailure;
|
||||
return rc > 0 ? Success : Busy;
|
||||
}
|
||||
|
||||
int Create(int ownerPid, uint64_t ownerPml4, const char* title, int w, int h,
|
||||
uint64_t& heapNext, uint64_t& outVa) {
|
||||
WsGuard guard;
|
||||
|
||||
if (w <= 0 || h <= 0 || w > 16384 || h > 16384) return -1;
|
||||
if (w <= 0 || h <= 0 || w > 16384 || h > 16384) return InvalidArgument;
|
||||
|
||||
int slotIdx = -1;
|
||||
for (int i = 0; i < MaxWindows; i++) {
|
||||
@@ -118,7 +119,7 @@ namespace WinServer {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (slotIdx < 0) return -1;
|
||||
if (slotIdx < 0) return GenericFailure;
|
||||
|
||||
uint64_t bufSize = (uint64_t)w * (uint64_t)h * 4ULL;
|
||||
Ipc::Surface* live = Ipc::CreateSurface(bufSize);
|
||||
@@ -128,7 +129,7 @@ namespace WinServer {
|
||||
if (live != nullptr) Ipc::ReleaseSurface(live);
|
||||
if (snapshot != nullptr) Ipc::ReleaseSurface(snapshot);
|
||||
if (mailbox != nullptr) Ipc::ReleaseMailbox(mailbox, false, false);
|
||||
return -1;
|
||||
return OutOfMemory;
|
||||
}
|
||||
|
||||
Ipc::RetainSurface(live);
|
||||
@@ -146,7 +147,7 @@ namespace WinServer {
|
||||
Ipc::ReleaseMailbox(mailbox, true, true);
|
||||
Ipc::ReleaseSurface(snapshot);
|
||||
Ipc::ReleaseSurface(live);
|
||||
return -1;
|
||||
return GenericFailure;
|
||||
}
|
||||
|
||||
WindowSlot& slot = g_slots[slotIdx];
|
||||
@@ -176,40 +177,41 @@ namespace WinServer {
|
||||
|
||||
int Destroy(int windowId, int callerPid) {
|
||||
WsGuard guard;
|
||||
if (windowId < 0 || windowId >= MaxWindows) return -1;
|
||||
if (windowId < 0 || windowId >= MaxWindows) return InvalidArgument;
|
||||
|
||||
WindowSlot& slot = g_slots[windowId];
|
||||
if (!slot.used || slot.ownerPid != callerPid) return -1;
|
||||
if (!slot.used) return InvalidArgument;
|
||||
if (slot.ownerPid != callerPid) return PermissionDenied;
|
||||
|
||||
ReleaseSlotResourcesLocked(slot, true);
|
||||
return 0;
|
||||
return Success;
|
||||
}
|
||||
|
||||
int Present(int windowId, int callerPid) {
|
||||
WsGuard guard;
|
||||
if (windowId < 0 || windowId >= MaxWindows) return -1;
|
||||
if (windowId < 0 || windowId >= MaxWindows) return InvalidArgument;
|
||||
|
||||
WindowSlot& slot = g_slots[windowId];
|
||||
if (!slot.used || slot.ownerPid != callerPid ||
|
||||
slot.liveSurface == nullptr || slot.snapshotSurface == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
if (!slot.used || slot.liveSurface == nullptr || slot.snapshotSurface == nullptr)
|
||||
return InvalidArgument;
|
||||
if (slot.ownerPid != callerPid) return PermissionDenied;
|
||||
|
||||
if (Ipc::CopySurface(slot.snapshotSurface, slot.liveSurface) != 0) return -1;
|
||||
if (Ipc::CopySurface(slot.snapshotSurface, slot.liveSurface) != 0) return GenericFailure;
|
||||
slot.dirty = true;
|
||||
return 0;
|
||||
return Success;
|
||||
}
|
||||
|
||||
int Poll(int windowId, int callerPid, montauk::abi::WinEvent* outEvent) {
|
||||
WsGuard guard;
|
||||
if (windowId < 0 || windowId >= MaxWindows || outEvent == nullptr) return -1;
|
||||
if (windowId < 0 || windowId >= MaxWindows || outEvent == nullptr) return InvalidArgument;
|
||||
|
||||
WindowSlot& slot = g_slots[windowId];
|
||||
if (!slot.used || slot.ownerPid != callerPid || slot.eventMailbox == nullptr) return -1;
|
||||
if (!slot.used || slot.eventMailbox == nullptr) return InvalidArgument;
|
||||
if (slot.ownerPid != callerPid) return PermissionDenied;
|
||||
|
||||
uint16_t len = sizeof(*outEvent);
|
||||
int rc = Ipc::MailboxRecv(slot.eventMailbox, nullptr, outEvent, &len, true);
|
||||
if (rc < 0) return -1;
|
||||
if (rc < 0) return GenericFailure;
|
||||
return rc > 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
@@ -259,7 +261,7 @@ namespace WinServer {
|
||||
if (!slot.used || slot.snapshotSurface == nullptr) return result;
|
||||
|
||||
int current = Ipc::UnmapSurfaceForPid(slot.snapshotSurface, callerPid, callerPml4);
|
||||
if (current == 0) return 0;
|
||||
if (current == 0) return Success;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -271,14 +273,15 @@ namespace WinServer {
|
||||
int Resize(int windowId, int callerPid, uint64_t ownerPml4, int newW, int newH,
|
||||
uint64_t& heapNext, uint64_t& outVa) {
|
||||
WsGuard guard;
|
||||
if (windowId < 0 || windowId >= MaxWindows) return -1;
|
||||
if (windowId < 0 || windowId >= MaxWindows) return InvalidArgument;
|
||||
|
||||
WindowSlot& slot = g_slots[windowId];
|
||||
if (!slot.used || slot.ownerPid != callerPid) return -1;
|
||||
if (newW <= 0 || newH <= 0 || newW > 16384 || newH > 16384) return -1;
|
||||
if (!slot.used) return InvalidArgument;
|
||||
if (slot.ownerPid != callerPid) return PermissionDenied;
|
||||
if (newW <= 0 || newH <= 0 || newW > 16384 || newH > 16384) return InvalidArgument;
|
||||
if (newW == slot.width && newH == slot.height) {
|
||||
outVa = slot.ownerVa;
|
||||
return 0;
|
||||
return Success;
|
||||
}
|
||||
|
||||
uint64_t bufSize = (uint64_t)newW * (uint64_t)newH * 4ULL;
|
||||
@@ -287,7 +290,7 @@ namespace WinServer {
|
||||
if (newLive == nullptr || newSnapshot == nullptr) {
|
||||
if (newLive != nullptr) Ipc::ReleaseSurface(newLive);
|
||||
if (newSnapshot != nullptr) Ipc::ReleaseSurface(newSnapshot);
|
||||
return -1;
|
||||
return OutOfMemory;
|
||||
}
|
||||
|
||||
Ipc::RetainSurface(newLive);
|
||||
@@ -297,7 +300,7 @@ namespace WinServer {
|
||||
if (Ipc::MapSurfaceForPid(newLive, callerPid, ownerPml4, heapNext, newOwnerVa, false) != 0) {
|
||||
Ipc::ReleaseSurface(newSnapshot);
|
||||
Ipc::ReleaseSurface(newLive);
|
||||
return -1;
|
||||
return GenericFailure;
|
||||
}
|
||||
|
||||
if (slot.liveSurface != nullptr) {
|
||||
@@ -327,27 +330,29 @@ namespace WinServer {
|
||||
slot.dirty = true;
|
||||
|
||||
outVa = newOwnerVa;
|
||||
return 0;
|
||||
return Success;
|
||||
}
|
||||
|
||||
int SetCursor(int windowId, int callerPid, int cursor) {
|
||||
WsGuard guard;
|
||||
if (windowId < 0 || windowId >= MaxWindows) return -1;
|
||||
if (windowId < 0 || windowId >= MaxWindows) return InvalidArgument;
|
||||
|
||||
WindowSlot& slot = g_slots[windowId];
|
||||
if (!slot.used || slot.ownerPid != callerPid) return -1;
|
||||
if (!slot.used) return InvalidArgument;
|
||||
if (slot.ownerPid != callerPid) return PermissionDenied;
|
||||
slot.cursor = (uint8_t)cursor;
|
||||
return 0;
|
||||
return Success;
|
||||
}
|
||||
|
||||
int SetFlags(int windowId, int callerPid, uint32_t flags) {
|
||||
WsGuard guard;
|
||||
if (windowId < 0 || windowId >= MaxWindows) return -1;
|
||||
if (windowId < 0 || windowId >= MaxWindows) return InvalidArgument;
|
||||
|
||||
WindowSlot& slot = g_slots[windowId];
|
||||
if (!slot.used || slot.ownerPid != callerPid) return -1;
|
||||
if (!slot.used) return InvalidArgument;
|
||||
if (slot.ownerPid != callerPid) return PermissionDenied;
|
||||
slot.flags = flags & montauk::abi::WIN_FLAG_FULLSCREEN;
|
||||
return 0;
|
||||
return Success;
|
||||
}
|
||||
|
||||
int SetScale(int scale) {
|
||||
@@ -364,7 +369,7 @@ namespace WinServer {
|
||||
SendEventLocked(i, &ev);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return Success;
|
||||
}
|
||||
|
||||
int GetScale() {
|
||||
|
||||
@@ -15,16 +15,16 @@
|
||||
namespace montauk::abi {
|
||||
|
||||
static int Sys_WinCreate(const char* title, int w, int h, WinCreateResult* result) {
|
||||
if (result == nullptr || title == nullptr) return -1;
|
||||
if (result == nullptr || title == nullptr) return InvalidArgument;
|
||||
auto* proc = Sched::GetCurrentProcessPtr();
|
||||
if (proc == nullptr) return -1;
|
||||
if (proc == nullptr) return GenericFailure;
|
||||
|
||||
uint64_t outVa = 0;
|
||||
int id = WinServer::Create(proc->pid, proc->pml4Phys, title, w, h,
|
||||
proc->heapNext, outVa);
|
||||
result->id = id;
|
||||
result->pixelVa = (id >= 0) ? outVa : 0;
|
||||
return id >= 0 ? 0 : -1;
|
||||
return id >= 0 ? Success : id;
|
||||
}
|
||||
|
||||
static int Sys_WinDestroy(int windowId) {
|
||||
@@ -36,7 +36,7 @@ namespace montauk::abi {
|
||||
}
|
||||
|
||||
static int Sys_WinPoll(int windowId, WinEvent* outEvent) {
|
||||
if (outEvent == nullptr) return -1;
|
||||
if (outEvent == nullptr) return InvalidArgument;
|
||||
return WinServer::Poll(windowId, Sched::GetCurrentPid(), outEvent);
|
||||
}
|
||||
|
||||
@@ -58,13 +58,13 @@ namespace montauk::abi {
|
||||
|
||||
static int Sys_WinUnmap(int windowId) {
|
||||
auto* proc = Sched::GetCurrentProcessPtr();
|
||||
if (proc == nullptr) return -1;
|
||||
if (proc == nullptr) return GenericFailure;
|
||||
return WinServer::Unmap(windowId, proc->pid, proc->pml4Phys);
|
||||
}
|
||||
|
||||
static int Sys_WinSendEvent(int windowId, const WinEvent* event) {
|
||||
if (!Sched::HasCapability(CAP_COMPOSITOR)) return SYS_ERR_PERMISSION;
|
||||
if (event == nullptr) return -1;
|
||||
if (!Sched::HasCapability(CAP_COMPOSITOR)) return CapabilityDenied;
|
||||
if (event == nullptr) return InvalidArgument;
|
||||
return WinServer::SendEvent(windowId, event);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* StatusCodes.hpp
|
||||
* MontaukOS system status codes.
|
||||
* Copyright (c) 2026 Daniel Hammer
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// Syscall return status. Mirrored for userspace in
|
||||
// programs/include/montauk/statuscodes.h and, as MTK_STATUS_*, in
|
||||
// programs/include/libc/montauk.h; scripts/montauk-syscalls.py checks all three.
|
||||
enum StatusCodes {
|
||||
Success = 0,
|
||||
GenericFailure = -1,
|
||||
PermissionDenied = -2,
|
||||
CapabilityDenied = -3,
|
||||
SystemIntegrityError = -4,
|
||||
BadPointer = -5,
|
||||
InvalidArgument = -6,
|
||||
UnsupportedOp = -7,
|
||||
NoDevice = -8,
|
||||
IoFailure = -9,
|
||||
BadInvocation = -10,
|
||||
NoSuchPath = -11,
|
||||
Busy = -12,
|
||||
BufferTooSmall = -13,
|
||||
OutOfMemory = -14
|
||||
};
|
||||
@@ -1153,7 +1153,7 @@ namespace Ipc {
|
||||
uint64_t writeCapability = Fs::RequiredFileWriteCapability(path);
|
||||
if (create && writeCapability != 0 &&
|
||||
!Sched::HasCapability(writeCapability)) {
|
||||
return montauk::abi::SYS_ERR_PERMISSION;
|
||||
return SystemIntegrityError;
|
||||
}
|
||||
|
||||
Fs::Vfs::BackendFile backend = {-1, -1, 0};
|
||||
@@ -1207,15 +1207,16 @@ namespace Ipc {
|
||||
|
||||
int FileWriteHandle(int handle, const uint8_t* buffer, uint64_t offset, uint64_t size) {
|
||||
if (buffer == nullptr) return -1;
|
||||
if (size > 0 && !montauk::abi::UserMemory::Range((uint64_t)buffer, size, false)) return -1;
|
||||
if (size > 0 && !montauk::abi::UserMemory::Range((uint64_t)buffer, size, false)) return BadPointer;
|
||||
|
||||
HandleSnapshot snapshot;
|
||||
if (!snapshot.Capture(CurrentSlot(), handle)) return -1;
|
||||
if (snapshot.type != HandleType::File || (snapshot.rights & RightWrite) == 0) return -1;
|
||||
if (!snapshot.Capture(CurrentSlot(), handle)) return InvalidArgument;
|
||||
if (snapshot.type != HandleType::File) return InvalidArgument;
|
||||
if ((snapshot.rights & RightWrite) == 0) return PermissionDenied;
|
||||
File* file = (File*)snapshot.object;
|
||||
if (file->writeCapability != 0 &&
|
||||
!Sched::HasCapability(file->writeCapability)) {
|
||||
return montauk::abi::SYS_ERR_PERMISSION;
|
||||
return SystemIntegrityError;
|
||||
}
|
||||
return Fs::Vfs::WriteBackendFile(file->backend, buffer, offset, size);
|
||||
}
|
||||
|
||||
@@ -161,25 +161,25 @@ namespace Sched::Consent {
|
||||
}
|
||||
|
||||
int Register() {
|
||||
if (!HasCapability(CAP_COMPOSITOR)) return SYS_ERR_PERMISSION;
|
||||
if (!HasCapability(CAP_COMPOSITOR)) return CapabilityDenied;
|
||||
int pid = GetCurrentPid();
|
||||
|
||||
g_lock.Acquire();
|
||||
// OnProcessExit clears a dead agent, so a live one is always current.
|
||||
if (g_agentPid >= 0 && g_agentPid != pid) {
|
||||
g_lock.Release();
|
||||
return -1;
|
||||
return Busy;
|
||||
}
|
||||
g_agentPid = pid;
|
||||
g_lock.Release();
|
||||
|
||||
Kt::KernelLogStream(Kt::INFO, "Consent") << "Agent registered: pid " << (uint64_t)pid;
|
||||
return 0;
|
||||
return Success;
|
||||
}
|
||||
|
||||
int Next(ConsentRequest* out) {
|
||||
int agent = GetCurrentPid();
|
||||
if (agent < 0 || agent != g_agentPid) return SYS_ERR_PERMISSION;
|
||||
if (agent < 0 || agent != g_agentPid) return PermissionDenied;
|
||||
|
||||
ConsentRequest local;
|
||||
for (;;) {
|
||||
@@ -226,7 +226,7 @@ namespace Sched::Consent {
|
||||
|
||||
int Reply(uint64_t id, int decision) {
|
||||
int agent = GetCurrentPid();
|
||||
if (agent < 0 || agent != g_agentPid) return SYS_ERR_PERMISSION;
|
||||
if (agent < 0 || agent != g_agentPid) return PermissionDenied;
|
||||
|
||||
Request* request = nullptr;
|
||||
int pid = -1;
|
||||
@@ -253,13 +253,13 @@ namespace Sched::Consent {
|
||||
}
|
||||
g_lock.Release();
|
||||
|
||||
if (request == nullptr) return -1;
|
||||
if (request == nullptr) return InvalidArgument;
|
||||
WakeObjectWaiters(request);
|
||||
|
||||
Kt::KernelLogStream(Kt::INFO, "Consent") << "pid " << (uint64_t)pid << " "
|
||||
<< NameOf(capability) << ": "
|
||||
<< (granted ? "allowed" : (decision == CONSENT_ALLOW ? "allow refused (no longer valid)" : "denied"));
|
||||
return 0;
|
||||
return Success;
|
||||
}
|
||||
|
||||
void OnProcessExit(int pid) {
|
||||
|
||||
Reference in new issue
Block a user