diff --git a/backport-core-shorten-long-unit-names-that-are-based-on-paths.patch b/backport-core-shorten-long-unit-names-that-are-based-on-paths.patch new file mode 100644 index 0000000000000000000000000000000000000000..da188caae7a9fe12d7232f7d13084cbb295bd309 --- /dev/null +++ b/backport-core-shorten-long-unit-names-that-are-based-on-paths.patch @@ -0,0 +1,247 @@ +From 05e696f300c8c8be081b41d034c4909d07e02916 Mon Sep 17 00:00:00 2001 +From: caiwentao +Date: Wed, 16 Jul 2025 13:43:13 +0800 +Subject: [PATCH] core: shorten long unit names that are based on paths and + append path hash at the end sync from + https://github.com/systemd/systemd/pull/22759/commits/1d0727e76fd5e9a07cc9991ec9a10ea1d78a99c7 + +--- + src/basic/string-util.h | 23 ++++++----- + src/basic/unit-name.c | 86 ++++++++++++++++++++++++++++++++++++++- + src/basic/unit-name.h | 3 ++ + src/core/mount.c | 3 ++ + src/test/test-unit-name.c | 12 +++++- + 5 files changed, 112 insertions(+), 15 deletions(-) + +diff --git a/src/basic/string-util.h b/src/basic/string-util.h +index 338dcd5..58fb017 100644 +--- a/src/basic/string-util.h ++++ b/src/basic/string-util.h +@@ -10,17 +10,18 @@ + #include "string-util-fundamental.h" + + /* What is interpreted as whitespace? */ +-#define WHITESPACE " \t\n\r" +-#define NEWLINE "\n\r" +-#define QUOTES "\"\'" +-#define COMMENTS "#;" +-#define GLOB_CHARS "*?[" +-#define DIGITS "0123456789" +-#define LOWERCASE_LETTERS "abcdefghijklmnopqrstuvwxyz" +-#define UPPERCASE_LETTERS "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +-#define LETTERS LOWERCASE_LETTERS UPPERCASE_LETTERS +-#define ALPHANUMERICAL LETTERS DIGITS +-#define HEXDIGITS DIGITS "abcdefABCDEF" ++#define WHITESPACE " \t\n\r" ++#define NEWLINE "\n\r" ++#define QUOTES "\"\'" ++#define COMMENTS "#;" ++#define GLOB_CHARS "*?[" ++#define DIGITS "0123456789" ++#define LOWERCASE_LETTERS "abcdefghijklmnopqrstuvwxyz" ++#define UPPERCASE_LETTERS "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ++#define LETTERS LOWERCASE_LETTERS UPPERCASE_LETTERS ++#define ALPHANUMERICAL LETTERS DIGITS ++#define HEXDIGITS DIGITS "abcdefABCDEF" ++#define LOWERCASE_HEXDIGITS DIGITS "abcdef" + + static inline char* strstr_ptr(const char *haystack, const char *needle) { + if (!haystack || !needle) +diff --git a/src/basic/unit-name.c b/src/basic/unit-name.c +index a227634..b9d3704 100644 +--- a/src/basic/unit-name.c ++++ b/src/basic/unit-name.c +@@ -5,11 +5,16 @@ + #include + #include + ++#include "sd-id128.h" ++ + #include "alloc-util.h" + #include "glob-util.h" + #include "hexdecoct.h" + #include "path-util.h" ++#include "random-util.h" ++#include "sparse-endian.h" + #include "special.h" ++#include "stdio-util.h" + #include "string-util.h" + #include "strv.h" + #include "unit-name.h" +@@ -30,6 +35,9 @@ + VALID_CHARS_WITH_AT \ + "[]!-*?" + ++#define LONG_UNIT_NAME_HASH_KEY SD_ID128_MAKE(ec,f2,37,fb,58,32,4a,32,84,9f,06,9b,0d,21,eb,9a) ++#define UNIT_NAME_HASH_LENGTH_CHARS 16 ++ + bool unit_name_is_valid(const char *n, UnitNameFlags flags) { + const char *e, *i, *at; + +@@ -506,6 +514,68 @@ int unit_name_template(const char *f, char **ret) { + return 0; + } + ++bool unit_name_is_hashed(const char *name) { ++ char *s; ++ ++ if (!unit_name_is_valid(name, UNIT_NAME_PLAIN)) ++ return false; ++ ++ assert_se(s = strrchr(name, '.')); ++ ++ if (s - name < UNIT_NAME_HASH_LENGTH_CHARS + 1) ++ return false; ++ ++ s -= UNIT_NAME_HASH_LENGTH_CHARS; ++ if (s[-1] != '_') ++ return false; ++ ++ for (size_t i = 0; i < UNIT_NAME_HASH_LENGTH_CHARS; i++) ++ if (!strchr(LOWERCASE_HEXDIGITS, s[i])) ++ return false; ++ ++ return true; ++} ++ ++int unit_name_hash_long(const char *name, char **ret) { ++ _cleanup_free_ char *n = NULL, *hash = NULL; ++ char *suffix; ++ le64_t h; ++ size_t len; ++ ++ if (strlen(name) < UNIT_NAME_MAX) ++ return -EMSGSIZE; ++ ++ suffix = strrchr(name, '.'); ++ if (!suffix) ++ return -EINVAL; ++ ++ if (unit_type_from_string(suffix+1) < 0) ++ return -EINVAL; ++ ++ h = htole64(siphash24_string(name, LONG_UNIT_NAME_HASH_KEY.bytes)); ++ ++ hash = hexmem(&h, sizeof(h)); ++ if (!hash) ++ return -ENOMEM; ++ ++ assert_se(strlen(hash) == UNIT_NAME_HASH_LENGTH_CHARS); ++ ++ len = UNIT_NAME_MAX - 1 - strlen(suffix+1) - UNIT_NAME_HASH_LENGTH_CHARS - 2; ++ assert(len > 0 && len < UNIT_NAME_MAX); ++ ++ n = strndup(name, len); ++ if (!n) ++ return -ENOMEM; ++ ++ if (!strextend(&n, "_", hash, suffix)) ++ return -ENOMEM; ++ assert_se(unit_name_is_valid(n, UNIT_NAME_PLAIN)); ++ ++ *ret = TAKE_PTR(n); ++ ++ return 0; ++} ++ + int unit_name_from_path(const char *path, const char *suffix, char **ret) { + _cleanup_free_ char *p = NULL, *s = NULL; + int r; +@@ -525,8 +595,17 @@ int unit_name_from_path(const char *path, const char *suffix, char **ret) { + if (!s) + return -ENOMEM; + +- if (strlen(s) >= UNIT_NAME_MAX) /* Return a slightly more descriptive error for this specific condition */ +- return -ENAMETOOLONG; ++ if (strlen(s) >= UNIT_NAME_MAX) { ++ _cleanup_free_ char *n = NULL; ++ ++ log_debug("Unit name \"%s\" too long, falling back to hashed unit name.", s); ++ ++ r = unit_name_hash_long(s, &n); ++ if (r < 0) ++ return r; ++ ++ free_and_replace(s, n); ++ } + + /* Refuse this if this got too long or for some other reason didn't result in a valid name */ + if (!unit_name_is_valid(s, UNIT_NAME_PLAIN)) +@@ -580,6 +659,9 @@ int unit_name_to_path(const char *name, char **ret) { + if (r < 0) + return r; + ++ if (unit_name_is_hashed(name)) ++ return -ENAMETOOLONG; ++ + return unit_name_path_unescape(prefix, ret); + } + +diff --git a/src/basic/unit-name.h b/src/basic/unit-name.h +index f6af01c..f82a0ea 100644 +--- a/src/basic/unit-name.h ++++ b/src/basic/unit-name.h +@@ -44,6 +44,9 @@ int unit_name_replace_instance(const char *f, const char *i, char **ret); + + int unit_name_template(const char *f, char **ret); + ++int unit_name_hash_long(const char *name, char **ret); ++bool unit_name_is_hashed(const char *name); ++ + int unit_name_from_path(const char *path, const char *suffix, char **ret); + int unit_name_from_path_instance(const char *prefix, const char *path, const char *suffix, char **ret); + int unit_name_to_path(const char *name, char **ret); +diff --git a/src/core/mount.c b/src/core/mount.c +index f4bc6eb..98f01fc 100644 +--- a/src/core/mount.c ++++ b/src/core/mount.c +@@ -630,6 +630,9 @@ static int mount_add_extras(Mount *m) { + + if (!m->where) { + r = unit_name_to_path(u->id, &m->where); ++ if (r == -ENAMETOOLONG) ++ log_unit_error_errno(u, r, "Failed to derive mount point path from unit name, because unit name is hashed. " ++ "Set \"Where=\" in the unit file explicitly."); + if (r < 0) + return r; + } +diff --git a/src/test/test-unit-name.c b/src/test/test-unit-name.c +index 0077c4c..af86161 100644 +--- a/src/test/test-unit-name.c ++++ b/src/test/test-unit-name.c +@@ -106,6 +106,7 @@ static void test_unit_name_replace_instance(void) { + + static void test_unit_name_from_path_one(const char *path, const char *suffix, const char *expected, int ret) { + _cleanup_free_ char *t = NULL; ++ int r; + + assert_se(unit_name_from_path(path, suffix, &t) == ret); + puts(strna(t)); +@@ -113,7 +114,13 @@ static void test_unit_name_from_path_one(const char *path, const char *suffix, c + + if (t) { + _cleanup_free_ char *k = NULL; +- assert_se(unit_name_to_path(t, &k) == 0); ++ ++ /* We don't support converting hashed unit names back to paths */ ++ r = unit_name_to_path(t, &k); ++ if (r == -ENAMETOOLONG) ++ return; ++ assert(r == 0); ++ + puts(strna(k)); + assert_se(path_equal(k, empty_to_root(path))); + } +@@ -130,7 +137,8 @@ static void test_unit_name_from_path(void) { + test_unit_name_from_path_one("///", ".mount", "-.mount", 0); + test_unit_name_from_path_one("/foo/../bar", ".mount", NULL, -EINVAL); + test_unit_name_from_path_one("/foo/./bar", ".mount", "foo-bar.mount", 0); +- test_unit_name_from_path_one("/waldoaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", ".mount", NULL, -ENAMETOOLONG); ++ test_unit_name_from_path_one("/waldoaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", ".mount", ++ "waldoaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa_7736d9ed33c2ec55.mount", 0); + } + + static void test_unit_name_from_path_instance_one(const char *pattern, const char *path, const char *suffix, const char *expected, int ret) { +-- +2.39.3 (Apple Git-146) + diff --git a/systemd.spec b/systemd.spec index 272af69e2a15bf22d7f76f555007e3c43668bb90..3b167e60595871fb0469fc1e6172d8b8f125cc41 100644 --- a/systemd.spec +++ b/systemd.spec @@ -25,7 +25,7 @@ Name: systemd Url: https://systemd.io/ Version: 249 -Release: 104 +Release: 105 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -747,6 +747,7 @@ Patch6693: backport-0002-coredump-get-rid-of-_META_MANDATORY_MAX.patch Patch6694: backport-CVE-2025-4598-coredump-use-d-in-kernel-core-pattern.patch Patch6695: backport-0001-coredump-get-rid-of-a-bogus-assertion.patch Patch6696: backport-core-mount-adjust-deserialized-state-based-on-proc-s.patch +Patch6697: backport-core-shorten-long-unit-names-that-are-based-on-paths.patch Patch9001: update-rtc-with-system-clock-when-shutdown.patch Patch9002: udev-add-actions-while-rename-netif-failed.patch @@ -2263,6 +2264,9 @@ grep -q -E '^KEYMAP="?fi-latin[19]"?' /etc/vconsole.conf 2>/dev/null && /usr/bin/systemd-cryptenroll %changelog +* Tue Jul 15 2025 caiwentao - 249-105 +- core: shorten long unit names that are based on paths and append path hash at the end + * Mon Jul 14 2025 Han Jinpeng - 249-104 - Fix mount units failed issue, which mount process finished, but there is no mount.