Simplify process spawning using SYS_clone

This commit is contained in:
Luke Street 2025-10-09 12:33:58 -06:00
parent 3078cef12b
commit dc5a91c480
3 changed files with 7 additions and 49 deletions

View File

@ -55,7 +55,6 @@ struct ProcessObject final : WaitableObject {
static constexpr ObjectType kType = ObjectType::Process;
pid_t pid;
pid_t tid = 0;
int pidfd;
DWORD exitCode = STILL_ACTIVE;
bool forcedExitCode = false;

View File

@ -651,7 +651,7 @@ BOOL WIN_FUNC CreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSE
if (lpProcessInformation) {
lpProcessInformation->dwProcessId = static_cast<DWORD>(obj->pid);
lpProcessInformation->dwThreadId = static_cast<DWORD>(obj->tid);
lpProcessInformation->dwThreadId = static_cast<DWORD>(obj->pid); // Use the process ID as the thread ID
lpProcessInformation->hProcess = wibo::handles().alloc(obj.clone(), 0 /* TODO: access */, 0);
// Give hThread a process handle for now
lpProcessInformation->hThread = wibo::handles().alloc(std::move(obj), 0 /* TODO: access */, 0);

View File

@ -373,52 +373,19 @@ std::optional<std::filesystem::path> resolveExecutable(const std::string &comman
return std::nullopt;
}
static int spawnClone3(pid_t &pid, int &pidfd, int &tid, char **argv, char **envp) {
int exefd = open("/proc/self/exe", O_PATH | O_CLOEXEC);
if (exefd < 0) {
int err = errno;
perror("open /proc/self/exe");
return err;
}
struct clone_args ca = {};
ca.flags = CLONE_PIDFD | CLONE_PARENT_SETTID | CLONE_CLEAR_SIGHAND;
ca.pidfd = reinterpret_cast<uintptr_t>(&pidfd);
ca.parent_tid = reinterpret_cast<uintptr_t>(&tid);
pid = static_cast<pid_t>(syscall(SYS_clone3, &ca, sizeof(ca)));
static int spawnClone(pid_t &pid, int &pidfd, char **argv, char **envp) {
pid = static_cast<pid_t>(syscall(SYS_clone, CLONE_PIDFD, nullptr, &pidfd));
if (pid < 0) {
int err = errno;
close(exefd);
perror("clone");
return err;
} else if (pid == 0) {
prctl(PR_SET_PDEATHSIG, SIGKILL);
// First, attempt to execveat using the open fd (atomic)
syscall(SYS_execveat, exefd, "", argv, envp, AT_EMPTY_PATH);
// Otherwise, fall back to direct execve
execve("/proc/self/exe", argv, envp);
// If we're still here, something went wrong
perror("execve");
_exit(127);
}
close(exefd);
return 0;
}
static int spawnPosixSpawn(pid_t &pid, int &pidfd, char **argv, char **envp) {
std::error_code ec;
auto resolved = std::filesystem::read_symlink("/proc/self/exe", ec);
if (ec) {
return ec.value();
}
int rc = posix_spawn(&pid, resolved.c_str(), nullptr, nullptr, argv, envp);
if (rc != 0) {
return rc;
}
pidfd = static_cast<int>(syscall(SYS_pidfd_open, pid, 0));
if (pidfd < 0) {
int err = errno;
perror("pidfd_open");
return err;
}
return 0;
}
@ -460,22 +427,14 @@ static int spawnInternal(const std::vector<std::string> &args, Pin<kernel32::Pro
pid_t pid = -1;
int pidfd = -1;
int tid = -1;
int rc = spawnClone3(pid, pidfd, tid, argv.data(), envp.data());
int rc = spawnClone(pid, pidfd, argv.data(), envp.data());
if (rc != 0) {
if (rc == ENOSYS) {
rc = spawnPosixSpawn(pid, pidfd, argv.data(), envp.data());
}
if (rc != 0) {
return rc;
}
tid = pid;
return rc;
}
DEBUG_LOG("Spawned process with PID %d (pidfd=%d, tid=%d)\n", pid, pidfd, tid);
DEBUG_LOG("Spawned process with PID %d (pidfd=%d)\n", pid, pidfd);
auto obj = make_pin<kernel32::ProcessObject>(pid, pidfd);
obj->tid = tid;
pinOut = obj.clone();
if (!processes().addProcess(std::move(obj))) {
fprintf(stderr, "Failed to add process to process manager\n");