[PATCH iproute2] lib/fs: fix cgroup2 path for cgroups outside the cgroup namespace
flat view
WARM2d
From: Gopal Malaviya <hidden>
Date: 2026-10-20 22:51:46
Subsystem:
library code, the rest · Maintainers:
Andrew Morton, Linus Torvalds
get_cgroup2_path() opens a cgroup by its ID, reads the path of the
resulting fd from /proc/self/fd and returns it with the cgroup2 mount
point stripped. It assumes that the path always starts with the mount
point.
That is not true for a cgroup outside the caller's cgroup namespace:
the link then reads as just "/". Skipping strlen(mnt) characters of
it reads past the end of the string into stale stack data, which ss
then prints as the cgroup path.
This happens when ss runs with CAP_DAC_READ_SEARCH (needed for
open_by_handle_at()) inside a cgroup namespace and shows sockets of
processes outside of it, for example in a container started with
--cgroupns private and --cap-add DAC_READ_SEARCH or --privileged.
Without that capability open_by_handle_at() fails, and the socket is
already shown as unreachable.
Reproducer, as root, with a listener in the original cgroup:
# python3 -m http.server 8080 --bind 127.0.0.1 &
# mkdir /sys/fs/cgroup/test
# echo $$ > /sys/fs/cgroup/test/cgroup.procs
# unshare --cgroup --mount --propagation private sh
# umount /sys/fs/cgroup; mount -t cgroup2 none /sys/fs/cgroup
# cat /proc/self/cgroup
0::/
# ss -tlne sport = :8080 | grep -o "cgroup:[^ ]*"
cgroup:-microsoft-standard-WSL2
The garbage depends on what is left on the stack; here it is part of
the kernel release string, and in an Alpine container it was
"s/cgroup".
Only strip the mount point when the path starts with it. Otherwise
return NULL, so that cg_id_to_path() shows the cgroup as unreachable,
the same as when open_by_handle_at() fails:
# ss -tlne sport = :8080 | grep -o "cgroup:[^ ]*"
cgroup:unreachable:550d
Fixes: d5e6ee0dac64 ("ss: introduce cgroup2 cache and helper functions")
Signed-off-by: Gopal Malaviya <redacted>
---
lib/fs.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/lib/fs.c b/lib/fs.c
index 6fe1d6db..1562d25c 100644
--- a/lib/fs.c
+++ b/lib/fs.c@@ -238,10 +238,18 @@ char *get_cgroup2_path(__u64 id, bool full) } link_buf[link_len] = '\0'; - if (full) + if (full) { path = strdup(link_buf); - else - path = strdup(link_buf + strlen(mnt)); + } else { + size_t mnt_len = strlen(mnt); + + /* A cgroup outside our cgroup namespace is not under the + * mount and the link reads as just "/". + */ + if (strncmp(link_buf, mnt, mnt_len) != 0) + goto out; + path = strdup(link_buf + mnt_len); + } if (!path) fprintf(stderr, "Failed to allocate memory for cgroup2 path\n");
--
2.43.0