feat: implement kernel capability model

This commit is contained in:
daniel committed 2026-08-29 16:53:04 +02:00
1 parent 9051b8a16e
commit e7646bbbdb
47 files changed
+1507 -264

No files matched your search

+46 -7
View File
@@ -4,6 +4,7 @@
* Copyright (c) 2025-2026 Daniel Hammer
*/
#include <Memory/UserRange.hpp>
#include "Scheduler.hpp"
#include "ElfLoader.hpp"
#include <Memory/PageFrameAllocator.hpp>
@@ -298,6 +299,9 @@ namespace Sched {
processTable[i].environment[0] = '\0';
processTable[i].environmentLength = 1;
processTable[i].user[0] = '\0';
processTable[i].permittedCaps = 0;
processTable[i].effectiveCaps = 0;
processTable[i].delegableCaps = 0;
processTable[i].sessionId = -1;
processTable[i].cwd[0] = '\0';
processTable[i].runningOnCpu = -1;
@@ -342,7 +346,9 @@ namespace Sched {
}
int Spawn(const char* vfsPath, const char* args, bool startReady,
const char* environment, uint32_t environmentLength) {
const char* environment, uint32_t environmentLength,
const montauk::abi::SpawnCapabilities* capabilities,
const char* userOverride) {
schedLock.Acquire();
int slot = -1;
@@ -547,9 +553,37 @@ namespace Sched {
proc.environmentLength = 1;
}
// Inherit user string from parent, or default to "system" if no parent
// Capabilities are kernel-owned and never inferred from the user name.
// A normal userspace spawn receives no privileged authority; callers
// must use SYS_SPAWN_CAPS for an explicit, kernel-validated delegation.
if (parentPrimarySlot >= 0) {
if (capabilities != nullptr) {
proc.permittedCaps = capabilities->permitted;
proc.effectiveCaps = capabilities->effective;
proc.delegableCaps = capabilities->delegable;
} else {
proc.permittedCaps = 0;
proc.effectiveCaps = 0;
proc.delegableCaps = 0;
}
} else {
// The kernel-created init process is the root of the capability
// delegation tree. No userspace pathname or PID receives this
// treatment; it is reached only with no current parent process.
proc.permittedCaps = montauk::abi::CAP_ALL;
proc.effectiveCaps = montauk::abi::CAP_ALL;
proc.delegableCaps = montauk::abi::CAP_ALL;
}
// Inherit user string from parent, or default to "system" if no parent.
// An explicit override is accepted only through the validated
// SYS_SPAWN_CAPS path.
{
if (parentSlot >= 0) {
if (userOverride != nullptr) {
int i = 0;
for (; i < 31 && userOverride[i]; i++) proc.user[i] = userOverride[i];
proc.user[i] = '\0';
} else if (parentSlot >= 0) {
int i = 0;
for (; i < 31 && processTable[parentSlot].user[i]; i++)
proc.user[i] = processTable[parentSlot].user[i];
@@ -684,7 +718,7 @@ namespace Sched {
mappedPages++;
}
if (!ok) {
Ipc::UnmapAndFreeUserRange(sharedPml4, base, mappedPages);
Memory::UnmapAndFreeUserRange(sharedPml4, base, mappedPages);
ReleaseUserHeapRange(primarySlot_, base, numPages * 0x1000ULL);
Kt::KernelLogStream(Kt::ERROR, "Sched")
<< "Thread TLS allocation failed";
@@ -711,7 +745,7 @@ namespace Sched {
void* stackMem = Memory::g_pfa->ReallocConsecutive(nullptr, StackPages);
if (stackMem == nullptr) {
if (threadTlsPages != 0) {
Ipc::UnmapAndFreeUserRange(sharedPml4, threadTlsBase, threadTlsPages);
Memory::UnmapAndFreeUserRange(sharedPml4, threadTlsBase, threadTlsPages);
ReleaseUserHeapRange(primarySlot_, threadTlsBase,
threadTlsPages * 0x1000ULL);
}
@@ -737,7 +771,7 @@ namespace Sched {
schedLock.Release();
Memory::g_pfa->Free(stackMem, StackPages);
if (threadTlsPages != 0) {
Ipc::UnmapAndFreeUserRange(sharedPml4, threadTlsBase, threadTlsPages);
Memory::UnmapAndFreeUserRange(sharedPml4, threadTlsBase, threadTlsPages);
ReleaseUserHeapRange(primarySlot_, threadTlsBase,
threadTlsPages * 0x1000ULL);
}
@@ -885,7 +919,7 @@ namespace Sched {
uint64_t base = thr.fsBase - blockSize;
uint64_t pages = (blockSize + 16 + 0xFFF) / 0x1000;
thr.fsBase = 0;
Ipc::UnmapAndFreeUserRange(primary.pml4Phys, base, pages);
Memory::UnmapAndFreeUserRange(primary.pml4Phys, base, pages);
ReleaseUserHeapRange(primarySlot_, base, pages * 0x1000ULL);
}
@@ -1418,6 +1452,11 @@ namespace Sched {
return &processTable[primary];
}
bool HasCapability(uint64_t capability) {
Process* proc = GetCurrentProcessPtr();
return proc != nullptr && (proc->effectiveCaps & capability) == capability;
}
Process* GetCurrentThreadPtr() {
auto* cpu = Smp::GetCurrentCpuData();
int slot = cpu->currentSlot;