]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: make the memory pressure cgroup path writable when ProtectControlGroups=yes
authorLuca Boccassi <bluca@debian.org>
Tue, 14 Mar 2023 20:12:33 +0000 (20:12 +0000)
committerLennart Poettering <lennart@poettering.net>
Wed, 15 Mar 2023 08:23:17 +0000 (09:23 +0100)
The interface requires services to write to the cgroup file to activate notifications,
but with ProtectControlGroups=yes we make it read-only. Add a writable bind mount.

Follow-up for 6bb0084204bd93122c9f04391b80aea5a8a0ff08

src/core/execute.c
test/units/testsuite-79.sh

index 6346ad79f670e44227df10b04ea24ebf172bfe1b..39c46857b383dc56a7a2fbba038a1d73195862db 100644 (file)
@@ -3591,13 +3591,16 @@ static int apply_mount_namespace(
                 const ExecContext *context,
                 const ExecParameters *params,
                 const ExecRuntime *runtime,
+                const char *memory_pressure_path,
                 char **error_path) {
 
-        _cleanup_strv_free_ char **empty_directories = NULL, **symlinks = NULL;
+        _cleanup_strv_free_ char **empty_directories = NULL, **symlinks = NULL,
+                        **read_write_paths_cleanup = NULL;
         const char *tmp_dir = NULL, *var_tmp_dir = NULL;
         const char *root_dir = NULL, *root_image = NULL;
         _cleanup_free_ char *creds_path = NULL, *incoming_dir = NULL, *propagate_dir = NULL,
                         *extension_dir = NULL;
+        char **read_write_paths;
         NamespaceInfo ns_info;
         bool needs_sandboxing;
         BindMount *bind_mounts = NULL;
@@ -3622,6 +3625,23 @@ static int apply_mount_namespace(
         if (r < 0)
                 goto finalize;
 
+        /* We need to make the pressure path writable even if /sys/fs/cgroups is made read-only, as the
+         * service will need to write to it in order to start the notifications. */
+        if (context->protect_control_groups && memory_pressure_path && !streq(memory_pressure_path, "/dev/null")) {
+                read_write_paths_cleanup = strv_copy(context->read_write_paths);
+                if (!read_write_paths_cleanup) {
+                        r = -ENOMEM;
+                        goto finalize;
+                }
+
+                r = strv_extend(&read_write_paths_cleanup, memory_pressure_path);
+                if (r < 0)
+                        goto finalize;
+
+                read_write_paths = read_write_paths_cleanup;
+        } else
+                read_write_paths = context->read_write_paths;
+
         needs_sandboxing = (params->flags & EXEC_APPLY_SANDBOXING) && !(command_flags & EXEC_COMMAND_FULLY_PRIVILEGED);
         if (needs_sandboxing) {
                 /* The runtime struct only contains the parent of the private /tmp,
@@ -3709,7 +3729,7 @@ static int apply_mount_namespace(
                 }
 
         r = setup_namespace(root_dir, root_image, context->root_image_options,
-                            &ns_info, context->read_write_paths,
+                            &ns_info, read_write_paths,
                             needs_sandboxing ? context->read_only_paths : NULL,
                             needs_sandboxing ? context->inaccessible_paths : NULL,
                             needs_sandboxing ? context->exec_paths : NULL,
@@ -4974,7 +4994,7 @@ static int exec_child(
         if (needs_mount_namespace) {
                 _cleanup_free_ char *error_path = NULL;
 
-                r = apply_mount_namespace(unit, command->flags, context, params, runtime, &error_path);
+                r = apply_mount_namespace(unit, command->flags, context, params, runtime, memory_pressure_path, &error_path);
                 if (r < 0) {
                         *exit_status = EXIT_NAMESPACE;
                         return log_unit_error_errno(unit, r, "Failed to set up mount namespacing%s%s: %m",
index fe34d5c5562aaeea76b6c26d8a68e6e18a4e67c7..53606e117b3debd294989e37d76d803e81b5f819 100755 (executable)
@@ -49,7 +49,7 @@ EOF
 
 chmod +x "$SCRIPT"
 
-systemd-run -u "$UNIT" -p Type=exec -p DynamicUser=1 -p MemoryPressureWatch=on -p MemoryPressureThresholdSec=123ms -p BindPaths=$SCRIPT --wait "$SCRIPT"
+systemd-run -u "$UNIT" -p Type=exec -p ProtectControlGroups=1 -p DynamicUser=1 -p MemoryPressureWatch=on -p MemoryPressureThresholdSec=123ms -p BindPaths=$SCRIPT --wait "$SCRIPT"
 
 rm "$SCRIPT"