--- Begin Message ---
Package: release.debian.org
Control: affects -1 + src:systemd
X-Debbugs-Cc: [email protected]
User: [email protected]
Usertags: pu
Tags: bookworm
X-Debbugs-Cc: [email protected]
Severity: normal
[ Reason ]
This update addresses open security problems such as CVE-2026-4105,
CVE-2026-29111, CVE-2026-40225, CVE-2026-40226. One of them allows a
local user to freeze systemd, not accepting any commands.
The update was prepared and verified by Tobias Deiminger. He also
tested some of the CVEs which provided an exploit to ensure that it no
longer works.
[ Checklist ]
[x] *all* changes are documented in the d/changelog
[x] I reviewed all changes and I approve them
[x] attach debdiff against the package in (old)stable
[x] the issue is verified as fixed in unstable
[ Changes ]
This update provides just backports of the relevant CVE fixes.
Sebastian
diff -Nru systemd-252.39/debian/changelog systemd-252.39/debian/changelog
--- systemd-252.39/debian/changelog 2025-06-26 16:58:40.000000000 +0200
+++ systemd-252.39/debian/changelog 2026-04-27 21:48:55.000000000 +0200
@@ -1,3 +1,18 @@
+systemd (252.39-1~deb12u2) bookworm; urgency=medium
+
+ [ Arnaud Rebillout ]
+ * test-cgroup: Ignore ENOENT from cg_create()
+ * CVE-2026-4105 (A flaw was found in systemd. The systemd-machined service
+ contains an ...)
+ * CVE-2026-29111 (systemd, a system and service manager, (as PID 1) hits an
+ assert and f ...)
+ * CVE-2026-40225 (In udev in systemd before 260, local root execution can
+ occur via mali ...)
+ * CVE-2026-40226 (In nspawn in systemd 233 through 259 before 260, an
+ escape-to-host act ...)
+
+ -- Tobias Deiminger <[email protected]> Mon, 27 Apr 2026
21:48:55 +0200
+
systemd (252.39-1~deb12u1) bookworm; urgency=medium
* New upstream version 252.39
diff -Nru systemd-252.39/debian/patches/CVE-2026-29111-1.patch
systemd-252.39/debian/patches/CVE-2026-29111-1.patch
--- systemd-252.39/debian/patches/CVE-2026-29111-1.patch 1970-01-01
01:00:00.000000000 +0100
+++ systemd-252.39/debian/patches/CVE-2026-29111-1.patch 2026-04-27
21:48:55.000000000 +0200
@@ -0,0 +1,170 @@
+From: Lennart Poettering <[email protected]>
+Date: Mon, 19 May 2025 12:58:52 +0200
+Subject: path-util: add flavour of path_startswith() that leaves a leading
+ slash in place
+
+(cherry picked from commit ee19edbb9f3455db3f750089082f3e5a925e3a0c)
+
+Origin: backport,
https://github.com/systemd/systemd/commit/20021e7686426052e3a7505425d7e12085feb2a6
+---
+ src/basic/fs-util.c | 2 +-
+ src/basic/mkdir.c | 4 ++--
+ src/basic/path-util.c | 39 ++++++++++++++++++++++++++++-----------
+ src/basic/path-util.h | 10 ++++++++--
+ src/test/test-path-util.c | 16 ++++++++++++++++
+ 5 files changed, 55 insertions(+), 16 deletions(-)
+
+diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c
+index d71c07c..9950ff3 100644
+--- a/src/basic/fs-util.c
++++ b/src/basic/fs-util.c
+@@ -67,7 +67,7 @@ int rmdir_parents(const char *path, const char *stop) {
+ assert(*slash == '/');
+ *slash = '\0';
+
+- if (path_startswith_full(stop, p, /* accept_dot_dot= */
false))
++ if (path_startswith_full(stop, p, /* flags= */ 0))
+ return 0;
+
+ if (rmdir(p) < 0 && errno != ENOENT)
+diff --git a/src/basic/mkdir.c b/src/basic/mkdir.c
+index c8ff342..478cb69 100644
+--- a/src/basic/mkdir.c
++++ b/src/basic/mkdir.c
+@@ -99,7 +99,7 @@ int mkdir_parents_internal(const char *prefix, const char
*path, mode_t mode, ui
+ assert(_mkdirat != mkdirat);
+
+ if (prefix) {
+- p = path_startswith_full(path, prefix, /* accept_dot_dot= */
false);
++ p = path_startswith_full(path, prefix, /* flags= */ 0);
+ if (!p)
+ return -ENOTDIR;
+ } else
+@@ -144,7 +144,7 @@ int mkdir_parents_internal(const char *prefix, const char
*path, mode_t mode, ui
+
+ s[n] = '\0';
+
+- if (!prefix || !path_startswith_full(prefix, path, /*
accept_dot_dot= */ false)) {
++ if (!prefix || !path_startswith_full(prefix, path, /* flags=
*/ 0)) {
+ r = mkdir_safe_internal(path, mode, uid, gid, flags |
MKDIR_IGNORE_EXISTING, _mkdirat);
+ if (r < 0 && r != -EEXIST)
+ return r;
+diff --git a/src/basic/path-util.c b/src/basic/path-util.c
+index 72c0d6b..0c2d08c 100644
+--- a/src/basic/path-util.c
++++ b/src/basic/path-util.c
+@@ -399,8 +399,8 @@ char* path_simplify_full(char *path, PathSimplifyFlags
flags) {
+ return path;
+ }
+
+-char* path_startswith_full(const char *path, const char *prefix, bool
accept_dot_dot) {
+- assert(path);
++char* path_startswith_full(const char *original_path, const char *prefix,
PathStartWithFlags flags) {
++ assert(original_path);
+ assert(prefix);
+
+ /* Returns a pointer to the start of the first component after the
parts matched by
+@@ -413,28 +413,45 @@ char* path_startswith_full(const char *path, const char
*prefix, bool accept_dot
+ * Returns NULL otherwise.
+ */
+
++ const char *path = original_path;
++
+ if ((path[0] == '/') != (prefix[0] == '/'))
+ return NULL;
+
+ for (;;) {
+ const char *p, *q;
+- int r, k;
++ int m, n;
+
+- r = path_find_first_component(&path, accept_dot_dot, &p);
+- if (r < 0)
++ m = path_find_first_component(&path, FLAGS_SET(flags,
PATH_STARTSWITH_ACCEPT_DOT_DOT), &p);
++ if (m < 0)
+ return NULL;
+
+- k = path_find_first_component(&prefix, accept_dot_dot, &q);
+- if (k < 0)
++ n = path_find_first_component(&prefix, FLAGS_SET(flags,
PATH_STARTSWITH_ACCEPT_DOT_DOT), &q);
++ if (n < 0)
+ return NULL;
+
+- if (k == 0)
+- return (char*) (p ?: path);
++ if (n == 0) {
++ if (!p)
++ p = path;
++
++ if (FLAGS_SET(flags,
PATH_STARTSWITH_RETURN_LEADING_SLASH)) {
++
++ if (p <= original_path)
++ return NULL;
++
++ p--;
++
++ if (*p != '/')
++ return NULL;
++ }
++
++ return (char*) p;
++ }
+
+- if (r != k)
++ if (m != n)
+ return NULL;
+
+- if (!strneq(p, q, r))
++ if (!strneq(p, q, m))
+ return NULL;
+ }
+ }
+diff --git a/src/basic/path-util.h b/src/basic/path-util.h
+index 09604ba..e083a91 100644
+--- a/src/basic/path-util.h
++++ b/src/basic/path-util.h
+@@ -62,9 +62,15 @@ int safe_getcwd(char **ret);
+ int path_make_absolute_cwd(const char *p, char **ret);
+ int path_make_relative(const char *from, const char *to, char **ret);
+ int path_make_relative_parent(const char *from_child, const char *to, char
**ret);
+-char* path_startswith_full(const char *path, const char *prefix, bool
accept_dot_dot) _pure_;
++
++typedef enum PathStartWithFlags {
++ PATH_STARTSWITH_ACCEPT_DOT_DOT = 1U << 0,
++ PATH_STARTSWITH_RETURN_LEADING_SLASH = 1U << 1,
++} PathStartWithFlags;
++
++char* path_startswith_full(const char *path, const char *prefix,
PathStartWithFlags flags) _pure_;
+ static inline char* path_startswith(const char *path, const char *prefix) {
+- return path_startswith_full(path, prefix, true);
++ return path_startswith_full(path, prefix,
PATH_STARTSWITH_ACCEPT_DOT_DOT);
+ }
+ int path_compare(const char *a, const char *b) _pure_;
+
+diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c
+index 7ab9f20..6e495e6 100644
+--- a/src/test/test-path-util.c
++++ b/src/test/test-path-util.c
+@@ -671,6 +671,22 @@ TEST(path_startswith) {
+ test_path_startswith_one("/foo/bar/barfoo/", "/fo", NULL, NULL);
+ }
+
++static void test_path_startswith_return_leading_slash_one(const char *path,
const char *prefix, const char *expected) {
++ const char *p;
++
++ log_debug("/* %s(%s, %s) */", __func__, path, prefix);
++
++ p = path_startswith_full(path, prefix,
PATH_STARTSWITH_RETURN_LEADING_SLASH);
++ assert_se(streq_ptr(p, expected));
++}
++
++TEST(path_startswith_return_leading_slash) {
++ test_path_startswith_return_leading_slash_one("/foo/bar", "/",
"/foo/bar");
++ test_path_startswith_return_leading_slash_one("/foo/bar", "/foo",
"/bar");
++ test_path_startswith_return_leading_slash_one("/foo/bar", "/foo/bar",
NULL);
++ test_path_startswith_return_leading_slash_one("/foo/bar/",
"/foo/bar", "/");
++}
++
+ static void test_prefix_root_one(const char *r, const char *p, const char
*expected) {
+ _cleanup_free_ char *s = NULL;
+ const char *t;
diff -Nru systemd-252.39/debian/patches/CVE-2026-29111-2.patch
systemd-252.39/debian/patches/CVE-2026-29111-2.patch
--- systemd-252.39/debian/patches/CVE-2026-29111-2.patch 1970-01-01
01:00:00.000000000 +0100
+++ systemd-252.39/debian/patches/CVE-2026-29111-2.patch 2026-04-27
21:48:55.000000000 +0200
@@ -0,0 +1,89 @@
+From: Lennart Poettering <[email protected]>
+Date: Fri, 23 May 2025 06:45:40 +0200
+Subject: path-util: invert PATH_STARTSWITH_ACCEPT_DOT_DOT flag
+
+As requested:
https://github.com/systemd/systemd/pull/37572#pullrequestreview-2861928094
+
+(cherry picked from commit ceed11e465f1c8efff1931412a85924d9de7c08d)
+
+Origin: backport,
https://github.com/systemd/systemd/commit/7ac3220213690e8a8d6d2a6e81e43bd1dce01d69
+---
+ src/basic/fs-util.c | 2 +-
+ src/basic/mkdir.c | 4 ++--
+ src/basic/path-util.c | 4 ++--
+ src/basic/path-util.h | 4 ++--
+ 4 files changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c
+index 9950ff3..702331a 100644
+--- a/src/basic/fs-util.c
++++ b/src/basic/fs-util.c
+@@ -67,7 +67,7 @@ int rmdir_parents(const char *path, const char *stop) {
+ assert(*slash == '/');
+ *slash = '\0';
+
+- if (path_startswith_full(stop, p, /* flags= */ 0))
++ if (path_startswith_full(stop, p,
PATH_STARTSWITH_REFUSE_DOT_DOT))
+ return 0;
+
+ if (rmdir(p) < 0 && errno != ENOENT)
+diff --git a/src/basic/mkdir.c b/src/basic/mkdir.c
+index 478cb69..c2ec09e 100644
+--- a/src/basic/mkdir.c
++++ b/src/basic/mkdir.c
+@@ -99,7 +99,7 @@ int mkdir_parents_internal(const char *prefix, const char
*path, mode_t mode, ui
+ assert(_mkdirat != mkdirat);
+
+ if (prefix) {
+- p = path_startswith_full(path, prefix, /* flags= */ 0);
++ p = path_startswith_full(path, prefix,
PATH_STARTSWITH_REFUSE_DOT_DOT);
+ if (!p)
+ return -ENOTDIR;
+ } else
+@@ -144,7 +144,7 @@ int mkdir_parents_internal(const char *prefix, const char
*path, mode_t mode, ui
+
+ s[n] = '\0';
+
+- if (!prefix || !path_startswith_full(prefix, path, /* flags=
*/ 0)) {
++ if (!prefix || !path_startswith_full(prefix, path,
PATH_STARTSWITH_REFUSE_DOT_DOT)) {
+ r = mkdir_safe_internal(path, mode, uid, gid, flags |
MKDIR_IGNORE_EXISTING, _mkdirat);
+ if (r < 0 && r != -EEXIST)
+ return r;
+diff --git a/src/basic/path-util.c b/src/basic/path-util.c
+index 0c2d08c..47248c7 100644
+--- a/src/basic/path-util.c
++++ b/src/basic/path-util.c
+@@ -422,11 +422,11 @@ char* path_startswith_full(const char *original_path,
const char *prefix, PathSt
+ const char *p, *q;
+ int m, n;
+
+- m = path_find_first_component(&path, FLAGS_SET(flags,
PATH_STARTSWITH_ACCEPT_DOT_DOT), &p);
++ m = path_find_first_component(&path, !FLAGS_SET(flags,
PATH_STARTSWITH_REFUSE_DOT_DOT), &p);
+ if (m < 0)
+ return NULL;
+
+- n = path_find_first_component(&prefix, FLAGS_SET(flags,
PATH_STARTSWITH_ACCEPT_DOT_DOT), &q);
++ n = path_find_first_component(&prefix, !FLAGS_SET(flags,
PATH_STARTSWITH_REFUSE_DOT_DOT), &q);
+ if (n < 0)
+ return NULL;
+
+diff --git a/src/basic/path-util.h b/src/basic/path-util.h
+index e083a91..33f4150 100644
+--- a/src/basic/path-util.h
++++ b/src/basic/path-util.h
+@@ -64,13 +64,13 @@ int path_make_relative(const char *from, const char *to,
char **ret);
+ int path_make_relative_parent(const char *from_child, const char *to, char
**ret);
+
+ typedef enum PathStartWithFlags {
+- PATH_STARTSWITH_ACCEPT_DOT_DOT = 1U << 0,
++ PATH_STARTSWITH_REFUSE_DOT_DOT = 1U << 0,
+ PATH_STARTSWITH_RETURN_LEADING_SLASH = 1U << 1,
+ } PathStartWithFlags;
+
+ char* path_startswith_full(const char *path, const char *prefix,
PathStartWithFlags flags) _pure_;
+ static inline char* path_startswith(const char *path, const char *prefix) {
+- return path_startswith_full(path, prefix,
PATH_STARTSWITH_ACCEPT_DOT_DOT);
++ return path_startswith_full(path, prefix, 0);
+ }
+ int path_compare(const char *a, const char *b) _pure_;
+
diff -Nru systemd-252.39/debian/patches/CVE-2026-29111-3.patch
systemd-252.39/debian/patches/CVE-2026-29111-3.patch
--- systemd-252.39/debian/patches/CVE-2026-29111-3.patch 1970-01-01
01:00:00.000000000 +0100
+++ systemd-252.39/debian/patches/CVE-2026-29111-3.patch 2026-04-27
21:48:55.000000000 +0200
@@ -0,0 +1,96 @@
+From: Mike Yuan <[email protected]>
+Date: Thu, 26 Feb 2026 11:06:00 +0100
+Subject: core/cgroup: avoid one unnecessary strjoina()
+
+(cherry picked from commit 42aee39107fbdd7db1ccd402a2151822b2805e9f)
+(cherry picked from commit 80acea4ef80a4bb78560ed970c34952299b890d6)
+(cherry picked from commit b5fd14693057e5f2c9b4a49603be64ec3608ff6c)
+
+Origin: backport,
https://github.com/systemd/systemd/commit/21167006574d6b83813c7596759b474f56562412
+---
+ src/core/cgroup.c | 27 +++++++++++++--------------
+ 1 file changed, 13 insertions(+), 14 deletions(-)
+
+diff --git a/src/core/cgroup.c b/src/core/cgroup.c
+index 89087a2..515debc 100644
+--- a/src/core/cgroup.c
++++ b/src/core/cgroup.c
+@@ -2268,12 +2268,13 @@ static int unit_update_cgroup(
+ return 0;
+ }
+
+-static int unit_attach_pid_to_cgroup_via_bus(Unit *u, pid_t pid, const char
*suffix_path) {
++static int unit_attach_pid_to_cgroup_via_bus(Unit *u, const char
*cgroup_path, pid_t pid) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+- char *pp;
+ int r;
+
+ assert(u);
++ assert(cgroup_path);
++ assert(pid_is_valid(pid));
+
+ if (MANAGER_IS_SYSTEM(u->manager))
+ return -EINVAL;
+@@ -2281,17 +2282,13 @@ static int unit_attach_pid_to_cgroup_via_bus(Unit *u,
pid_t pid, const char *suf
+ if (!u->manager->system_bus)
+ return -EIO;
+
+- if (!u->cgroup_path)
+- return -EINVAL;
+-
+ /* Determine this unit's cgroup path relative to our cgroup root */
+- pp = path_startswith(u->cgroup_path, u->manager->cgroup_root);
++ const char *pp = path_startswith_full(cgroup_path,
++ u->manager->cgroup_root,
++
PATH_STARTSWITH_RETURN_LEADING_SLASH|PATH_STARTSWITH_REFUSE_DOT_DOT);
+ if (!pp)
+ return -EINVAL;
+
+- pp = strjoina("/", pp, suffix_path);
+- path_simplify(pp);
+-
+ r = bus_call_method(u->manager->system_bus,
+ bus_systemd_mgr,
+ "AttachProcessesToUnit",
+@@ -2330,8 +2327,10 @@ int unit_attach_pids_to_cgroup(Unit *u, Set *pids,
const char *suffix_path) {
+ return r;
+
+ if (isempty(suffix_path))
+- p = u->cgroup_path;
++ p = empty_to_root(u->cgroup_path);
+ else {
++ assert(path_is_absolute(suffix_path));
++
+ joined = path_join(u->cgroup_path, suffix_path);
+ if (!joined)
+ return -ENOMEM;
+@@ -2352,7 +2351,7 @@ int unit_attach_pids_to_cgroup(Unit *u, Set *pids, const
char *suffix_path) {
+
+ log_unit_full_errno(u, again ? LOG_DEBUG : LOG_INFO,
r,
+ "Couldn't move process "PID_FMT"
to%s requested cgroup '%s': %m",
+- pid, again ? " directly" : "",
empty_to_root(p));
++ pid, again ? " directly" : "", p);
+
+ if (again) {
+ int z;
+@@ -2362,9 +2361,9 @@ int unit_attach_pids_to_cgroup(Unit *u, Set *pids, const
char *suffix_path) {
+ * Since it's more privileged it might be
able to move the process across the
+ * leaves of a subtree whose top node is not
owned by us. */
+
+- z = unit_attach_pid_to_cgroup_via_bus(u, pid,
suffix_path);
++ z = unit_attach_pid_to_cgroup_via_bus(u, p,
pid);
+ if (z < 0)
+- log_unit_info_errno(u, z, "Couldn't
move process "PID_FMT" to requested cgroup '%s' (directly or via the system
bus): %m", pid, empty_to_root(p));
++ log_unit_info_errno(u, z, "Couldn't
move process "PID_FMT" to requested cgroup '%s' (directly or via the system
bus): %m", pid, p);
+ else {
+ if (ret >= 0)
+ ret++; /* Count successful
additions */
+@@ -2408,7 +2407,7 @@ int unit_attach_pids_to_cgroup(Unit *u, Set *pids, const
char *suffix_path) {
+ continue; /* Success! */
+
+ log_unit_debug_errno(u, r, "Failed to attach
PID " PID_FMT " to requested cgroup %s in controller %s, falling back to unit's
cgroup: %m",
+- pid, empty_to_root(p),
cgroup_controller_to_string(c));
++ pid, p,
cgroup_controller_to_string(c));
+ }
+
+ /* So this controller is either not delegate or
realized, or something else weird happened. In
diff -Nru systemd-252.39/debian/patches/CVE-2026-29111-4.patch
systemd-252.39/debian/patches/CVE-2026-29111-4.patch
--- systemd-252.39/debian/patches/CVE-2026-29111-4.patch 1970-01-01
01:00:00.000000000 +0100
+++ systemd-252.39/debian/patches/CVE-2026-29111-4.patch 2026-04-27
21:48:55.000000000 +0200
@@ -0,0 +1,30 @@
+From: Mike Yuan <[email protected]>
+Date: Thu, 26 Feb 2026 11:06:34 +0100
+Subject: [PATCH] core: validate input cgroup path more prudently
+
+(cherry picked from commit efa6ba2ab625aaa160ac435a09e6482fc63bdbe8)
+(cherry picked from commit 3cee294fe8cf4fa0eff933ab21416d099942cabd)
+(cherry picked from commit 1d22f706bd04f45f8422e17fbde3f56ece17758a)
+
+Origin: upstream,
https://github.com/systemd/systemd/commit/54588d2dedff54bfb6036670820650e4ea74628f
+---
+ src/core/dbus-manager.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
+index 9df3153..ac51a49 100644
+--- a/src/core/dbus-manager.c
++++ b/src/core/dbus-manager.c
+@@ -644,6 +644,12 @@ static int
method_get_unit_by_control_group(sd_bus_message *message, void *userd
+ if (r < 0)
+ return r;
+
++ if (!path_is_absolute(cgroup))
++ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"Control group path is not absolute: %s", cgroup);
++
++ if (!path_is_normalized(cgroup))
++ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"Control group path is not normalized: %s", cgroup);
++
+ u = manager_get_unit_by_cgroup(m, cgroup);
+ if (!u)
+ return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT,
diff -Nru systemd-252.39/debian/patches/CVE-2026-40225.patch
systemd-252.39/debian/patches/CVE-2026-40225.patch
--- systemd-252.39/debian/patches/CVE-2026-40225.patch 1970-01-01
01:00:00.000000000 +0100
+++ systemd-252.39/debian/patches/CVE-2026-40225.patch 2026-04-27
21:48:55.000000000 +0200
@@ -0,0 +1,122 @@
+From: Luca Boccassi <[email protected]>
+Date: Fri, 6 Mar 2026 19:32:35 +0000
+Subject: [PATCH] udev: check for invalid chars in various fields received
+ from the kernel
+
+(cherry picked from commit 16325b35fa6ecb25f66534a562583ce3b96d52f3)
+(cherry picked from commit 3513862eabe9ec4a6a095d7266e98f998f289ed2)
+(cherry picked from commit c20d21e0da293e715db468f9f4a15a5c8fbf8273)
+
+Origin: backport,
https://github.com/systemd/systemd/commit/03bb697b8df0339c37f4b845025320b261aeb7cc
+---
+ src/udev/dmi_memory_id/dmi_memory_id.c | 3 ++-
+ src/udev/scsi_id/scsi_id.c | 3 ++-
+ src/udev/udev-builtin-net_id.c | 15 ++++++++++++++-
+ src/udev/v4l_id/v4l_id.c | 5 ++++-
+ 4 files changed, 22 insertions(+), 4 deletions(-)
+
+diff --git a/src/udev/dmi_memory_id/dmi_memory_id.c
b/src/udev/dmi_memory_id/dmi_memory_id.c
+index 4793c0f..8f170d6 100644
+--- a/src/udev/dmi_memory_id/dmi_memory_id.c
++++ b/src/udev/dmi_memory_id/dmi_memory_id.c
+@@ -51,6 +51,7 @@
+ #include "udev-util.h"
+ #include "unaligned.h"
+ #include "version.h"
++#include "utf8.h"
+
+ #define SUPPORTED_SMBIOS_VER 0x030300
+
+@@ -185,7 +186,7 @@ static void dmi_memory_device_string(
+
+ str = strdupa_safe(dmi_string(h, s));
+ str = strstrip(str);
+- if (!isempty(str))
++ if (!isempty(str) && utf8_is_valid(str) && !string_has_cc(str, /* ok=
*/ NULL))
+ printf("MEMORY_DEVICE_%u_%s=%s\n", slot_num, attr_suffix,
str);
+ }
+
+diff --git a/src/udev/scsi_id/scsi_id.c b/src/udev/scsi_id/scsi_id.c
+index 364d567..f689582 100644
+--- a/src/udev/scsi_id/scsi_id.c
++++ b/src/udev/scsi_id/scsi_id.c
+@@ -27,6 +27,7 @@
+ #include "strxcpyx.h"
+ #include "udev-util.h"
+ #include "version.h"
++#include "utf8.h"
+
+ static const struct option options[] = {
+ { "device", required_argument, NULL, 'd' },
+@@ -441,7 +442,7 @@ static int scsi_id(char *maj_min_dev) {
+ }
+ if (dev_scsi.tgpt_group[0] != '\0')
+ printf("ID_TARGET_PORT=%s\n", dev_scsi.tgpt_group);
+- if (dev_scsi.unit_serial_number[0] != '\0')
++ if (dev_scsi.unit_serial_number[0] != '\0' &&
utf8_is_valid(dev_scsi.unit_serial_number) &&
!string_has_cc(dev_scsi.unit_serial_number, /* ok= */ NULL))
+ printf("ID_SCSI_SERIAL=%s\n",
dev_scsi.unit_serial_number);
+ goto out;
+ }
+diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c
+index 6425494..3587a1d 100644
+--- a/src/udev/udev-builtin-net_id.c
++++ b/src/udev/udev-builtin-net_id.c
+@@ -39,6 +39,7 @@
+ #include "strv.h"
+ #include "strxcpyx.h"
+ #include "udev-builtin.h"
++#include "utf8.h"
+
+ #define ONBOARD_14BIT_INDEX_MAX ((1U << 14) - 1)
+ #define ONBOARD_16BIT_INDEX_MAX ((1U << 16) - 1)
+@@ -220,7 +221,13 @@ static int dev_pci_onboard(sd_device *dev, const LinkInfo
*info, NetNames *names
+ special_glyph(SPECIAL_GLYPH_ARROW_RIGHT),
empty_to_na(names->pci_onboard));
+
+ if (sd_device_get_sysattr_value(names->pcidev, "label",
&names->pci_onboard_label) >= 0)
+- log_device_debug(dev, "Onboard label from PCI device: %s",
names->pci_onboard_label);
++ {
++ if (!utf8_is_valid(names->pci_onboard_label) ||
string_has_cc(names->pci_onboard_label, /* ok= */ NULL)) {
++ names->pci_onboard_label = NULL;
++ log_device_debug_errno(dev, SYNTHETIC_ERRNO(EINVAL),
"Invalid label");
++ } else
++ log_device_debug(dev, "Onboard label from PCI device:
%s", names->pci_onboard_label);
++ }
+ else
+ names->pci_onboard_label = NULL;
+
+@@ -1083,6 +1090,12 @@ static int get_link_info(sd_device *dev, LinkInfo
*info) {
+ return r;
+
+ (void) sd_device_get_sysattr_value(dev, "phys_port_name",
&info->phys_port_name);
++ if (!isempty(info->phys_port_name)) {
++ if (!utf8_is_valid(info->phys_port_name) ||
string_has_cc(info->phys_port_name, /* ok= */ NULL)) {
++ info->phys_port_name = NULL;
++ log_device_debug_errno(dev, SYNTHETIC_ERRNO(EINVAL),
"Invalid phys_port_name");
++ }
++ }
+
+ r = sd_device_get_sysattr_value(dev, "address", &s);
+ if (r < 0 && r != -ENOENT)
+diff --git a/src/udev/v4l_id/v4l_id.c b/src/udev/v4l_id/v4l_id.c
+index c2312c7..f363441 100644
+--- a/src/udev/v4l_id/v4l_id.c
++++ b/src/udev/v4l_id/v4l_id.c
+@@ -28,6 +28,8 @@
+
+ #include "fd-util.h"
+ #include "util.h"
++#include "string-util.h"
++#include "utf8.h"
+
+ int main(int argc, char *argv[]) {
+ static const struct option options[] = {
+@@ -66,7 +68,8 @@ int main(int argc, char *argv[]) {
+ if (ioctl(fd, VIDIOC_QUERYCAP, &v2cap) == 0) {
+ int capabilities;
+ printf("ID_V4L_VERSION=2\n");
+- printf("ID_V4L_PRODUCT=%s\n", v2cap.card);
++ if (utf8_is_valid((char *)v2cap.card) && !string_has_cc((char
*)v2cap.card, /* ok= */ NULL))
++ printf("ID_V4L_PRODUCT=%s\n", v2cap.card);
+ printf("ID_V4L_CAPABILITIES=:");
+ if (v2cap.capabilities & V4L2_CAP_DEVICE_CAPS)
+ capabilities = v2cap.device_caps;
diff -Nru systemd-252.39/debian/patches/CVE-2026-40226-1.patch
systemd-252.39/debian/patches/CVE-2026-40226-1.patch
--- systemd-252.39/debian/patches/CVE-2026-40226-1.patch 1970-01-01
01:00:00.000000000 +0100
+++ systemd-252.39/debian/patches/CVE-2026-40226-1.patch 2026-04-27
21:48:55.000000000 +0200
@@ -0,0 +1,56 @@
+From: Luca Boccassi <[email protected]>
+Date: Wed, 11 Mar 2026 12:15:26 +0000
+Subject: [PATCH] nspawn: apply BindUser/Ephemeral from settings file only if
+ trusted
+
+Originally reported on yeswehack.com as:
+YWH-PGM9780-116
+
+Follow-up for 2f8930449079403b26c9164b8eeac78d5af2c8df
+Follow-up for a2f577fca0be79b23f61f033229b64884e7d840a
+
+(cherry picked from commit 61bceb1bff4b1f9c126b18dc971ca3e6d8c71c40)
+(cherry picked from commit 718711ed876c870a72149eea279b819cdab14e91)
+(cherry picked from commit e4db9c12957d315c0ed22c6ca87a816d0927d6dc)
+
+Origin: upstream,
https://github.com/systemd/systemd/commit/773fd3b6e72e6c83cbb1cfc1cb20f3793db8649a
+---
+ src/nspawn/nspawn.c | 18 ++++++++++++++----
+ 1 file changed, 14 insertions(+), 4 deletions(-)
+
+diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
+index 0e27c6d..cd12042 100644
+--- a/src/nspawn/nspawn.c
++++ b/src/nspawn/nspawn.c
+@@ -4329,8 +4329,13 @@ static int merge_settings(Settings *settings, const
char *path) {
+ }
+
+ if ((arg_settings_mask & SETTING_EPHEMERAL) == 0 &&
+- settings->ephemeral >= 0)
+- arg_ephemeral = settings->ephemeral;
++ settings->ephemeral >= 0) {
++
++ if (!arg_settings_trusted)
++ log_warning("Ignoring ephemeral setting, file %s is
not trusted.", path);
++ else
++ arg_ephemeral = settings->ephemeral;
++ }
+
+ if ((arg_settings_mask & SETTING_DIRECTORY) == 0 &&
+ settings->root) {
+@@ -4498,8 +4503,13 @@ static int merge_settings(Settings *settings, const
char *path) {
+ }
+
+ if ((arg_settings_mask & SETTING_BIND_USER) == 0 &&
+- !strv_isempty(settings->bind_user))
+- strv_free_and_replace(arg_bind_user, settings->bind_user);
++ !strv_isempty(settings->bind_user)) {
++
++ if (!arg_settings_trusted)
++ log_warning("Ignoring bind user setting, file %s is
not trusted.", path);
++ else
++ strv_free_and_replace(arg_bind_user,
settings->bind_user);
++ }
+
+ if ((arg_settings_mask & SETTING_NOTIFY_READY) == 0 &&
+ settings->notify_ready >= 0)
diff -Nru systemd-252.39/debian/patches/CVE-2026-40226-2.patch
systemd-252.39/debian/patches/CVE-2026-40226-2.patch
--- systemd-252.39/debian/patches/CVE-2026-40226-2.patch 1970-01-01
01:00:00.000000000 +0100
+++ systemd-252.39/debian/patches/CVE-2026-40226-2.patch 2026-04-27
21:48:55.000000000 +0200
@@ -0,0 +1,33 @@
+From: Luca Boccassi <[email protected]>
+Date: Wed, 11 Mar 2026 13:27:14 +0000
+Subject: [PATCH] nspawn: normalize pivot_root paths
+
+Originally reported on yeswehack.com as:
+YWH-PGM9780-116
+
+Follow-up for b53ede699cdc5233041a22591f18863fb3fe2672
+
+(cherry picked from commit 7b85f5498a958e5bb660c703b8f4a71cceed3373)
+(cherry picked from commit 6566dc1451089e07090f5a114ae2eb43ed39188d)
+(cherry picked from commit 1c55a0a5e26a07df828f72092ad1203e221b60db)
+
+Origin: upstream,
https://github.com/systemd/systemd/commit/bfa0a842822c4f79da9d47f8a773fd128d8f8a0a
+---
+ src/nspawn/nspawn-mount.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c
+index 63f59fe..0a4da9f 100644
+--- a/src/nspawn/nspawn-mount.c
++++ b/src/nspawn/nspawn-mount.c
+@@ -1244,7 +1244,9 @@ int pivot_root_parse(char **pivot_root_new, char
**pivot_root_old, const char *s
+
+ if (!path_is_absolute(root_new))
+ return -EINVAL;
+- if (root_old && !path_is_absolute(root_old))
++ if (!path_is_normalized(root_new))
++ return -EINVAL;
++ if (root_old && (!path_is_absolute(root_old) ||
!path_is_normalized(root_old)))
+ return -EINVAL;
+
+ free_and_replace(*pivot_root_new, root_new);
diff -Nru systemd-252.39/debian/patches/CVE-2026-4105.patch
systemd-252.39/debian/patches/CVE-2026-4105.patch
--- systemd-252.39/debian/patches/CVE-2026-4105.patch 1970-01-01
01:00:00.000000000 +0100
+++ systemd-252.39/debian/patches/CVE-2026-4105.patch 2026-04-27
21:48:55.000000000 +0200
@@ -0,0 +1,28 @@
+From: Luca Boccassi <[email protected]>
+Date: Sun, 8 Mar 2026 14:30:52 +0000
+Subject: machined: reject invalid class types when registering machines
+
+Follow-up for fbe550738d03b178bb004a1390e74115e904118a
+
+(cherry picked from commit 6df5f80bd374be1b45c52d740e88f0236da922c7)
+(cherry picked from commit 497d0172416cbb5b70f96b95399d041407c223bd)
+(cherry picked from commit 749e2eaf7086c91598cf7043a31919854b1c2dfe)
+
+Origin: backport,
https://github.com/systemd/systemd/commit/6941d92dc299667036cbe264435971cec59ebc76
+---
+ src/machine/machined-dbus.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/machine/machined-dbus.c b/src/machine/machined-dbus.c
+index 1e16046..9fb955f 100644
+--- a/src/machine/machined-dbus.c
++++ b/src/machine/machined-dbus.c
+@@ -270,7 +270,7 @@ static int method_create_or_register_machine(Manager
*manager, sd_bus_message *m
+ c = _MACHINE_CLASS_INVALID;
+ else {
+ c = machine_class_from_string(class);
+- if (c < 0)
++ if (c < 0 || !IN_SET(c, MACHINE_CONTAINER, MACHINE_VM))
+ return sd_bus_error_set(error,
SD_BUS_ERROR_INVALID_ARGS, "Invalid machine class parameter");
+ }
+
diff -Nru systemd-252.39/debian/patches/series
systemd-252.39/debian/patches/series
--- systemd-252.39/debian/patches/series 2025-06-26 16:57:46.000000000
+0200
+++ systemd-252.39/debian/patches/series 2026-04-27 21:48:55.000000000
+0200
@@ -18,3 +18,12 @@
debian/systemctl-do-not-shutdown-immediately-on-scheduled-shutdo.patch
debian/Downgrade-a-couple-of-warnings-to-debug.patch
debian/Skip-flaky-test_resolved_domain_restricted_dns-in-network.patch
+test-cgroup-Ignore-ENOENT-from-cg_create.patch
+CVE-2026-4105.patch
+CVE-2026-29111-1.patch
+CVE-2026-29111-2.patch
+CVE-2026-29111-3.patch
+CVE-2026-29111-4.patch
+CVE-2026-40225.patch
+CVE-2026-40226-1.patch
+CVE-2026-40226-2.patch
diff -Nru
systemd-252.39/debian/patches/test-cgroup-Ignore-ENOENT-from-cg_create.patch
systemd-252.39/debian/patches/test-cgroup-Ignore-ENOENT-from-cg_create.patch
---
systemd-252.39/debian/patches/test-cgroup-Ignore-ENOENT-from-cg_create.patch
1970-01-01 01:00:00.000000000 +0100
+++
systemd-252.39/debian/patches/test-cgroup-Ignore-ENOENT-from-cg_create.patch
2026-04-27 21:48:55.000000000 +0200
@@ -0,0 +1,28 @@
+From: Solar Designer <[email protected]>
+Date: Fri, 11 Jul 2025 00:28:14 +0200
+Subject: [PATCH] test-cgroup: Ignore ENOENT from cg_create()
+
+which was the only test failure building systemd-252-51.el9 in a
+container, also previously reported against 252-rc1 under Gentoo
+in #25015
+
+(cherry picked from commit 470da651109e2636c624ac27257a7a64472192f6)
+
+Origin: upstream,
https://github.com/systemd/systemd/commit/2fb0cb64c346e464b7189328146f7d003dc0f714
+---
+ src/test/test-cgroup.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/test/test-cgroup.c b/src/test/test-cgroup.c
+index 8b86c60..f77b9f6 100644
+--- a/src/test/test-cgroup.c
++++ b/src/test/test-cgroup.c
+@@ -66,7 +66,7 @@ TEST(cg_create) {
+ (void) cg_trim(SYSTEMD_CGROUP_CONTROLLER, test_b, /* delete_root= */
true);
+
+ r = cg_create(SYSTEMD_CGROUP_CONTROLLER, test_a);
+- if (IN_SET(r, -EPERM, -EACCES, -EROFS)) {
++ if (IN_SET(r, -EPERM, -EACCES, -EROFS, -ENOENT)) {
+ log_info_errno(r, "Skipping %s: %m", __func__);
+ return;
+ }
--- End Message ---