From aae054e1ab156d44f669c60140c213c0ec35b2d0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 6 Nov 2025 10:46:58 +0100 Subject: [PATCH] nsresource: allow multiple userns from the same process in parallel When generating a name for a transient userns automatically we so far just included our PID to make it unique. That doens't really work if multiple userns shall be kept in parallel by a single process. Let's hence include a counter as well. --- src/shared/nsresource.c | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/src/shared/nsresource.c b/src/shared/nsresource.c index a5d1ee7034f..eef72e631bc 100644 --- a/src/shared/nsresource.c +++ b/src/shared/nsresource.c @@ -15,30 +15,44 @@ #include "process-util.h" #include "string-util.h" +/* Maximum namespace name length */ +#define NAMESPACE_NAME_MAX 16U + +/* So the namespace name should be 16 chars at max (because we want that it is usable in usernames, which + * have a limit of 31 chars effectively, and the nsresourced service wants to prefix/suffix some bits). But + * it also should be unique if we are called multiple times in a row. Hence we take the "comm" name (which is + * 15 chars), and suffix it with the PID and a counter, possibly overriding the end. */ +assert_cc(TASK_COMM_LEN == NAMESPACE_NAME_MAX); + static int make_pid_name(char **ret) { char comm[TASK_COMM_LEN]; + static uint64_t counter = 0; assert(ret); if (prctl(PR_GET_NAME, comm) < 0) return -errno; - /* So the namespace name should be 16 chars at max (because we want that it is usable in usernames, - * which have a limit of 31 chars effectively, and the nsresourced service wants to prefix/suffix - * some bits). But it also should be unique if we are called multiple times in a row. Hence we take - * the "comm" name (which is 15 chars), and suffix it with the PID, possibly overriding the end. */ - assert_cc(TASK_COMM_LEN == 15 + 1); - char spid[DECIMAL_STR_MAX(pid_t)]; xsprintf(spid, PID_FMT, getpid_cached()); - assert(strlen(spid) <= 16); - strshorten(comm, 16 - strlen(spid)); + /* Include a counter in the name, so that we can allocate multiple namespaces per process, with + * unique names. For the first namespace we suppress the suffix */ + char scounter[sizeof(counter) * 2 + 1]; + if (counter == 0) + scounter[0] = 0; + else + xsprintf(scounter, "%" PRIx64, counter); + counter++; - _cleanup_free_ char *s = strjoin(comm, spid); + strshorten(comm, LESS_BY(NAMESPACE_NAME_MAX, strlen(spid) + strlen(scounter))); + + _cleanup_free_ char *s = strjoin(comm, spid, scounter); if (!s) return -ENOMEM; + strshorten(s, NAMESPACE_NAME_MAX); + *ret = TAKE_PTR(s); return 0; } -- 2.47.3