diff --git a/man/systemd-nspawn.xml b/man/systemd-nspawn.xml
index db3f10c3a2..c0427aa42f 100644
--- a/man/systemd-nspawn.xml
+++ b/man/systemd-nspawn.xml
@@ -1296,30 +1296,32 @@
MODE
- Configures how to set up standard input, output and error output for the container payload, as
- well as the /dev/console device for the container. Takes one of
- , , or . If
- a pseudo-TTY is allocated and made available as /dev/console
- in the container. It is then bi-directionally connected to the standard input and output passed to
- systemd-nspawn. is similar but only the output of the container
- is propagated and no input from the caller is read. In mode a pseudo TTY is allocated,
- but it is not connected anywhere. Finally, in mode no pseudo TTY is allocated, but the
- passed standard input, output and error output file descriptors are passed on — as they are — to the container
- payload. In this mode /dev/console will not exist in the container. Note that in this mode
- the container payload generally cannot be a full init system as init systems tend to require
- /dev/console to be available. On the other hand, in this mode container invocations can be
- used within shell pipelines. This is because intermediary pseudo TTYs do not permit independent bidirectional
- propagation of the end-of-file (EOF) condition, which is necessary for shell pipelines to work
- correctly.
-
- Note that the mode should be used carefully, as passing arbitrary file descriptors
- to less trusted container payloads might open up unwanted interfaces for access by the container payload. For
- example, if a passed file descriptor refers to a TTY of some form, APIs such as TIOCSTI
- may be used to synthesize input that might be used for escaping the container. Hence mode
- should only be used if the payload is sufficiently trusted or when the standard input/output/error output file
- descriptors are known safe, for example pipes. Defaults to if
+ Configures how to set up standard input, output and error output for the container
+ payload, as well as the /dev/console device for the container. Takes one of
+ , , , or
+ . If , a pseudo-TTY is allocated and made available
+ as /dev/console in the container. It is then bi-directionally connected to the
+ standard input and output passed to systemd-nspawn. is
+ similar but only the output of the container is propagated and no input from the caller is read. If
+ , a pseudo TTY is allocated, but it is not connected anywhere. Finally, in
+ mode no pseudo TTY is allocated, but the standard input, output and error
+ output file descriptors passed to systemd-nspawn are passed on — as they are — to
+ the container payload, see the following paragraph. Defaults to if
systemd-nspawn is invoked from a terminal, and
- otherwise.
+ otherwise.
+
+ In mode, /dev/console will not exist in the
+ container. This means that the container payload generally cannot be a full init system as init
+ systems tend to require /dev/console to be available. On the other hand, in this
+ mode container invocations can be used within shell pipelines. This is because intermediary pseudo
+ TTYs do not permit independent bidirectional propagation of the end-of-file (EOF) condition, which is
+ necessary for shell pipelines to work correctly. Note that the mode
+ should be used carefully, as passing arbitrary file descriptors to less trusted container
+ payloads might open up unwanted interfaces for access by the container payload. For example, if a
+ passed file descriptor refers to a TTY of some form, APIs such as TIOCSTI may be
+ used to synthesize input that might be used for escaping the container. Hence
+ mode should only be used if the payload is sufficiently trusted or when the standard
+ input/output/error output file descriptors are known safe, for example pipes.
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 0cd960157c..40a7de981a 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -261,6 +261,30 @@ STATIC_DESTRUCTOR_REGISTER(arg_seccomp, seccomp_releasep);
STATIC_DESTRUCTOR_REGISTER(arg_cpu_set, cpu_set_reset);
STATIC_DESTRUCTOR_REGISTER(arg_sysctl, strv_freep);
+static int handle_arg_console(const char *arg) {
+ if (streq(arg, "help")) {
+ puts("interactive\n"
+ "read-only\n"
+ "passive\n"
+ "pipe");
+ return 0;
+ }
+
+ if (streq(arg, "interactive"))
+ arg_console_mode = CONSOLE_INTERACTIVE;
+ else if (streq(arg, "read-only"))
+ arg_console_mode = CONSOLE_READ_ONLY;
+ else if (streq(arg, "passive"))
+ arg_console_mode = CONSOLE_PASSIVE;
+ else if (streq(arg, "pipe"))
+ arg_console_mode = CONSOLE_PIPE;
+ else
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown console mode: %s", optarg);
+
+ arg_settings_mask |= SETTING_CONSOLE_MODE;
+ return 1;
+}
+
static int help(void) {
_cleanup_free_ char *link = NULL;
int r;
@@ -1389,29 +1413,16 @@ static int parse_argv(int argc, char *argv[]) {
break;
case ARG_CONSOLE:
- if (streq(optarg, "interactive"))
- arg_console_mode = CONSOLE_INTERACTIVE;
- else if (streq(optarg, "read-only"))
- arg_console_mode = CONSOLE_READ_ONLY;
- else if (streq(optarg, "passive"))
- arg_console_mode = CONSOLE_PASSIVE;
- else if (streq(optarg, "pipe"))
- arg_console_mode = CONSOLE_PIPE;
- else if (streq(optarg, "help"))
- puts("interactive\n"
- "read-only\n"
- "passive\n"
- "pipe");
- else
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown console mode: %s", optarg);
-
- arg_settings_mask |= SETTING_CONSOLE_MODE;
+ r = handle_arg_console(optarg);
+ if (r <= 0)
+ return r;
break;
case 'P':
case ARG_PIPE:
- arg_console_mode = CONSOLE_PIPE;
- arg_settings_mask |= SETTING_CONSOLE_MODE;
+ r = handle_arg_console("pipe");
+ if (r <= 0)
+ return r;
break;
case ARG_NO_PAGER: