diff --git a/pkg/utils/normalize_path_test.go b/pkg/utils/normalize_path_test.go index 32d5e300c..c3829b79c 100644 --- a/pkg/utils/normalize_path_test.go +++ b/pkg/utils/normalize_path_test.go @@ -50,6 +50,30 @@ func TestNormalizePath(t *testing.T) { input: "/46/task", expected: "/proc/46/task", }, + { + // #721 regression: runc:[2:INIT] user-namespace-setup paths outside + // the old (task|fd) allowlist previously leaked /proc-less. + name: "headless proc path (setgroups)", + input: "/17/setgroups", + expected: "/proc/17/setgroups", + }, + { + name: "headless proc path (gid_map)", + input: "/1/gid_map", + expected: "/proc/1/gid_map", + }, + { + name: "headless proc path (uid_map)", + input: "/1/uid_map", + expected: "/proc/1/uid_map", + }, + { + // A non-proc path whose leading segment is non-numeric must be + // untouched even though a later segment looks proc-like. + name: "non-proc path with data dir", + input: "/data/appendonlydir/x", + expected: "/data/appendonlydir/x", + }, { name: "relative path (not dot)", input: "usr/bin/ls", diff --git a/pkg/utils/path.go b/pkg/utils/path.go index 9a9fcd481..041eb3c97 100644 --- a/pkg/utils/path.go +++ b/pkg/utils/path.go @@ -6,7 +6,17 @@ import ( "strings" ) -var headlessProcRegex = regexp.MustCompile(`^/\d+/(task|fd)(/|$)`) +// headlessProcRegex matches a headless /proc// path — a /proc//... +// path stripped of its /proc root — which NormalizePath re-roots under /proc. +// +// The allowlist enumerates the /proc/ entries opened by runc:[2:INIT] +// during container/user-namespace setup. It was previously only (task|fd), +// which let the sibling entries (setgroups, gid_map, uid_map, status, cgroup, +// ...) leak /proc-less into learned ContainerProfiles — a regression of #721. +// It stays an explicit allowlist rather than a bare `^/\d+` catch-all so a +// genuine top-level numeric directory is never misread as a PID; extend it if +// another /proc/ entry is observed leaking. +var headlessProcRegex = regexp.MustCompile(`^/\d+/(task|fd|setgroups|gid_map|uid_map|status|stat|cgroup|mountinfo|maps|environ|comm|cmdline|ns)(/|$)`) // NormalizePath normalizes a path by: // 1. Prepending "/proc" to "headless" proc paths (e.g. /46/task/46/fd -> /proc/46/task/46/fd)