refactor(kernel/syscalls): improve linux_execve implementation

Signed-off-by: EnderIce2 <enderice2@protonmail.com>
This commit is contained in:
EnderIce2 2025-03-27 18:45:25 +00:00
parent 2f18d390e4
commit 31181d5b5d
Signed by: enderice2
GPG Key ID: FEB6B8A8507BA62E

View File

@ -1614,9 +1614,7 @@ static pid_t linux_vfork(SysFrm *sf)
return (int)NewProcess->ID; return (int)NewProcess->ID;
} }
__no_sanitize("undefined") static int linux_execve(SysFrm *sf, const char *pathname, __no_sanitize("undefined") static int linux_execve(SysFrm *sf, const char *pathname, char *const argv[], char *const envp[])
char *const argv[],
char *const envp[])
{ {
/* FIXME: exec doesn't follow the UNIX standard /* FIXME: exec doesn't follow the UNIX standard
The pid, open files, etc. should be preserved */ The pid, open files, etc. should be preserved */
@ -1762,13 +1760,66 @@ __no_sanitize("undefined") static int linux_execve(SysFrm *sf, const char *pathn
} }
safeArgv[i] = nullptr; safeArgv[i] = nullptr;
return ConvertErrnoToLinux(linux_execve(sf, safeArgv[0], debug("calling linux_execve with %s", safeArgv[0]);
(char *const *)safeArgv,
(char *const *)safeEnvp)); PCB *newPcb = TaskManager->CreateProcess(pcb, safeArgv[0], Tasking::TaskExecutionMode::User, false, pcb->Security.Real.UserID, pcb->Security.Real.GroupID);
if (!newPcb)
{
error("Failed to create process for interpreter");
return -linux_EAGAIN;
}
newPcb->Security = pcb->Security;
newPcb->Info = pcb->Info;
newPcb->FileDescriptors = pcb->FileDescriptors;
newPcb->CWD = pcb->CWD;
newPcb->PageTable = pcb->PageTable;
newPcb->vma = pcb->vma;
newPcb->ProgramBreak = pcb->ProgramBreak;
char **newArgv = (char **)newPcb->vma->RequestPages(TO_PAGES(i * sizeof(char *)));
char **newEnvp = (char **)newPcb->vma->RequestPages(TO_PAGES(envpLen * sizeof(char *)));
for (int j = 0; j < i; j++)
{
size_t len = strlen(safeArgv[j]);
char *newArg = (char *)newPcb->vma->RequestPages(TO_PAGES(len));
memcpy(newArg, safeArgv[j], len);
newArg[len] = '\0';
newArgv[j] = newArg;
}
newArgv[i] = nullptr;
for (int j = 0; j < envpLen; j++)
{
size_t len = strlen(safeEnvp[j]);
char *newEnv = (char *)newPcb->vma->RequestPages(TO_PAGES(len));
memcpy(newEnv, safeEnvp[j], len);
newEnv[len] = '\0';
newEnvp[j] = newEnv;
}
newEnvp[envpLen] = nullptr;
int ret = Execute::Spawn((char *)safeArgv[0], (const char **)newArgv, (const char **)newEnvp,
newPcb, true, newPcb->Info.Compatibility);
if (ret < 0)
{
error("Failed to spawn interpreter");
return ConvertErrnoToLinux(ret);
}
GetCurrentCPU()->CurrentProcess = newPcb;
GetCurrentCPU()->CurrentThread = newPcb->Threads[0];
while (true)
newPcb->GetContext()->Yield();
__builtin_unreachable();
} }
if (pcb->Linux.vforked) if (pcb->Linux.vforked)
{ {
debug("vforked: %s", pPathname);
CriticalSection cs; CriticalSection cs;
pcb->Linux.CallingThread->SetState(Tasking::Ready); pcb->Linux.CallingThread->SetState(Tasking::Ready);
@ -1777,14 +1828,11 @@ __no_sanitize("undefined") static int linux_execve(SysFrm *sf, const char *pathn
pcb->PageTable = KernelPageTable->Fork(); pcb->PageTable = KernelPageTable->Fork();
pcb->vma = new Memory::VirtualMemoryArea(pcb->PageTable); pcb->vma = new Memory::VirtualMemoryArea(pcb->PageTable);
pcb->ProgramBreak = new Memory::ProgramBreak(pcb->PageTable, pcb->vma); pcb->ProgramBreak = new Memory::ProgramBreak(pcb->PageTable, pcb->vma);
// tcb->Stack = new Memory::StackGuard(true, pcb->vma);
} }
int ret = Execute::Spawn((char *)pPathname, debug("spawn(%s %#lx %#lx %#lx %d %d)", pPathname, safeArgv, safeEnvp, pcb, true, pcb->Info.Compatibility);
(const char **)safeArgv, int ret = Execute::Spawn((char *)pPathname, (const char **)safeArgv, (const char **)safeEnvp,
(const char **)safeEnvp, pcb, true, pcb->Info.Compatibility);
pcb, true,
pcb->Info.Compatibility);
if (ret < 0) if (ret < 0)
{ {