summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2020-01-17 12:41:53 +0100
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2020-02-05 14:44:29 +0100
commitb78fe3c1b1a81435248deaffe7ee4b594b55b64b (patch)
tree81ff1b3e72122e852da0b947e3ab49c25efc5446
parenta1561a08f2d5af9ebc68916ce0cb430091a64bce (diff)
downloadsystemd-b78fe3c1b1a81435248deaffe7ee4b594b55b64b.tar.gz
core: make sure StandardInput=file: doesn't get dup'ed to stdout/stderr by default
Fixes: #14560 (cherry picked from commit 3b7f79dc9fc5557074ebe4a3b060e8dcf8cdcc0f)
-rw-r--r--src/core/service.c37
1 files changed, 25 insertions, 12 deletions
diff --git a/src/core/service.c b/src/core/service.c
index 49ad166c26..f3df541fce 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -650,24 +650,37 @@ static int service_add_default_dependencies(Service *s) {
return unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, true, UNIT_DEPENDENCY_DEFAULT);
}
-static void service_fix_output(Service *s) {
+static void service_fix_stdio(Service *s) {
assert(s);
- /* If nothing has been explicitly configured, patch default output in. If input is socket/tty we avoid this
- * however, since in that case we want output to default to the same place as we read input from. */
+ /* Note that EXEC_INPUT_NULL and EXEC_OUTPUT_INHERIT play a special role here: they are both the
+ * default value that is subject to automatic overriding triggered by other settings and an explicit
+ * choice the user can make. We don't distuingish between these cases currently. */
+
+ if (s->exec_context.std_input == EXEC_INPUT_NULL &&
+ s->exec_context.stdin_data_size > 0)
+ s->exec_context.std_input = EXEC_INPUT_DATA;
+
+ if (IN_SET(s->exec_context.std_input,
+ EXEC_INPUT_TTY,
+ EXEC_INPUT_TTY_FORCE,
+ EXEC_INPUT_TTY_FAIL,
+ EXEC_INPUT_SOCKET,
+ EXEC_INPUT_NAMED_FD))
+ return;
+
+ /* We assume these listed inputs refer to bidirectional streams, and hence duplicating them from
+ * stdin to stdout/stderr makes sense and hence leaving EXEC_OUTPUT_INHERIT in place makes sense,
+ * too. Outputs such as regular files or sealed data memfds otoh don't really make sense to be
+ * duplicated for both input and output at the same time (since they then would cause a feedback
+ * loop), hence override EXEC_OUTPUT_INHERIT with the default stderr/stdout setting. */
if (s->exec_context.std_error == EXEC_OUTPUT_INHERIT &&
- s->exec_context.std_output == EXEC_OUTPUT_INHERIT &&
- s->exec_context.std_input == EXEC_INPUT_NULL)
+ s->exec_context.std_output == EXEC_OUTPUT_INHERIT)
s->exec_context.std_error = UNIT(s)->manager->default_std_error;
- if (s->exec_context.std_output == EXEC_OUTPUT_INHERIT &&
- s->exec_context.std_input == EXEC_INPUT_NULL)
+ if (s->exec_context.std_output == EXEC_OUTPUT_INHERIT)
s->exec_context.std_output = UNIT(s)->manager->default_std_output;
-
- if (s->exec_context.std_input == EXEC_INPUT_NULL &&
- s->exec_context.stdin_data_size > 0)
- s->exec_context.std_input = EXEC_INPUT_DATA;
}
static int service_setup_bus_name(Service *s) {
@@ -715,7 +728,7 @@ static int service_add_extras(Service *s) {
if (s->type == SERVICE_ONESHOT && !s->start_timeout_defined)
s->timeout_start_usec = USEC_INFINITY;
- service_fix_output(s);
+ service_fix_stdio(s);
r = unit_patch_contexts(UNIT(s));
if (r < 0)