vmspawn: Redirect QEMU's stdin/stdout/stderr to the PTY

When a PTY is allocated for the console, QEMU's own stdio file
descriptors were still inherited directly from vmspawn, meaning any
output QEMU writes to stdout/stderr (e.g. warnings) would bypass the
PTY forwarder and go straight to the terminal. Similarly, QEMU could
read directly from the terminal's stdin.

Fix this by opening the PTY slave side and passing it as stdio_fds to
the fork call with FORK_REARRANGE_STDIO, so that all of QEMU's I/O
goes through the PTY and is properly forwarded.
This commit is contained in:
Daan De Meyer authored and Daan De Meyer committed 2026-04-06 13:58:31 +02:00
1 parent fb4bfe651b
commit bde83a9e1e
1 file changed
+11 -2
+11 -2
View File
@@ -3517,12 +3517,20 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
log_debug("Executing: %s", joined);
}
_cleanup_close_ int child_pty = -EBADF;
if (master >= 0) {
child_pty = pty_open_peer(master, O_RDWR|O_CLOEXEC|O_NOCTTY);
if (child_pty < 0)
return log_error_errno(child_pty, "Failed to open PTY slave: %m");
}
_cleanup_(pidref_done) PidRef child_pidref = PIDREF_NULL;
r = pidref_safe_fork_full(
qemu_binary,
/* stdio_fds= */ NULL,
child_pty >= 0 ? (const int[]) { child_pty, child_pty, child_pty } : NULL,
pass_fds, n_pass_fds,
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_CLOEXEC_OFF|FORK_RLIMIT_NOFILE_SAFE,
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_CLOEXEC_OFF|FORK_RLIMIT_NOFILE_SAFE|
(child_pty >= 0 ? FORK_REARRANGE_STDIO : 0),
&child_pidref);
if (r < 0)
return r;
@@ -3539,6 +3547,7 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
}
/* Close relevant fds we passed to qemu in the parent. We don't need them anymore. */
child_pty = safe_close(child_pty);
child_vsock_fd = safe_close(child_vsock_fd);
tap_fd = safe_close(tap_fd);