From: Lennart Poettering Date: Tue, 26 Aug 2025 07:00:06 +0000 (+0200) Subject: nsresourced: use a hashed rather than a mangled name as fallback X-Git-Tag: v258-rc4~43 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3ef74e44b81add0191a59c624a0119a7aaca2ea2;p=thirdparty%2Fsystemd.git nsresourced: use a hashed rather than a mangled name as fallback If we are asked to come up with our own name for the namespace to allocate (because client enabled "mangle"), then we so far created a randomized name if shortening what was proposed didn't work. This broke polkit authorization however, because when polkit is in the mix, we process method calls twice, submitting the polkit request on the first and then assuming a response is known on the second invocation. But if we generate a randomized name for the two checks we'll not be ablet to match up the requests because it's going to be different. Let's fix that by not using a randomized name, but one hashed from the socket connection we are processing mixed with the client provided name. This will ensure that for the same method call we'll generate the same name, but different calls (i.e. calls with different names on the same socket, or with any name on any socket) we'll end up with different names, minimizing chance of collision. This ensures PK starts to work with nsresourced userns registration when a bad or no name is specified, which previously would end up in a PK query loop. --- diff --git a/src/nsresourced/nsresourcework.c b/src/nsresourced/nsresourcework.c index a648a72a07d..0fc8d1cb010 100644 --- a/src/nsresourced/nsresourcework.c +++ b/src/nsresourced/nsresourcework.c @@ -630,14 +630,35 @@ static int test_userns_api_support(sd_varlink *link) { return 0; } -static char* random_name(void) { - char *s = NULL; +static char* hash_name(sd_varlink *link, const char *name) { + int r; + + assert(link); + assert(name); + + /* Make up a hashed name for this userns. We take the passed name, and hash it together with the + * connection cookie. This should make collisions unlikely but generation still deterministic (this + * matters because on polkit requests we might be called twice, and should generate the same string + * each time, to ensure the Polkit query looks the same) */ + + uint64_t cookie = 0; + r = socket_get_cookie(sd_varlink_get_fd(link), &cookie); + if (r < 0) + log_debug_errno(r, "Failed to determine connection cookie, ignoring: %m"); + + struct siphash h; + static sd_id128_t key = SD_ID128_MAKE(ed,3a,bb,01,3a,14,4b,b3,8a,63,a4,ad,ba,2d,c9,0a); + siphash24_init(&h, key.bytes); + siphash24_compress_typesafe(cookie, &h); + siphash24_compress_string(name, &h); + + /* Make sure the hashed name fits into utmpx even if prefixed with "ns-", the peer's UID, "-", and + * suffixed by "-65535". */ - /* Make up a random name for this userns. Make sure the random name fits into utmpx even if prefixed - * with "ns-", the peer's UID, "-", and suffixed by "-65535". */ assert_cc(STRLEN("ns-65535-") + 16 + STRLEN("-65535") < sizeof_field(struct utmpx, ut_user)); - if (asprintf(&s, "%016" PRIx64, random_u64()) < 0) + char *s = NULL; + if (asprintf(&s, "%016" PRIx64, siphash24_finalize(&h)) < 0) return NULL; return s; @@ -690,8 +711,8 @@ static int validate_name(sd_varlink *link, const char *name, bool mangle, char * if (!userns_name_is_valid(un)) { free(un); - /* if not, make up a random name */ - un = random_name(); + /* if not, make up a hashed name */ + un = hash_name(link, name); if (!un) return -ENOMEM; } @@ -716,7 +737,7 @@ static int validate_name(sd_varlink *link, const char *name, bool mangle, char * free_and_replace(un, c); else { free(c); - c = random_name(); + c = hash_name(link, name); if (!c) return -ENOMEM;