linux: Fix broken process limits implementation

This commit is contained in:
EnderIce2 2024-10-13 02:19:26 +03:00
parent 02cf233534
commit 93e8e3f354
Signed by untrusted user who does not match committer: enderice2
GPG Key ID: EACC3AD603BAB4DD
3 changed files with 78 additions and 23 deletions

View File

@ -451,6 +451,7 @@ namespace Tasking
bool IsCritical = false;
bool IsDebugEnabled = false;
bool IsKernelDebugEnabled = false;
bool CanAdjustHardLimits = false;
struct
{
uint16_t UserID = UINT16_MAX;
@ -460,11 +461,17 @@ namespace Tasking
pid_t SessionID = 0;
} Security{};
struct
{
rlim_t OpenFiles = 128;
rlim_t Threads = 64;
rlim_t Memory = 1073741824; /* 1 GiB */
} SoftLimits{};
struct
{
rlim_t OpenFiles = 4096;
rlim_t Threads = 1024;
rlim_t Memory = 8589934592; /* 8 GiB */
} Limits{};
} HardLimits{};
TaskInfo Info{};
ThreadLocalStorage TLS{};

View File

@ -166,7 +166,7 @@ namespace vfs
{
Tasking::PCB *pcb = thisProcess;
for (size_t i = 0; i < pcb->Limits.OpenFiles; i++)
for (size_t i = 0; i < pcb->SoftLimits.OpenFiles; i++)
{
auto it = this->FileMap.find(i);
if (it == this->FileMap.end())

View File

@ -2687,30 +2687,32 @@ static int linux_prlimit64(SysFrm *, pid_t pid, int resource,
{
static_assert(sizeof(struct rlimit) < PAGE_SIZE);
PCB *pcb = thisProcess;
Memory::VirtualMemoryArea *vma = pcb->vma;
PCB *pcb = nullptr;
if (likely(pid == 0))
pcb = thisProcess;
else
{
pcb = thisProcess->GetContext()->GetProcessByID(pid);
if (pcb == nullptr)
return -linux_ESRCH;
fixme("implement CAP_SYS_RESOURCE");
return -linux_EPERM;
}
Memory::VirtualMemoryArea *vma = thisProcess->vma;
auto pOldLimit = vma->UserCheckAndGetAddress(old_limit);
auto pNewLimit = vma->UserCheckAndGetAddress(new_limit);
if (pOldLimit == nullptr && old_limit != nullptr)
return -EFAULT;
return -linux_EFAULT;
if (pNewLimit == nullptr && new_limit != nullptr)
return -EFAULT;
UNUSED(pOldLimit);
UNUSED(pNewLimit);
return -linux_EFAULT;
if (new_limit)
{
debug("new limit: rlim_cur:%lld rlim_max:%lld",
pNewLimit->rlim_cur, pNewLimit->rlim_max);
}
if (old_limit)
{
debug("old limit: rlim_cur:%lld rlim_max:%lld",
pOldLimit->rlim_cur, pOldLimit->rlim_max);
if (pNewLimit->rlim_cur > pNewLimit->rlim_max)
return -linux_EINVAL;
}
switch (resource)
@ -2724,22 +2726,70 @@ static int linux_prlimit64(SysFrm *, pid_t pid, int resource,
goto __stub;
case linux_RLIMIT_NPROC:
{
if (old_limit)
{
pOldLimit->rlim_cur = pcb->SoftLimits.Threads;
pOldLimit->rlim_max = pcb->HardLimits.Threads;
debug("read NPROC limit: {%#lx, %#lx}", pOldLimit->rlim_cur, pOldLimit->rlim_max);
}
if (new_limit)
pcb->Limits.Threads = pNewLimit->rlim_max;
{
if (pNewLimit->rlim_max > pcb->HardLimits.Threads && !pcb->Security.CanAdjustHardLimits)
return -linux_EPERM;
debug("setting NPROC limit to {%#lx, %#lx}->{%#lx, %#lx}",
pcb->SoftLimits.Threads, pcb->HardLimits.Threads,
pNewLimit->rlim_cur, pNewLimit->rlim_max);
pcb->SoftLimits.Threads = pNewLimit->rlim_cur;
pcb->HardLimits.Threads = pNewLimit->rlim_max;
}
return 0;
}
case linux_RLIMIT_NOFILE:
{
if (old_limit)
{
pOldLimit->rlim_cur = pcb->SoftLimits.OpenFiles;
pOldLimit->rlim_max = pcb->HardLimits.OpenFiles;
debug("read NOFILE limit: {%#lx, %#lx}", pOldLimit->rlim_cur, pOldLimit->rlim_max);
}
if (new_limit)
pcb->Limits.OpenFiles = pNewLimit->rlim_max;
{
if (pNewLimit->rlim_max > pcb->HardLimits.OpenFiles && !pcb->Security.CanAdjustHardLimits)
return -linux_EPERM;
debug("setting NOFILE limit to {%#lx, %#lx}->{%#lx, %#lx}",
pcb->SoftLimits.OpenFiles, pcb->HardLimits.OpenFiles,
pNewLimit->rlim_cur, pNewLimit->rlim_max);
pcb->SoftLimits.OpenFiles = pNewLimit->rlim_cur;
pcb->HardLimits.OpenFiles = pNewLimit->rlim_max;
}
return 0;
}
case linux_RLIMIT_MEMLOCK:
goto __stub;
case linux_RLIMIT_AS:
{
if (old_limit)
{
pOldLimit->rlim_cur = pcb->SoftLimits.Memory;
pOldLimit->rlim_max = pcb->HardLimits.Memory;
debug("read AS limit: {%#lx, %#lx}", pOldLimit->rlim_cur, pOldLimit->rlim_max);
}
if (new_limit)
pcb->Limits.Memory = pNewLimit->rlim_max;
{
if (pNewLimit->rlim_max > pcb->HardLimits.Memory && !pcb->Security.CanAdjustHardLimits)
return -linux_EPERM;
debug("setting AS limit to {%#lx, %#lx}->{%#lx, %#lx}",
pcb->SoftLimits.Memory, pcb->HardLimits.Memory,
pNewLimit->rlim_cur, pNewLimit->rlim_max);
pcb->SoftLimits.Memory = pNewLimit->rlim_cur;
pcb->HardLimits.Memory = pNewLimit->rlim_max;
}
return 0;
}
case linux_RLIMIT_LOCKS:
@ -2757,11 +2807,9 @@ static int linux_prlimit64(SysFrm *, pid_t pid, int resource,
default:
{
debug("Invalid resource %d", resource);
return -EINVAL;
return -linux_EINVAL;
}
}
return 0;
}
static ssize_t linux_getrandom(SysFrm *, void *buf,