From d5a4a5f51536ce00f433cb24430ac0b36147e3ee Mon Sep 17 00:00:00 2001 From: Jan Macku Date: Thu, 16 Apr 2026 14:54:52 +0200 Subject: [PATCH] systemd-252-69 Resolves: RHEL-163871, RHEL-108575, RHEL-163877 --- ...dUser-Ephemeral-from-settings-file-o.patch | 55 +++++++++ 1331-nspawn-normalize-pivot_root-paths.patch | 32 +++++ ...not-propagate-reload-for-combined-RE.patch | 81 +++++++++++++ ...nvalid-chars-in-various-fields-recei.patch | 110 ++++++++++++++++++ 1334-udev-fix-review-mixup.patch | 32 +++++ ...ck-for-invalid-chars-in-various-fiel.patch | 52 +++++++++ systemd.spec | 16 ++- 7 files changed, 377 insertions(+), 1 deletion(-) create mode 100644 1330-nspawn-apply-BindUser-Ephemeral-from-settings-file-o.patch create mode 100644 1331-nspawn-normalize-pivot_root-paths.patch create mode 100644 1332-core-service-do-not-propagate-reload-for-combined-RE.patch create mode 100644 1333-udev-check-for-invalid-chars-in-various-fields-recei.patch create mode 100644 1334-udev-fix-review-mixup.patch create mode 100644 1335-udev-scsi-id-check-for-invalid-chars-in-various-fiel.patch diff --git a/1330-nspawn-apply-BindUser-Ephemeral-from-settings-file-o.patch b/1330-nspawn-apply-BindUser-Ephemeral-from-settings-file-o.patch new file mode 100644 index 0000000..ff6adfa --- /dev/null +++ b/1330-nspawn-apply-BindUser-Ephemeral-from-settings-file-o.patch @@ -0,0 +1,55 @@ +From 6615811a8c6a36677a389ada8cd7be10e9756e58 Mon Sep 17 00:00:00 2001 +From: Luca Boccassi +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) + +Resolves: RHEL-163871 +--- + 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 db45968cd3..39d036ef7e 100644 +--- a/src/nspawn/nspawn.c ++++ b/src/nspawn/nspawn.c +@@ -4304,8 +4304,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) { +@@ -4473,8 +4478,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 --git a/1331-nspawn-normalize-pivot_root-paths.patch b/1331-nspawn-normalize-pivot_root-paths.patch new file mode 100644 index 0000000..ac0b8c0 --- /dev/null +++ b/1331-nspawn-normalize-pivot_root-paths.patch @@ -0,0 +1,32 @@ +From cfb234e332fe820ef843fb817598ebbbdffdd05f Mon Sep 17 00:00:00 2001 +From: Luca Boccassi +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) + +Resolves: RHEL-163871 +--- + 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 a54f1464ba..af96d2d1d7 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 --git a/1332-core-service-do-not-propagate-reload-for-combined-RE.patch b/1332-core-service-do-not-propagate-reload-for-combined-RE.patch new file mode 100644 index 0000000..e3fcc60 --- /dev/null +++ b/1332-core-service-do-not-propagate-reload-for-combined-RE.patch @@ -0,0 +1,81 @@ +From 3fe4b84a1c363e187be6fc30a19fbf2e66471473 Mon Sep 17 00:00:00 2001 +From: Mike Yuan +Date: Wed, 26 Feb 2025 15:02:58 +0100 +Subject: [PATCH] core/service: do not propagate reload for combined + RELOADING=1 + READY=1 when notify-reload + +Follow-up for 3bd28bf721dc70722ff1c675026ed0b44ad968a3 + +SERVICE_RELOAD_SIGNAL state can only be reached via explicit reload jobs, +and we have a clear distinction between that and plain RELOADING=1 +notifications, the latter of which is issued by clients doing reload +outside of our job engine. I.e. upon SERVICE_RELOAD_SIGNAL + RELOADING=1 +we don't propagate reload jobs again, since that's done during transaction +construction stage already. The handling of combined RELOADING=1 + READY=1 +so far is bogus however, as it tries to propagate duplicate reload jobs. +Amend this by following the logic for standalone RELOADING=1. + +(cherry picked from commit c337a1301f2de4105fc8023e45db20238c6a895a) + +Resolves: RHEL-108575 +--- + src/core/service.c | 39 ++++++++++++++++++++++----------------- + 1 file changed, 22 insertions(+), 17 deletions(-) + +diff --git a/src/core/service.c b/src/core/service.c +index 9c938aee91..53f40b2d78 100644 +--- a/src/core/service.c ++++ b/src/core/service.c +@@ -4218,7 +4218,28 @@ static void service_notify_message( + + s->notify_state = NOTIFY_READY; + +- /* Type=notify services inform us about completed initialization with READY=1 */ ++ /* Combined RELOADING=1 and READY=1? Then this is indication that the service started and ++ * immediately finished reloading. */ ++ if (strv_contains(tags, "RELOADING=1")) { ++ if (s->state == SERVICE_RELOAD_SIGNAL && ++ monotonic_usec != USEC_INFINITY && ++ monotonic_usec >= s->reload_begin_usec) ++ /* Valid Type=notify-reload protocol? Then we're all good. */ ++ service_enter_running(s, SERVICE_SUCCESS); ++ ++ else if (s->state == SERVICE_RUNNING) { ++ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; ++ ++ /* Propagate a reload explicitly for plain RELOADING=1 (semantically equivalent to ++ * service_enter_reload_by_notify() call in below) */ ++ r = manager_propagate_reload(UNIT(s)->manager, UNIT(s), JOB_FAIL, &error); ++ if (r < 0) ++ log_unit_warning(UNIT(s), "Failed to schedule propagation of reload, ignoring: %s", ++ bus_error_message(&error, r)); ++ } ++ } ++ ++ /* Type=notify(-reload) services inform us about completed initialization with READY=1 */ + if (IN_SET(s->type, SERVICE_NOTIFY, SERVICE_NOTIFY_RELOAD) && + s->state == SERVICE_START) + service_enter_start_post(s); +@@ -4227,22 +4248,6 @@ static void service_notify_message( + if (s->state == SERVICE_RELOAD_NOTIFY) + service_enter_running(s, SERVICE_SUCCESS); + +- /* Combined RELOADING=1 and READY=1? Then this is indication that the service started and +- * immediately finished reloading. */ +- if (s->state == SERVICE_RELOAD_SIGNAL && +- strv_contains(tags, "RELOADING=1") && +- monotonic_usec != USEC_INFINITY && +- monotonic_usec >= s->reload_begin_usec) { +- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; +- +- /* Propagate a reload explicitly */ +- r = manager_propagate_reload(UNIT(s)->manager, UNIT(s), JOB_FAIL, &error); +- if (r < 0) +- log_unit_warning(UNIT(s), "Failed to schedule propagation of reload, ignoring: %s", bus_error_message(&error, r)); +- +- service_enter_running(s, SERVICE_SUCCESS); +- } +- + notify_dbus = true; + + } else if (strv_contains(tags, "RELOADING=1")) { diff --git a/1333-udev-check-for-invalid-chars-in-various-fields-recei.patch b/1333-udev-check-for-invalid-chars-in-various-fields-recei.patch new file mode 100644 index 0000000..70b6432 --- /dev/null +++ b/1333-udev-check-for-invalid-chars-in-various-fields-recei.patch @@ -0,0 +1,110 @@ +From 967b7954b78bc59e0247e908ea74b19da7112b39 Mon Sep 17 00:00:00 2001 +From: Luca Boccassi +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) + +Resolves: RHEL-163877 +--- + src/udev/dmi_memory_id/dmi_memory_id.c | 3 ++- + src/udev/scsi_id/scsi_id.c | 5 +++-- + src/udev/udev-builtin-net_id.c | 7 ++++++- + src/udev/v4l_id/v4l_id.c | 5 ++++- + 4 files changed, 15 insertions(+), 5 deletions(-) + +diff --git a/src/udev/dmi_memory_id/dmi_memory_id.c b/src/udev/dmi_memory_id/dmi_memory_id.c +index 1345289219..d833a5989d 100644 +--- a/src/udev/dmi_memory_id/dmi_memory_id.c ++++ b/src/udev/dmi_memory_id/dmi_memory_id.c +@@ -50,6 +50,7 @@ + #include "string-util.h" + #include "udev-util.h" + #include "unaligned.h" ++#include "utf8.h" + #include "version.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 364d567705..2a489f4e38 100644 +--- a/src/udev/scsi_id/scsi_id.c ++++ b/src/udev/scsi_id/scsi_id.c +@@ -26,6 +26,7 @@ + #include "strv.h" + #include "strxcpyx.h" + #include "udev-util.h" ++#include "utf8.h" + #include "version.h" + + static const struct option options[] = { +@@ -441,8 +442,8 @@ 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') +- printf("ID_SCSI_SERIAL=%s\n", dev_scsi.unit_serial_number); ++ 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", serial_str); + goto out; + } + +diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c +index e1895a38c0..6bb6465832 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) +@@ -1188,9 +1189,13 @@ static int get_link_info(sd_device *dev, LinkInfo *info) { + return r; + + r = device_get_sysattr_value_filtered(dev, "phys_port_name", &info->phys_port_name); +- if (r >= 0) ++ if (r >= 0) { ++ if (!utf8_is_valid(info->phys_port_name) || string_has_cc(info->phys_port_name, /* ok= */ NULL)) ++ return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EINVAL), "Invalid phys_port_name"); ++ + /* Check if phys_port_name indicates virtual device representor */ + (void) sscanf(info->phys_port_name, "pf%*uvf%d", &info->vf_representor_id); ++ } + + r = device_get_sysattr_value_filtered(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 c2312c7909..ae8459c456 100644 +--- a/src/udev/v4l_id/v4l_id.c ++++ b/src/udev/v4l_id/v4l_id.c +@@ -27,6 +27,8 @@ + #include + + #include "fd-util.h" ++#include "string-util.h" ++#include "utf8.h" + #include "util.h" + + int main(int argc, char *argv[]) { +@@ -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 --git a/1334-udev-fix-review-mixup.patch b/1334-udev-fix-review-mixup.patch new file mode 100644 index 0000000..e53b3ce --- /dev/null +++ b/1334-udev-fix-review-mixup.patch @@ -0,0 +1,32 @@ +From 320ca2d881198cab52b4c6dd073967f2d4b2e919 Mon Sep 17 00:00:00 2001 +From: Luca Boccassi +Date: Fri, 13 Mar 2026 11:10:47 +0000 +Subject: [PATCH] udev: fix review mixup + +The previous version in the PR changed variable and sanitized it +in place. The second version switched to skip if CCs are in the +string instead, but didn't move back to the original variable. +Because it's an existing variable, no CI caught it. + +Follow-up for 16325b35fa6ecb25f66534a562583ce3b96d52f3 + +(cherry picked from commit 54f880b02ecf7362e630ffc885d1466df6ee6820) + +Resolves: RHEL-163877 +--- + src/udev/scsi_id/scsi_id.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/udev/scsi_id/scsi_id.c b/src/udev/scsi_id/scsi_id.c +index 2a489f4e38..71c5534851 100644 +--- a/src/udev/scsi_id/scsi_id.c ++++ b/src/udev/scsi_id/scsi_id.c +@@ -443,7 +443,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' && utf8_is_valid(dev_scsi.unit_serial_number) && !string_has_cc(dev_scsi.unit_serial_number, /* ok= */ NULL)) +- printf("ID_SCSI_SERIAL=%s\n", serial_str); ++ printf("ID_SCSI_SERIAL=%s\n", dev_scsi.unit_serial_number); + goto out; + } + diff --git a/1335-udev-scsi-id-check-for-invalid-chars-in-various-fiel.patch b/1335-udev-scsi-id-check-for-invalid-chars-in-various-fiel.patch new file mode 100644 index 0000000..dad2bcc --- /dev/null +++ b/1335-udev-scsi-id-check-for-invalid-chars-in-various-fiel.patch @@ -0,0 +1,52 @@ +From a7e7bf455cb22e95c4487c91cd040e3c27fa64e7 Mon Sep 17 00:00:00 2001 +From: Luca Boccassi +Date: Fri, 10 Apr 2026 19:04:04 +0100 +Subject: [PATCH] udev/scsi-id: check for invalid chars in various fields + received from the kernel + +Follow-up for 16325b35fa6ecb25f66534a562583ce3b96d52f3 + +(cherry picked from commit 5f700d148c44063c0f0dbb9fc136866339cd3fa7) + +Related: RHEL-163877 +--- + src/udev/scsi_id/scsi_id.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/src/udev/scsi_id/scsi_id.c b/src/udev/scsi_id/scsi_id.c +index 71c5534851..2f2a07891f 100644 +--- a/src/udev/scsi_id/scsi_id.c ++++ b/src/udev/scsi_id/scsi_id.c +@@ -389,6 +389,10 @@ static int set_inq_values(struct scsi_id_device *dev_scsi, const char *path) { + return 0; + } + ++static bool scsi_string_is_valid(const char *s) { ++ return !isempty(s) && utf8_is_valid(s) && !string_has_cc(s, /* ok= */ NULL); ++} ++ + /* + * scsi_id: try to get an id, if one is found, printf it to stdout. + * returns a value passed to exit() - 0 if printed an id, else 1. +@@ -432,17 +436,17 @@ static int scsi_id(char *maj_min_dev) { + udev_replace_chars(serial_str, NULL); + printf("ID_SERIAL_SHORT=%s\n", serial_str); + } +- if (dev_scsi.wwn[0] != '\0') { ++ if (scsi_string_is_valid(dev_scsi.wwn)) { + printf("ID_WWN=0x%s\n", dev_scsi.wwn); +- if (dev_scsi.wwn_vendor_extension[0] != '\0') { ++ if (scsi_string_is_valid(dev_scsi.wwn_vendor_extension)) { + printf("ID_WWN_VENDOR_EXTENSION=0x%s\n", dev_scsi.wwn_vendor_extension); + printf("ID_WWN_WITH_EXTENSION=0x%s%s\n", dev_scsi.wwn, dev_scsi.wwn_vendor_extension); + } else + printf("ID_WWN_WITH_EXTENSION=0x%s\n", dev_scsi.wwn); + } +- if (dev_scsi.tgpt_group[0] != '\0') ++ if (scsi_string_is_valid(dev_scsi.tgpt_group)) + printf("ID_TARGET_PORT=%s\n", dev_scsi.tgpt_group); +- 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)) ++ if (scsi_string_is_valid(dev_scsi.unit_serial_number)) + printf("ID_SCSI_SERIAL=%s\n", dev_scsi.unit_serial_number); + goto out; + } diff --git a/systemd.spec b/systemd.spec index e39eff2..20c6a11 100644 --- a/systemd.spec +++ b/systemd.spec @@ -21,7 +21,7 @@ Name: systemd Url: https://systemd.io Version: 252 -Release: 68%{?dist} +Release: 69%{?dist} # For a breakdown of the licensing, see README License: LGPLv2+ and MIT and GPLv2+ Summary: System and Service Manager @@ -1412,6 +1412,12 @@ Patch1326: 1326-integritysetup-Add-support-for-hmac-sha512.patch Patch1327: 1327-integritysetup-Add-PHMAC-algorithm-to-list-of-known-.patch Patch1328: 1328-manager-fix-scope-for-environment-generators.patch Patch1329: 1329-core-validate-input-cgroup-path-more-prudently.patch +Patch1330: 1330-nspawn-apply-BindUser-Ephemeral-from-settings-file-o.patch +Patch1331: 1331-nspawn-normalize-pivot_root-paths.patch +Patch1332: 1332-core-service-do-not-propagate-reload-for-combined-RE.patch +Patch1333: 1333-udev-check-for-invalid-chars-in-various-fields-recei.patch +Patch1334: 1334-udev-fix-review-mixup.patch +Patch1335: 1335-udev-scsi-id-check-for-invalid-chars-in-various-fiel.patch # Downstream-only patches (9000–9999) @@ -2289,6 +2295,14 @@ systemd-hwdb update &>/dev/null || : %{_prefix}/lib/dracut/modules.d/70rhel-net-naming-sysattrs/* %changelog +* Thu Apr 16 2026 systemd maintenance team - 252-69 +- nspawn: apply BindUser/Ephemeral from settings file only if trusted (RHEL-163871) +- nspawn: normalize pivot_root paths (RHEL-163871) +- core/service: do not propagate reload for combined RELOADING=1 + READY=1 when notify-reload (RHEL-108575) +- udev: check for invalid chars in various fields received from the kernel (RHEL-163877) +- udev: fix review mixup (RHEL-163877) +- udev/scsi-id: check for invalid chars in various fields received from the kernel (RHEL-163877) + * Wed Apr 08 2026 systemd maintenance team - 252-68 - integritysetup: Add support for hmac-sha512 (RHEL-50213) - integritysetup: Add PHMAC algorithm to list of known algorithms (RHEL-50213)