From a2872389e30219feb0a298c7030ab040aee28641 Mon Sep 17 00:00:00 2001 From: Andrew Potter Date: Thu, 24 Oct 2024 13:14:57 -0700 Subject: [PATCH 1/2] core: Setup ExecDirectories before stdin/stdout. Fixes #27591 --- src/core/exec-invoke.c | 17 +++++++++-------- src/test/test-execute.c | 6 ++++++ .../exec-runtimedirectory-stdoutput.service | 9 +++++++++ 3 files changed, 24 insertions(+), 8 deletions(-) create mode 100644 test/test-execute/exec-runtimedirectory-stdoutput.service diff --git a/src/core/exec-invoke.c b/src/core/exec-invoke.c index cdfa9f823b1..081ac1a2814 100644 --- a/src/core/exec-invoke.c +++ b/src/core/exec-invoke.c @@ -4382,6 +4382,15 @@ int exec_invoke( } } + /* Setup ExecDirectories now, as they may be targeted by stdin/stdout */ + needs_mount_namespace = exec_needs_mount_namespace(context, params, runtime); + + for (ExecDirectoryType dt = 0; dt < _EXEC_DIRECTORY_TYPE_MAX; dt++) { + r = setup_exec_directory(context, params, uid, gid, dt, needs_mount_namespace, exit_status); + if (r < 0) + return log_exec_error_errno(context, params, r, "Failed to set up special execution directory in %s: %m", params->prefix[dt]); + } + r = setup_input(context, params, socket_fd, named_iofds); if (r < 0) { *exit_status = EXIT_STDIN; @@ -4602,14 +4611,6 @@ int exec_invoke( } } - needs_mount_namespace = exec_needs_mount_namespace(context, params, runtime); - - for (ExecDirectoryType dt = 0; dt < _EXEC_DIRECTORY_TYPE_MAX; dt++) { - r = setup_exec_directory(context, params, uid, gid, dt, needs_mount_namespace, exit_status); - if (r < 0) - return log_exec_error_errno(context, params, r, "Failed to set up special execution directory in %s: %m", params->prefix[dt]); - } - r = exec_setup_credentials(context, params, params->unit_id, uid, gid); if (r < 0) { *exit_status = EXIT_CREDENTIALS; diff --git a/src/test/test-execute.c b/src/test/test-execute.c index 95ccf5490de..1f0160e9bb6 100644 --- a/src/test/test-execute.c +++ b/src/test/test-execute.c @@ -1128,6 +1128,11 @@ static void test_exec_runtimedirectory(Manager *m) { test(m, "exec-runtimedirectory-owner-" NOBODY_GROUP_NAME ".service", MANAGER_IS_SYSTEM(m) ? 0 : EXIT_GROUP, CLD_EXITED); } +static void test_exec_runtimedirectory_stdoutput(Manager *m) { + (void) rm_rf("/run/test-exec_runtimedirectory_standardoutput", REMOVE_ROOT|REMOVE_PHYSICAL); + test(m, "exec-runtimedirectory-stdoutput.service", 0, CLD_EXITED); +} + static void test_exec_capabilityboundingset(Manager *m) { int r; @@ -1359,6 +1364,7 @@ static void run_tests(RuntimeScope scope, char **patterns) { entry(test_exec_readwritepaths), entry(test_exec_restrictnamespaces), entry(test_exec_runtimedirectory), + entry(test_exec_runtimedirectory_stdoutput), entry(test_exec_specifier), entry(test_exec_standardinput), entry(test_exec_standardoutput), diff --git a/test/test-execute/exec-runtimedirectory-stdoutput.service b/test/test-execute/exec-runtimedirectory-stdoutput.service new file mode 100644 index 00000000000..7803c3f1ab4 --- /dev/null +++ b/test/test-execute/exec-runtimedirectory-stdoutput.service @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +[Unit] +Description=Test for RuntimeDirectory used by StandardOutput + +[Service] +ExecStart=sh -c 'printf "hello\nhello\n"' +Type=oneshot +RuntimeDirectory=test-exec_runtimedirectory_standardoutput +StandardOutput=file:/run/test-exec_runtimedirectory_standardoutput/test-exec-runtimedirectory_standardoutput-output From 353f417f483b3eef7e9b2134a310b90a99002664 Mon Sep 17 00:00:00 2001 From: Andrew Potter Date: Thu, 24 Oct 2024 15:41:56 -0700 Subject: [PATCH 2/2] core: Adjust ExecDirectory-Stdout test to use DynamicUser For test environments that set e.g. $RUNTIME_DIRECTORY to /run/fake-runtime-dir, the test service file can't properly define the StandardOutput path, as it must be absolute. Instead, try using DynamicUser & StateDirectory, which should result in an appropriate directory always seen at /var/lib/foo --- src/test/test-execute.c | 20 +++++++++++++++---- .../exec-runtimedirectory-stdoutput.service | 9 --------- .../exec-statedirectory-stdoutput.service | 10 ++++++++++ 3 files changed, 26 insertions(+), 13 deletions(-) delete mode 100644 test/test-execute/exec-runtimedirectory-stdoutput.service create mode 100644 test/test-execute/exec-statedirectory-stdoutput.service diff --git a/src/test/test-execute.c b/src/test/test-execute.c index 1f0160e9bb6..51bb56d542a 100644 --- a/src/test/test-execute.c +++ b/src/test/test-execute.c @@ -1128,9 +1128,21 @@ static void test_exec_runtimedirectory(Manager *m) { test(m, "exec-runtimedirectory-owner-" NOBODY_GROUP_NAME ".service", MANAGER_IS_SYSTEM(m) ? 0 : EXIT_GROUP, CLD_EXITED); } -static void test_exec_runtimedirectory_stdoutput(Manager *m) { - (void) rm_rf("/run/test-exec_runtimedirectory_standardoutput", REMOVE_ROOT|REMOVE_PHYSICAL); - test(m, "exec-runtimedirectory-stdoutput.service", 0, CLD_EXITED); +static void test_exec_statedirectory_stdoutput(Manager *m) { + if (MANAGER_IS_USER(m)) { + log_notice("Skipping %s for user manager", __func__); + return; + } + + _cleanup_free_ char *bad = private_directory_bad(m); + if (bad) { + log_warning("%s: %s has bad permissions, skipping test.", __func__, bad); + return; + } + + int status = can_unshare ? 0 : EXIT_NAMESPACE; + + test(m, "exec-statedirectory-stdoutput.service", status, CLD_EXITED); } static void test_exec_capabilityboundingset(Manager *m) { @@ -1364,7 +1376,7 @@ static void run_tests(RuntimeScope scope, char **patterns) { entry(test_exec_readwritepaths), entry(test_exec_restrictnamespaces), entry(test_exec_runtimedirectory), - entry(test_exec_runtimedirectory_stdoutput), + entry(test_exec_statedirectory_stdoutput), entry(test_exec_specifier), entry(test_exec_standardinput), entry(test_exec_standardoutput), diff --git a/test/test-execute/exec-runtimedirectory-stdoutput.service b/test/test-execute/exec-runtimedirectory-stdoutput.service deleted file mode 100644 index 7803c3f1ab4..00000000000 --- a/test/test-execute/exec-runtimedirectory-stdoutput.service +++ /dev/null @@ -1,9 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -[Unit] -Description=Test for RuntimeDirectory used by StandardOutput - -[Service] -ExecStart=sh -c 'printf "hello\nhello\n"' -Type=oneshot -RuntimeDirectory=test-exec_runtimedirectory_standardoutput -StandardOutput=file:/run/test-exec_runtimedirectory_standardoutput/test-exec-runtimedirectory_standardoutput-output diff --git a/test/test-execute/exec-statedirectory-stdoutput.service b/test/test-execute/exec-statedirectory-stdoutput.service new file mode 100644 index 00000000000..5c255b67f76 --- /dev/null +++ b/test/test-execute/exec-statedirectory-stdoutput.service @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +[Unit] +Description=Test for StateDirectory used by StandardOutput + +[Service] +ExecStart=sh -c 'printf "hello\nhello\n"' +Type=oneshot +DynamicUser=true +StateDirectory=test-exec_statedirectory_standardoutput +StandardOutput=file:/var/lib/test-exec_statedirectory_standardoutput/test-exec-statedirectory_standardoutput-output