diff --git a/src/nspawn/nspawn-stub-pid1.c b/src/nspawn/nspawn-stub-pid1.c index f785a3b248..60d7439fb1 100644 --- a/src/nspawn/nspawn-stub-pid1.c +++ b/src/nspawn/nspawn-stub-pid1.c @@ -53,12 +53,6 @@ int stub_pid1(sd_id128_t uuid) { assert_se(sigfillset(&fullmask) >= 0); assert_se(sigprocmask(SIG_BLOCK, &fullmask, &oldmask) >= 0); - /* Surrender the terminal this stub may control so that child processes can have a controlling terminal - * without resorting to setsid hacks. */ - r = ioctl(STDIN_FILENO, TIOCNOTTY); - if (r < 0 && errno != ENOTTY) - return log_error_errno(errno, "Failed to surrender controlling terminal: %m"); - pid = fork(); if (pid < 0) return log_error_errno(errno, "Failed to fork child pid: %m"); @@ -79,6 +73,12 @@ int stub_pid1(sd_id128_t uuid) { (void) close_all_fds(NULL, 0); log_open(); + if (ioctl(STDIN_FILENO, TIOCNOTTY) < 0) { + if (errno != ENOTTY) + log_warning_errno(errno, "Unexpected error from TIOCNOTTY ioctl in init stub process, ignoring: %m"); + } else + log_warning("Expected TIOCNOTTY to fail, but it succeeded in init stub process, ignoring."); + /* Flush out /proc/self/environ, so that we don't leak the environment from the host into the container. Also, * set $container= and $container_uuid= so that clients in the container that query it from /proc/1/environ * find them set. */ diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 1b7578581d..282f12d9c1 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -11,10 +11,12 @@ #endif #include #include +#include #include #include #include #include +#include #include #include "sd-bus.h" @@ -2278,7 +2280,9 @@ static int setup_stdio_as_dev_console(void) { _cleanup_close_ int terminal = -1; int r; - terminal = open_terminal("/dev/console", O_RDWR); + /* We open the TTY in O_NOCTTY mode, so that we do not become controller yet. We'll do that later + * explicitly, if we are configured to. */ + terminal = open_terminal("/dev/console", O_RDWR|O_NOCTTY); if (terminal < 0) return log_error_errno(terminal, "Failed to open console: %m"); @@ -3373,8 +3377,7 @@ static int inner_child( * wait until the parent is ready with the * setup, too... */ if (!barrier_place_and_sync(barrier)) /* #5 */ - return log_error_errno(SYNTHETIC_ERRNO(ESRCH), - "Parent died too early"); + return log_error_errno(SYNTHETIC_ERRNO(ESRCH), "Parent died too early"); if (arg_chdir) if (chdir(arg_chdir) < 0) @@ -3386,6 +3389,13 @@ static int inner_child( return r; } + if (arg_console_mode != CONSOLE_PIPE) { + /* So far our pty wasn't controlled by any process. Finally, it's time to change that, if we + * are configured for that. Acquire it as controlling tty. */ + if (ioctl(STDIN_FILENO, TIOCSCTTY) < 0) + return log_error_errno(errno, "Failed to acquire controlling TTY: %m"); + } + log_debug("Inner child completed, invoking payload."); /* Now, explicitly close the log, so that we then can close all remaining fds. Closing the log explicitly first