From 5bb9063505fe64788e696dc133899231506866c6 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 7 Sep 2025 06:16:02 +0900 Subject: [PATCH 1/5] musl: hostname-util: introduce LINUX_HOST_NAME_MAX glibc defines HOST_NAME_MAX as 64 and our code rely on that, but musl defines the constant as 255. Let's provide our own definition for the maximum length. --- src/basic/hostname-util.c | 6 +++--- src/basic/hostname-util.h | 3 +++ src/core/load-fragment.c | 2 +- src/libsystemd-network/sd-lldp-tx.c | 8 ++------ src/shared/hostname-setup.c | 6 +++--- 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/basic/hostname-util.c b/src/basic/hostname-util.c index 2238e86d76..01434d3d64 100644 --- a/src/basic/hostname-util.c +++ b/src/basic/hostname-util.c @@ -94,8 +94,8 @@ bool hostname_is_valid(const char *s, ValidHostnameFlags flags) { if (hyphen) return false; - if (p-s > HOST_NAME_MAX) /* Note that HOST_NAME_MAX is 64 on Linux, but DNS allows domain names up to - * 255 characters */ + /* Note that host name max is 64 on Linux, but DNS allows domain names up to 255 characters. */ + if (p - s > (ssize_t) LINUX_HOST_NAME_MAX) return false; return true; @@ -107,7 +107,7 @@ char* hostname_cleanup(char *s) { assert(s); - for (p = s, d = s, dot = hyphen = true; *p && d - s < HOST_NAME_MAX; p++) + for (p = s, d = s, dot = hyphen = true; *p && d - s < (ssize_t) LINUX_HOST_NAME_MAX; p++) if (*p == '.') { if (dot || hyphen) continue; diff --git a/src/basic/hostname-util.h b/src/basic/hostname-util.h index e9e605cab0..73cd83fbb8 100644 --- a/src/basic/hostname-util.h +++ b/src/basic/hostname-util.h @@ -4,6 +4,9 @@ #include "basic-forward.h" #include "strv.h" +/* HOST_NAME_MAX should be 64 on linux, but musl uses the one by POSIX (255). */ +#define LINUX_HOST_NAME_MAX CONST_MIN((size_t) HOST_NAME_MAX, (size_t) 64) + char* get_default_hostname_raw(void); bool valid_ldh_char(char c) _const_; diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index 2f212b6e7a..4b33d918fc 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -6633,7 +6633,7 @@ int config_parse_protect_hostname( const char *colon = strchr(rvalue, ':'); if (colon) { - r = unit_full_printf_full(u, colon + 1, HOST_NAME_MAX, &h); + r = unit_full_printf_full(u, colon + 1, LINUX_HOST_NAME_MAX, &h); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", colon + 1); diff --git a/src/libsystemd-network/sd-lldp-tx.c b/src/libsystemd-network/sd-lldp-tx.c index e8e1ea10f3..f2f08e40ef 100644 --- a/src/libsystemd-network/sd-lldp-tx.c +++ b/src/libsystemd-network/sd-lldp-tx.c @@ -186,12 +186,8 @@ int sd_lldp_tx_set_hostname(sd_lldp_tx *lldp_tx, const char *hostname) { assert_return(lldp_tx, -EINVAL); /* An empty string unset the previously set hostname. */ - if (!isempty(hostname)) { - assert_cc(HOST_NAME_MAX < 512); - - if (!hostname_is_valid(hostname, 0)) - return -EINVAL; - } + if (!isempty(hostname) && !hostname_is_valid(hostname, /* flags= */ 0)) + return -EINVAL; return free_and_strdup(&lldp_tx->hostname, empty_to_null(hostname)); } diff --git a/src/shared/hostname-setup.c b/src/shared/hostname-setup.c index 9e83445040..0eb05d3714 100644 --- a/src/shared/hostname-setup.c +++ b/src/shared/hostname-setup.c @@ -51,7 +51,7 @@ int sethostname_idempotent(const char *s) { int shorten_overlong(const char *s, char **ret) { _cleanup_free_ char *h = NULL; - /* Shorten an overlong name to HOST_NAME_MAX or to the first dot, + /* Shorten an overlong name to LINUX_HOST_NAME_MAX or to the first dot, * whatever comes earlier. */ assert(s); @@ -70,7 +70,7 @@ int shorten_overlong(const char *s, char **ret) { if (p) *p = 0; - strshorten(h, HOST_NAME_MAX); + strshorten(h, LINUX_HOST_NAME_MAX); if (!hostname_is_valid(h, /* flags= */ 0)) return -EDOM; @@ -403,7 +403,7 @@ int pidref_gethostname_full(PidRef *pidref, GetHostnameFlags flags, char **ret) if (r < 0) return r; - char buf[HOST_NAME_MAX+1]; + char buf[LINUX_HOST_NAME_MAX+1]; ssize_t n = loop_read(result_pipe[0], buf, sizeof(buf), /* do_poll = */ false); if (n < 0) return n; From ebbc0ea7fd764c870bb8689111138b4f73854d42 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 1 Jul 2025 12:53:14 +0900 Subject: [PATCH 2/5] musl: avoid multiple evaluations in CPU_ISSET_S() macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit musl's CPU_ISSET_S() macro does not avoid multiple evaluations, and it only accepts simple variable or constant. Fixes the following error. ``` ../src/shared/cpu-set-util.c: In function ‘cpu_set_to_mask_string’: ../src/shared/cpu-set-util.c:101:41: warning: operation on ‘i’ may be undefined [-Werror=sequence-point] 101 | if (CPU_ISSET_S(--i, c->allocated, c->set)) | ^ ``` --- src/shared/cpu-set-util.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/shared/cpu-set-util.c b/src/shared/cpu-set-util.c index 25288046c1..a9bdd235f8 100644 --- a/src/shared/cpu-set-util.c +++ b/src/shared/cpu-set-util.c @@ -96,9 +96,11 @@ char* cpu_set_to_mask_string(const CPUSet *c) { for (size_t i = c->allocated * 8; i > 0; ) { uint32_t m = 0; - for (int j = (i % 32 ?: 32) - 1; j >= 0; j--) - if (CPU_ISSET_S(--i, c->allocated, c->set)) + for (int j = (i % 32 ?: 32) - 1; j >= 0; j--) { + --i; + if (CPU_ISSET_S(i, c->allocated, c->set)) SET_BIT(m, j); + } if (!found_nonzero) { if (m == 0) From 3866923a6831a95a2aeca9b6f25694ec18440951 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 7 Sep 2025 08:53:07 +0900 Subject: [PATCH 3/5] musl: core: there is one less usable signal when built with musl musl internally reserves one more signal, hence we can only use 29 signals. --- src/core/manager.c | 7 ++++--- src/test/test-signal-util.c | 5 +++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/core/manager.c b/src/core/manager.c index b501d3f1c5..deed863e18 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -526,8 +526,9 @@ static int manager_setup_signals(Manager *m) { assert_se(sigaction(SIGCHLD, &sa, NULL) == 0); - /* We make liberal use of realtime signals here. On Linux/glibc we have 30 of them, between - * SIGRTMIN+0 ... SIGRTMIN+30 (aka SIGRTMAX). */ + /* We make liberal use of realtime signals here. On Linux we have 29 of them, between + * SIGRTMIN+0 ... SIGRTMIN+29. The glibc has one more (SIGRTMAX is SIGRTMIN+30), + * but musl does not (SIGRTMAX is SIGRTMIN+29). */ assert_se(sigemptyset(&mask) == 0); sigset_add_many(&mask, @@ -572,7 +573,7 @@ static int manager_setup_signals(Manager *m) { SIGRTMIN+28, /* systemd: set log target to kmsg */ SIGRTMIN+29, /* systemd: set log target to syslog-or-kmsg (obsolete) */ - /* ... one free signal here SIGRTMIN+30 ... */ + /* ... one free signal here SIGRTMIN+30 (glibc only) ... */ -1); assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0); diff --git a/src/test/test-signal-util.c b/src/test/test-signal-util.c index 7d069a7fb2..822556022d 100644 --- a/src/test/test-signal-util.c +++ b/src/test/test-signal-util.c @@ -13,8 +13,9 @@ TEST(rt_signals) { info(SIGRTMIN); info(SIGRTMAX); - /* We use signals SIGRTMIN+0 to SIGRTMIN+30 unconditionally */ - assert_se(SIGRTMAX - SIGRTMIN >= 30); + /* We use signals SIGRTMIN+0 to SIGRTMIN+29 unconditionally. SIGRTMIN+30 can be used only when + * built with glibc. */ + assert_se(SIGRTMAX - SIGRTMIN >= 29); } static void test_signal_to_string_one(int val) { From 4b774c740ba35d16c8a32d66d8bd5747c03d0d1a Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sat, 6 Sep 2025 12:06:06 +0900 Subject: [PATCH 4/5] musl: build-path: fix reading DT_RUNPATH or DT_RPATH musl records DT_STRTAB as offset, rather than address. So, need to add obtained bias to read runpath or rpath. --- src/basic/build-path.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/basic/build-path.c b/src/basic/build-path.c index 577ff72bce..3212089379 100644 --- a/src/basic/build-path.c +++ b/src/basic/build-path.c @@ -34,11 +34,11 @@ static int get_runpath_from_dynamic(const ElfW(Dyn) *d, ElfW(Addr) bias, const c break; case DT_STRTAB: - /* On MIPS and RISC-V DT_STRTAB records an offset, not a valid address, so it has to be adjusted - * using the bias calculated earlier. */ + /* On MIPS, RISC-V, or with musl, DT_STRTAB records an offset, not a valid address, + * so it has to be adjusted using the bias calculated earlier. */ if (d->d_un.d_val != 0) strtab = (const char *) ((uintptr_t) d->d_un.d_val -#if defined(__mips__) || defined(__riscv) +#if defined(__mips__) || defined(__riscv) || !defined(__GLIBC__) + bias #endif ); From a580dd4e53d218ceb7cb4cad46e7044dfa59bd48 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 9 Jun 2025 12:00:01 +0900 Subject: [PATCH 5/5] musl: format-util: use %llu for formatting rlim_t glibc uses uint32_t or uint64_t for rlim_t, while musl uses unsigned long long. --- src/basic/format-util.h | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/basic/format-util.h b/src/basic/format-util.h index c603e99d82..16727c45bd 100644 --- a/src/basic/format-util.h +++ b/src/basic/format-util.h @@ -39,12 +39,18 @@ assert_cc(sizeof(gid_t) == sizeof(uint32_t)); # error Unknown timex member size #endif -#if SIZEOF_RLIM_T == 8 -# define RLIM_FMT "%" PRIu64 -#elif SIZEOF_RLIM_T == 4 -# define RLIM_FMT "%" PRIu32 +#ifdef __GLIBC__ +# if SIZEOF_RLIM_T == 8 +# define RLIM_FMT "%" PRIu64 +# elif SIZEOF_RLIM_T == 4 +# define RLIM_FMT "%" PRIu32 +# else +# error Unknown rlim_t size +# endif #else -# error Unknown rlim_t size +/* Assume musl, and it unconditionally uses unsigned long long. */ +assert_cc(SIZEOF_RLIM_T == 8); +# define RLIM_FMT "%llu" #endif #if SIZEOF_DEV_T == 8