Spoof PID across execve() on Windows

It's now possible with cosmo and redbean, to deliver a signal to a child
process after it has called execve(). However the executed program needs
to be compiled using cosmocc. The cosmo runtime WinMain() implementation
now intercepts a _COSMO_PID environment variable that's set by execve().
It ensures the child process will use the same C:\ProgramData\cosmo\sigs
file, which is where kill() will place the delivered signal. We are able
to do this on Windows even better than NetBSD, which has a bug with this

Fixes #1334
This commit is contained in:
Justine Tunney 2024-12-14 12:23:02 -08:00
parent 9cc1bd04b2
commit 26c051c297
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
8 changed files with 187 additions and 21 deletions

View file

@ -92,6 +92,7 @@ textwindows int sys_kill_nt(int pid, int sig) {
int64_t handle, closeme = 0;
if (!(handle = __proc_handle(pid))) {
if ((handle = OpenProcess(kNtProcessTerminate, false, pid))) {
STRACE("warning: kill() using raw win32 pid");
closeme = handle;
} else {
goto OnError;
@ -103,7 +104,7 @@ textwindows int sys_kill_nt(int pid, int sig) {
// now that we know the process exists, if it has a shared memory file
// then we can be reasonably certain it's a cosmo process which should
// be trusted to deliver its signal, unless it's a nine exterminations
if (pid > 0 && sig != 9) {
if (pid > 0) {
atomic_ulong *sigproc;
if ((sigproc = __sig_map_process(pid, kNtOpenExisting))) {
if (sig > 0)
@ -112,12 +113,15 @@ textwindows int sys_kill_nt(int pid, int sig) {
UnmapViewOfFile(sigproc);
if (closeme)
CloseHandle(closeme);
return 0;
if (sig != 9)
return 0;
}
}
// perform actual kill
// process will report WIFSIGNALED with WTERMSIG(sig)
if (sig != 9)
STRACE("warning: kill() sending %G via terminate", sig);
bool32 ok = TerminateProcess(handle, sig);
if (closeme)
CloseHandle(closeme);