From 6c5703f9bc8b9cd38eeb5e5c9c3dc6d083fae736 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Michal=20Koutn=C3=BD?= Date: Mon, 3 Feb 2025 14:44:20 +0100 Subject: [PATCH] cgroup-util: Handle capsule@ paths like user@ paths The capsule instances are related to user instances, so treat them equally to user@.service when handling cgroup paths. This also saves us from polluting public libsystemd API with variant for capsules too. Fix: #36098 --- src/basic/cgroup-util.c | 34 +++++++++++++++++++++++----------- src/test/test-cgroup-util.c | 8 ++++++++ 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 5cedd45f3d9..8067bc082bb 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -12,6 +12,7 @@ #include #include "alloc-util.h" +#include "capsule-util.h" #include "cgroup-util.h" #include "constants.h" #include "dirent-util.h" @@ -1284,7 +1285,7 @@ static const char *skip_session(const char *p) { } /** - * Skip user@*.service, but require it to be there. + * Skip user@*.service or capsule@*.service, but require either of them to be there. */ static const char *skip_user_manager(const char *p) { size_t n; @@ -1295,26 +1296,37 @@ static const char *skip_user_manager(const char *p) { p += strspn(p, "/"); n = strcspn(p, "/"); - if (n < STRLEN("user@x.service")) + if (n < CONST_MIN(STRLEN("user@x.service"), STRLEN("capsule@x.service"))) return NULL; - if (memcmp(p, "user@", 5) == 0 && memcmp(p + n - 8, ".service", 8) == 0) { - char buf[n - 5 - 8 + 1]; + /* Any possible errors from functions called below are converted to NULL return, so our callers won't + * resolve user/capsule name. */ + _cleanup_free_ char *unit_name = strndup(p, n); + if (!unit_name) + return NULL; - memcpy(buf, p + 5, n - 5 - 8); - buf[n - 5 - 8] = 0; + _cleanup_free_ char *i = NULL; + UnitNameFlags type = unit_name_to_instance(unit_name, &i); - /* Note that user manager services never need unescaping, - * since they cannot conflict with the kernel's own - * names, hence we don't need to call cg_unescape() - * here. */ + if (type != UNIT_NAME_INSTANCE) + return NULL; - if (parse_uid(buf, NULL) < 0) + /* Note that user manager services never need unescaping, since they cannot conflict with the + * kernel's own names, hence we don't need to call cg_unescape() here. Prudently check validity of + * instance names, they should be always valid as we validate them upon unit start. */ + if (startswith(unit_name, "user@")) { + if (parse_uid(i, NULL) < 0) return NULL; p += n; p += strspn(p, "/"); + return p; + } else if (startswith(unit_name, "capsule@")) { + if (capsule_name_is_valid(i) <= 0) + return NULL; + p += n; + p += strspn(p, "/"); return p; } diff --git a/src/test/test-cgroup-util.c b/src/test/test-cgroup-util.c index 0170cb279bf..3f91aa6a72d 100644 --- a/src/test/test-cgroup-util.c +++ b/src/test/test-cgroup-util.c @@ -113,6 +113,9 @@ TEST(path_get_user_unit) { check_p_g_u_u("/user.slice/user-1000.slice/user@1000.service/server.service", 0, "server.service"); check_p_g_u_u("/user.slice/user-1000.slice/user@1000.service/foobar.slice/foobar@pie.service", 0, "foobar@pie.service"); check_p_g_u_u("/user.slice/user-1000.slice/user@.service/server.service", -ENXIO, NULL); + check_p_g_u_u("/capsule.slice/capsule@test.service/app.slice/run-p9-i1.service", 0, "run-p9-i1.service"); + check_p_g_u_u("/capsule.slice/capsule@usr-joe.service/foo.slice/foo-bar.slice/run-p9-i1.service", 0, "run-p9-i1.service"); + check_p_g_u_u("/capsule.slice/capsule@#.service/foo.slice/foo-bar.slice/run-p9-i1.service", -ENXIO, NULL); } static void check_p_g_s(const char *path, int code, const char *result) { @@ -157,6 +160,7 @@ TEST(path_get_slice) { check_p_g_slice("foobar", 0, SPECIAL_ROOT_SLICE); check_p_g_slice("foobar.slice", 0, "foobar.slice"); check_p_g_slice("foo.slice/foo-bar.slice/waldo.service", 0, "foo-bar.slice"); + check_p_g_slice("/capsule.slice/capsule@test.service/app.slice/run-p9-i1.service", 0, "capsule.slice"); } static void check_p_g_u_slice(const char *path, int code, const char *result) { @@ -181,6 +185,10 @@ TEST(path_get_user_slice) { check_p_g_u_slice("foo.slice/foo-bar.slice/user@1000.service/waldo.service", 0, SPECIAL_ROOT_SLICE); check_p_g_u_slice("foo.slice/foo-bar.slice/user@1000.service/piep.slice/foo.service", 0, "piep.slice"); check_p_g_u_slice("/foo.slice//foo-bar.slice/user@1000.service/piep.slice//piep-pap.slice//foo.service", 0, "piep-pap.slice"); + + check_p_g_u_slice("/capsule.slice/capsule@test.service/app.slice/run-p9-i1.service", 0, "app.slice"); + check_p_g_u_slice("/capsule.slice/capsule@usr-joe.service/app.slice/run-p9-i1.service", 0, "app.slice"); + check_p_g_u_slice("/capsule.slice/capsule@usr-joe.service/foo.slice/foo-bar.slice/run-p9-i1.service", 0, "foo-bar.slice"); } TEST(get_paths, .sd_booted = true) { -- 2.47.3