feat: implement kernel capability model
This commit is contained in:
1 parent
9051b8a16e
commit
e7646bbbdb
47 files changed
+1507
-264
No files matched your search
@@ -86,6 +86,39 @@ namespace montauk::abi {
|
||||
return childPid;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
// Snapshot all security-sensitive userspace inputs before evaluating
|
||||
// them. This prevents another thread from changing a mask or owner
|
||||
// name between validation and process creation.
|
||||
SpawnCapabilities copy = *requested;
|
||||
char childUser[32];
|
||||
const char* userOverride = nullptr;
|
||||
if (user != nullptr) {
|
||||
if (!Sched::HasCapability(CAP_USER_ADMIN))
|
||||
return SYS_ERR_PERMISSION;
|
||||
int i = 0;
|
||||
for (; i < 31 && user[i]; i++) childUser[i] = user[i];
|
||||
childUser[i] = '\0';
|
||||
userOverride = childUser;
|
||||
}
|
||||
|
||||
// Authority may only diminish down the process tree. In particular,
|
||||
// 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;
|
||||
}
|
||||
|
||||
char resolved[256];
|
||||
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return -1;
|
||||
return Sched::Spawn(resolved, args, true, nullptr, 0, ©,
|
||||
userOverride);
|
||||
}
|
||||
|
||||
// Copy the absolute path this process was spawned from (argv[0]).
|
||||
static int Sys_GetExecPath(char* buf, uint64_t maxLen) {
|
||||
auto* proc = Sched::GetCurrentProcessPtr();
|
||||
@@ -150,12 +183,29 @@ namespace montauk::abi {
|
||||
}
|
||||
buf[count].heapUsed = Sched::g_allocatedPages[i] * 0x1000;
|
||||
buf[count].cpuTimeMs = proc->cpuTimeMs;
|
||||
buf[count].permittedCaps = proc->permittedCaps;
|
||||
buf[count].effectiveCaps = proc->effectiveCaps;
|
||||
buf[count].delegableCaps = proc->delegableCaps;
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static int Sys_Kill(int pid) {
|
||||
if (!Sched::HasCapability(CAP_PROCESS_ADMIN)) {
|
||||
int ancestor = pid;
|
||||
bool descendant = false;
|
||||
for (int depth = 0; depth < Sched::MaxProcesses; depth++) {
|
||||
auto* target = Sched::GetProcessByPid(ancestor);
|
||||
if (target == nullptr || target->parentPid < 0) break;
|
||||
if (target->parentPid == Sched::GetCurrentPid()) {
|
||||
descendant = true;
|
||||
break;
|
||||
}
|
||||
ancestor = target->parentPid;
|
||||
}
|
||||
if (!descendant) return SYS_ERR_PERMISSION;
|
||||
}
|
||||
return Sched::KillProcess(pid);
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user