fix: inherit redirected console in SYS_SPAWN_CAPS

This commit is contained in:
2026-08-29 18:47:42 +02:00
parent f0bea7736d
commit f69f08acbb
2 changed files with 51 additions and 30 deletions
+1 -1
View File
@@ -12,4 +12,4 @@
#pragma once
#define MONTAUK_BUILD_NUMBER 177
#define MONTAUK_BUILD_NUMBER 178
+50 -29
View File
@@ -43,6 +43,43 @@ namespace montauk::abi {
return Sched::LookupExitCode(pid);
}
// Hand a freshly spawned child the parent's redirected console. Both spawn
// syscalls need this: a console tool launched from a GUI terminal must read
// its keys from the terminal's mailbox and write its output back up the
// stream, whether or not it also carries a capability grant. The child is
// created suspended (startReady == false) so its first instruction cannot
// run before the channels exist, and is started here once they do.
// Returns childPid, or kills the child and returns -1 on failure.
static int InheritRedirection(int childPid, Sched::Process* parent, int parentSlot) {
auto* child = Sched::GetProcessByPid(childPid);
int childSlot = Ipc::SlotForPid(childPid);
if (child == nullptr || childSlot < 0 || parentSlot < 0) {
Sched::KillProcess(childPid);
return -1;
}
child->ioOutHandle = DuplicateHandleBetweenSlots(parentSlot, parent->ioOutHandle, childSlot);
child->ioInHandle = DuplicateHandleBetweenSlots(parentSlot, parent->ioInHandle, childSlot);
child->ioKeyHandle = DuplicateHandleBetweenSlots(parentSlot, parent->ioKeyHandle, childSlot);
if (child->ioOutHandle < 0 || child->ioInHandle < 0 || child->ioKeyHandle < 0 ||
!ConfigureRedirWaitsetForSlot(childSlot, child)) {
Sched::KillProcess(childPid);
return -1;
}
child->redirected = true;
child->parentPid = parent->pid;
child->termCols = parent->termCols;
child->termRows = parent->termRows;
if (Sched::StartProcess(childPid) < 0) {
Sched::KillProcess(childPid);
return -1;
}
return childPid;
}
static int Sys_Spawn(const char* path, const char* args,
const char* environment = nullptr, uint32_t environmentLength = 0) {
char resolved[256];
@@ -55,33 +92,8 @@ namespace montauk::abi {
environment, environmentLength);
if (childPid < 0) return childPid;
if (inheritRedirection) {
auto* child = Sched::GetProcessByPid(childPid);
int childSlot = Ipc::SlotForPid(childPid);
if (child == nullptr || childSlot < 0 || parentSlot < 0) {
Sched::KillProcess(childPid);
return -1;
}
child->ioOutHandle = DuplicateHandleBetweenSlots(parentSlot, parent->ioOutHandle, childSlot);
child->ioInHandle = DuplicateHandleBetweenSlots(parentSlot, parent->ioInHandle, childSlot);
child->ioKeyHandle = DuplicateHandleBetweenSlots(parentSlot, parent->ioKeyHandle, childSlot);
if (child->ioOutHandle < 0 || child->ioInHandle < 0 || child->ioKeyHandle < 0 ||
!ConfigureRedirWaitsetForSlot(childSlot, child)) {
Sched::KillProcess(childPid);
return -1;
}
child->redirected = true;
child->parentPid = parent->pid;
child->termCols = parent->termCols;
child->termRows = parent->termRows;
if (Sched::StartProcess(childPid) < 0) {
Sched::KillProcess(childPid);
return -1;
}
}
if (inheritRedirection)
return InheritRedirection(childPid, parent, parentSlot);
return childPid;
}
@@ -115,8 +127,17 @@ namespace montauk::abi {
char resolved[256];
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return -1;
return Sched::Spawn(resolved, args, true, nullptr, 0, &copy,
userOverride);
int parentSlot = Ipc::CurrentSlot();
bool inheritRedirection = parent->redirected;
int childPid = Sched::Spawn(resolved, args, !inheritRedirection,
nullptr, 0, &copy, userOverride);
if (childPid < 0) return childPid;
if (inheritRedirection)
return InheritRedirection(childPid, parent, parentSlot);
return childPid;
}
// Copy the absolute path this process was spawned from (argv[0]).