diff --git a/SOURCES/0228-update-utmp-do-not-give-up-if-the-first-attempt-at-c.patch b/SOURCES/0228-update-utmp-do-not-give-up-if-the-first-attempt-at-c.patch
new file mode 100644
index 0000000000000000000000000000000000000000..8635997098733315117b3f6ad718489ec7ddf9e8
--- /dev/null
+++ b/SOURCES/0228-update-utmp-do-not-give-up-if-the-first-attempt-at-c.patch
@@ -0,0 +1,72 @@
+From 39c06ea84187cda78fdce843482765cdf52537b3 Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Wed, 18 Dec 2024 22:27:29 +0900
+Subject: [PATCH] update-utmp: do not give up if the first attempt at
+ connecting bus failed
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Otherwise, the program exits with failure if the first attempt in run() failed:
+```
+Dec 18 20:27:37 systemd-update-utmp[254]: Bus n/a: changing state UNSET → OPENING
+Dec 18 20:27:37 systemd-update-utmp[254]: sd-bus: starting bus by connecting to /run/systemd/private...
+Dec 18 20:27:37 systemd-update-utmp[254]: Bus n/a: changing state OPENING → CLOSED
+Dec 18 20:27:37 systemd-update-utmp[254]: Failed to get D-Bus connection: Connection refused
+```
+
+(cherry picked from commit 85d040dabd2cc67c89b7ed6157429b8f6f2240f4)
+---
+ src/update-utmp/update-utmp.c | 15 ++++++++++-----
+ 1 file changed, 10 insertions(+), 5 deletions(-)
+
+diff --git a/src/update-utmp/update-utmp.c b/src/update-utmp/update-utmp.c
+index e40843cf35..a10e6d478a 100644
+--- a/src/update-utmp/update-utmp.c
++++ b/src/update-utmp/update-utmp.c
+@@ -53,6 +53,12 @@ static int get_startup_monotonic_time(Context *c, usec_t *ret) {
+         assert(c);
+         assert(ret);
+ 
++        if (!c->bus) {
++                r = bus_connect_system_systemd(&c->bus);
++                if (r < 0)
++                        return log_warning_errno(r, "Failed to get D-Bus connection, ignoring: %m");
++        }
++
+         r = bus_get_property_trivial(
+                         c->bus,
+                         bus_systemd_mgr,
+@@ -94,10 +100,13 @@ static int get_current_runlevel(Context *c) {
+                                 UINT64_C(100) * USEC_PER_MSEC +
+                                 random_u64_range(UINT64_C(1900) * USEC_PER_MSEC * n_attempts / MAX_ATTEMPTS);
+                         (void) usleep_safe(usec);
++                }
+ 
++                if (!c->bus) {
+                         r = bus_connect_system_systemd(&c->bus);
+                         if (r == -ECONNREFUSED && n_attempts < 64) {
+-                                log_debug_errno(r, "Failed to reconnect to system bus, retrying after a slight delay: %m");
++                                log_debug_errno(r, "Failed to %s to system bus, retrying after a slight delay: %m",
++                                                n_attempts <= 1 ? "connect" : "reconnect");
+                                 continue;
+                         }
+                         if (r < 0)
+@@ -251,7 +260,6 @@ static int run(int argc, char *argv[]) {
+                 .audit_fd = -EBADF,
+ #endif
+         };
+-        int r;
+ 
+         log_setup();
+ 
+@@ -264,9 +272,6 @@ static int run(int argc, char *argv[]) {
+                 log_full_errno(IN_SET(errno, EAFNOSUPPORT, EPROTONOSUPPORT) ? LOG_DEBUG : LOG_WARNING,
+                                errno, "Failed to connect to audit log, ignoring: %m");
+ #endif
+-        r = bus_connect_system_systemd(&c.bus);
+-        if (r < 0)
+-                return log_error_errno(r, "Failed to get D-Bus connection: %m");
+ 
+         return dispatch_verb(argc, argv, verbs, &c);
+ }
diff --git a/SOURCES/0229-bootctl-fix-potential-uninitialized-memory-access.patch b/SOURCES/0229-bootctl-fix-potential-uninitialized-memory-access.patch
new file mode 100644
index 0000000000000000000000000000000000000000..e24e0a64ec15e57ae722ad1a5556825bab55022c
--- /dev/null
+++ b/SOURCES/0229-bootctl-fix-potential-uninitialized-memory-access.patch
@@ -0,0 +1,78 @@
+From d42ebb344d8692e0fd437ce38396d89d06017065 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Sun, 9 Feb 2025 09:53:39 +0100
+Subject: [PATCH] bootctl: fix potential uninitialized memory access
+
+And while we are at it, let' get rid of have_xyz_partition_uuid
+variables, to simplify things.
+
+(cherry picked from commit df28afe9b2de9e480121c25f222fa487fed927ce)
+---
+ src/bootctl/bootctl-status.c | 34 +++++++++++++++++-----------------
+ 1 file changed, 17 insertions(+), 17 deletions(-)
+
+diff --git a/src/bootctl/bootctl-status.c b/src/bootctl/bootctl-status.c
+index 6bcb348935..3b46632b92 100644
+--- a/src/bootctl/bootctl-status.c
++++ b/src/bootctl/bootctl-status.c
+@@ -476,10 +476,9 @@ int verb_status(int argc, char *argv[], void *userdata) {
+                         for (size_t i = 0; i < ELEMENTSOF(loader_flags); i++)
+                                 print_yes_no_line(i == 0, FLAGS_SET(loader_features, loader_flags[i].flag), loader_flags[i].name);
+ 
+-                        sd_id128_t loader_partition_uuid;
+-                        bool have_loader_partition_uuid = efi_loader_get_device_part_uuid(&loader_partition_uuid) >= 0;
+-
+-                        print_yes_no_line(false, have_loader_partition_uuid, "Boot loader set ESP information");
++                        sd_id128_t loader_partition_uuid = SD_ID128_NULL;
++                        (void) efi_loader_get_device_part_uuid(&loader_partition_uuid);
++                        print_yes_no_line(/* first= */ false, !sd_id128_is_null(loader_partition_uuid), "Boot loader set partition information");
+ 
+                         if (current_entry)
+                                 printf("Current Entry: %s\n", current_entry);
+@@ -488,14 +487,14 @@ int verb_status(int argc, char *argv[], void *userdata) {
+                         if (oneshot_entry && !streq_ptr(oneshot_entry, default_entry))
+                                 printf("OneShot Entry: %s\n", oneshot_entry);
+ 
+-                        if (have_loader_partition_uuid && !sd_id128_is_null(esp_uuid) && !sd_id128_equal(esp_uuid, loader_partition_uuid))
+-                                printf("WARNING: The boot loader reports a different partition UUID than the detected ESP ("SD_ID128_UUID_FORMAT_STR" vs. "SD_ID128_UUID_FORMAT_STR")!\n",
+-                                       SD_ID128_FORMAT_VAL(loader_partition_uuid), SD_ID128_FORMAT_VAL(esp_uuid));
++                        if (!sd_id128_is_null(loader_partition_uuid)) {
++                                if (!sd_id128_is_null(esp_uuid) && !sd_id128_equal(esp_uuid, loader_partition_uuid))
++                                        printf("WARNING: The boot loader reports a different partition UUID than the detected ESP ("SD_ID128_UUID_FORMAT_STR" vs. "SD_ID128_UUID_FORMAT_STR")!\n",
++                                               SD_ID128_FORMAT_VAL(loader_partition_uuid), SD_ID128_FORMAT_VAL(esp_uuid));
+ 
+-                        if (!sd_id128_is_null(loader_partition_uuid))
+                                 printf("    Partition: /dev/disk/by-partuuid/" SD_ID128_UUID_FORMAT_STR "\n",
+                                        SD_ID128_FORMAT_VAL(loader_partition_uuid));
+-                        else
++                        } else
+                                 printf("    Partition: n/a\n");
+                         printf("       Loader: %s%s\n", special_glyph(SPECIAL_GLYPH_TREE_RIGHT), strna(loader_path));
+                         printf("\n");
+@@ -507,17 +506,18 @@ int verb_status(int argc, char *argv[], void *userdata) {
+                         for (size_t i = 0; i < ELEMENTSOF(stub_flags); i++)
+                                 print_yes_no_line(i == 0, FLAGS_SET(stub_features, stub_flags[i].flag), stub_flags[i].name);
+ 
+-                        sd_id128_t stub_partition_uuid;
+-                        bool have_stub_partition_uuid = efi_stub_get_device_part_uuid(&stub_partition_uuid) >= 0;
++                        sd_id128_t stub_partition_uuid = SD_ID128_NULL;
++                        (void) efi_stub_get_device_part_uuid(&stub_partition_uuid);
++
++                        if (!sd_id128_is_null(stub_partition_uuid)) {
++                                if (!(!sd_id128_is_null(esp_uuid) && sd_id128_equal(esp_uuid, stub_partition_uuid)) &&
++                                    !(!sd_id128_is_null(xbootldr_uuid) && sd_id128_equal(xbootldr_uuid, stub_partition_uuid)))
++                                        printf("WARNING: The stub loader reports a different UUID than the detected ESP or XBOOTDLR partition ("SD_ID128_UUID_FORMAT_STR" vs. "SD_ID128_UUID_FORMAT_STR"/"SD_ID128_UUID_FORMAT_STR")!\n",
++                                               SD_ID128_FORMAT_VAL(stub_partition_uuid), SD_ID128_FORMAT_VAL(esp_uuid), SD_ID128_FORMAT_VAL(xbootldr_uuid));
+ 
+-                        if (have_stub_partition_uuid && (!(!sd_id128_is_null(esp_uuid) && sd_id128_equal(esp_uuid, stub_partition_uuid)) &&
+-                                                         !(!sd_id128_is_null(xbootldr_uuid) && sd_id128_equal(xbootldr_uuid, stub_partition_uuid))))
+-                                printf("WARNING: The stub loader reports a different UUID than the detected ESP or XBOOTDLR partition ("SD_ID128_UUID_FORMAT_STR" vs. "SD_ID128_UUID_FORMAT_STR"/"SD_ID128_UUID_FORMAT_STR")!\n",
+-                                       SD_ID128_FORMAT_VAL(stub_partition_uuid), SD_ID128_FORMAT_VAL(esp_uuid), SD_ID128_FORMAT_VAL(xbootldr_uuid));
+-                        if (!sd_id128_is_null(stub_partition_uuid))
+                                 printf("    Partition: /dev/disk/by-partuuid/" SD_ID128_UUID_FORMAT_STR "\n",
+                                        SD_ID128_FORMAT_VAL(stub_partition_uuid));
+-                        else
++                        } else
+                                 printf("    Partition: n/a\n");
+                         printf("         Stub: %s%s\n", special_glyph(SPECIAL_GLYPH_TREE_RIGHT), strna(stub_path));
+                         printf("\n");
diff --git a/SOURCES/0230-bootctl-also-shown-whether-stub-loader-partition-dat.patch b/SOURCES/0230-bootctl-also-shown-whether-stub-loader-partition-dat.patch
new file mode 100644
index 0000000000000000000000000000000000000000..f997b7c8d37a89dcb7fc8be7dbba225013665a4c
--- /dev/null
+++ b/SOURCES/0230-bootctl-also-shown-whether-stub-loader-partition-dat.patch
@@ -0,0 +1,27 @@
+From 6e8f67eac6a3c7b159559f21e2146fce608d483e Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Sun, 9 Feb 2025 23:21:08 +0100
+Subject: [PATCH] bootctl: also shown whether stub loader partition data was
+ passed
+
+Let's make the stub and loader output sections more alike, and say in
+both cases whether we recieved that data from the boot phase or not the
+same way.
+
+(cherry picked from commit 26bfd97216ab55664214d1e0fac7065e5573a36b)
+---
+ src/bootctl/bootctl-status.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/src/bootctl/bootctl-status.c b/src/bootctl/bootctl-status.c
+index 3b46632b92..9a4c233581 100644
+--- a/src/bootctl/bootctl-status.c
++++ b/src/bootctl/bootctl-status.c
+@@ -508,6 +508,7 @@ int verb_status(int argc, char *argv[], void *userdata) {
+ 
+                         sd_id128_t stub_partition_uuid = SD_ID128_NULL;
+                         (void) efi_stub_get_device_part_uuid(&stub_partition_uuid);
++                        print_yes_no_line(/* first= */ false, !sd_id128_is_null(stub_partition_uuid), "Stub loader set partition information");
+ 
+                         if (!sd_id128_is_null(stub_partition_uuid)) {
+                                 if (!(!sd_id128_is_null(esp_uuid) && sd_id128_equal(esp_uuid, stub_partition_uuid)) &&
diff --git a/SOURCES/0231-bootctl-suppress-output-of-empty-partition-info-if-w.patch b/SOURCES/0231-bootctl-suppress-output-of-empty-partition-info-if-w.patch
new file mode 100644
index 0000000000000000000000000000000000000000..bfb5df8793e4f4cb72a8e1515f8fcad3ccf17aa8
--- /dev/null
+++ b/SOURCES/0231-bootctl-suppress-output-of-empty-partition-info-if-w.patch
@@ -0,0 +1,53 @@
+From 5f631785cc2dc16bd85566f901cc474417fc0856 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Sun, 9 Feb 2025 23:23:38 +0100
+Subject: [PATCH] bootctl: suppress output of empty partition info if we also
+ have no idea about EFI binary path
+
+So far we'd output both the partition and the binary path always, even
+if we didn't know either (but in that case show empty information).
+Let's address this, and show partition info only if we know it, or if we
+know the EFI binary path, but suppress both if we know neither.
+
+Note that we'll show the partition info if we don't know it still if we
+know the EFI binary path used for boot, since it is relative to the
+partition of course, and hence it's really strange to know one but not
+the other, hence it deserves some mentioning in the output.
+
+(cherry picked from commit df418fa234a5b12e302a336df82c97f33871ae35)
+---
+ src/bootctl/bootctl-status.c | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/src/bootctl/bootctl-status.c b/src/bootctl/bootctl-status.c
+index 9a4c233581..25c9f66a22 100644
+--- a/src/bootctl/bootctl-status.c
++++ b/src/bootctl/bootctl-status.c
+@@ -494,9 +494,11 @@ int verb_status(int argc, char *argv[], void *userdata) {
+ 
+                                 printf("    Partition: /dev/disk/by-partuuid/" SD_ID128_UUID_FORMAT_STR "\n",
+                                        SD_ID128_FORMAT_VAL(loader_partition_uuid));
+-                        } else
++                        } else if (loader_path)
+                                 printf("    Partition: n/a\n");
+-                        printf("       Loader: %s%s\n", special_glyph(SPECIAL_GLYPH_TREE_RIGHT), strna(loader_path));
++
++                        if (loader_path)
++                                printf("       Loader: %s%s\n", special_glyph(SPECIAL_GLYPH_TREE_RIGHT), strna(loader_path));
+                         printf("\n");
+                 }
+ 
+@@ -518,9 +520,11 @@ int verb_status(int argc, char *argv[], void *userdata) {
+ 
+                                 printf("    Partition: /dev/disk/by-partuuid/" SD_ID128_UUID_FORMAT_STR "\n",
+                                        SD_ID128_FORMAT_VAL(stub_partition_uuid));
+-                        } else
++                        } else if (stub_path)
+                                 printf("    Partition: n/a\n");
+-                        printf("         Stub: %s%s\n", special_glyph(SPECIAL_GLYPH_TREE_RIGHT), strna(stub_path));
++
++                        if (stub_path)
++                                printf("         Stub: %s%s\n", special_glyph(SPECIAL_GLYPH_TREE_RIGHT), strna(stub_path));
+                         printf("\n");
+                 }
+ 
diff --git a/SOURCES/0232-bootctl-minor-reordering-of-fields-in-output.patch b/SOURCES/0232-bootctl-minor-reordering-of-fields-in-output.patch
new file mode 100644
index 0000000000000000000000000000000000000000..4b7b6f7ec038b69f2ab837092d92ef783227e161
--- /dev/null
+++ b/SOURCES/0232-bootctl-minor-reordering-of-fields-in-output.patch
@@ -0,0 +1,52 @@
+From 44260aa86bc3017d03046cac0cfe1e4d13a82e45 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Sun, 9 Feb 2025 23:34:29 +0100
+Subject: [PATCH] bootctl: minor reordering of fields in output
+
+Let's move the currently used/default/oneshot entry output after the
+basic info about the boot loader itself, since conceptually these are
+objects kinda "one level down" from the boot loader perspective. Hence,
+let's *first* show all info about the boot loader itself before we
+display the objects it manages.
+
+This is just a trivial change in output, just swaps th elines for these
+fields with the ones showing where the boot loader is installed.
+
+(cherry picked from commit af5b961ad8f22be04f47c1c0e729b1e6fd78b423)
+---
+ src/bootctl/bootctl-status.c | 15 ++++++++-------
+ 1 file changed, 8 insertions(+), 7 deletions(-)
+
+diff --git a/src/bootctl/bootctl-status.c b/src/bootctl/bootctl-status.c
+index 25c9f66a22..6f38b0f793 100644
+--- a/src/bootctl/bootctl-status.c
++++ b/src/bootctl/bootctl-status.c
+@@ -480,13 +480,6 @@ int verb_status(int argc, char *argv[], void *userdata) {
+                         (void) efi_loader_get_device_part_uuid(&loader_partition_uuid);
+                         print_yes_no_line(/* first= */ false, !sd_id128_is_null(loader_partition_uuid), "Boot loader set partition information");
+ 
+-                        if (current_entry)
+-                                printf("Current Entry: %s\n", current_entry);
+-                        if (default_entry)
+-                                printf("Default Entry: %s\n", default_entry);
+-                        if (oneshot_entry && !streq_ptr(oneshot_entry, default_entry))
+-                                printf("OneShot Entry: %s\n", oneshot_entry);
+-
+                         if (!sd_id128_is_null(loader_partition_uuid)) {
+                                 if (!sd_id128_is_null(esp_uuid) && !sd_id128_equal(esp_uuid, loader_partition_uuid))
+                                         printf("WARNING: The boot loader reports a different partition UUID than the detected ESP ("SD_ID128_UUID_FORMAT_STR" vs. "SD_ID128_UUID_FORMAT_STR")!\n",
+@@ -499,6 +492,14 @@ int verb_status(int argc, char *argv[], void *userdata) {
+ 
+                         if (loader_path)
+                                 printf("       Loader: %s%s\n", special_glyph(SPECIAL_GLYPH_TREE_RIGHT), strna(loader_path));
++
++                        if (current_entry)
++                                printf("Current Entry: %s\n", current_entry);
++                        if (default_entry)
++                                printf("Default Entry: %s\n", default_entry);
++                        if (oneshot_entry && !streq_ptr(oneshot_entry, default_entry))
++                                printf("OneShot Entry: %s\n", oneshot_entry);
++
+                         printf("\n");
+                 }
+ 
diff --git a/SOURCES/0233-missing_sched-add-CLONE_PIDFD.patch b/SOURCES/0233-missing_sched-add-CLONE_PIDFD.patch
new file mode 100644
index 0000000000000000000000000000000000000000..7422c1f657a27300ff263daf53a35ea4256cf8cd
--- /dev/null
+++ b/SOURCES/0233-missing_sched-add-CLONE_PIDFD.patch
@@ -0,0 +1,46 @@
+From 480e39dbbb3df253e02a4908dfcfecf1fb3511e2 Mon Sep 17 00:00:00 2001
+From: Michael Olbrich <m.olbrich@pengutronix.de>
+Date: Sun, 9 Feb 2025 13:32:36 +0100
+Subject: [PATCH] missing_sched: add CLONE_PIDFD
+
+CLONE_PIDFD was introduced in v5.2 and in sched.h in glibc-2.31 so
+without this, building with older version fails with:
+
+src/basic/raw-clone.h:41:108: error: 'CLONE_PIDFD' undeclared (first use in this function); did you mean 'CLONE_FILES'?
+
+(cherry picked from commit e91c5cf06ab7ca9e5576c6feac5f743927f2b063)
+---
+ src/basic/missing_sched.h | 7 +++++++
+ src/basic/raw-clone.h     | 1 +
+ 2 files changed, 8 insertions(+)
+
+diff --git a/src/basic/missing_sched.h b/src/basic/missing_sched.h
+index bbfc30cc8f..6e5e2b1e20 100644
+--- a/src/basic/missing_sched.h
++++ b/src/basic/missing_sched.h
+@@ -13,6 +13,13 @@
+ assert_cc(CLONE_NEWCGROUP == 0x02000000);
+ #endif
+ 
++/* b3e5838252665ee4cfa76b82bdf1198dca81e5be (5.2) */
++#ifndef CLONE_PIDFD
++#  define CLONE_PIDFD 0x00001000
++#else
++assert_cc(CLONE_PIDFD == 0x00001000);
++#endif
++
+ /* 769071ac9f20b6a447410c7eaa55d1a5233ef40c (5.8) */
+ #ifndef CLONE_NEWTIME
+ #  define CLONE_NEWTIME 0x00000080
+diff --git a/src/basic/raw-clone.h b/src/basic/raw-clone.h
+index 36202cc0ba..91b0069fb5 100644
+--- a/src/basic/raw-clone.h
++++ b/src/basic/raw-clone.h
+@@ -11,6 +11,7 @@
+ 
+ #include "log.h"
+ #include "macro.h"
++#include "missing_sched.h"
+ #include "process-util.h"
+ 
+ /**
diff --git a/SOURCES/0234-stub-Mention-that-VirtualSize-should-be-SizeOfRawDat.patch b/SOURCES/0234-stub-Mention-that-VirtualSize-should-be-SizeOfRawDat.patch
new file mode 100644
index 0000000000000000000000000000000000000000..eefebfa173119044ed382863e0653bfd05514491
--- /dev/null
+++ b/SOURCES/0234-stub-Mention-that-VirtualSize-should-be-SizeOfRawDat.patch
@@ -0,0 +1,30 @@
+From e8d5d7f355ae826f4f8c0f61f62c31e828bde7d0 Mon Sep 17 00:00:00 2001
+From: Daan De Meyer <daan.j.demeyer@gmail.com>
+Date: Tue, 4 Feb 2025 14:52:02 +0100
+Subject: [PATCH] stub: Mention that VirtualSize should be <= SizeOfRawData
+
+(cherry picked from commit 2443b4d9a17787fd0a63d6591fbdb74650c43994)
+---
+ man/systemd-stub.xml | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/man/systemd-stub.xml b/man/systemd-stub.xml
+index 902b4013a0..779867f4d6 100644
+--- a/man/systemd-stub.xml
++++ b/man/systemd-stub.xml
+@@ -376,6 +376,15 @@
+     core kernel, the embedded initrd and kernel command line (see above for a full list), including all UKI
+     profiles.</para>
+ 
++    <para>Also note that when <command>systemd-stub</command> measures a PE section, it will measure the
++    amount of bytes that the section takes up in memory (<varname>VirtualSize</varname>) and not the amount
++    of bytes that the section takes up on disk (<varname>SizeOfRawData</varname>). This means that if the
++    size in memory is larger than the size on disk, <command>systemd-stub</command> will end up measuring
++    extra zeroes. To avoid this from happening, it is recommended to make sure that the size in memory of
++    each section that is measured by <command>systemd-stub</command> is always smaller than or equal to the
++    size on disk. <command>ukify</command> automatically makes sure this is the case when building UKIs or
++    addons.</para>
++
+     <para>Also note that the Linux kernel will measure all initrds it receives into TPM PCR 9. This means
+     every type of initrd (of the selected UKI profile) will possibly be measured two or three times: the
+     initrds embedded in the kernel image will be measured to PCR 4, PCR 9 and PCR 11; the initrd synthesized
diff --git a/SOURCES/0235-import-pubring.gpg-add-openSUSE-build-key.patch b/SOURCES/0235-import-pubring.gpg-add-openSUSE-build-key.patch
new file mode 100644
index 0000000000000000000000000000000000000000..810b8b35329247f185ada13f15d5834d9fb772ea
--- /dev/null
+++ b/SOURCES/0235-import-pubring.gpg-add-openSUSE-build-key.patch
@@ -0,0 +1,42 @@
+From 131eff83701ed40468fb68fb0ed33108f215950e Mon Sep 17 00:00:00 2001
+From: Thorsten Kukuk <kukuk@suse.com>
+Date: Fri, 7 Feb 2025 14:36:06 +0100
+Subject: [PATCH] import-pubring.gpg: add openSUSE build key
+
+(cherry picked from commit c8c5ce5772b08da0ad317331b1f4929c1b466ae0)
+---
+ src/import/import-pubring.gpg | Bin 9551 -> 10746 bytes
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+
+diff --git a/src/import/import-pubring.gpg b/src/import/import-pubring.gpg
+index be27776896f30f580b03ad79d733483f81c8d117..57f9d04d8bc0c84e55f15c9c64203294c8b2584e 100644
+GIT binary patch
+delta 1188
+zcmV;V1Y7&hO8Qf<PbGhu0u2OWuzn%|5CGowvXMDvvE(8=+@&SU_E8Slf^H<Iy=TEI
+zS6%|!Rr;dSXH7cO-5x+Ar83tegx9*`P$7%-urk0)G{a(Y9{+XN4Gf=sAH$xXse#Sy
+zG-pF)gJIcKn43scSiTRfb}R1lcC`amc~e~lqWm1$tO8YQH;aF-*RGY~DU<p9__sw}
+zitSehuHTbU4f28@q10GPoEOL$FO)J7@N~5RLze;jw}64Rxsfa7Sfp~8yx;)!WC!y}
+zx~TK}BiZ!3No8@^t~$NRp)$~)G%|l~PGw+$nw?DbvE(VpTK?GG`PObi|GE^>xH*k~
+zF51yT!QQCJT)=-PjIlpDEqG8(yj}Axlu3jU<{`FI<sZ0j6gVQS5zXpLEC%zbPvs(#
+zp<yTDENZYSo_fS=J*PXeXSb{;VgFEA`Q`U`c6(3ii-KxT-0=5&?0hi|WBj2`>Z-m2
+zdUmFR*Z@H_<ODQ=K31Be&S}J##NIscj&JHjEe`IJsQ7;mNc*x>BX)Z~!9n2hv4q~^
+z1#yvNqC@ZKEII+awTe1{d+L}6*0Sz-BIARoI>K*?yl<yX3`Pqk_%9)Q;Cw(fO$BBm
+zK1fGo5n|+I5>bsf7AcX~8g6x8YbK`3KSdtQN?e<JW~jS}bJhaJqb=i0TR`O%O1njI
+ziDk5(@=bqSZr+(xrwd6L2CoQ{J4FBy0RRE83;+OUaAyGk000000JJo3aAj^&RZ~SE
+zP;zf-Wn*+8Q)y>zX>MmAOJ#W=Ja2GiZgX{WWk7FmWo~nIb7d}Xa%VoU3;+OUaAyJl
+z000000Eq%V1QP)Q04N0lVz7Q90viJb2?vDE00xr+4IF<pqWEqpw*aK1YY+g5G8SR5
+z@<BRACIH*V=4z#rZriL4$Yz5$@}%<-7n{tcv}Ao>ff7I5IBR?s3((G2IlcbdqBDC+
+zZjT~Rv#m{*jbd)pDhiCQcJu$HW;Oj<_wS4)Fi>s@@FR7ncwu=Pd%C+AXz1y|eD<qB
+zeL94-q-%eCI4wN9f3x4#T(PLpb}9%Yk5+{`>NFTNz^&eq{)VirzI#_BI8^vM-a2#w
+zIUqqE5R6GZ#6tSwH}R((|ExP-RG9j59DNfrly2hi>w_|wDL=x^xn+H#Qj^yNxi&mX
+z{cJz}!DqHFI87{|hz!=nVAAc;|71?bLkgg`D(rttOT(@n6YM9$*2iI#4Vf>A|6eKW
+z8ayMnzVT#Y`fusF&P5Sx2p?Oa#G>FNVM9!D#%9&Nn<(c~HPs?YNgA@KqFmUFcS@BO
+z4B7Q=G>u-Xpqc3LSA%6SqV-(ODaJ7E_Z^Wm_WEFv5W%kvZx>2GT6whENT64&SRPJr
+zCm(+=FTOB7@SDTE)HOd&N!(ZiKFL0zjt{3PDel*B0rs(pr5czZ0EII~ujNGH1?F6M
+zOAvhD!c^hx@el8TC3nG0PYGseMzO{3?~J{iD^fX}+VG=_kIF7t8GGN+OrIZPMc&6A
+zJ<}sBrlR+b4t9Hgas-zwg|aYK-FuMrcj*{rvLwKJnq^*0>aC&r7#20K1^@$RaAyFO
+C!7JPV
+
+delta 7
+OcmewreBNt=zbXI_)dPzF
+
diff --git a/SOURCES/0236-import-update-to-current-fedora-keyring.patch b/SOURCES/0236-import-update-to-current-fedora-keyring.patch
new file mode 100644
index 0000000000000000000000000000000000000000..265ad2b13b07896f8e28f18cd883b560cfb44f36
--- /dev/null
+++ b/SOURCES/0236-import-update-to-current-fedora-keyring.patch
@@ -0,0 +1,630 @@
+From d14161d4d08037f28070c9766ae1aebc32876064 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Fri, 7 Feb 2025 14:58:29 +0100
+Subject: [PATCH] import: update to current fedora keyring
+
+Add a bunch of more released keys. Kinda a follow-up for c8c5ce5772b08da0ad317331b1f4929c1b466ae0
+
+(cherry picked from commit 8135d37f81917f2a7f98a52bdae92eae5878946d)
+---
+ src/import/import-pubring.gpg | Bin 10746 -> 45015 bytes
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+
+diff --git a/src/import/import-pubring.gpg b/src/import/import-pubring.gpg
+index 57f9d04d8bc0c84e55f15c9c64203294c8b2584e..8c6d2ebea6014006d327964bed4cdbd78637789f 100644
+GIT binary patch
+delta 34116
+zcmbT;V|1l&mOuR1wr$(4Bo*7XZPp#5Do#Zet76+urDEH*&1e03x_heE%=CZeIq%L{
+z`<z$b^;!Gc_rA`v>cR$C^)oGy28IY>Iw{8hiUKmA)Bz#Vep!%v_WcRZS%vc;*MrHu
+z<gl_M_`P;q+r-U<+pz{y3_|d=$f~Uzv3Wn2<7caO57{wXzy9f`^EiUGD18YT-#b60
+zkso5GaE-45#M8I3D~uGS;qUOx3FD}zeyw=Ld0FAsJ7Cc=j7f`fPFNto-~u{%7e-2z
+zmCJ&!W3BP}PV(l{H9|^&(SlxP;jqbZoz<ZOXJ)GDn3=KpMuFlg@9w0IuG^Q_L^7C~
+zvFzM$p))cEtw+^x(@mP$n7lvu$Rtw}t;#&9vl>lI)%@Uz!9-Uj1G?=xENwuDU9S2y
+zcPpT75&RLyIyMUAw(}B!m=c=KWB8;k)L9x>Fr|@BwiwNBbwwpGVor>?(jYw4GBB;P
+z)?{4Jn|2nm*Yr2`LFq%Eq}&OKHx%Aa-x3Z9<4F&#;x%$vGTP>OtT&H<eI>sEi?~E(
+zSzS$@MfT^o-TBtT_Zi!S6C8X))|lHgIYQ(~Cj6blP5Lz7v@=9NHMdC@d5g@8Hw81>
+z094Q+!<>8Uu}jZoFY{udnThJm!1eKlo&#m)i%%bQj=s35NobZWG&Q|i=RJZ+r#Dif
+z#vsG0EgF#{bbg;xwE8DyFyc%IV*38s(BFtZ6B;HdtViyPJqZ`$ioRnuFb0}VlAgZz
+zRNgAxMw0sP?kO7r5#+&hKej&LI;W7{K0>`gP(eXJs}VpzES)StLH_otXO%QJb96B#
+zq2XYmB@wXr+Z#p>7Dgu*YkOlCZ;}7_#L30c#@y76$<f79=<h!O_8&hG38nyn4hjRp
+zgGCB~s{d5^s2M7BD6S6&P3`mr$kp{8g#`O6fnfN^knpfD&|pxQaIi4&U=Ubf;Gkec
+zpkUYmAaJlKe^vigEX|Mnp<fD%?>9E1F~?r<D?>X<_llaCt;{0#)oi&P=EKD$oTscm
+z)oIw4Ah#pt;3hVEAZ%I7d)PA$omM*VOyiu7ky+k`?NiUfh0-sePQ5vcBSavwe`<eR
+zN;%NnHD(<@f6CXJBRgeWuowThip!C1cx{&2#x+BI8A`Pt>9!h#;KDdqZqvL1VE}{@
+z5srCnUazXHt=JMJO+k9BUxf;~uix)e^U!`-Ugpdl3$i?gr;WV@gn6Cxnf_7-Y<$J1
+zTMqj?Pj7-%mlOcFYIl(^_Gfd=Ofx8s?vXJP$w%jA3f-f0DuBMP-SxuA4yvW3cX?rO
+z#1H<#WY*-o&^oCHA}?YcDW4k<AwB&O3$@;gAlvWz1(Pzmx9oVmNfZKhxiC}cnh&MB
+zvHzzXgG;jkC3B^TwaSkRREV#TpRzyf&h=RA!X~M6ihaX@<gh3H!_iJQ4u?;4-@{k?
+zO=lIj>4F)AucF_+7(ZWIcH#u-qRR<<aPnmmjG~aViddXD3@G?AM{X<dwO<c(*j;2N
+z9~8spS?q^%5|4KYfQAXC>a}@LT)s!@Bc>4dRMEF@LQyL14R_?0iXGw^wnRPD)arV2
+z7!X(~UJ9=Q$ZVj>38qL@zw#t;_Ox2ZkIe|7vL<T<cTv5Hg*VgYMm}m9zizVgYfy`B
+zUZ1e2Ay~h`|Kt-}WUqz-0k?Fr1o;avvuWeM081ozAII1+dr@+?1v4<_!@wBOHBKPs
+zdVFJVzXZ~6h%-ZzlNLM%PiG->59f$xINhle08<#Nh?P)N>(TPy+WYarO~qJdjkkS+
+zhQmrOq%q;u!EVyi8)J0h7@zApaKgipPX#MYoU;PAx=}?vdhOF7K6)-(6>B_Qo#+va
+ztfG<5v1+-o#bs_S;Vi;q4J^s2<ovAIZ*!l)wp;ip_De1d)M!r|zsMVZAQW~<F|oWI
+z0*`c(u_(V#mWWfX%C#s`A#>MVTY2A$c_jlVxD%z)R5&K-@=(q+2rhMCk_&^O&P8aF
+zXB6^#lzvgTS+(4@?_R-K$GViPOH_3hc;tMmd0VVot-;kCSGfE^v)_rP9+-dFI&>n=
+zUqCwt?OpqW3L-mH?Q!;IN%=14pbHJt5NLQFKX1A&bfb4!S#<eXN-25t3zl?MUfo5+
+zNA~=J&Z&c--&Hy+@CkRPY0pMz;fle;yKx~jG_wRnV!95;wbeSlx@30+{4viY`SUuD
+z#fw^H{IB$dbc#F<syDoR@7V(LtxTI_oz*u)vt5#?CMS$CDaW~2xV0_GhIL^RP{5xl
+z%&ox@3o|SCgR@BT8jxa93|nT-rE~r{nYqx16<Na41zBH*pGBjs*D$%GtI-wI+@u+z
+zFSoB-B|?Y98s;3i*7VHEx_xC;Wz#uUL;CLlWBmg#*1rG){?CF*+FdU;!uLV?lt>6o
+znoyV=W!g+Zg8h}i{|8|IDE>@}{9(_Lgv0+E&zuzqaB*UDj#_kxcbypnDNAu6s@N{0
+z7ccc#PKwU>U0TxfBag(H=ELu<B7+JHQ#e+onhDGo>W7~sX)V24{m-0V<qy~mNDjV}
+z1*cD{si97BRpR_&o9f3;+6W#Pw-4;Nrh#mc6&?2aqH{z?zU?XDC7!yJrney2%A}y5
+zZ^~@|$yAilX{VMc9#o9Eu=&r6;Wgu<<+5}!7mVss?s{+$#i{VR?zVJeB-2iFpJjSn
+z2ZO`f)B##2ZEc@<&{F{wLolfwo=0Xeh^<OoF`eip)b9naUa!V@2ceSvNZvx0?iYJ<
+zh4XTfk_!4bxEC*NO)zD1_+=RDGiRAqujLxRo?k(fS@6~v3%JJs?oE&7eX`k?V&reV
+zOWXbJ?Y=t0k{0%l&rS1<saUX|E{+CCU-R^?L-Gl^smmE2;!?$Px+jjmXQwZE90tQz
+zj%U*>CK64c5y2q9=RAH1M@PnUQclqF(GXHT5bWp<(?3oKvbj_C%Z}k*XKCII$$b<B
+z{K2(J0@b67AsiIyzsj=J;Un4Ki4$nq<9UdofyBd)_xOLQ7!3mNvR|qTaJ+}cv&NhO
+zv-XHj+HF_~k2kbg$I;8fYQX|c@O9vU4=iVu#)2EPZ(gtPxkJuBx;KvlIj2RrsG=tq
+zwiVbGc*ANd^+WqUjhQ9Ba@X`Xz<|FCW<DG|1&RVvRSh%cqOC_<k|ePwJdM+0;z!r2
+z`Vz2+!5*<FL|5r#;2tc4#ad%FrPY`1h8@!m&(UVO9c8Dw#m8$;o?`H@T(+Z>ZR8~>
+z+Dh$$nMyZFQgmBIcv7J+z%%wLFs~B<8Rm2?r98#B=;Izx+13dV00j~1mzAC-kZ`vz
+zP`ErG$Ie~h{6EZJFM<Ywm;_@)aNs}jDcAbvyClGQniPKQPB%6NFGyMs7YaT-2n;3G
+zvG-MN=;wb;+nduiVoJ!Yf{I#{KkK^huZe5p*1xUU6maSi{IXDcDccrZR?2uheH00`
+zxCBq?j2(A0rOJ|~37pVqC=lJ*;jxcY;ZZTl`@D+WkhSwUc@?;WeFMHxPB+}958Vn(
+zLh+L9qtBB-)5PZM2jTQpg1vw%MZ=N^(Qet4K+>o}9Y&Og99+4p!t4swmv*=*9+Mya
+zT*h6BO3r6D$MVbNNK<~4V$YMIHKHZn+V%ZrQO;=WEZ)y$2Y`<1Fy4yN&<*jE=@%L-
+zk_jVQeF*BGW)O@;S%qJ^xz((`K0I*Ak26(KiS67`W{L{!@!dNQaB#a-pt_`9J=cT>
+z(a0%A1$u5P+*_!u!^q>dmzcO(zT1!rY_bOJoeS+u#mdvbS2ukRgkXNu)=wUrqtDAr
+zHXUdX{`GFo5B$DW@t1@bDB`W_>x>&w;3uU0_kywgAsE~LuNJKOHVH!OJ_}W8aNukR
+zD3``UF?bS(1p6z2{|~{2{$AXihWz0h0fUFaCzl>l+MpOvrjo%`O(u9NXR)gnRgFR~
+z19u^RRWg$-!S&|$6`z#bj9Uib{DoiN^TsG|0nG?5MYp(^2VXwRNeoDw<+lv}ve}fS
+zl7PMONt6h&V<~0le7}^G5R#0Yr+AZy?%E$3dHXFvjhkF&B%L;=8AE>~Vv_jvb|pS!
+zi9{DJ?m&bj*Ia0zOz9)fH7<auJZ?P>-O|w{zeq-TH~u9l2}3KV&SKc_Go8w_dKwvf
+zOT%b!n^O<miT77Z#2tXxmEaz3>+uv689o135{=QX)Y8gBLy8HymyP2QCZff8c3=5K
+znwHPnJue~QY%8`7Yb6Z*;Z#T^oIda%A9!K9S00ecG2p=A4%n*zc1F9&&y+$)_r4+A
+zOZ5$5od{hDZo0E`dr#W5LVUzuJQ^~m_{7|irb@#NJ6jH1dolpp&Vay3CKD9IwfY|C
+z5s{=uAZ*=I4hM|8*SX+}a0v*HtR0n@nzr5h8-Y7_BGta0V-QxrxLQvW1gRvfzv*u<
+zMc%<3ag>u_4~*kgbWGSEha=)4!BJzebu)}m8jE!`j}!vih7m{H^jm6B{T^I5>eo+s
+zj87@sU849(RK9@kb+K&0jOZD)QruGT)ee!K!9Ms6^wE~w&5*>lL9|y1<xnr){-P0s
+zo|`HuNlrr_6mmtV+{#FWQ3mp#Eto~)>I5hXNb~6`924{A60_8DmUM&U?-|DZC3^qy
+z5;T;h)V`1SCzC3xw`p2ZC2Tjc;~!yq*?<5Dn_8R(Est?+?igX@c5iC%af8Jr-laM_
+ziZbLL_cKaiPkme+J!V!H=71cT`wL9ev`#yf6SSn2dAmN$4GPO4%5S!X&28c45=B++
+z+EmudL9UNRZNnsral8dBUoW!HJemC)HFi|bDxte6iiH%Sy0tc5v*(}QWS+Pc%mJu2
+z2!nugtS*1rmj|%-jn$MJByBqQE7G)AZPfJnSTAKa=<TH|iv~@4x28d|?<7ajfi|hu
+zLRjI&CH|vAk~(EAxRirAjbR2Spj{v`(af7qDu?F@hHL|n>jQ+%iIQvLTVTUSA`PBB
+z2)7_Tb7*Sf<$IYBTpaF`a17Tk?|`jyEMSczqy08xFDAE{-XP}o<|gKbTLs~f@|z##
+zrM`$(5!O4UJy%0hx9Se}rcpih5W}M7y69QOj@!vRyk+g%k3BdJpHz2S5#ha)3(Pc<
+zhj*g`JBf)A7BlIXPYZC$r{n5+>!xaM3a()yyAuMkWIUJRVO*90y;DD`VgSJK6l$j{
+z1U@#>AW`8IgC6Z_lNv>TIE0U;`UJJK=yjL2p9t!UC9^Cn7Si{E8&He)_(F`z$gQq)
+z+ol+wxlU`Jc^OjC`Tp+UPpQw)b|-Zu+W#If_CEk)X9WKDhe(yb9U=v=NFfFfE(0e5
+zwpb-C9U_9#jVxHr)L9|H{z~9K0Rtxk1O3-?B=q0Uk^lID4FvKV78cN#dW-vVkz@@n
+z$}^(|`>Ub0Qlt@K!R2aiZGK*!<jB)DPxEo;ace7hQ5|F<q1)?QAv|Lp&Gk8-68Y#S
+zkQDi~?q7>PO@O3}AcmC70?67p<auJL)Gb}_gzxu_=X_kPcqQ)oXoH!&oEFqNjq;Bc
+zXRxxI&vmMhC(8kQsEvSzA0QR0jv_3KS@)A`%F3pfNCn5$MFA&owgo<m>E?T|jpEgc
+zb+W<q1}4!i)ODFvw&EA`8PM%xG?BHYBZFuMPB%xqI;X%|U(NiNuOX{lG%E8%?9oRu
+z*z_|Q+c6_?x0fzIJJ_+zAw!s3z`1F2=h-n&p*FYJk8TtpBCY^;93ysp1t0(Y?-KMw
+ztqh)QQd_v`XriF^3DOYce66upEI%?rSnXdumJ7E8)76<*6%@B5O25;lxm5N(A2bVZ
+z8;dM}^sxhid-oIs$6DAy+IQ5!mG~J7aAFs?^9N}@9W<ehZp==<b_y>8j*SAgI-e3R
+zuJC7_`*9alWs-mv8R6^1=ncI%WFv&-_j$WGEp;sT<ouI3D7C$Zwii2`)AzB-0OTGe
+z4mlO~Uq8!Ni|Ra>A7&zRa+v)P&~^w5X$>uA`tup#c`bbMw|iHk<B%0@Ly*o3*uko0
+z28~E^-&q_~y`{Ryz6@<s%9PVTqML&G?gR-p2`G%jYeoS`H-9Ro>rig_R~t5iV)dZz
+zku4hnZ@YD}S`9~0+aZPc3ITm7X$`9@ce<KS2lmsxkq6(+joqtk0dv1Y<bqy7aN{{9
+zLT4u-&2h|G6)$n-n_Nk;6{~BCTONkU?D!M&83>vBAs^`EMz*l)x0ow`SP(>cz!aqb
+z)Lup^6_VP`v{h!Kgmk_Uqrvm5z!%hOnuL%ny8eCCW9Upm>$?-kM_l*(@>QmiLNp=)
+z&Bpw1v#6zVa-;)&ax|jEAmOo7*^U1A(+4jid0BS#nYG}N315DKb?cEQLtf5~_2na&
+zRJr`X4K3}SY2qj|e999T-_(Z;2O@+ar7OxIstF%p99XYm>F#3Rh9)MszcKO$B=ef!
+zRN9o3Oh*&nJwnGhc&?y)pO2yfq5DCCuEci4tdDXAZ5+wA{o}0+-HiSD^N;ms%F~Mz
+z!8~kKaj>u<gbbrR6xzXnmwW-muE8hvU*=!JDQzODs6Zb@8d0(Kem-}|Jpr;oTUai(
+zJNBB~^M0jLd`Rn_kXpGG8iSL9Toca;-+!oVP{Zr)`P6U{Nus({YrMmpeho~`xMMTZ
+z`QoG<EGn%s^?cG(lr+;g<#8abWP4)|xkrY^>h1*Vw19S1-Am%fw1M1NzK~%8i2&b(
+zqz1D;s#2Obr_E43Gi*&Om<ar|Yqwqu%$we@A~j!9`_;XlwKH(<*4NYVZxv(zV-m*x
+zf0=~wK%j$yfsjFh{gpH@eB?wmFhbx$0F`)RP`hRJ0QtlHLTqH+FHv12G!<v&0m>^d
+z@~C$@NwDgO&QI5#Iq-)?M)2&3;<C0wet7w`Y-HxrFXf|`k(w%(!(++C?#ORppF)tD
+z9<APd32*t-19e3c1b{9DY|O~>p^g_X;;}=2<v{V`UE<M*5iPy!%rXu>cK{IHmHVV&
+z`+PH1eBS-pcA0yX<jLE2A!{wvwHG&XkY%>GpXx|*43<mpf?_1VyV6o#;6NfzyT0m*
+zZunbv<|lfE-P@iyOpgK{0HwbBdyvMZKlf0<xt3(5Njk2ELm7^?8rz(4BsOJhs8RhB
+zHY`7pE8a}@x7aoAQ|V`_14n@V`kmHS%&}@nOUxt>`8Sirl7zI%e(~BSEjmDPF>!cR
+zfTZB8WVy#Fi`?29s5;0OFM_!zX5V>=@9B^mpn$}n?;h)5N60)r<a$(-{ZuIRYqE{_
+zDX}=9O&cW~7HKKS@@^aE&;>c(u`xZ-ooaxM61v&BO&dL#bd5t~Y6)n2;RBVpOo`iT
+zPG}-^Kwx=KS5Ie05Uz>fNKxjiwXC-G#?;L7Tn-;IShl3blCfxmN6~^-@gtx*8%Z>+
+z7fN9bv1Mu3Y=vJqLP8X{dS9H*ANztv!ksUhXBt%ZK!Z45Fj9OLKl<e%Fbn>5=pzmJ
+z%}%!Di~AL8$9$yQff0Z~d$gUoDcH{Y*!D8%GaB`$NP0GF;GifVvmutfes3l*G$c@a
+zx}Tp#5h<hK-RA8t+kdWagr?zC(z^PaBlz=^#l8NNX-;t3(G<=Z`<-QbzDQ51sa~Ew
+zMV1FCen!>u>`zQRPs85zO7Bus7dIBg$Ej<~58Njgks4B^KG#L0)dZFTi=e*^@yk*C
+zx`z6z>DBoJMO8gU?OG6O&;*~XzD04db$+$sz+fW1pb5sPDGb+D73z#7*yzNtg67PO
+z3R(NO%J*EONT^m|wMJs(i&^j=M^=wgRD{}HiQ6nTH5qV}uD14HLU&q;y#`UdZ5I>a
+z284Vy146UCgMAA0n!ch`nLZj;H#?4(i?BkC5Wr(jDG|Pkd<nulo9(wjV{<ZjW+jar
+z$;{toEKsdIuUj^yFy4Hs+yY&NA6wz#^W%uAlk@3G(~T{algm~ZWP!lzTBw8cdTzBz
+zGz`b^=vA}1wx#xMs}Q6N!8XCG7aYAG0cP47>3|r$OR%-+1fZr};S~{d`TFhzN+z}G
+z>Sseb1&(@pcXBUie4VF%hf_P7_}=JTxB$vUgGW<k{=gwe{>D9T(&tq=c4Q0FE=PEx
+zy{;HH=*E5yf4Mkg-0=P>%y@e@98-RO1lI8k2~0+X5A*)a8>S1A&lW@QG7%ffRwHg$
+zXj>>7o3BBLhVx<??ZXF`>nqjK(Se*UP~h)s`=7*Xqpy?t{=G<ljJDYSHro2HldZ%o
+zYJx;%FaiJ)OwVRl9ugL90{QK)*}BpQFT4P|c0X<~@`oFV9*CbNN?AN&O4s2c70SK*
+z4|moT&F@wudqMB9QU~{E*?R3-Jc_)ZENY=<OYrKBhxatnj2>HP$%NVjRr;Xe)a}T`
+zuA>dd7d+V7lS)?34=R#1Flowzgd!adzU15vzXRSGfbQ#e_fj1U+ukFua)HfM=6(Yw
+z_1E~wHI1lfa47i-D>biv>e)T6`xDC*H?5}#V&~dVFF6YdD;o)ZJbT$xXWw<`s^&m4
+zqa8X?6yvP(cfLm^q)a?^72t->S%3Dpoj87d@jCLCL3)0+l=icygh=$;a9S{Jma-?n
+zO8`dHkp*B1aQ&4IKr`FweV=VVK=HE4^MiIGN^*7(>6OUZs>+k<7Jm|8e}z$*SWRuV
+zhj6#`wfQ{!S=?>2EGsr>fzgsxo`~|w=|%yIMBt6&MG#x$M|ZrIiA?(t>}C_aa;yv`
+zBL{+tTvw^K6-x&~fWR`c=1po^Y_%#TH4Q*zjcU5f++`k~6J?hHjO&cEb2y|iEc3Y}
+z-+~u@eGK2idA&Ufj=U7FK?L)K{>;7Pa*TwFksxX8;!Vi)6g}zCz|vIDeL+0v>oGU%
+z#za;e7cnT*apnE0!fD|Doh!5L$=ef`@#?IjPE?-%uJclT(_uNnB~^mvg~-mB0Sgej
+ziakhGB1%0*GU8L-+oKXPOUEoPX1uk-^bR6u<9GcNAbn+xGEfwdc^16XuB(Qs;LBn1
+zN!UkTe`iU3eF@mi`{JRFfCls~rIhnVHsT=a*tNsRiNYprlxcCWxL}1IXm&p7Ry|$_
+zAL*!aZ)&P|+1~nLU=yP8su6MtXM}wh_H8N!p>MJJjWMq6a3J^O&TOh|LgW!PhI0T!
+zBp5c>#aRyo&kv_jWpq~Q(~#;Hx#5F>Cd*h)ZQ)}~5&r&0b)kDj%xTk_<t_in>G(Q_
+z0zRaQZcRRtS|6BiiXvzCObua*>Pir}m~=KzZjHq7!}}^B07TkGcP5CFT!*=ry@pZf
+z#wDVGL6^&dl041V>F(m$tOz#GpxR{avfGk5jua2P6IrGJ5d96TkSFx4Ymwd&_n)Bo
+zEpx~MQ*m68u89<?>7^p7!i#TDDRGba;#VYA5&q)8YbziXq0?z_J1=nI)rM8co`ONY
+zQ*AK&G_&mz0NkG%s}AfLIE)^gLd&);Mbx7Rp~6(Juo*Jt6@@FuQnx}~AwsFIk0N%!
+z3Nxjk9>?KpYiT64R^FQuINR2Ze0f|m7rH;!o11~Vfw*hy$s8Gc2(_zivK=+&qL*a$
+zzqKO=A=a)4^p%%wIyPB}Azq)+Nx-!p;k2ag%?xXH0z5034Ocm9isnJoBon2Wi3U@O
+zQgip)&-BrDxS4ju@3r!7a5m5)CLNda3?9rek-;pTALj|O{~n+}CR6PHelmssx5tbB
+zd^-5gp6IWrB`SlF0CwnL_GrJwC!0i&U*X)q83Dc*e!KdU7bGE{l~utvQ=<htVzy~g
+zDv3$il}VeuHs@X=3fo$3@g#}<7bK0JJ~R-fvWkZ=xRI_>z2e{!a5FqAoS)_CS<6$-
+zg+3Q{w#cKe=zY!)l1$Hky*E;>c>78{@TxZJ$3wb>>^?|A127f!^l!UXluZ%^b!hU9
+za<W$*W)<#mhmFM^x(Edq3b**rA$>S+;;5Q%2KOGCyZVrDgFq@zch};4awsh_>XB1l
+zMI&ueklV8)?84zxUG*mS%a5yPd8T$W{A$p_6BNF2+jdTJ^BMiaUTpA}^Tp;IVNtby
+zjo%prjMFAr7J!Jh2g-NeQ7Ncrq09Vq#P+?Ik4?Bgy2hX}Nie^4g`DwZY(ScAM&IZF
+zamBSl&AaGpWm_5Mtlbj<sD{LTV@cPyVh(f8wBN=t$6)%8?g1sy@+Nf6PkqcBjTNbg
+z<$M9<;!7d-mHF&fXc|!A*BB+2mhf%-{_ma0=JAEQ^uVl-rb2{Z<NO8v_|`ttIAJXU
+zEcLPxqacA2JW^pDGP#&FPVnRsY3oqsNa}ew#;Got+zW|0<1|78JNwKK{sHt}4zh|6
+zDda+R@|JLR=F{3fpHI1GDLDHhJq^K0SSV4>e5UJ4T})mfUrU)=h$pn*t29k=(n8CZ
+z^BSQ%eIV6BnTzwxmCW3pd=4Sf>erth8L&XTfTDm*ruC$&OZG{~V1sZNNSel={Hk^H
+zBCXHqXu%gWT9!0U0DWrCva`TVds4Ec-ueKg<u~slO&Kh39oaGWm2R&p9=hbx75?IW
+z3b*jch)2v(h2ps|79Um?IH7zBpt8T)Vbcu7i|Tzr=A|k&uU&>~jt~@1Wys#ul!j5@
+z@Y^dUG10Wz=2R4P)XA%6WKx}4*#9=iqmaE&ou7tx<Cn)|JXunTr7(i}<Brv%EQ~S9
+zcDy_oA5wHsoc5)q5#+W?p4pJ6AeZJ~J%^XlK|)tyU_L%}tHv9c_JmCaCWj7Zq)n;P
+zZughg0+liAtau{1SDZ}k^2cS6*ml<ReGfa4hWndPd}<RPHHICkz<-lzF1L(>ckU`V
+z5Zt0>zjio4iJ)ICe`Zqn4#XLz(>bfiWlEdf4czu+Bg&Pb*R%ERfw;!6X07Hrnlbi$
+zYo?%{M-lJ2cRW)|h7wHyWK6P)#74+bAOrCoA9=o1^dU%08_{*Buc`}GWPUM&UW~v~
+zqEOxG>R|qLJctI-KBM#?kRfU=%C;HKV;=UE3$5eV%#_$(1_^%h(eC<3iHvqiZ9n}_
+zh9(o)P77=sbSJE2pK$I^coP!(-d=23Mv3@g?s(tc_hg#wP>l*`0Yc@kkC5BHwSLTq
+z?<EdeKKLx~TxQ#u?4V0)Owiq#DYC^MO<&fs|9g-A7&Ni7{~sphJP`1IKcoE>wZC~J
+z{pKm1<n+Os)`<LJR!R1_{^0o{GRC?ou<T!TZx+9JOGoF|^nh+|^jiC&mnM9jl3R&r
+zOcL<WAuGMU*A@8@p4?9d8a|M6)^JnD=N_d_k@$tfh5f<sb;ea*6!UafWY@gm8W|aF
+zwylLg9rA6J>8^6Wsy)UgL^l3d4q6gWABn((4%Aci!)KKK>RSf_&{I;IDet>EA8Oc%
+z+uVp~urC-}uj}hxyyLwQ=O{S}8#sQ0(I_cCxzY!{IuTlV`AjY?aHzx-ZD2Cpx{#8D
+zl+#?upEW5mxkUV&d}|Bcqaw6IoxwC>tu%f7C@F?lumt;+)fmrw8U(?P?WO@B`?$pB
+zsQ=L`ZhvNTZB?&987S5|<-L%EFqJ@T8}w@i)nhX9E>onBCYYy}s)KYiJ85o>ET3Dg
+zpD+y#VyE>}mCX|9MfKvW>XM{*C@H*<{{p!!%Me5@Yj=9fC-@moM@pWS-#f)THE$YJ
+zp@f`VQ<GRhr_MX`v~xO)w5Q*I=#yMzd^QCcw&CZyPHO2@0ag+QO5ZJ1VA{>wUu~_@
+zs<`0!2J4WC@I&Pu3T7?6$ixtmQnooBy_Mo-CUO8<8)(;03wa3px)35p(b1H#n|CE>
+zpxY~}8@&dDp>PEW0XEFpWaIMF@op@ohH@t9hBOM@i#Nr*RiK%6A{!il5XmW-*mbW;
+z(g6i2Y8_wv(<4I$&;(EvkYSVS&5w9}Mo-Kt5=hT_fzn!=6*ph+b~Q!a=1XpY!8T%}
+zWE-nr)V8lqJMFmK)CF5vsYQI*KfI<+0XA{qE(Co0ok1%DDOjy@d~GXaUjvGo-4ope
+zUXewC99R}EEW4;bPQG2&AUhFoDaZt0Yv>w89`E>oWXr+J>2M$~V?l1JUM5lvdH3X(
+z4Yo%c!Z>-a{ycS(x17EG^BT1|{TCx!VoUv(AxDlK`V#Ugx#L_>#Qm8{#~>&>%wgd^
+z(+>|O_};*;NpEaVm<n{AtAWSdepI4Fw!(vF(m=2{k#rebNLxV<w_EDDAABU9l(lEY
+z9A}d52L>&P2h}~}Y~#|<r}mXwBvL<{4ujlv*+6o8<qmOIO;mD8-3f8yQOhx;90)p&
+zC-_XYRYT2hu||cCaM*C>12PWxP9zm`469()Iy%G<6>i_nU-%75Kr32}^*r2t3!P&&
+zrhuWG7LQ0uzeC+-LlSC#F`?Mq=EH$<=Q@5EGA7N8N8>@(YhmY4l?ThkYmU4)zSNCZ
+z2#I5pOk(*Ek^LrIDxk$j?`q8=h6%`D&BcV0T(zU%EXhtZu?^!g$n>@Pr?tmEFQF#t
+zs<14_<krOpS>Z3;55>9l1?QD^6PeMJr2%3@h@T9|6}fy;c*J#+HoQcKEO73{HDt+!
+ztVn$XL#1SdDCc8kod3N?9RE4^X6N`nc%%RU{9}76O7~|P{0h}pHXU97s&S>Yg!2zx
+zNU*;W_|L)jzYe|su{`yUV)bU^4>4De8Cw^Ra$5G*N9`=6PIVhh<E?BTa4U>zsHf-8
+zI$)Cn=~Z2p8A=E1%PR44v+kY1<q+Jyl_3TGh*U4Vcfas&aK3m*jgAQ`t#yAD%%a(M
+zJWph(L6S~pM%f2{tXeq8ay-<M>3K&4W*b5JNz2M7gYS~t>42Px=ssvlU#)X)QJ4RH
+zq<4!fBg&q%;R;Q<f6Z6@wghSf`@Er0X#bK5V|YuH>2Gg!K7DO!uYn{0j8Bb_=~P4}
+ziM$BeURZjOVI)x*1^W2sbTi2QVQRx{@6U`bmMr-KR$>CM)YJjSUkBzM6}L5AT*61L
+z?Ba?SKCT1TG$;BC;7+>8<rM2RF{Og<ze>_lLwIB(pnPwfGztvryKP`JxZe-NNxyd=
+zKynSO$b}%z9$;WU?KwpT%!i2TUO847HyEH+=Kx5Gf)0v=dUHf)gfL0Q@ekr2ln{Gu
+z0;8Onj(o5F!MV^f=ay%%)EDT*i3fB%T`U3CHf#Z}?~COmM(A|YV<iijDYe~F*Bu*z
+z*oaHh@z<e~J~Q`Ct|SExJD5KjB&5pTTkzfwYRcAXP*9lfIbsZe@)!<0*W2~oOk!x#
+z#p9{4IeQFkZnr8{jjvO<<nPU|_yX%SxlxI-CFVm7S?a}2_40P-gSQflH~hH(efIaf
+zZG*9bAP0NX<EUq_oOkmY=05>5B9I;iMFANB2BG6me;*Z@vqte-8Ap6iE^O*GT_NsS
+ztO9aLubKL7tu=(!8F9c>JM*oDtkr}pFnT?IelGGRURAIu75n5OHl(>6g551QE8QW+
+z(VY!rMPb;_HI_zC+Fgb%&edC+o>Z0@s+gx<(v9@H;VO`>rc*@q%UXlX=o%EE4zlu-
+zSFFDwDh<xejPD%8ft<`B_ibZPb{_5Q$q{fFNb?#Vq8@FNN*)WES8o^p(DKLwcTiBb
+zJKY1B=tXwblJLwkaL99A-QG_;(9EeP%-oU**C@Qo;a_8O#`>e1>DI;CM|ND0z<jvO
+z^mochu2vQ{os$LpWbe`e`^2V{Y!{{4iK&7|ss#EeHU32;0fE|p-*3t+(XOdG9#8<Q
+zWhU@pP>`absj0mP*&uklIY+(Pt!hRB$_OFW=d|;t3F9r0l)Z&pS|$Hz8#kCHieHX$
+zE-+ZUh$#h@;TE|vS&B24>#@#n-{R)>)CPUPfh#(%MVmP~G$re%0y|er*HxuN_He@@
+z;<Q{=`|^I)a-SKy-@0NhpptckN*;(TL<<<;ajpSjfI@AUY^zzah=P{lB2Qdpod#Tr
+z4`+T6RI+HcGH6sXnY7Jd7Y!%A-PUp05|Y8bzW<c@*3Xpm(sq8FtNY5h)Moj05w*5>
+ztA8ZlSOM2D!mQqqlvZ)Uu#>A4?TP+>01Wt#^-p%rKLq3aKMD2^z`VZvtVI2MzGo*=
+zhp-~a>zryi5DN+RR|5YXU;rE}%0H^3jgVg;zZ#`b1egbI#ggTI96XOc%yrb<Ps%jK
+z#f)R1yJa-IL&{sU-gcJoC#;#AKzldg9oZKYh*RX9rN@KM*VO63p)b(+8^ywdaLd7v
+z*G9pd=9&wfg)+fktYq=ccoTjT-^?DmY&&xF+b2&-|K8~U^n>?RH!`*8gN!2}9kW@g
+z<<(oHZ5F_5Y$T#qczqp2!=bs!uUov*|IMf17F3vXV+uIfhm0}J+_;Azc9?ex!6d&L
+zk>zCt>$~blSyY6iQN(3;ale0`ZEeGWjwSv*L#w^moQ~HS27(ZCCs79ay;^Dv!iD3t
+zTcl`EJh+Vx_^Au&$bor|66(i$w#Y`w>6hqNv)=c!$9Z=m#lw|alsUYTV}eF-U#CUH
+z!x=qv9`l;ZtkCMy@Yu)0LQI%EJ(FL3)GCF|!AGPbl561wo79MSuhE{OIz5?#wykTA
+z_YTXthPaXq{Wsh^Q-m+`GsK21zw0$#5icMcYb5L|fHS$V=+X6fD)Gp?vD>a+PH_>R
+z)gW)GxDY2PQ4IAHtxzIE;y`~!P9}(q`cB28$ufa88bgs0%(*PD{T|Xhtte^fAxY+a
+zRP>7a2FWGe*((42e*H`T+d=)tBDz#7!csYtdOye4_*B$zb;%AglnjQtc!X9|`BI_O
+z<b$cM5a1fyqPEznVwjN`_{OFrk82;*{V#%1(8GYDfOL|Al@?t}&8aX;;ALdufegx>
+zn)*1CGRi(Okyu*|vA!8VU>tWXeD#d_T;s^0)^(OLreSW{b(%E%19TjT@}w(pA0fE-
+zDARc0&{Q4OlZ;5HI(JHs%%}(WC7to>Sgz#PH)@n1=-^iDWc$atMJ=i>g8CRjgx$-)
+z{rTvLXxY@8AIh*rf}Sularwe&<#ZgPyzRWOYsJ><^@Z%l8JO{aqk!x{bN3f=j*u9$
+zMpfSTaMe`UzEzAnEGt`K3bPxLN)=O!KEE|aYz78v+d_=Ma907=aV=XwPs^6u;YK8h
+zi^+PVC?_DMgZ0BKiT?*wnthXsph_R*bPp}25n+=mNCoVJ{s0=K;Hru8Uekweyc~D+
+z+%Z0^+ED7d^zR?y1L&)yh&27K;@u_~Oz_GF<2T4S>APNXZ<%;Sw%;*YW9ANPdHfSq
+zWpqM^BD#1hmh!Y>hE7O<{<QBKjGwI*pnd8ZGBjoyvQFRF0z+f1uqx5F!PJM;Yd3rV
+z3IT;ib<+Z8iV4U;w};lxQ8G8E<8~6ZRy(+?<wPX06)aoT>h0QX)?nZo+21FMeJMGy
+ziEWC<gxsUT`HyH<$JH8cIA#j;IDZ-D*mQ3j)ZGtI6O`eMZcj)8*98+eDQm*+?Y_!5
+zlsf{4NYx3hF{1Y98Z9{*MjH#g4^vC-4Yw6C0S*6yV1EaU>kq)V{`Y_Ze=M-8u1}97
+zFn){9GJV5I%l7NyDRaJs1p6z2|4uMCSd@PhhuNZld}q;Ui53g@V5sd0X(@_n$=yd1
+z6ev=}QUX;IKzAb%uK#JK6w3fP-j>}r=n?z`eD0+dYD`+Fy0vGsq<pd)30LOc;;=#U
+zB1gz<6Txesrpa6<w6Jmc7Md!3)!|T`J8{aFdk$o=^52WWogEJMa-P#PSomvYITl^&
+zjAR5fC=_yq2Bv1WLNWr&R$MW7*cFe$>ZhIWOhv{C6zo9+Mhsza%(l@Jh-|Q6Bka3?
+zK)T(Ctq$~_zVe_;l#bq95f%Ih>WAYrnt@QkiJU5DC-0{?tfn%<4+Qvx<4#+<h#NL>
+zmY6=DbxO|bTrr}sz(e|3M$l<g@wXzdPuDo*8Jhg?4vPkq?zo|)3(QKFd@^!e+D&2E
+zq62_ndXub!Dq76)q|gLdLL5Xt1QrH>YhNw&V1ZiXr?}v5<GT^PzksB%?8y7x#4dc6
+z)pQ_4@RX_m6{&DR45AO2%d*xiXnQN5Y-@wK7GNUqabVyjZ3TSbfdUc){FqIAN0+&m
+z94Bmjo9Q%N{J@brX;z{H9qMi7=*&t=GbWZ&dQ~X>zQ1+&34}#{F57AOXd|HA@ol!;
+z7rdoplsV~sZx}iJ_;{H0H|0L1tgRd<i2E1gp2>z>Nwid}T?J5Q3zZWIRZR6f8bmll
+zD$T401cv96*XtV%Nnc7R9x>e6DTmx>h>(A2!Hm(`S3yxg+K9S?6?AjdH>X+DpRMh0
+zK(6GzT-sGH0`E5qYiaFz<SV|)G1){<6!<*fQH6<K7JIG;yL#Nfa85a?Pl(gOo2}O1
+z-POoL%I3I)L-#o=)*U230(5ve6AsIc`;5U9;$QrP`3|BD=$#zkyjnezxCN+v*Ef6*
+zH8FmC7oLSTF8<BHF6Qc#T++VuO^(8iGc#p`Y(M+D0SE)v^zCVh{ft(gn)>v^b+3Rz
+zaXtSb&*I2F;CWIia)2kh(5qAHUJ*B_)mD?jd=SFKGWTN*4#sP*H1GL0uWNKi)<jF~
+zR~+YD*gT$R%#a9$H@B4ix}!wciO1(T4YUMwoNEjo?TuPy6ZO#=LGC#>=5;$my%5U;
+z_;dl*TmUU=%Xk_>p_Uz8Be(4(%&2oMt|hf@8HJ-O_>Hv%=1rE_K+!rkMD>dAt-}~O
+zwwm!q&qa<^kny{v@8aEOQAAjy9YZ#3u$O9R9Ob&}EaBd-_fdh8^WRF*^ESpEY4k1R
+zOzgXVFWCyeni-d3amep5e`MB*2Ugv)pJnXD!2#j-8g~RG3nKL=eZ}m@X%Tb>(}-UE
+z7^{{Tv2Ovt?LyMc4tCLyx$DwVEgol>BkB8;CNatRW@m+Y+{*$@QoZ<U)xAXG2xJ(u
+znTHOX2$S^Sjfl{7KBbTG^L5Vo3Ja>z8~r3oX;OB$|MlMi2K@5|4m<ZBf^q-v1^WZA
+z@`iJTU;?)`Kdfl#JDr&qRdRJYNU*;W_&)*${KpNPe^ev0p@4iH@r|omY#0q>ey|tL
+zG8SrqRm@>~It%VxNB)N094UBj>NU7vQEX_k`0-Suwo{_HMXDb%<Cy%d$;8xl;ut1R
+zBC-7(=2T}MhfreZ@N=WCs<eERumuZM&0ENuXwj-w51HeYd4lUhuv#=Ofbo@Ke}-~B
+z&|zK^Mv;RO4f|1`_2s7Sv|&nryW}fvZj#$w@9uIjn0VvXn%E=1hu9-B3+$rScL`1J
+zphudO%492YJipWd$@(yYw0hUQFH_m_wOg-~$rI_vy(&a%=rf}u{5HvD<{rx#3;SvF
+zl=vEZi!<4xD%K)lmQU5NfM~+JP>5tY@jFG@Rfco5tRjh2w*2CKmHUMcg*heBafMI%
+zqprP)fF~?kK>)aUO&Ddp$>p^*9J0${9{0hIV4EqfuPp}oOj!n{GPWnN@+fBK%qPbz
+zhu|lj4H=>SJ=DFo$-=)7=Y=e|q#a4Q%#HLd_c}IwcyZNdeoA~t1QHoW2LcJVBqc->
+zwW<iIlPB>4G1?td3yPPxlzG2+l1L^l!t+uYgH}X(7}51y*eX_;T31q-_3riG^lmut
+z)s3A^kM9+=4ZN^T_}x|wreicBXSWE)U=*ghp-P--Lx7(WjXJSs1V78Y#_3mEC$b9M
+zY;5uRHA8;m=wk*g1m?Tc&jM}zJAe&+DJmH<s}_XI8p@bITQC!_r9n^>kl(-0bkIdm
+z7h0=h%NYo*#l$qp!fXndM|cA33TDHrAZs2YU7VB8)46wy<-3Cni^9|Lo`j)39MTX{
+z>%Y8rd|K-5qj$g=zwwDnyOe-L2P}0<B6CuKNh6ZqopDg<kcpQ{?(Dyj#T4%%3%}m+
+zeru<QB<$CJ%BoxM^&VH2sVQl0_jgkY`i;h5h|zHv6Qx3zW=AOuai_Ah-VPOdBLO9*
+z&4TruA47zHf1SDvItq%w_yWUApe!Z}QI@$OU=gsgo=}DGtFj`LOqkUhuz4S+G-KNb
+z5;%V|7iBXAp8x8iixYsBHpgdyVK7#L6Vxa{^drLXbP$oHDok7)M|bYIlz$4)oG^Gv
+znfLdWb02dBhxkUd%V)j56ot*)pNq5nl(%?10<p!`dhDW~^PZqCKm3W1!<z`ulFSYx
+z(twX8rGI(#?H}_WS-`tBC!@+)K}CfIobn<<Bf`>p$)kH6eV8BM@1wSVWZ|fY+N%}y
+z`DC%9ejLJevmn}m&gR0&-kb31Vaq(W2IT9{HVxK(o0yq~D=TiQcad=ox#RNvqWL@7
+zV5#g#-kLfxxJKqmJwdrk_Un2QYN+m*NuAH|C&ae=a*u%`YL~Jh?A8{3dkT*}K-M7W
+zcWnb);s>JZQhR2Av5)k<pfDjzGcuG&>EpG5Xy^jp^VKh`{NV{fWcB|}u>S;%=MTVm
+z{+ECOApdfQ&_=nftW{9WvJo4NG~h?H-w8^+86?<W3H%=g`wzhWQJgV?`~uMuys1aF
+z1*P>6wb!Yl&vmdQQ8w;l7NM^6D~Im25JbeI?U0?$nR4BgJs1ck%e9N1r^Q<ARQO!F
+z^Nz8SM8j}})S!rgv{qSGd+a}1Q=6QBrk4VeKvDR9iFQ4`nQ{0O7Dc8@I5k<u>NeVm
+z-yBdXis=ya3|jbO^I9(Xy5fC1h2BV$)1LI!R<U6NpmmIh)FuY|x#JEV^SWRp?TG@a
+zJcrY*2st`p5ebCX1aXbN`;`fug~*6XS+f{8WWSXRO)ES$&f(ZWSv=y=PiNO6KUV1#
+zxkmOO2<lr;M-buRBOXTH@5|=kU#JPZn8LS}y<F_DArFpdK`b{PT@NG8V>icros{tZ
+z#6<I}@@z`9&>A)ThDl2$KVm`d^Em}ktei#?wLqVxObGD$Ix#oWWg11lb5Z)R7oxnS
+zBNLJfVWV({t|my#(A1n<oJFOR=JX?Z(opjKMn&2>TVQ+nb@Atg7W~r94oqT%gaO=J
+zugVZ^<?aG0e$!{<bd358?JZW7mSY{rYyyD_XJ3azD-xSri5zA3pM5*8cljko+gd1^
+zGjB>%OHlyz)0jA>bnuHm%csWJH%!Qsb@pr#)6#+946-B)zf4Q<C7F}}B=gZ=b1kz6
+z+P8kx+2TW}fGe<HWOa>qdbb$C)q&$>rTZ-EV7`cC`24{!gIeXmN{Rmh*mVN(Uwc-P
+zY!!iUN?ef+k$2m+d)!#ZVXzzkXJ2z-8KGMHqO4(=?j6i^%F9lQR?6T3y{Cz2R{h6{
+zl72%DXxLe<Fw;t5Pe`020upUEYn-bq!!Kv%-x0=3p7&I&W*C9hdtk{|n54;(t|W?L
+zc6-ozBcMb35kYDCl=0aGp;^fB>OT|9(gH)XDYjaAvs4kD4voD<Hpy0iWBkUGH60{J
+z-G{lwVyP|rZFbrD0kJ0APaJae3?o&28g+fg%ZqH|7mS1InUF3nAiag|?5B-oE&;V~
+z%Ac)H$xuFVmU?k@XMH5Q9p#ZfD*Mc@bkBWh#D%98#6n&JTkQCax(93c9dA4M!f(3I
+zi|i+bGNdv~h=)ChNeFlpP^+}Ic6>V~*oZm)&V?}5Uqr!8S=&2SJ(nF7M^xUJ$qa63
+zj9+G>#}9O(NHr2tfT>BT<w9vPYL)DTBCUsoQ<N@ZH&{|6<S$vU=CS%gyI<(uMddx|
+zR47B%NLydOED9bk(AYW=X4%+CvrZ0#<s*wi>1DD{&TW+8!c6M`0;&Yp1tKon-KdtK
+zTk;AImarTQR^m$Dh9j7plH>7`H(W|zX`bPj7AI`8Z#5F|!zpI7gX%b-OhDmyOuMZT
+zHrz;ud;7E!30;UOYtIZ7O!_h5#-Y~^BX=S{Niuv(MKSFkS3Jh;(CR28hi&^WfB_(X
+zT!Loj{X;O`|D|C63fSQ_Z}K%8ju}F|T&MelPCribfgB{*UkUv00R#Ry$Nxul<__|Q
+z#UiPF(i4p?Bk!b2#bA#gS;x4U<Jdv|sI|}c>+CWFU!JYSer;vj85|}<6#Qzs6AEQr
+zfqo*2^cgTGZNI067LYW<jY1}t%#HyBxW1ilO$!YmnT0|sT1NC*e9L+;OH(Bs994Pf
+zpsc{A7Ibo;=L!5bcg9Exxg{^>F0AC<u0xFGVWcCH@>_Oq{ed@6XFQC$R|_>Yb?b`Z
+zp6~~${74S-%0+b?bG0#ooNWTyCh~r;4j3xGXMTM$!VidbS88zyHn@b^hE(l?Gl=M6
+zt;TECTPL(--vOG2GxHUR7qq-`7!B}uaSGrE=$u33H(?wKJ4L@t<L-;rl}O_s5C?u4
+zV@FXR%1dS{96N0MH284oGZMryJoMH*I>#(f4*n6k^8`AYM@KDN!_7O1PNwn_@e~-P
+zzJ|q=p)ye{7*4qC5%}K^3(AbVM}1(jCiAFN2V3$?)ENXV;t3uDQNEb}j>=7l8=M91
+zm!kdZ{c9zZs2D~SmN7o*2Wv4mY?WMPxp{=+ZYi<g*&EbSr$~BtbywOc#kwF=6t8i^
+zoF`62dG#mA8Y7qvU-Rv=NYofZY;WPf?z1PxNXt2bN0jI^rXbqm)4yVqw}-QR=F|SV
+zrs)=;Cld+D=bM%Kv&%*7=~M%?e#8ZUpSuuMG|ZB_cRCvr|1p#v;(VpJG$A8G`ln!O
+zJK@TIwP58D3YSgRI=^~NAAGo%0+79fIgbYFk|t>_zh{X03e}Z8hicRBGA^nVCZ9eb
+z`s9|-8QeCFFZyANw<a3~;v$VW2Bk;F_fX;3wv@X2xYtJ(0j`!VHu_Rj&|Bd=KLjjM
+zqeqVYciq%z?PTfFbrxl^#>DbL{PO2+NfTexm!sy=<_)uGLOOBD#qti<8eIwui;FQi
+z&(DNXIA-+K>Wq4p2}xjhWYmT}c@y601uA~YpYOQyBqZL#qg%f>o`J1#q$9E%X0y`w
+z!AtFpg+dAS0$`B8XuvPkNCfdA5?Jt;ZOm~Z{QO1J+Sczwa-hWp=_gAhc?UzfhMF6g
+z2hfH}VKe8TxRDCP-Q)uc3Q4W>HfGID_*6<f-(Wrs7nm!ll6YDA=|Divl*#op7lm5y
+z2Sg|bW_!fz_)D;n7U`2rwKPf$wL#m`=<(ec-L$Uu0~JSB&KXVx9$@~Bp{LRrKKn1y
+zE_%(pN-N1+^>fQ=xq2;L<BQ!+LYj(ud6GnRis5F{?i9fov^y(&1nLimQJq>Z6rh@E
+zu?=*udq@}_Cp|(0F%}FhyGk;5o=Y|rV2M#_#+nB%lbSZlv@)ND!Im@trgH?C4Ua{t
+zYw-3G;A^lI(adAm{7S{$=!D+jzQ*XjqGg<=c`KKR>Sy7PG<}&8jxz!--tB7i<cI@j
+z%KswRpMbIbu^7SjzgmpI_}l+DME>WZ)?ZQk+hPRUXSqj?(~Q<^Arz3BET$pM^#HKw
+zBH1X++5-5^gW|(pSp1#G*34BlEsNkTT`CGiHD0zmLVFjsPM*eFdD<r$^p9Ne@4ghM
+zoD4a9?Uc$$)p`#LJ2!YH`JRtST5U2bWT9<O0`w$Y%t*&8R=|Ax53+M;a-ZKob8>U=
+ziWYE%8ci%aO+J@sgD+%k+dQ*hNUY7R=doA8Xd%8`>zr=F62%uf*|u26P2qmDK-1C(
+zg3QJDg#>O}1iBS$bo6UhMihZGqcGHy>IX5O{$uFRakir7b13HQtQDm#i3w6Y7su`u
+zV~5CBJSco(vxXkpRGCqOqtHP^;taSR1783fR|4+E2zmI_%>t#Vjw{a7vXm}r5lnX0
+zpNVu9wDC)Cu#ddxuj0gLXu`70(XEB0G%kREY4_Oq$n2I^BV)h)ffB^TX`^RX;AIB;
+zzN>8PL1L5l8BG-<Vk`$+!4(=Br-8Gv{day}gJj;eGNCOk!8%U9Mq27`hknco)m(tP
+zS0>>m1B{W=3G&g*F-Rx7&&S^=0dgz}Pd9KDn4^CcNh6Qx>JQQLpcmnXoO*4Y4C?)b
+zzs05|9*Sv~CMK8qf?%Wu1py_ZgvR^aZ@L@%2&z7KhePGRp<ai|<0P@QyXq&8ZEit#
+z63~v503P#mb?8;rJ+MUdo*oSRZ2)Lgn-Sa=arn@^PnK3G5%>DjBlWuBAD}28{Sk`b
+zqC#eG=ranx!)P>oz@-p~MZzDkIA9urShUdAq!&7*u^5tXN7_ENeu-?;-NHk_c*6$q
+z2s!k~8jU=SDodplOMR`?xF{3;@$_^j8~h-C1%WlyRoRwr4aB5w&1O<QWsLgV8xCMZ
+zZB%lDUTFP>SiJseEangW|8@3GL7J`G)^6IiZKKk*ZQHIizqD;vT9vFcDs9`gZT?Yn
+zuNh~qIP2`Q_kTTZTRicM9<BG+z21m87>xVV&(=m$!EIfh3F2aLT2QyQ3;81|f!Qvz
+z0oQsZ&=T7SZeQk&Fj-u}pZEb^6Zh2MhgO5!jX?)Yj37y9%q}5o89KRzt_=gt7?<|R
+zsEV1b_FZA7=8T3X4q#pnElxH?RyikVZ8|JE8_okKiOO&^;}^<!{YfQJOy@JZ%+j@a
+z6Q<S)@T!c1(?$GR947LriJgE1x|86xR@USM^ZQvoQEWwSI<9S^MEP)DeD!8}uEV_!
+z-lN=gHCojhXxnvQHOvCD-HkCC*l(rYyT*KRRQ1Z<@IgO!V1U5D>Dhrk^M;aSDKf=C
+z@#uYu;E$vhR~Px?z|P`UypXMt@g~B8-pv9vIz=#>1D|9FnBW<^%4)(F5Y?KvBH&hC
+zdbxqNOVHcx2Hw~tB2q%VAX?$FwW{2tn@n1=_U1}niIkoOiwE@P+8!Cl=<7{86OfkQ
+zHJ*w?v<OMm3IGZyATFZ*%!UnwRv9>7H?=#H^GNl{x_Q{^O8n4Aj=TV$lv&vtuK%7#
+z|0qVV{BMd8|4&itPt^Y6k@N49pnwK5;%j>(pav}>#2P>(R*-TTIM$VS)?i=p;*+B@
+z7Q}Oqt#e(;@5KE9LH3C@&9@fysm=SnUk0col1$a{b+B3nZ}zkdR!WdmniryBL<w%-
+zdWXLW$Rn+nn5mIZ6IcusMVh%JM*O+#(5t$Tyxkc)PghgKjvQea0k0*k+T-y$rG3?5
+zzjK=RNr+!8vR~W6RcCSiTk?eNT-fiF>Lu9>8=?j{uyyyt_(i53Hr>?Rg-h!>c-XKx
+z6AJ95e!Ekxizl;%g;0FNCFoodrxNwTxj4BK!J<h@e3^bF6t3Ez44aGu`xH5ambYO}
+zljreM-IX-Q6P71119CHr_^My+xxmylthe>BViUd({2J^Rzg4xqF?$_@hsaL;&E!5}
+z;tBzQi6nhS-od=DIu+IRLy~BTA$=!ea0_>}6b;PLda>qilGI@d{DBudpiF-6gZ^vM
+z61~`>kaLdILl)TiELiA#T^$G=6EUD-WKHe&=1vIN=$U9}AD}wPFGfu-64LFQWZa{(
+zBj!wf%rp6fqX;u`IwWCEfP=DVeE4-g1Ue|6DQVeGnr*!^|2%M|1_?};hHw2-<ZZk2
+zLLX9~aASdpaA!OSH{NR6@pdjm8vwsVb7yxR5FdhoOEN0RvD~C6fRg%C+9<!ay9Qg2
+z>Gom_>>wLK7?7}OuItisVeEorY}9A$7Wq#esehQT0wV$aTENa?u8#f|X@DOs(+iXb
+zt~FptDU6?)>Klqht5039H1fF1z7xyz8n8=$2p|Y(L_#Bhe;D$b$v`54K@KKIt<@35
+z#9xR0z%G}T7pwn1Y=o!l4M>zM`E}n4h+|$BkVvQOjvluR`&p^Y<u9^5Z?wr9;a_Bp
+zmtmvu2m}6s7X~(UCy>VxZ^z5pH;rTm_jG5CfYLl;<s<+PvzLZn{6jJ~meQE(vTxj6
+zo^Wd*e<G4Yz6o@}!lGSu9w<_w&&i?-*%IZc!e$(M@h#zVa1821bd{5`u~$e0@R|MT
+z>OuQ+4HRY9oIPTC?E3h)ZL$3^>8z7nCJXK|I}<z`lad7E$n|ie|22;jK?CS8$)(+}
+zt)Avd%wwPRmLdZmmBy~%g^sXe`I`|G79k#n^+JFwZ8$zE-K+|7A1965&Mx&2IY0Ie
+zV*W~@qm2;j*1Gm;C=%PsBl6}0Ko2AhSEvMo%Ag^g{9aQgx-?f=lDFW-!9dxX49l0)
+zDrA-N>*dK^x=&FvfjwrA!?EDDl70+y*DwSzQwSjz0V6jXB4usN=uNr<%6H~K6h*`%
+z$}MX8Fqrg=Y?9?$5eN!fPK&1qx7B2*`Sld*JcL90U<HX?U_ChL!E3Nm011RAIs6@w
+z#dC^?1cdvg6q@>kKi2^hi`Eu8O*;BZh21{SI-)4-f8r7Ezph-dun{T#*I_FnDwcmV
+z9$5YdjR%bXcc=YN>i$BLV8rt6M_qRM0yE;5OjlPpFP?<iBTR9Kp7-NJFIjqMGn31C
+zfPec{N%go;CAT$Sa({iP`2Ki(Czix_qvfhZl8C-;k1nT_+?Tw___pW1oKd(0)I^*&
+z17+`Hr*uW4x2r_(+zmmB^pACEHRty4Rd(F6&joLb)a%-@s9xRx>-(;)&QYezw?W%t
+zxO}n<TTsI24A!)7LF`I)R@k&qXyBBc!PLh@u};|6zIcT|IXLGvEjY|VNAawBYbye}
+zpXWbyN${)(V`T%Az8CG;rl1nh#}NNOAmA|@NX<qrbkEe2O`f;2jXIrZcX%EAMCeOV
+zpmfy@V^&$?mu0B|DBB@`t?jL2H-SU!-XP!7sSjyCJK^xI-I#x|c<Q=xnXXS1@PFZJ
+zy6z!OSv;`(l3ua`6VO=y8XU7ktJv92G@yR%q8hZFAk2AA&wsuY8T(uvCHY?4C9w|)
+z=g{&Di7WN?um>r0vH&`aIc|@5oPjrd*nNf^jEs1#tK{MjXr;>nR&RM}!XB9<O)SA$
+z1{E+F4`CE=x;4;|$N8LnRIokUrVeJLUgLfg7~VC#`bb@;c)mK%uZY`eYLkNdEIs=M
+z&o1}r-Gd(RY$}}ZRN%k@V}w|2M+Bx3eCKL8x`?QUjnf4kB5`JwMq$7$HuwlvDGxv?
+z#_@b6;N&>~=v!r#Si4{+Ae%!{!ATSf{1Z(YbNnR0NI<3H2J|Y_#c<nl<dzpiG=#eA
+z(Yrt0%5Rb~E|x9C)wn8K4-?zwcXx+pmxj~&2$$ScO0|BZV9_m!Zh+6IAGTt9Do3uR
+z&z(Bgw|=;Vbg7KshdOAFAKgl*<$nUM2Joc{^kgo(8=cFK+Ed6mB<LOTc&A871-72j
+z;H#NH#Ftyo=#BJ3aLue8he3&Ca*VZDk2mBaK`}aImUWdDU=_KJC?&jHfB3>pTfU07
+zBzB)EB3r~)8^qT6Z^t<wCU!t~AxcniG2Dctp;b%>9`01BQ&`vGdfwx>;Hv<f{FZv4
+zuFgaVe`7Sd{tnr<<8a3HE=^I47(!}twM#w4c#>R3w3RmqB>vqDyP$G0SgXbaj7ctL
+znL)t5=*FcaFZx}Ei_Fb+H93<5Hv|ZYW54rwd}Z1LVKYx%Fzz==N>O!~{Ini{;bh$)
+zp$*$t++<~e$?x2R*{a{JjiFHh2mCmr8^*qT@9J@ztEoW<-l^<zn9Z@YelF$P>I(%W
+zO^qqhNmj6<{T;INxFPZ(YA~ik7EDLN9;NqG9E|}CLR?FMAkY!H0N8^MHnHFKSxWlF
+zX^EDqiAJ!K{XisdncCdIu#Paa^GNUZb!y|Mm+p!s=g#5iZsK~{DJ%*Ab2|TmhNGtx
+zxCl5p*R_qK1>4*h7y(|4>U=|jPm?5MJ7lSn`xf~B7ESE`K+`|E3@rbHF2jF7)1TD+
+zg{A-+8yVBp7Cj6F#4oiBG$CML>5nlmCr?GD@Je4CxUF0J#?mdi5?6@0KF^I`wSl{(
+zEO}^64gfvS8SG$#vVv+VgJ)2(KyK?0fysJ&P77NNT%Yj*vU4GhB*4M4>Hrrut_s)U
+zje-b)yPJFF7Q$^&T9E=|e@-<wZ!ze_JYZq{yP>-|LIKl97H;`05k*wjQzktgAy}^&
+zqZsBjrw4jri-ZT~#OU~qHy)<uR#PJp%1lxRZA%Y?bak-aC_$NBC5su4xD$a0UbA)~
+zmMf;SGW!<T<{=a$LzitNq>`9U+!a6S8&{h!R7)mftUupO2!75z5(AahY2qk|58#an
+z3a$EE^J7E!oWV_Eq~}@YFY2?hSwXKKi}{+vrG#V21`d5WO@0`dl$|n$wZeic1YeQU
+z3)pUtH0%iQzb#+;yH)nyI{GG;94xJ>k3gn6yF2?bznASl(p@(`(f3^lMEZKU_{*}G
+z9XW*aV!MRg%|AR4jaQ|CX{5H8mI6Lf$FsWQ<4eRS-i60CA7cD>n@=mJi%um;oi9#w
+zmz>(n(@=7rO1L_wsuZi?({z>QL*Np^vHP28*a`S9$RTY6@E}NFrP1SSUj3Q8p~w5?
+z2S$3is{#mRqVa)(Li33Myj`L{Z7mg(nQnlEt3=H&hi2y<%zt~K#8$4*9{|F4t|B_Z
+zTm+SbBvPfhE06z)Ce6ykLSQ7IIr~u{{rIV*9Xn?rQNCn!Z*e4}xeDv2X(7cgF@HRQ
+z@9OVWI_78$wOI4SM|@H@1)JM)?B;jjuqW>C*-VwG1PAd9hK9BgKP#Nq!0s@!Fk^7s
+zOh7eFRJmPB0i2Jo5Q?EC7*d}_B8>L;@a9tT%`^rV0EEvFzd7gcyuLgBXvFL2P+&6X
+zBo2K{?|Y#Vjua2KIiS0Z@oDiS6b`yW@R)?n(62b1$a)cDWeUbwPPFyn_OEWcF$Bu1
+z0yV>S*>d4*`8PxhMd~5^+6f<opS={_Cs&TlpMe%pfGwri3F@%tMt|FBar{Kzz4tOH
+zN=%*SNp6vM$DgZ==CMm8C}+eXm#m1c21~e|VgfcRU<*$hMJpi-*GEb{WNkY%+y<G<
+zI%r_x-6E5}YG6csIx!X2uCrOl0zooHujec(8fL!dty}!0IkXeR1{n49>2I4sYTOlB
+z`Pd9w1HN{06>QK4xiq^U_Nsex=9l75#uV!a@(A{xbTWwrBD<^SxH;#1s#SOMr^i%{
+zdWvO-#g=I=kfP>c0v=yCL`=|42P@?UD3x!^ru`^Nrt0R>2d!gpXL3-<Cu?gev+#W1
+z*_0Yi)Ltr6&3w~{aiK9L&6%wkJil5k7H`dy04KPv3@5abTNwvZ*9dRAwNYCY&}dYF
+zRpARS33(la^>e+>J(K4_{|QZWe_Im=5f#fn$_XqS|AVuj|62Tm00;S#vcFLDpzp%;
+zK*g}X-iP=}r?P-bZrC!E`~d`v(!+%&;+@bv<C&$`TYd6T5V*Ed4~rQV2vudcQ(PHj
+zN@?%^v%)XmzV<v@NHb$JpGlL9+4)=O$ya_BZX}GO)S^(@Tn@@yO=@+5hB}x=%{V=A
+zTT_{B<x^}ZGBJStM2%JEnsW&-ev-|m(3HtBG@0`7@q4wcV0Gm~Bn=5RzG&--RFIh|
+ze#?-MpY&tG(x$S9t7nZyJj2zH-6e`!_gt9BgXfkZMFbSC{%kADW=+Ep1iCLJXJg}d
+zT~c^^3>gl;aoTM>4*4o{&uWyeYVZf`jvIm}+=ca+BvlgCFCk{6n-^a|DfhRRqV}r#
+z0O1ceWFEU&mbq@$Z@fq5uBnpeR*L6wtk%#!(I92|c)w4h4i?UF5Pw6fZ}EaDcGgrN
+zac(@pV7$jnkil%1_2x*)hfw!R^=M;QR6Wx221|4OaVVXGK$Q87&G$jZ9&YU+N0yzV
+zp}tDYr97D&IGH{&f6J@|fNhY#@FsZ-qV_Ho0xd)+nzIQyCKW}Jd!$zzN!_K%=`gNS
+z&5K*Uk~7!(oJkJ)tF~3{XlGuSR;6*sJ8sahq!)-dOIdS|+14LgtK;YvYKw#)8~*g0
+zS<29iCTN1URhK5Ogn0ref0;unmQIQVsTo*J&doyZL58Hm2OIVefPJ{9oL4l7&#e3j
+z#XSn<;6G8Ml?bd3j0CirAQ9oe(k);Zy!p-_9)p&(aMgnP$~J={P9ll)j2T=UJ@*5e
+zFMhum8C51y2hvA%`1ZH}2H~pQ$O9RHR}i8!BkQZZ-x*r7g2&!##`qDF&UWqwelJR7
+zHsJ!`%^tD9kDwT#qxMT>frKGCqZkUPOn>=EgsT5GqVf8YH77msM3Y`2I%VIkKYPe%
+zpu0-$W}WVCUTZT$$1)A@@Q!<k4LUr^7v^HmIAFeO&?Truts6=hZMz!FouWpoUrZ-H
+z0*jQzH(g0ZHc7f;>k13J)4Fu9B=`N@35X5=$tL+jRp3Dv05sIuM-Z-LH-y{}YHcbE
+z<JohgL9AC}<)5|^tVg$saqp~E(^|KkhZEvLG;I`DDB9qm+>gP^VEvLC%u6=6da`d^
+z^tLRo(bPF+y%GX_&4+DUa$`w)-gpuylsQey>CyyQPXew%J&`<1zrra_xE&mgzij~^
+z^eYwZwy*>Y#dl;3yH21+op)zC^0V4mhusM>eaai=E+3A1F_I{kjun1Ed-pQthAH1O
+zn9aNgTaJ|Nqi4TRAWMDoO{JKqK4;kFk8F!J^q$WW-+q*luBWPsGQzM)l{FFQ7tPID
+z8j#qOzSAUV+MDpdI_sQ0%}jM!{gnrJvZtX?A1gN8MJzYA;!<coD_X9{s?O~%OSi}p
+zR4QyvZMMQYC0F@xQN&3^#qy7u0So8<3PpcX_7{q_WBrVCni%V%5s-lTz=(^TGzN~z
+z0_myIYx%BEnia9)8@o3%z>4dI`Y8w_9!FY&L<^Uz_k*=Ypnf8;X^p_^I`scAc?Z@)
+zX^@RQQpKzVF}n?FShwDUhP*5Q;Vl<H<VdsEzT=ykF*qSho8^jDG_uYvua(taqbl}O
+zfC>jxwB>9h6#nY;mjpl!8+bPXV@0g2Yh`GUHoh1qnUce&Bl5o-gxlK`Rl<;XGS78{
+zA!JPD_!a|YvQ=@rbKfhdW-!$v_2BZUpk!p-S9rO^<E1JccseC}vxgj74kp#4CYw}3
+zx3m-6*=}bZSyp}6yUNlSYde`{DZ*k)c=G^?D_O*smONY-9IzL0bJHs3bodz83p|Hl
+ztR8-(Osl^5YuU%?KgeEwb+(lv12vUk$x!GN&{W1H2^UoT5Ss*zxeihlk34sYbAnMs
+zLo8n!16?h}L%KVD*6U>LTcQ6X3#Abk^|i>FreJ-0JgE8Tv&%v_K<iAy=&|QA?o$Ee
+ze;eP~Osem6Nv0FnuG%B;n$|&iQ+tQ)6M7ibwNNj>O#VIOu}gU`jWY_TwhCg$&ji4Q
+zd7QfKBnZy}#XY{zpzarl+3H>8U%h!3l^r+)rnn=L&d-E(#*Fjps`y}4pi3fI#Jo>i
+z<8CR+OYO8Qg2-Ttsv3*5itwW3q1go7tJuyfMFp1|fL*iFrtYTv6GhtLW*opsK!ss~
+zqhp{O(>}hW5rf8q^Y#U37t9$!7)g&@3sP8QPD?Wt8-W6K_>CC16(VS~B#-MP*PsIF
+z(iR`+Ul#pn#n+mVillN{;s_g$!N3{Vhs{AXWnMa=4Y@?JT7U<c3Ukupj3P&zJO*gL
+zHE`>v8$OI0<#8_hiSc>N4klphb835=ZXudiM$)8wWhGYGa&zmm^>&0;=350MQe4aS
+zG)YD`pK?f3=MR<~9!|T(?56-*GF0x_f<(NJX6D$FQqbZnSUZrBRZ=ExC_XfzN$bWN
+zp>OKxzPq0Bz5pA*p0mH^$Q`}NAcY>XZ`JmBS|_f*5bg44lt^WEul*UR9t50GWT}q@
+z4U1`SB5<8ivw^Dlc)gEndS8~A36fox1l9(OEJlbs5D$toa3%4t^*HrG4+tVdRL+MY
+z-UqZn_3%etW(99+2MDbF@<(x`XXxz09c3Khn;hl}YQUUI`wh4l0j9)SXja);TvcQ+
+z{Etj2PD(@Ni0=uBb?7qBl>$S$BuRbClkvYB*5~INgrk<v4WvyUL4%|rM(M3@O(n4{
+z!*s!WMRw%QlQ}oQ_xnsnr8L$*YC1msRl4!o5*v&QS1ED3Ch(a|w*sV^35tVd9+nEs
+zKFkc+8UcFP$#c<nw+y+)C{uIr#S>#NIJ!<lTd~bonwZD&ESb7j*3go8&HpWmxQM7&
+z{?Qj;;rd^p=ugW2LQw%sv5j!DTZ6X^5>V=%gviF+<<%`QL=wy-19sOQ3c{(qeZB;N
+z#jlEuEU!rR@>|{N#$4x#JQlemwR{UWPO;UiexgZSx|m?o+*qC^)*>M|k@WZSpi|tq
+z!g0Anh7nbV;8iO}S&MdjD$a`yCPGRPwr?`RMfYkMCrN1fn}DqNZB{wFRPhB`<h1)A
+zE6QvJM1Wwo0qkG1_dkcWtb~bx=$lJ*u)k@+F4JLkrb&F3or`h#rN60UE{A^`u!<}x
+zvumVJReQp<h6z}wlG40ndlP#py0Ln|we4MTaiRCyRP`GKKe#?lJ)}>+k%n~J%I;rO
+zQMMu($J-hI4h9I*4gh%&zM~Jcmn$Qsbtg>{Go@<7vli8@>(Xn`U=B#g5p*9nXbpNe
+zwWqKS*r`t9%7pz~u2}0!uolCO2^*VQ+0HEm6lGA}_o+MMH4o#;yRy?bU9~MeOecjQ
+zug<({Sj1i2z8el6vx`jG4UVRajpE*KThY_2*U2gyvH=DScf&Yd15X8kR&-g!sb;Y|
+zr!-|cVak5xc;s{Akspi!sW~33TR1EpRxo{k>%9DI`)MLXMi1$$@48(Gj+7><%;ted
+z6xN@hXk66wXh;~1h8-<fiVE-gmNK=IR@?%nl@ezh7XPF*Arc{^PUyXX-0WeX>uRh5
+z?|O@kY6(cUfqHO^S6@}K!9#+NwN(Bmid6SPzkrc|dQk;CfCU$cu#%~6F)?&LsZ?$A
+zip*1CQP>MJc=#etl9eIZVcxic#TGst=X*I7y{<@_^x0>=?Etx+am2d}!B6gPR5#58
+z$;msl3F=y^;dCKo6O)xD8m^{#175^_5qhNM`%SoMbSj0&z&G$HmLcH)AGy_udp1zr
+zXb9BR?NW3SLz^1vsB*zom>M**Si0jHo<d|da|HBJN?TufbAXaeck}kSI^)nU>`Gw+
+zP+yccv>L#s@7;1k>Zo(Wp{}Jr54Zu*LnLYYf>FaUm<Jz)_h+w;=tV^nfEqX(KlAYG
+zKJ(%Erk=(o4@^TGZN{@gbu(;=wdk5M#UV>3wD}{IEf`-RkKm_N)gk*ru0V*<nhSo_
+zFP8nbLs#Gv;t(QgmaK*wlI$KG3#>@Fi&Np0(@c`GwrA@qJ#GSO0e50&=6w!<poRwM
+z8k8`Vgnn5_q<FzmzNI=?fV5|LNdP9NoNe8L#ITBc<K~8nT#Enn(`p@whOPIylFU@=
+z(@^UT@{I)j`*9&Pwr9Kw*<lnV=9(Hc!XSP0@DK!3TUbmA$O*zt&9t*Ll)NCG_R+HJ
+z%AQVgPzq?sHr(!e0-8~`&6k@EQ&t{NcDqr_jW<$Ni-Tz`syxyZU>WzdrMgy*_B@IT
+zo2)vPuZCOqTf;E3k2p;c!Mh~mNc9UDm-m6ge?k%8zkbkE%uF2YO^v?)nQH%g0l@k1
+zFaMux!u$`nTK>fDFE%x_hv9{>QMW|FA%5wTcKG(OyrQ}v&zgf>RCW^<TO}|9zgAkQ
+z8-4#>+&W94ie&Zku$yX*2qHhlZ@J;hibF?1(AHqI>9pX7b^Fu3<u^^QyW^FHMEbtO
+z0QKo)PSC>Do1f=2@@o5+aRc2ZCzQ>8(3cAWdP*it4g4}XHS~b+T*|_6AvY@XmTrgP
+z4&gj|rk6!lNClEUe-C#eeAkfd=v~k?$Qr5jt&-a-_buc#q}6g*sO?sPOte<+>FPW9
+zbqP>OXofY(Qu7)~8U1H>$~CcmmcFBj4%rp+df<Y*B(H^Kk6XW#x>}D!{vKo4TNzTs
+z^}Efzd$ysiNj*Sqgo~nqJw2>Z1GUl6*zuvoPaMi^uaxmmn5@YJoll;L$3fnvigd5I
+zpp6C+D;dGrX?*KnT;AdWfk(mm;rZFl+{;btFfbaN)ixpwTtm!`N9p0HG?xMW^RO<q
+z<`TNSgFCt$7pyF*WG1>-#yyP*+J}&wLSh%%?*I|Wa&3UEzetX~8-!rZjn86riBv5D
+zg1#s+XH0ou`z|T=`m~SEi6a?!q{ar>!yf&p%!JOUiM!H<Xqq{;A8XBetIDnLMnUbR
+z6K`o-K9E~SFW3P`(~U}}vuiAIx+411c4a09P;UC&=z14urRf0!ia`+1j|7fb=#NS_
+zCxLDm-w*(L$1rUxb5`*c+aprU=?>iAY-$C8|BFpXP(bDBLL^~RWk=}oI=JQG1C5JJ
+z!aopZo6Dple&qeWHIh_#Pi|zK@w77OB=}gG@wxXkA(VF7zDy8mrhFIw1!2kK<O!#5
+zptNhc<LhCtPcz?9<2p3-NGR^2SzZMw>e4sQ6S~vWmu8;-88(_M67a!Ccq5eRg^S#&
+zB}=oSZlpI!-`Z{^rOs8(<>ab+OfvIZBO`t!0aT;*2L<?qaj>UTa~RZg6UaCy#m3xO
+zSO?xsH#aDF1F4%g;lOI=ruoP|6(!LcGE-~)T-DIBF0uDg(}}bVFqMeBu>vjN1|-po
+z_oh|c(5SRe5Js$o*xGytU<paU&tqtDtoMDZP;%170SFWv3MhG>+obnlUy|J~EVeBx
+zFDJdzsgJLevIBbT>c*DEfX$%A{ktHYyA-Q}{ilWkCEMyeY%O`TGTX>?SbPz;*PC2|
+z2<vR$n)@b3f_YWbH3@iyk-$B`>o)@{k@_tftI;<^^}W2g>WxZ4y^~Gq)k~yToPBug
+zZ3Jo!n;oU&e4-FaZ;A6jB2HaW5|VBq9q@qUdw%YBbFDplYtocwqsg-rLZ=j~`Y&y3
+zyFi-h(0H(pRZLpqdeE$X%B0v-Gmf257qwI-L9coh7kW!Hm)%m<_c8~7W+_3&ugYki
+z??-a^S-hp{Sl1m56DRN(_<NXT;LZyvhnQxOzr>pnxp6pwB0vbiuz*2;puzv*2M8|Q
+zpUt?x2|_xE1Qf3sFZ86ltID0Wv1T@r{QO<uDcdQH80u&75wUM%cy$BJ5u;T0DkE0(
+zfekz<M}aZ`^VvhGQ++JNRZwP3OB*Euy?kYc$4sfo-E*O5#PKeA(^VOdljasf_q;?7
+z>(XtVA6CAw7|g&XPh|mn46J(4WVelExuvd8aZP#!Ig}^3k=tmA(sl~B?=kkr!z;Xx
+z;j&%v$5nW+vep*Qn<Db?uot?P{|iA0kg6=`NPjrs-u0ktmyUa+pBM|)V_!Nh!NzCs
+z9VqmIR84((WiM$Rb&Q*<VWJ$`1j!`%mv;R^`l*qCy?TOya&#XV1Q=sBnyiH{!f`8A
+z=1wY+LPqhN@_PW;lgGe%_2LoX?2$B~821nNa_G^A)la?h42xv;BC_P06aa+0apd+T
+zu0t@Of-F<g-)YBCA+g1`R4^1X)LnAQN-W^Jwi=RHLq!Yd?oQ<?gfY#a>M~Ui2$r=m
+zsT)$ZzEj#wTAlD>*F}1s@V#1D6ggHkDXC9&>nTK0c&Gbh(bjji#Q_hIW3u9fk3#ms
+z)l+Y=lb5zUbpyY8zn<=OdrL2cvQ4}L`?-1md_u`_k1ROBArjlnZx4wlipg7;r~R6^
+z4Wt98ijQM-h!xKTio+TO(sg1vy04uks`lkBny4!#_zjd<we<dzdkcjQ6_gv{RB&N^
+z1w$atVZOf!^5<n2wMO@AU?iYyKr$_==7L`)N%3R59#3t`RsX>?;ad@m0Kh(6Gqzpq
+zG$f@=T5P))44ulPa_!f7Gab16Fov$q4vxtnNbDiHb;;@L9%F7vm16)FxJCM~v3%Kz
+zzzvY~c$?5rU5}7|r6Tq7LMM|#acY)ZSZFx(@U&UYjc(|&E*%tv^MLtAo*pCkm8~xw
+zxw9Bt7v!YX?DO#WIUQC0Jm6bX{ZnQGgsgUhBm9-``)Ka1Mz0m;bdmPKJMMD2mQp^U
+z3Vn}(K|Gw+%sobR(w3iOk15@6%a0DW)ti`zx|$X;!fy&jYVS>KXv1BpDzuzTZqKsl
+zz)Op@G;|KK`*ai95vQ0U1@F_>H!`Rd9<tD)7++g0Q({+y-#dCT=mAcauF4Lsv~IkR
+zr>0iHyY&ge>KR3mKqC6M2Z=JC%<Hd<>nzK$N%q`(m?lT}!PzOomHFxd-LrlT^T{4<
+zPVJrEXqCJJ%*$e%VUJvG9sTx1<Cm5Uib}URqu8PfC<W-<%Uqh=jHaR^elylvG%E}4
+zB%f`i)ofI@`!Taj-2idfCf~x}zcBl@6(Vup34Ze~Ka1f_Oin?FbAiaj#hu{OYBC(F
+zL(MvilmMMtMd*4S^B_N)4}pc-eH<rBo6A>rfCiVR4X)trgK8ZM(ibs^UF)N+mNx4h
+z&=I$B_y$?_lGNfZr5XRnQX`+Z)_?8x{!?%My-)Q2uQ&g}ZvMpXFS}_m(LV!)*S^TJ
+zL;U)Ve_kTNXrNQ`43g=P6&s#n*^vkKl6chKk!z@(PlM9O+OrZ?Up=Y?B!om>I&I{x
+zcqG(nkjry|Y|#--B<Oy%`wBw7!;l(RaRi(cQ((=QHputPqF=C2gP*Q`qJU}PojJm7
+zs3x=qrf#e?jEpiSTM9saj8!ORH~W$8lz*}E0#oDg*0XGOI*L7)#dhi#JpMu3_6?DP
+z0PagW?T|*2G@4E~vMStXvRBV+#K7w75NC?BEk2hb@yDvP5E!i?kcBEdFgdQ(EfPfW
+z`l%JnW+Z1~FmF!ba_fz`v&~P1N!}9%3Rdc++Tg94$YL~hg<=4yAsutjJ2M#v4=!q8
+z`_qFT&pK#SRNY6|+t9B!K%a1bHlL7i9Jd?F&F?<rTDt-IZPo!{^~90YPS6n$y^AvN
+zSA<k9D(lE4S`4y*bcQ>-uaaX+`JtYCQu)}`^z=(qtY70^8BA7}B~gHv>$dgdj<=*d
+zB8Jerw+qFy1U0}Lf4}A^CZm4S<;)of-A_C#r4En!7dhz=t1oh$fU0@bjV#O9T&GS9
+zI}Ag86khhmhS}*9h#+d39ZZB`S3=aoeg6J!Zl%KX`M^b%i_upP*(NKtCvG)yUu0xN
+zT-R@E2yGhmS#2s>rukeBzkq`{D;Tg>=zBCr8zc8S9?AibQ%cfjF9ilpGZE_W?T*2J
+zv+0lB{0RvX6i}s%_h6UmyK1E6n^#C?ER&!jHs;RY#JMNplrRG1j5A|-M}HTXykv%&
+zlr5H&PZl6g4EFm69<P7GtdaN`UJb`MOsTHQd-c0z=EPtd16UomybR2fZUvHv(kWn8
+zGNete7I6gFOU?dQrEeucB=>pymT*#J2<!>UtW53G8pNipS9*gDnC2K1>8%7cZy#EW
+zb@+xjd6=TrDrD$*^+`}zb>XWfDnmBzH<w}Y&8oQ|%t>r+^)OJfEJESkq$}c)O8wx*
+z?nKNXV6LBYCLefaj3cp%?9@0rsU?7)c|{i6s=LjS(vO-xIQTQrHB5@>{FlD8yDG$K
+zz$ZYdHvvXdK;X!bUy6G=@-zeDYaLx(sW_@RU7bwr`j-y5Kg9>Nn{Ue?S7BcnX#8Q!
+z;j}tte3$pcB|<UuduBPeo%bLKP1QM`uFpK|KIiMQ-4{trzMVCY877Q%Y9j+AVlDV}
+zsCXZ|FB3W7^if=vejKF?2}DrMoU7Q{*;D;=oqfgbe?iRZs3U<tVqprGij+0N><Ijn
+zSiIBbdRd{p4rf?vk25~lH`@Xh7q$?M16jj(GvU!<$VWji20l8_+ACal4Q_whNzbG;
+z37c(?Xr%}PBNmtk_MK|-t8W8<&3fALk%?&ynbSo&+GV=%mY@w0Qt9f(!HS;R+u_0j
+zw{;;tGd?LKVnOKt!*2dW<6n03H$g7<5kFZSea*3<37L}AJKRRnW9OefgjT-vyAl@1
+zZRDY2bSz=xK*@@Z8zqvGeD?=&1TI?vOD0)KRQsaPk-rc22NV$NxC2C!ds^*m=0M^O
+z4fv~<kSqZj@xe4M3CEB>W6k)s8>eHcNCIl9TG<d|fqbqQo~(*MTM-ZqGP6Hk$*kY=
+zCA2IcdPqRwc@q-@L1U#p*YIHyGx7a6&6gkS7|jq5ug7osp?Of3fH%MGDG?$7pa84I
+zs*K3Hb#VNF8R9pvWvKed^Wq-3>(u1JjV}k4XUboCq&SZ~`Z4(x9vqyhwq@OrToNVU
+zozmWzBEqR*<>=5rry-HpDo(36=nrVq8oBA*XG?8*j>=M?AxFLlaK0H(ssbR6ymY{k
+zQ*rfh&26-L-<5`HO*;^dLcC`I23>#@^@LKtN8qx+mzW7=l*kd#A{s)6x7pp~bO-=j
+zqzXJ8cDj#(JTW&k=GZ!LG+7|z>BNKHHr*<rGhA;P)B0D^(k{wg0f7fA!fqfkj*wn0
+zONex}&&P9c<pa?-b!49d-rqsOspd$%X1nIY39)_g951^Q_b(1V#E6dp-8_LWi<}a(
+z{v!}O<CdRGD~6??F;;i)R8bHhP$C>Tok0@R7(dte(6g`lXJ)d3n+^vLe>LUmaO9S5
+zB_FyFwlSvNJl7vb`lgE3lPE$(Y5m(ROZ5*=kw1^7=&Io6v==a#A&QrlX3Zx!uF&e)
+zoNRdnkO9zP{EFF&@~9KzXN_+s+QiK?xvtY_md3ArG?Nj&ALBNec;^^5b}~WdHhh3N
+z_hdIY)Ma9|VE1?NkV7|mIqqeqP0C;_S(jWYM0Uv|CM5<ARoh{?Ev_-JX2tOC@D}|x
+z@awlbW4bRcy~ow0J-V`yn#i`unF)db21@a0JOdbc?~7p53LLjxoqnMtN}}k5pfopl
+zZ^AH&Hq7gxw|yh9Jz#i7A)+3J$%8e6V}o!!e(uH=a=b=1A|HUC&>9}MUUKQl0f!e~
+zvMk%zn?e{3vsiGiD7aAuHA=2peD@v}{~)Qt-IY9N80x1)^|qAG)7ENe*-QKY`CWfO
+zya7P&g34Y}dssqbROezl<3)&74&tvIMt4k#+9K<wJ3|<(dD@Uk%HgDDT=7~0#Pwuh
+za$)ho1h{OpNU!G@meqqet&{60Z>=6(A5Q?k_F*0Lb1a~$^C8II@SPG+j*L%I8XRwE
+zCQ^hP+)L(*fAd@<-u8cv5txue>js|i1_zX0(0bXFPt{EiByb-m>6r622xB*)s+=-O
+z)oH0c(zuWt`Ll*WN{vyrdLEnSE4rmMqxcp%V`4b81EjO@9DBDa`LQSwP}NYq%c%uc
+zyeHBpKo&u*z=?mxeCH!GN&g^Hc9QjE75E_iPqQ0Aaozv28y2>I6P$l<CH`Lt&Y$G{
+zB{(=(x*L1nk2%k+5I-<=nEkkKe+5t8Oc{tBJGBWG-K^W^4SLmA9)9R4`pm_*kKa&)
+zh{~VvI+<eS^+p+Gax>x$t5q$fG*C&sh^36_r~0Lpz(Qs04n_e;(S?BY3hq>TSh{Us
+ztY%*KaSA)a4H=MEdZimys1x^s){SMe>jAJ?<Ru)fj!uxEIaW$CWwg2MITv+r3NS1v
+zUem9Zw?m1dE-3cUr}QLL5Af632ohGvdk!aSJ7Y@(y)zZTxNO7Yfca4Gc9GzY`Iw#1
+z=iIDy-_4Fy&)Fo@pemQK*!k-0Ry&U&PGRMt@qw6!;|*dMG)j8}aaEFS;l4roSioX}
+z<V3YIb(>b^o7!0$s;EX-v?b({cVccHzWZuKjgYwN_%>`*=!@z)S^UVLS!$D!&JTqw
+z|NddeX6s<=?9bKFq*($ru%+@lc?kvjn#rsgvk|AqR3G$@d5)GveTRh4o_I?>Zrx1C
+zUMY+fsAw^IF4fi_W2z=@X4e;97JwMiI~KsxF18pa^CUlSaP4n&2h(2)3l1#XqPm&0
+z&56kEsbYNWV9|(7SMgu{8IESI!xbsKMTT&reZvIO*m;bm>pKlsW!WOk-9ro*tTXsj
+zR9@w={Z<qkt8<JQZ~BI~x+J+?2$s=eCopMH2ieOL6htqXlOk!F!P6+nvVb2qDOFKI
+zYY6;%71L|hR@46!oIfE!f&vObe|yd>FTiu6Kck<wz8J9V@8+H#OSD;e?Ap|03cRN-
+z2-tW*X<oDg`OVbYI^%ps%lzC03!9xPg1jq{A}1C7yJcyWwf6^vl<W$8qF9E*JGL~(
+z^q%LW*-{gr*v;W}66Ez0(&>Z?7<}zs3i8Fb>oDv1vtVPJ?rjr=eBR-MTAsWR3G|C&
+zJjUaRzGhZqd$PoeNAc%y*k^3mN=M;c2g!Gs=YRq}QH}=8JVT%yNmU}d1tiypyNiP#
+zzyW<mX6wdtct>Yh=|NJ8M^x9~#8bO@`1D99R;T@dkm+y!cm~^+4-Slk{Hdwb6z-}T
+z=tLjI1;zVW4|s(R`RCw7T|l7Vke__|me9jsgH8?WeQ?>7JcoDB!7QDqq*cI{MLWhq
+zEtGP3ksw{PaL<Oy`kPCLGxD3|l!~I{n&03&&HcWiAjP$t9+=fX-CzT2m~3;zZ0O(;
+zq(j*Pwjq08VwBQ*8D51@0g)IpT3k;{XATzEa_OPpSMa_woUl)M^-b}umXo)so_Bg>
+zvv!)7(lE!-5*?*Pq(V#x>JbL&bX!%dGOFJ$JwMeJx|;YbfVQO4pPx+;O7rbF^AYq4
+zl-(FEe#!otUcpR5IN&iIErdSF{$=*vE|Yu|U}w2GZf|jgf@lsjq#UyWf)PBcd_HjX
+z(h1vtE5zE*-@~(e^UUNOby*8v^bf)L6ODff&ff%~w?O>ziWck6{5ISLX7JD@OuFB;
+z9zQQnk1>*(#w2^~=NWGzoQ4Ro)JAEW(5Af373kP907$@8Zz9i`!11yq``EWtcolU%
+z$!_PDJmGy*oZ<X*@EOh(iBAnvkm6WWs=aH>zn<dt4Ep|Iba<#GJZb*mSDlAZcffRq
+z;-f(Ynq4UL+nLkuw6A&E2ecC^nMAq6+F-mZxwqDz^M`(8q*Tmn0>}R1rd%&~6OHQT
+z%r#BRG9Z@@ZHEs6?dMvdp6s`$ZkmPP+cT7Q#4yOHL7w>&99VJRB^`j#cr2yW1pVwq
+z3e!o%jSSAorg)qrjHmhJtw!UJf5kx8lelFHInFd%nsY3PwzMj`=+Jd3M@A5?u@3v2
+zDm15Bt{G7ec`JLWi50SSe%g+u+Ph>V6|Gell>$x#g%xs8*;^IO53s0hytVt-Ksi-7
+zTPB@9-!snGQ4_};R5v{lG+C7BJo6%|@CQj$&B2yGPGEdwfpiZCB*J@X9Bic6(Ze2Q
+z4r?%eo>UnvD@Bl2m8Xpn9Yk4~lg0;Y{(3T#1R3YWkQ_IaTMWPn<<f0bNZX#k4`{;8
+z_XQZ259gXvx}_!e5S<q*$aOvFOM8Agk}O(gRTRxm<X4)s>mxLLiXB_f(u^7<^VLTa
+z`q2R8q@Kj}{>oi10#@8jm-l{W8oEqLxb%d*JyHfW`<ozt#y1*ej;X*%K=+14r;{5<
+z>d;{cs13M1Cp~NMsI1-Wf{WgOz`%uwQCZG|-S8{$o9vyAF^A(N)|l6Aw$Of<#S;)Q
+z9l=G?>2untR@tkJsC7FA1|i)7iarahu)0xOO1TC+l`RxDB{c>R;rH@(yb#lQ8jxjJ
+z-P&HxkW6+SA2I40k2~QO&4J2O4iN{57wbp41>iFcIm}6<W7W!V8#y!pWo@-j^{Cjc
+zYlRu-E8_6Jqy<vNl*rcOh5fkK12i~QAmQNCN`Jt*Qwbpj);62`i$kc{@jRor9Vz7S
+z2}U7mhy7g_Y?e4tQM)*b!tw0^R>nxdi}6u|=oh|@tU;ZI5^BdeThUD0J31%k5|K`5
+z+=TUX=H$7(gpP4Zq4_O<>$Je-{b#a{RF}#YBsn-$sOOf@_^#Cg;e_u->Y4TP2u%8e
+z(FM=<DwZ)3yVdso5{71E{{XJS_y-bgqt7>~46V4=Hyxv+T)%JPrFUYY%}5{&&iK+z
+zg=S;%9+UQ7l)ZeFFBO3It+)$;c*}Pq><*@nPRxefJHI$AeZ4IJ=judxHb5jn*r@Gd
+zoyK+A&nD3b6utQRM2x*p$QAo?w}d0AZ1k2>az{R<2LjB=suX#*wW^VQRtbi;T>DLZ
+zbpJ$k&RCLtzahdWkV%|{epw$H4ISIbA6^r4tji^b{fi_aC7tsv<-Zpk_J0$cfA2Q`
+zUkT2i<ozW$Vul}bJc;<wMrnxe2)JnnEgQ}2M$>gU>cZ|p)-`ugH@}9LitPwgRMX8Z
+zo_|E;h~g3m^p)soM^LCCBzv(}x$c7qV~Zv08Q#MI@*~0QX4TSF70!K@$}PayJbR_w
+zsY9xI=eLNK%o`!Sa{DB4TQPQeJ?|XZkfdnVJ?|R<`WZXohV#vhnK_NIS_nmni})ZC
+z3+@j4AF&qr;#O-JrLlbq_Cs4<pLKEzz&i`3k+n*@Kch{6mZn%D8TmyoQ-z-VJG2D-
+z4eugZGlg4{-5DbVqn!#>Xl7-QaG*~OqCj+^_92;4d0?^<DlByuV|uI%D0!3?S=ooL
+z`h`OPQN&b4%Uj*`VMS#gz0Q`!pde#+mvctk25hGj`1T8qd(MUhmxGscb(!Be&q3kw
+za06@+PpPrEy|%nkEJ)MS6PK{*w$;TXrGf78hL#;H_gk>2ie^lM71VMYb9*yiesZE_
+zvcNYUDO;^sdu=IS!!n*t8Zi@~5qVcoKBCA2eA-x$z?xYz6q;l@sa>J%FGbUH+hP($
+zozRZKwKwhENNW%9YjQ-IR6$S>)F>0-!b(k(vmL=!5KtP27$s))&4fNk4vh1*jzHm-
+z<yd}kQ)o=mm=3`mN%Is%FktYPS}-*9vLP(;Xa5QSn*GQTVc7Z<TX)`r#=I&pVN?DD
+z+#-q1)jf7GIW!5DnK>aX{f(zT6P!OGL4pE0k%c(+h(i^^+K|=;il3IIxRA+SCEkF%
+zA>VO<<}lN7wjZG&?NMuiD>&QRNt-)g!CH`*qJEI#cGZi|!SO*znMU9F5j{d!Amu4<
+zHQ1izq-O%*Vo?AxwU9gxm}wQ4oJ$*#D9r^Orrd)O;<rhI0Jib|xM&%-w?>j7!5M4i
+zlw~Th@zrOaD1m>1$Z>P_YfIugDTtpW)ya_Wl~PKh)rDz#oW;x$(%WnA`;{X<D($(v
+zKsT&jtp)~Ep5qz6_qImf7mQg_94#<*m>#WD6>|6#`APx-P94Dp@XV>YPMvULHW1B^
+zqUjr6aj++x`a!z2^b@f}23QuS;u0dG&f<^Yd`VdI${rJAsMtNp()xU0TAw5f9A+>)
+zzUD0VOMPqSD}IpBr6ZVIRb?x+;v@vE{#i)_IQw}>{aH<*vZ;cPEGiyOnOjZuaWqE=
+ziQuaR-qf+aN*e*NP%E!^1ptyELS5RG0%&i1I_&TD`EF)r-AZ~C&TM}oAUMC>_p+Yy
+zptzFnmmm~Z&8(%gDGD7UpR1BoYL#xapc%cr6gJV7oF@xE0c+A)2^wQajij{{5xP00
+za)zi=kwVmra2R>QwB~|f3Yr~>Z7K<PCG*ph@yoG#w+R8NR`uR2<L5+8B+4%%VHu^%
+z{B3R=ai&%xwt~TTkpK;BDA=GcUWo3VJ+1uz5S%~J_?O`PO%UK&B%qccL0K!<)}Jgx
+zUW9At-cAZp1FZvNz$dqKfHER!&W+Jo<@D(YpPtACyvKoPgRVnBtN@tiP8Kn!rs?Iw
+zvSho@U3>duwMAQaiW*F^(8|kNBNtNZtE6-_bzbz>3JKaWl}9)kUk}5?Pb9OAA(v_B
+zV95aNhO>f53rnOiH^^L=f)bPZE&-FBF{^a`7^@b{je|l(x|{qb_pIvm(|&YXba)Y-
+zLKs+WI{#uLU^pIt5RZP1c3X`M_x0zVgbZrco^N0x$s5v}S8@g)2=WUTty7R8{rvzq
+z=l9pZk@}yWWYZGDUx0TsJ9hf>=)$j|jGpJ;z4-NNG11&%O%wcS#CBy=2_lc;?ZjCG
+z<NY4ISfW@|+>ZxYd~Vl7A3N5+t;Qp-CDiB(R|5;i%5!A_PtSqV+{ASzSr^o<v|lpC
+zA|9mXBomB!CHrGXz>=KS5tTFcuRS41xOWy#-Of}BMvBmeQsulqB(eF(bZ})!Im2*K
+zAAd?GvnLG{^<m>F?`&~9T7Q{<EqW}*ulj}U03sfBd%BH97yV=g1rqd%!u-l(C9`)8
+zv$xZazjerJM@)<qH$NO8V$NEE+UF>#zM1cUtp--@>me6nq-ZPMik+l6^J2G_<%V3O
+ue3U-ctTB~?BCN#3Uf!nlny+a`<S)Ayr29X-(22qvfF%tvj(q!@ApZw*v$N&^
+
+delta 8
+Pcmcb9pXpcdhF_Wh7eEBr
+
diff --git a/SOURCES/0237-ukify-do-not-fail-if-pefile-complains-about-hardcode.patch b/SOURCES/0237-ukify-do-not-fail-if-pefile-complains-about-hardcode.patch
new file mode 100644
index 0000000000000000000000000000000000000000..fafca0d26c198aa7cef52e7a1286d9433b5bb06b
--- /dev/null
+++ b/SOURCES/0237-ukify-do-not-fail-if-pefile-complains-about-hardcode.patch
@@ -0,0 +1,39 @@
+From 87224a2d4efa30b48407f71aad3ee2df591fe224 Mon Sep 17 00:00:00 2001
+From: Luca Boccassi <luca.boccassi@gmail.com>
+Date: Thu, 30 Jan 2025 01:19:59 +0000
+Subject: [PATCH] ukify: do not fail if pefile complains about hardcoded 256MB
+ limit
+
+pefile has an hardcoded limit to 256MB per section:
+
+https://github.com/erocarrera/pefile/issues/396
+
+When building an initrd with large firmware files and
+lots of kernel modules, this limit can be reached.
+Skip over those warnings.
+
+(cherry picked from commit 32caed550f5a81eb87d2e39bc83917df2898d844)
+---
+ src/ukify/ukify.py | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/src/ukify/ukify.py b/src/ukify/ukify.py
+index 7a9f63e1d4..6ad4298ebe 100755
+--- a/src/ukify/ukify.py
++++ b/src/ukify/ukify.py
+@@ -892,8 +892,14 @@ def pe_add_sections(uki: UKI, output: str) -> None:
+     )
+     pe = pefile.PE(data=pe.write(), fast_load=True)
+ 
++    # pefile has an hardcoded limit of 256MB, which is not enough when building an initrd with large firmware
++    # files and all kernel modules. See: https://github.com/erocarrera/pefile/issues/396
+     warnings = pe.get_warnings()
+-    if warnings:
++    for w in warnings:
++        if 'VirtualSize is extremely large' in w:
++            continue
++        if 'VirtualAddress is beyond' in w:
++            continue
+         raise PEError(f'pefile warnings treated as errors: {warnings}')
+ 
+     security = pe.OPTIONAL_HEADER.DATA_DIRECTORY[pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_SECURITY']]
diff --git a/SOURCES/0238-tmpfiles-fix-copypasta-in-create_symlink-FIFO-symlin.patch b/SOURCES/0238-tmpfiles-fix-copypasta-in-create_symlink-FIFO-symlin.patch
new file mode 100644
index 0000000000000000000000000000000000000000..00516b78742dc65f71326a30586f82111ebc2953
--- /dev/null
+++ b/SOURCES/0238-tmpfiles-fix-copypasta-in-create_symlink-FIFO-symlin.patch
@@ -0,0 +1,23 @@
+From 6caab0c58c8c43c5d4244e2ef2bb739aa06d81c0 Mon Sep 17 00:00:00 2001
+From: Mike Yuan <me@yhndnzj.com>
+Date: Sun, 9 Feb 2025 15:38:05 +0100
+Subject: [PATCH] tmpfiles: fix copypasta in create_symlink() (FIFO -> symlink)
+
+(cherry picked from commit 6f91e7a3bea2c5046354b31cb650b54e3b2884d5)
+---
+ src/tmpfiles/tmpfiles.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
+index bff05cda6f..b699a1e5be 100644
+--- a/src/tmpfiles/tmpfiles.c
++++ b/src/tmpfiles/tmpfiles.c
+@@ -2422,7 +2422,7 @@ static int create_symlink(Context *c, Item *i) {
+                 return log_error_errno(r, "Failed to extract filename from path '%s': %m", i->path);
+         if (r == O_DIRECTORY)
+                 return log_error_errno(SYNTHETIC_ERRNO(EISDIR),
+-                                       "Cannot open path '%s' for creating FIFO, is a directory.", i->path);
++                                       "Cannot open path '%s' for creating symlink, is a directory.", i->path);
+ 
+         if (arg_dry_run) {
+                 log_info("Would create symlink %s -> %s", i->path, i->argument);
diff --git a/SOURCES/0239-udev-worker-add-debugging-log-about-success-of-flock.patch b/SOURCES/0239-udev-worker-add-debugging-log-about-success-of-flock.patch
new file mode 100644
index 0000000000000000000000000000000000000000..2a72cada72d4b423471dd76d03ac5f453a4994a0
--- /dev/null
+++ b/SOURCES/0239-udev-worker-add-debugging-log-about-success-of-flock.patch
@@ -0,0 +1,23 @@
+From a112fca1212c1488c6c43991df2be1fc171b8138 Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Wed, 12 Feb 2025 09:20:51 +0900
+Subject: [PATCH] udev-worker: add debugging log about success of flock() for
+ whole block device
+
+(cherry picked from commit 951def0e276c041a262b3f147bb42206195fe13e)
+---
+ src/udev/udev-worker.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/src/udev/udev-worker.c b/src/udev/udev-worker.c
+index 59f56f653c..fc1bfd684c 100644
+--- a/src/udev/udev-worker.c
++++ b/src/udev/udev-worker.c
+@@ -123,6 +123,7 @@ static int worker_lock_whole_disk(sd_device *dev, int *ret_fd) {
+         if (flock(fd, LOCK_SH|LOCK_NB) < 0)
+                 return log_device_debug_errno(dev, errno, "Failed to flock(%s): %m", val);
+ 
++        log_device_debug(dev, "Successfully took flock(LOCK_SH) for %s, it will be released after the event has been processed.", val);
+         *ret_fd = TAKE_FD(fd);
+         return 1;
+ 
diff --git a/SOURCES/0240-udev-watch-mention-that-the-failure-is-ignored.patch b/SOURCES/0240-udev-watch-mention-that-the-failure-is-ignored.patch
new file mode 100644
index 0000000000000000000000000000000000000000..2f8ec37da0d8bc0938a2b66557164bbc3e847237
--- /dev/null
+++ b/SOURCES/0240-udev-watch-mention-that-the-failure-is-ignored.patch
@@ -0,0 +1,23 @@
+From cc77e140a8b194f710f33c9f552750ce350e6122 Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Wed, 12 Feb 2025 09:22:49 +0900
+Subject: [PATCH] udev-watch: mention that the failure is ignored
+
+(cherry picked from commit a52aad3b4bb735a22ce67110142d135819589a87)
+---
+ src/udev/udev-watch.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/udev/udev-watch.c b/src/udev/udev-watch.c
+index 1b8e2b8dbd..9bd34af858 100644
+--- a/src/udev/udev-watch.c
++++ b/src/udev/udev-watch.c
+@@ -167,7 +167,7 @@ finalize:
+         /* 5. remove symlink ID -> wd.
+          * The file is always owned by the device. Hence, it is safe to remove it unconditionally. */
+         if (unlinkat(dirfd, id, 0) < 0 && errno != ENOENT)
+-                log_device_debug_errno(dev, errno, "Failed to remove '/run/udev/watch/%s': %m", id);
++                log_device_debug_errno(dev, errno, "Failed to remove '/run/udev/watch/%s', ignoring: %m", id);
+ 
+         return r;
+ }
diff --git a/SOURCES/0241-udev-watch-do-not-try-to-remove-invalid-watch-handle.patch b/SOURCES/0241-udev-watch-do-not-try-to-remove-invalid-watch-handle.patch
new file mode 100644
index 0000000000000000000000000000000000000000..1c6a5742ee50cd4d568986ca9aa60308757f2ed0
--- /dev/null
+++ b/SOURCES/0241-udev-watch-do-not-try-to-remove-invalid-watch-handle.patch
@@ -0,0 +1,42 @@
+From d32f4bcaf274e208568a5e6151c0a81d00d80438 Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Wed, 12 Feb 2025 09:23:33 +0900
+Subject: [PATCH] udev-watch: do not try to remove invalid watch handle
+
+When a new device is processed, there should be no watch handle for
+the device, hence udev_watch_clear() provides -1. Let's not try to call
+inotify_rm_watch() in that case.
+
+This should not change any behavior. Just for suppressing spurious
+debugging log:
+=====
+(udev-worker)[3626140]: zram1: Removing watch handle -1.
+=====
+
+(cherry picked from commit b3b442062045eac61a9dd3ed73b650dfb5be0b46)
+---
+ src/udev/udev-watch.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/udev/udev-watch.c b/src/udev/udev-watch.c
+index 9bd34af858..82db39fecd 100644
+--- a/src/udev/udev-watch.c
++++ b/src/udev/udev-watch.c
+@@ -161,7 +161,7 @@ static int udev_watch_clear(sd_device *dev, int dirfd, int *ret_wd) {
+ 
+         if (ret_wd)
+                 *ret_wd = wd;
+-        r = 0;
++        r = 1;
+ 
+ finalize:
+         /* 5. remove symlink ID -> wd.
+@@ -249,7 +249,7 @@ int udev_watch_end(int inotify_fd, sd_device *dev) {
+ 
+         /* First, clear symlinks. */
+         r = udev_watch_clear(dev, dirfd, &wd);
+-        if (r < 0)
++        if (r <= 0)
+                 return r;
+ 
+         /* Then, remove inotify watch. */
diff --git a/SOURCES/0242-login-Continue-watching-leader-pidfd-after-stop.patch b/SOURCES/0242-login-Continue-watching-leader-pidfd-after-stop.patch
new file mode 100644
index 0000000000000000000000000000000000000000..a297845d7ce00cb4b15ed23a26b891323c315f79
--- /dev/null
+++ b/SOURCES/0242-login-Continue-watching-leader-pidfd-after-stop.patch
@@ -0,0 +1,35 @@
+From b555b473a4c206db28d75d82f2a7fc43accf998f Mon Sep 17 00:00:00 2001
+From: msizanoen <msizanoen@qtmlabs.xyz>
+Date: Wed, 12 Feb 2025 22:09:01 +0700
+Subject: [PATCH] login: Continue watching leader pidfd after stop
+
+This ensures that garbage collection will be triggered when the leader
+process dies.
+
+(cherry picked from commit b2a4109031c1bd79c498f8642df150deeebe1708)
+---
+ src/login/logind-session.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/src/login/logind-session.c b/src/login/logind-session.c
+index 351b64b60b..e825d39f6c 100644
+--- a/src/login/logind-session.c
++++ b/src/login/logind-session.c
+@@ -90,6 +90,9 @@ static int session_dispatch_leader_pidfd(sd_event_source *es, int fd, uint32_t r
+         Session *s = ASSERT_PTR(userdata);
+ 
+         assert(s->leader.fd == fd);
++
++        s->leader_pidfd_event_source = sd_event_source_unref(s->leader_pidfd_event_source);
++
+         session_stop(s, /* force= */ false);
+ 
+         return 1;
+@@ -950,7 +953,6 @@ int session_stop(Session *s, bool force) {
+                 return 0;
+ 
+         s->timer_event_source = sd_event_source_unref(s->timer_event_source);
+-        s->leader_pidfd_event_source = sd_event_source_unref(s->leader_pidfd_event_source);
+ 
+         if (s->seat)
+                 seat_evict_position(s->seat, s);
diff --git a/SOURCES/0243-login-Queue-session-for-garbage-collection-on-leader.patch b/SOURCES/0243-login-Queue-session-for-garbage-collection-on-leader.patch
new file mode 100644
index 0000000000000000000000000000000000000000..1a2b86d1b91199f2e155370ad8eebe02ab3884ac
--- /dev/null
+++ b/SOURCES/0243-login-Queue-session-for-garbage-collection-on-leader.patch
@@ -0,0 +1,35 @@
+From 528d7d616fab8466111c8767010143e1beb1e22d Mon Sep 17 00:00:00 2001
+From: msizanoen <msizanoen@qtmlabs.xyz>
+Date: Wed, 12 Feb 2025 21:27:25 +0700
+Subject: [PATCH] login: Queue session for garbage collection on leader death
+
+This ensures sessions are cleaned up properly in case the user service
+manager was manually stopped.
+
+(cherry picked from commit a6bccda28d398925397d3a8f0c7491ba03941f23)
+---
+ src/login/logind-session.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/src/login/logind-session.c b/src/login/logind-session.c
+index e825d39f6c..57cc37ccc4 100644
+--- a/src/login/logind-session.c
++++ b/src/login/logind-session.c
+@@ -95,6 +95,8 @@ static int session_dispatch_leader_pidfd(sd_event_source *es, int fd, uint32_t r
+ 
+         session_stop(s, /* force= */ false);
+ 
++        session_add_to_gc_queue(s);
++
+         return 1;
+ }
+ 
+@@ -1263,6 +1265,8 @@ static int session_dispatch_fifo(sd_event_source *es, int fd, uint32_t revents,
+         session_remove_fifo(s);
+         session_stop(s, /* force = */ false);
+ 
++        session_add_to_gc_queue(s);
++
+         return 1;
+ }
+ 
diff --git a/SOURCES/0244-ukify-print-debug-progress-messages-to-stderr.patch b/SOURCES/0244-ukify-print-debug-progress-messages-to-stderr.patch
new file mode 100644
index 0000000000000000000000000000000000000000..b19329caa6d982b05ccaeed634132c1620c83359
--- /dev/null
+++ b/SOURCES/0244-ukify-print-debug-progress-messages-to-stderr.patch
@@ -0,0 +1,180 @@
+From 47be0e801ef7761a2472fd704400e4fd3b737625 Mon Sep 17 00:00:00 2001
+From: Luca Boccassi <luca.boccassi@gmail.com>
+Date: Sun, 19 Jan 2025 15:42:47 +0000
+Subject: [PATCH] ukify: print debug/progress messages to stderr
+
+Otherwise json will be interleaved with plain text messages
+
+(cherry picked from commit 7d64e2f368ec7c683fee95d21f527c406b8eb5e6)
+---
+ src/ukify/ukify.py | 39 +++++++++++++++++++++------------------
+ 1 file changed, 21 insertions(+), 18 deletions(-)
+
+diff --git a/src/ukify/ukify.py b/src/ukify/ukify.py
+index 6ad4298ebe..9570898011 100755
+--- a/src/ukify/ukify.py
++++ b/src/ukify/ukify.py
+@@ -324,7 +324,7 @@ class Uname:
+             filename,
+         ]
+ 
+-        print('+', shell_join(cmd))
++        print('+', shell_join(cmd), file=sys.stderr)
+         try:
+             notes = subprocess.check_output(cmd, stderr=subprocess.PIPE, text=True)
+         except subprocess.CalledProcessError as e:
+@@ -355,7 +355,7 @@ class Uname:
+         for func in (cls.scrape_x86, cls.scrape_elf, cls.scrape_generic):
+             try:
+                 version = func(filename, opts=opts)
+-                print(f'Found uname version: {version}')
++                print(f'Found uname version: {version}', file=sys.stderr)
+                 return version
+             except ValueError as e:
+                 print(str(e))
+@@ -495,7 +495,7 @@ class PeSign(SignTool):
+             '-o', output_f,
+         ]  # fmt: skip
+ 
+-        print('+', shell_join(cmd))
++        print('+', shell_join(cmd), file=sys.stderr)
+         subprocess.check_call(cmd)
+ 
+     @staticmethod
+@@ -505,7 +505,7 @@ class PeSign(SignTool):
+         tool = find_tool('pesign', opts=opts)
+         cmd = [tool, '-i', opts.linux, '-S']
+ 
+-        print('+', shell_join(cmd))
++        print('+', shell_join(cmd), file=sys.stderr)
+         info = subprocess.check_output(cmd, text=True)
+ 
+         return 'No signatures found.' in info
+@@ -527,7 +527,7 @@ class SbSign(SignTool):
+             '--output', output_f,
+         ]  # fmt: skip
+ 
+-        print('+', shell_join(cmd))
++        print('+', shell_join(cmd), file=sys.stderr)
+         subprocess.check_call(cmd)
+ 
+     @staticmethod
+@@ -537,7 +537,7 @@ class SbSign(SignTool):
+         tool = find_tool('sbverify', opts=opts)
+         cmd = [tool, '--list', opts.linux]
+ 
+-        print('+', shell_join(cmd))
++        print('+', shell_join(cmd), file=sys.stderr)
+         info = subprocess.check_output(cmd, text=True)
+ 
+         return 'No signature table present' in info
+@@ -579,7 +579,7 @@ class SystemdSbSign(SignTool):
+             '--output', output_f,
+         ]  # fmt: skip
+ 
+-        print('+', shell_join(cmd))
++        print('+', shell_join(cmd), file=sys.stderr)
+         subprocess.check_call(cmd)
+ 
+     @staticmethod
+@@ -626,7 +626,7 @@ def check_splash(filename: Optional[Path]) -> None:
+         return
+ 
+     img = Image.open(filename, formats=['BMP'])
+-    print(f'Splash image {filename} is {img.width}×{img.height} pixels')
++    print(f'Splash image {filename} is {img.width}×{img.height} pixels', file=sys.stderr)
+ 
+ 
+ def check_inputs(opts: UkifyConfig) -> None:
+@@ -769,7 +769,7 @@ def call_systemd_measure(uki: UKI, opts: UkifyConfig, profile_start: int = 0) ->
+                 *(f'--phase={phase_path}' for phase_path in itertools.chain.from_iterable(pp_groups)),
+             ]
+ 
+-            print('+', shell_join(cmd))
++            print('+', shell_join(cmd), file=sys.stderr)
+             subprocess.check_call(cmd)
+ 
+     # PCR signing
+@@ -807,7 +807,7 @@ def call_systemd_measure(uki: UKI, opts: UkifyConfig, profile_start: int = 0) ->
+ 
+                 extra += [f'--phase={phase_path}' for phase_path in group or ()]
+ 
+-                print('+', shell_join(cmd + extra))  # type: ignore
++                print('+', shell_join(cmd + extra), file=sys.stderr)  # type: ignore
+                 pcrsig = subprocess.check_output(cmd + extra, text=True)  # type: ignore
+                 pcrsig = json.loads(pcrsig)
+                 pcrsigs += [pcrsig]
+@@ -1120,7 +1120,7 @@ def make_uki(opts: UkifyConfig) -> None:
+             signtool.sign(os.fspath(opts.linux), os.fspath(linux), opts=opts)
+ 
+     if opts.uname is None and opts.linux is not None:
+-        print('Kernel version not specified, starting autodetection 😖.')
++        print('Kernel version not specified, starting autodetection 😖.', file=sys.stderr)
+         opts.uname = Uname.scrape(opts.linux, opts=opts)
+ 
+     uki = UKI(opts.stub)
+@@ -1138,7 +1138,7 @@ def make_uki(opts: UkifyConfig) -> None:
+                 if opts.certificate_provider:
+                     cmd += ['--certificate-source', f'provider:{opts.certificate_provider}']
+ 
+-                print('+', shell_join(cmd))
++                print('+', shell_join(cmd), file=sys.stderr)
+                 pcrpkey = subprocess.check_output(cmd)
+             else:
+                 pcrpkey = Path(opts.pcr_public_keys[0])
+@@ -1150,7 +1150,7 @@ def make_uki(opts: UkifyConfig) -> None:
+             if opts.signing_provider:
+                 cmd += ['--private-key-source', f'provider:{opts.signing_provider}']
+ 
+-            print('+', shell_join(cmd))
++            print('+', shell_join(cmd), file=sys.stderr)
+             pcrpkey = subprocess.check_output(cmd)
+ 
+     hwids = None
+@@ -1249,7 +1249,10 @@ def make_uki(opts: UkifyConfig) -> None:
+             if n not in to_import:
+                 continue
+ 
+-            print(f"Copying section '{n}' from '{profile}': {pesection.Misc_VirtualSize} bytes")
++            print(
++                f"Copying section '{n}' from '{profile}': {pesection.Misc_VirtualSize} bytes",
++                file=sys.stderr,
++            )
+             uki.add_section(
+                 Section.create(n, pesection.get_data(length=pesection.Misc_VirtualSize), measure=True)
+             )
+@@ -1278,7 +1281,7 @@ def make_uki(opts: UkifyConfig) -> None:
+         os.umask(umask := os.umask(0))
+         os.chmod(opts.output, 0o777 & ~umask)
+ 
+-    print(f'Wrote {"signed" if sign_args_present else "unsigned"} {opts.output}')
++    print(f'Wrote {"signed" if sign_args_present else "unsigned"} {opts.output}', file=sys.stderr)
+ 
+ 
+ @contextlib.contextmanager
+@@ -1930,14 +1933,14 @@ def apply_config(namespace: argparse.Namespace, filename: Union[str, Path, None]
+         if namespace.config:
+             # Config set by the user, use that.
+             filename = namespace.config
+-            print(f'Using config file: {filename}')
++            print(f'Using config file: {filename}', file=sys.stderr)
+         else:
+             # Try to look for a config file then use the first one found.
+             for config_dir in DEFAULT_CONFIG_DIRS:
+                 filename = Path(config_dir) / DEFAULT_CONFIG_FILE
+                 if filename.is_file():
+                     # Found a config file, use it.
+-                    print(f'Using found config file: {filename}')
++                    print(f'Using found config file: {filename}', file=sys.stderr)
+                     break
+             else:
+                 # No config file specified or found, nothing to do.
+@@ -2061,7 +2064,7 @@ def finalize_options(opts: argparse.Namespace) -> None:
+     elif opts.linux or opts.initrd:
+         raise ValueError('--linux=/--initrd= options cannot be used with positional arguments')
+     else:
+-        print("Assuming obsolete command line syntax with no verb. Please use 'build'.")
++        print("Assuming obsolete command line syntax with no verb. Please use 'build'.", file=sys.stderr)
+         if opts.positional:
+             opts.linux = Path(opts.positional[0])
+         # If we have initrds from parsing config files, append our positional args at the end
diff --git a/SOURCES/0245-ukify-Calculate-section-size-more-correctly.patch b/SOURCES/0245-ukify-Calculate-section-size-more-correctly.patch
new file mode 100644
index 0000000000000000000000000000000000000000..de580c90b8c3a65656920f8f4588132147f9473d
--- /dev/null
+++ b/SOURCES/0245-ukify-Calculate-section-size-more-correctly.patch
@@ -0,0 +1,53 @@
+From f01ba41caefd8e574a6eda2af9f577d2d24d03e6 Mon Sep 17 00:00:00 2001
+From: Daan De Meyer <daan.j.demeyer@gmail.com>
+Date: Wed, 29 Jan 2025 14:44:27 +0100
+Subject: [PATCH] ukify: Calculate section size more correctly
+
+We should only use Misc_VirtualSize if it's smaller than SizeOfRawData,
+since in that case it'll be the non-aligned section size. Otherwise we
+have to use SizeOfRawData to get the size on disk.
+
+(cherry picked from commit 33b25fa11c408ae40f2aa4300220504329a23a52)
+---
+ src/ukify/ukify.py | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/src/ukify/ukify.py b/src/ukify/ukify.py
+index 9570898011..b246fe13ca 100755
+--- a/src/ukify/ukify.py
++++ b/src/ukify/ukify.py
+@@ -710,6 +710,10 @@ def pe_strip_section_name(name: bytes) -> str:
+     return name.rstrip(b'\x00').decode()
+ 
+ 
++def pe_section_size(section: pefile.SectionStructure) -> int:
++    return cast(int, min(section.Misc_VirtualSize, section.SizeOfRawData))
++
++
+ def call_systemd_measure(uki: UKI, opts: UkifyConfig, profile_start: int = 0) -> None:
+     measure_tool = find_tool(
+         'systemd-measure',
+@@ -1250,11 +1254,11 @@ def make_uki(opts: UkifyConfig) -> None:
+                 continue
+ 
+             print(
+-                f"Copying section '{n}' from '{profile}': {pesection.Misc_VirtualSize} bytes",
++                f"Copying section '{n}' from '{profile}': {pe_section_size(pesection)} bytes",
+                 file=sys.stderr,
+             )
+             uki.add_section(
+-                Section.create(n, pesection.get_data(length=pesection.Misc_VirtualSize), measure=True)
++                Section.create(n, pesection.get_data(length=pe_section_size(pesection)), measure=True)
+             )
+ 
+         call_systemd_measure(uki, opts=opts, profile_start=prev_len)
+@@ -1434,8 +1438,7 @@ def inspect_section(
+ 
+     ttype = config.output_mode if config else DEFAULT_SECTIONS_TO_SHOW.get(name, 'binary')
+ 
+-    size = section.Misc_VirtualSize
+-    # TODO: Use ignore_padding once we can depend on a newer version of pefile
++    size = pe_section_size(section)
+     data = section.get_data(length=size)
+     digest = sha256(data).hexdigest()
+ 
diff --git a/SOURCES/0246-mkosi-Update-to-latest.patch b/SOURCES/0246-mkosi-Update-to-latest.patch
new file mode 100644
index 0000000000000000000000000000000000000000..80f3f67ff627994494096316a6e774c708731dde
--- /dev/null
+++ b/SOURCES/0246-mkosi-Update-to-latest.patch
@@ -0,0 +1,281 @@
+From 158c9ca6a9f28fce35422cf5e55d6fa55e402f41 Mon Sep 17 00:00:00 2001
+From: Daan De Meyer <daan.j.demeyer@gmail.com>
+Date: Wed, 12 Feb 2025 11:09:36 +0100
+Subject: [PATCH] mkosi: Update to latest
+
+In https://github.com/systemd/mkosi/pull/3497, mkosi has started parsing
+options passed after the verb as regular mkosi options instead of options
+for the invoked command. We adapt to this change by adding '--' as a delimiter
+everywhere where required.
+
+(cherry picked from commit b429f82eaf774d9b9f67c201770074a9ec72647e)
+---
+ .github/workflows/coverage.yml     | 16 ++++++------
+ .github/workflows/mkosi.yml        | 12 ++++-----
+ docs/HACKING.md                    | 40 +++++++++++++++---------------
+ test/README.testsuite              | 14 +++++------
+ test/fmf/integration-tests/test.sh |  8 +++---
+ 5 files changed, 45 insertions(+), 45 deletions(-)
+
+diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml
+index 6503059ef4..1cce9a97f3 100644
+--- a/.github/workflows/coverage.yml
++++ b/.github/workflows/coverage.yml
+@@ -16,7 +16,7 @@ jobs:
+ 
+     steps:
+       - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
+-      - uses: systemd/mkosi@0de0aa905625317ff10cc4b44ec9379a7aa65aa6
++      - uses: systemd/mkosi@d501139032aa659fa8d34bdb850f4eb6b5f458ed
+ 
+       # Freeing up disk space with rm -rf can take multiple minutes. Since we don't need the extra free space
+       # immediately, we remove the files in the background. However, we first move them to a different location
+@@ -74,23 +74,23 @@ jobs:
+         run: mkosi summary
+ 
+       - name: Build tools tree
+-        run: sudo mkosi -f sandbox true
++        run: sudo mkosi -f sandbox -- true
+ 
+       - name: Configure meson
+         run: |
+-          sudo mkosi sandbox \
++          sudo mkosi sandbox -- \
+             meson setup \
+             --buildtype=debugoptimized \
+             -Dintegration-tests=true \
+             build
+ 
+       - name: Build image
+-        run: sudo mkosi sandbox meson compile -C build mkosi
++        run: sudo mkosi sandbox -- meson compile -C build mkosi
+ 
+       - name: Initial coverage report
+         run: |
+           sudo mkdir -p build/test/coverage
+-          sudo mkosi sandbox \
++          sudo mkosi sandbox -- \
+             lcov \
+             --directory build/mkosi.builddir/arch~rolling~x86-64 \
+             --capture \
+@@ -107,7 +107,7 @@ jobs:
+           # --preserve-env makes sure all the github actions environment variables are propagated which are
+           # used in integration-test-wrapper.py to construct the `gh` command line to download the journals
+           # of failed tests.
+-          sudo --preserve-env mkosi sandbox \
++          sudo --preserve-env mkosi sandbox -- \
+             meson test \
+             -C build \
+             --no-rebuild \
+@@ -136,10 +136,10 @@ jobs:
+               lcov_args+=(--add-tracefile "${file}")
+           done < <(find build/test/coverage -name "TEST-*.coverage-info")
+ 
+-          sudo mkosi sandbox lcov --ignore-errors inconsistent,inconsistent "${lcov_args[@]}" --output-file build/test/coverage/everything.coverage-info
++          sudo mkosi sandbox -- lcov --ignore-errors inconsistent,inconsistent "${lcov_args[@]}" --output-file build/test/coverage/everything.coverage-info
+ 
+       - name: List coverage report
+-        run: sudo mkosi sandbox lcov --ignore-errors inconsistent,inconsistent --list build/test/coverage/everything.coverage-info
++        run: sudo mkosi sandbox -- lcov --ignore-errors inconsistent,inconsistent --list build/test/coverage/everything.coverage-info
+ 
+       - name: Coveralls
+         uses: coverallsapp/github-action@648a8eb78e6d50909eff900e4ec85cab4524a45b
+diff --git a/.github/workflows/mkosi.yml b/.github/workflows/mkosi.yml
+index d662d65dad..2b00498243 100644
+--- a/.github/workflows/mkosi.yml
++++ b/.github/workflows/mkosi.yml
+@@ -120,7 +120,7 @@ jobs:
+ 
+     steps:
+       - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
+-      - uses: systemd/mkosi@0de0aa905625317ff10cc4b44ec9379a7aa65aa6
++      - uses: systemd/mkosi@d501139032aa659fa8d34bdb850f4eb6b5f458ed
+ 
+       # Freeing up disk space with rm -rf can take multiple minutes. Since we don't need the extra free space
+       # immediately, we remove the files in the background. However, we first move them to a different location
+@@ -188,22 +188,22 @@ jobs:
+         run: mkosi summary
+ 
+       - name: Build tools tree
+-        run: sudo mkosi -f sandbox true
++        run: sudo mkosi -f sandbox -- true
+ 
+       - name: Configure meson
+         run: |
+-          sudo mkosi sandbox \
++          sudo mkosi sandbox -- \
+             meson setup \
+             --buildtype=debugoptimized \
+             -Dintegration-tests=true \
+             build
+ 
+       - name: Build image
+-        run: sudo mkosi sandbox meson compile -C build mkosi
++        run: sudo mkosi sandbox -- meson compile -C build mkosi
+ 
+       - name: Run integration tests
+         run: |
+-          if [[ "$(sudo mkosi sandbox meson test --help)" == *"--max-lines"* ]]; then
++          if [[ "$(sudo mkosi sandbox -- meson test --help)" == *"--max-lines"* ]]; then
+               MAX_LINES=(--max-lines 300)
+           else
+               MAX_LINES=()
+@@ -212,7 +212,7 @@ jobs:
+           # --preserve-env makes sure all the github actions environment variables are propagated which are
+           # used in integration-test-wrapper.py to construct the `gh` command line to download the journals
+           # of failed tests.
+-          sudo --preserve-env mkosi sandbox \
++          sudo --preserve-env mkosi sandbox -- \
+             env \
+             TEST_PREFER_QEMU=${{ matrix.vm }} \
+             TEST_SKIP=${{ matrix.skip }} \
+diff --git a/docs/HACKING.md b/docs/HACKING.md
+index e534a51335..697ec9b545 100644
+--- a/docs/HACKING.md
++++ b/docs/HACKING.md
+@@ -39,18 +39,18 @@ chance that your distribution's packaged version of mkosi will be too old.
+ Then, you can build and run systemd executables as follows:
+ 
+ ```sh
+-$ mkosi -f sandbox meson setup build
+-$ mkosi -f sandbox meson compile -C build
+-$ mkosi -f sandbox build/systemctl --version
++$ mkosi -f sandbox -- meson setup build
++$ mkosi -f sandbox -- meson compile -C build
++$ mkosi -f sandbox -- build/systemctl --version
+ ```
+ 
+ To build and boot an OS image with the latest systemd installed:
+ 
+ ```sh
+-$ mkosi -f genkey                               # Generate signing keys once.
+-$ mkosi -f sandbox meson compile -C build mkosi # (re-)build the OS image
+-$ mkosi boot                                    # Boot the image with systemd-nspawn.
+-$ mkosi vm                                      # Boot the image with qemu.
++$ mkosi -f genkey                                  # Generate signing keys once.
++$ mkosi -f sandbox -- meson compile -C build mkosi # (re-)build the OS image
++$ mkosi boot                                       # Boot the image with systemd-nspawn.
++$ mkosi vm                                         # Boot the image with qemu.
+ ```
+ 
+ Putting this all together, here's a series of commands for preparing a patch for
+@@ -61,15 +61,15 @@ $ git clone https://github.com/systemd/mkosi.git
+ $ ln -s $PWD/mkosi/bin/mkosi ~/.local/bin/mkosi # Make sure ~/.local/bin is in $PATH.
+ $ git clone https://github.com/systemd/systemd.git
+ $ cd systemd
+-$ git checkout -b <BRANCH>                      # where BRANCH is the name of the branch
+-$ $EDITOR src/core/main.c                       # or wherever you'd like to make your changes
+-$ mkosi -f sandbox meson setup build            # Set up meson
+-$ mkosi -f genkey                               # Generate signing keys once.
+-$ mkosi -f sandbox meson compile -C build mkosi # (re-)build the test image
+-$ mkosi vm                                      # Boot the image in qemu
+-$ git add -p                                    # interactively put together your patch
+-$ git commit                                    # commit it
+-$ git push -u <REMOTE>                          # where REMOTE is your "fork" on GitHub
++$ git checkout -b <BRANCH>                         # where BRANCH is the name of the branch
++$ $EDITOR src/core/main.c                          # or wherever you'd like to make your changes
++$ mkosi -f sandbox -- meson setup build            # Set up meson
++$ mkosi -f genkey                                  # Generate signing keys once.
++$ mkosi -f sandbox -- meson compile -C build mkosi # (re-)build the test image
++$ mkosi vm                                         # Boot the image in qemu
++$ git add -p                                       # interactively put together your patch
++$ git commit                                       # commit it
++$ git push -u <REMOTE>                             # where REMOTE is your "fork" on GitHub
+ ```
+ 
+ And after that, head over to your repo on GitHub and click "Compare & pull
+@@ -101,10 +101,10 @@ the following commands in another terminal on your host after booting the image
+ machine):
+ 
+ ```sh
+-mkosi -t none && mkosi ssh dnf upgrade --disablerepo="*" --assumeyes "/work/build/*.rpm"             # CentOS/Fedora
+-mkosi -t none && mkosi ssh apt-get install "/work/build/*.deb"                                       # Debian/Ubuntu
+-mkosi -t none && mkosi ssh pacman --upgrade --needed --noconfirm "/work/build/*.pkg.tar"             # Arch Linux
+-mkosi -t none && mkosi ssh zypper --non-interactive install --allow-unsigned-rpm "/work/build/*.rpm" # OpenSUSE
++mkosi -t none && mkosi ssh -- dnf upgrade --disablerepo="*" --assumeyes "/work/build/*.rpm"             # CentOS/Fedora
++mkosi -t none && mkosi ssh -- apt-get install "/work/build/*.deb"                                       # Debian/Ubuntu
++mkosi -t none && mkosi ssh -- pacman --upgrade --needed --noconfirm "/work/build/*.pkg.tar"             # Arch Linux
++mkosi -t none && mkosi ssh -- zypper --non-interactive install --allow-unsigned-rpm "/work/build/*.rpm" # OpenSUSE
+ ```
+ 
+ and optionally restart the daemon(s) you're working on using
+diff --git a/test/README.testsuite b/test/README.testsuite
+index 02f5404410..3a16255b96 100644
+--- a/test/README.testsuite
++++ b/test/README.testsuite
+@@ -11,7 +11,7 @@ reconfiguring meson to make sure it is picked up properly.
+ Next, we can build the integration test image with meson:
+ 
+ ```shell
+-$ mkosi -f sandbox meson compile -C build mkosi
++$ mkosi -f sandbox -- meson compile -C build mkosi
+ ```
+ 
+ By default, the `mkosi` meson target which builds the integration test image depends on
+@@ -32,24 +32,24 @@ directory (`OutputDirectory=`) to point to the other directory using `mkosi.loca
+ After the image has been built, the integration tests can be run with:
+ 
+ ```shell
+-$ env SYSTEMD_INTEGRATION_TESTS=1 mkosi -f sandbox meson test -C build --no-rebuild --suite integration-tests --num-processes "$(($(nproc) / 4))"
++$ env SYSTEMD_INTEGRATION_TESTS=1 mkosi -f sandbox -- meson test -C build --no-rebuild --suite integration-tests --num-processes "$(($(nproc) / 4))"
+ ```
+ 
+ As usual, specific tests can be run in meson by appending the name of the test
+ which is usually the name of the directory e.g.
+ 
+ ```shell
+-$ env SYSTEMD_INTEGRATION_TESTS=1 mkosi -f sandbox meson test -C build --no-rebuild -v TEST-01-BASIC
++$ env SYSTEMD_INTEGRATION_TESTS=1 mkosi -f sandbox -- meson test -C build --no-rebuild -v TEST-01-BASIC
+ ```
+ 
+-See `mkosi -f sandbox meson introspect build --tests` for a list of tests.
++See `mkosi -f sandbox -- meson introspect build --tests` for a list of tests.
+ 
+ To interactively debug a failing integration test, the `--interactive` option
+ (`-i`) for `meson test` can be used. Note that this requires meson v1.5.0 or
+ newer:
+ 
+ ```shell
+-$ env SYSTEMD_INTEGRATION_TESTS=1 mkosi -f sandbox meson test -C build --no-rebuild -i TEST-01-BASIC
++$ env SYSTEMD_INTEGRATION_TESTS=1 mkosi -f sandbox -- meson test -C build --no-rebuild -i TEST-01-BASIC
+ ```
+ 
+ Due to limitations in meson, the integration tests do not yet depend on the
+@@ -58,7 +58,7 @@ running the integration tests. To rebuild the image and rerun a test, the
+ following command can be used:
+ 
+ ```shell
+-$ mkosi -f sandbox meson compile -C build mkosi && env SYSTEMD_INTEGRATION_TESTS=1 mkosi -f sandbox meson test -C build --no-rebuild -v TEST-01-BASIC
++$ mkosi -f sandbox -- meson compile -C build mkosi && env SYSTEMD_INTEGRATION_TESTS=1 mkosi -f sandbox -- meson test -C build --no-rebuild -v TEST-01-BASIC
+ ```
+ 
+ The integration tests use the same mkosi configuration that's used when you run
+@@ -72,7 +72,7 @@ To iterate on an integration test, let's first get a shell in the integration te
+ the following:
+ 
+ ```shell
+-$ mkosi -f sandbox meson compile -C build mkosi && env SYSTEMD_INTEGRATION_TESTS=1 TEST_SHELL=1 mkosi -f sandbox meson test -C build --no-rebuild -i TEST-01-BASIC
++$ mkosi -f sandbox -- meson compile -C build mkosi && env SYSTEMD_INTEGRATION_TESTS=1 TEST_SHELL=1 mkosi -f sandbox -- meson test -C build --no-rebuild -i TEST-01-BASIC
+ ```
+ 
+ This will get us a shell in the integration test environment after booting the machine without running the
+diff --git a/test/fmf/integration-tests/test.sh b/test/fmf/integration-tests/test.sh
+index aff79340f7..c5ba7507de 100755
+--- a/test/fmf/integration-tests/test.sh
++++ b/test/fmf/integration-tests/test.sh
+@@ -132,11 +132,11 @@ export TEST_SKIP="TEST-21-DFUZZER"
+ mkdir -p /etc/pacman.d/gnupg
+ 
+ mkosi summary
+-mkosi -f sandbox true
+-mkosi -f sandbox meson setup --buildtype=debugoptimized -Dintegration-tests=true build
++mkosi -f sandbox -- true
++mkosi -f sandbox -- meson setup --buildtype=debugoptimized -Dintegration-tests=true build
+ mkosi genkey
+-mkosi -f sandbox meson compile -C build mkosi
+-mkosi -f sandbox \
++mkosi -f sandbox -- meson compile -C build mkosi
++mkosi -f sandbox -- \
+     meson test \
+     -C build \
+     --no-rebuild \
diff --git a/SOURCES/0247-core-condition-fix-segfault-when-key-not-found-in-os.patch b/SOURCES/0247-core-condition-fix-segfault-when-key-not-found-in-os.patch
new file mode 100644
index 0000000000000000000000000000000000000000..c7a0fcab70d4141324054074ca8eb867e9dcc6d6
--- /dev/null
+++ b/SOURCES/0247-core-condition-fix-segfault-when-key-not-found-in-os.patch
@@ -0,0 +1,82 @@
+From 8f8514c03f166c352ebdcb577c29d2dff88a37f7 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
+Date: Thu, 13 Feb 2025 15:49:50 +0100
+Subject: [PATCH] core/condition: fix segfault when key not found in os-release
+
+'ConditionOSRelease=|ID_LIKE$=*rhel*' results in a segfault.
+The key 'ID_LIKE' is not present in Fedora's os-release file.
+
+I think the most reasonable behaviour is to treat missing keys as empty.
+This matches the "shell-like" sprit, since in a shell empty keys would
+by default be treated as empty too. Thus, "ID_LIKE=" would match, if
+ID_LIKE is not present in the file, and ID_LIKE=!$foo" would also match.
+The other option would be to make those matches fail, but I think that'd
+make the feature harder to use, esp. with negative matches.
+
+Documentation is updated to clarify the new behaviour.
+
+https://bugzilla.redhat.com/show_bug.cgi?id=2345544
+(cherry picked from commit de02b551adcf74e5677454fd36bf7653b1a4def1)
+---
+ man/systemd.unit.xml      |  2 ++
+ src/shared/condition.c    |  4 +++-
+ src/test/test-condition.c | 18 ++++++++++++++++++
+ 3 files changed, 23 insertions(+), 1 deletion(-)
+
+diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml
+index 2c7f0bd71f..d44eb028ca 100644
+--- a/man/systemd.unit.xml
++++ b/man/systemd.unit.xml
+@@ -1960,6 +1960,8 @@
+           wildcard comparisons (<literal>*</literal>, <literal>?</literal>, <literal>[]</literal>) are
+           supported with the <literal>$=</literal> (match) and <literal>!$=</literal> (non-match).</para>
+ 
++          <para>If the given key is not found in the file, the match is done against an empty value.</para>
++
+           <xi:include href="version-info.xml" xpointer="v249"/>
+           </listitem>
+         </varlistentry>
+diff --git a/src/shared/condition.c b/src/shared/condition.c
+index 9dfa1f8901..1a03fdbe37 100644
+--- a/src/shared/condition.c
++++ b/src/shared/condition.c
+@@ -273,7 +273,9 @@ static int condition_test_osrelease(Condition *c, char **env) {
+                 if (r < 0)
+                         return log_debug_errno(r, "Failed to parse os-release: %m");
+ 
+-                r = version_or_fnmatch_compare(operator, actual_value, word);
++                /* If not found, use "". This means that missing and empty assignments
++                 * in the file have the same result. */
++                r = version_or_fnmatch_compare(operator, strempty(actual_value), word);
+                 if (r < 0)
+                         return r;
+                 if (!r)
+diff --git a/src/test/test-condition.c b/src/test/test-condition.c
+index fc27924621..eb94abe324 100644
+--- a/src/test/test-condition.c
++++ b/src/test/test-condition.c
+@@ -1095,6 +1095,24 @@ TEST(condition_test_os_release) {
+         ASSERT_OK_POSITIVE(condition_test(condition, environ));
+         condition_free(condition);
+ 
++        /* Test shell style globs */
++
++        ASSERT_NOT_NULL(condition = condition_new(CONDITION_OS_RELEASE, "ID_LIKE$=*THISHOPEFULLYWONTEXIST*", false, false));
++        ASSERT_OK_ZERO(condition_test(condition, environ));
++        condition_free(condition);
++
++        ASSERT_NOT_NULL(condition = condition_new(CONDITION_OS_RELEASE, "ID_THISHOPEFULLYWONTEXIST$=*rhel*", false, false));
++        ASSERT_OK_ZERO(condition_test(condition, environ));
++        condition_free(condition);
++
++        ASSERT_NOT_NULL(condition = condition_new(CONDITION_OS_RELEASE, "ID_LIKE!$=*THISHOPEFULLYWONTEXIST*", false, false));
++        ASSERT_OK_POSITIVE(condition_test(condition, environ));
++        condition_free(condition);
++
++        ASSERT_NOT_NULL(condition = condition_new(CONDITION_OS_RELEASE, "ID_THISHOPEFULLYWONTEXIST!$=*rhel*", false, false));
++        ASSERT_OK_POSITIVE(condition_test(condition, environ));
++        condition_free(condition);
++
+         /* load_os_release_pairs() removes quotes, we have to add them back,
+          * otherwise we get a string: "PRETTY_NAME=Debian GNU/Linux 10 (buster)"
+          * which is wrong, as the value is not quoted anymore. */
diff --git a/SOURCES/0248-meson-bump-version-to-257.3.patch b/SOURCES/0248-meson-bump-version-to-257.3.patch
new file mode 100644
index 0000000000000000000000000000000000000000..06b6c45207ae9555f0e6a87d43217a045f3d0531
--- /dev/null
+++ b/SOURCES/0248-meson-bump-version-to-257.3.patch
@@ -0,0 +1,16 @@
+From 876ee10e0eb4bbb0920bdab7817a9f06cc34910f Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
+Date: Thu, 13 Feb 2025 18:48:27 +0100
+Subject: [PATCH] meson: bump version to 257.3
+
+---
+ meson.version | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/meson.version b/meson.version
+index f813cadc5d..198eb843d0 100644
+--- a/meson.version
++++ b/meson.version
+@@ -1 +1 @@
+-257.2
++257.3
diff --git a/SOURCES/0228-ci-update-workflows-to-run-on-source-git-setup.patch b/SOURCES/0249-ci-update-workflows-to-run-on-source-git-setup.patch
similarity index 97%
rename from SOURCES/0228-ci-update-workflows-to-run-on-source-git-setup.patch
rename to SOURCES/0249-ci-update-workflows-to-run-on-source-git-setup.patch
index 7ed59287c53470e9b7ae119e51320c4dac51a50b..0813cdc121157dd8b4e5eb1af532249d39610420 100644
--- a/SOURCES/0228-ci-update-workflows-to-run-on-source-git-setup.patch
+++ b/SOURCES/0249-ci-update-workflows-to-run-on-source-git-setup.patch
@@ -1,4 +1,4 @@
-From 3a8ccc456c8508b70ced7ee02023c7ff4c887999 Mon Sep 17 00:00:00 2001
+From 889998fe8c67de3d346eeced121824a117dd5741 Mon Sep 17 00:00:00 2001
 From: Jan Macku <jamacku@redhat.com>
 Date: Thu, 16 May 2024 14:24:38 +0200
 Subject: [PATCH] ci: update workflows to run on source-git setup
diff --git a/SOURCES/0229-ci-setup-source-git-automation.patch b/SOURCES/0250-ci-setup-source-git-automation.patch
similarity index 99%
rename from SOURCES/0229-ci-setup-source-git-automation.patch
rename to SOURCES/0250-ci-setup-source-git-automation.patch
index 0e7c08d3067710246ad6644d0eaadab56161e3fc..4d0f963d6029b3e9d6af65bd31bcef9200630eda 100644
--- a/SOURCES/0229-ci-setup-source-git-automation.patch
+++ b/SOURCES/0250-ci-setup-source-git-automation.patch
@@ -1,4 +1,4 @@
-From bb8b5a45670f68907549070551866e99999336c2 Mon Sep 17 00:00:00 2001
+From edf345c8736485b43cf63310f7ac20f2fcdbe10d Mon Sep 17 00:00:00 2001
 From: Jan Macku <jamacku@redhat.com>
 Date: Thu, 16 May 2024 14:36:04 +0200
 Subject: [PATCH] ci: setup source-git automation
diff --git a/SOURCES/0230-ci-reconfigure-Packit-for-RHEL-10.patch b/SOURCES/0251-ci-reconfigure-Packit-for-RHEL-10.patch
similarity index 97%
rename from SOURCES/0230-ci-reconfigure-Packit-for-RHEL-10.patch
rename to SOURCES/0251-ci-reconfigure-Packit-for-RHEL-10.patch
index daf3626777355dd411bd6e2edc839ca603698fe4..2cf7ef12b3cfd40083e62d56811d55ebbd619138 100644
--- a/SOURCES/0230-ci-reconfigure-Packit-for-RHEL-10.patch
+++ b/SOURCES/0251-ci-reconfigure-Packit-for-RHEL-10.patch
@@ -1,4 +1,4 @@
-From 3898fb729b4bae5fbbdfd433f595836dce0d475e Mon Sep 17 00:00:00 2001
+From 2805c34051650355bc4e3a299ff23a9965a43af1 Mon Sep 17 00:00:00 2001
 From: Jan Macku <jamacku@redhat.com>
 Date: Fri, 17 May 2024 13:55:40 +0200
 Subject: [PATCH] ci: reconfigure Packit for RHEL 10
diff --git a/SOURCES/0231-journal-again-create-user-journals-for-users-with-hi.patch b/SOURCES/0252-journal-again-create-user-journals-for-users-with-hi.patch
similarity index 97%
rename from SOURCES/0231-journal-again-create-user-journals-for-users-with-hi.patch
rename to SOURCES/0252-journal-again-create-user-journals-for-users-with-hi.patch
index 0927b6d668031a086579c15a4b2a03c6d474b2a7..451fdeeee2e5bc742b185f37254b943c67d6a3c0 100644
--- a/SOURCES/0231-journal-again-create-user-journals-for-users-with-hi.patch
+++ b/SOURCES/0252-journal-again-create-user-journals-for-users-with-hi.patch
@@ -1,4 +1,4 @@
-From af3c2d2ece5aa4f4c9869c0587be5aba50af6618 Mon Sep 17 00:00:00 2001
+From 7178ac9b0ad716e4bdcf09a63c961109cbb02dfc Mon Sep 17 00:00:00 2001
 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
 Date: Tue, 9 Jan 2024 11:28:04 +0100
 Subject: [PATCH] journal: again create user journals for users with high uids
diff --git a/SOURCES/0232-tmpfiles-make-purge-hard-to-mis-use.patch b/SOURCES/0253-tmpfiles-make-purge-hard-to-mis-use.patch
similarity index 96%
rename from SOURCES/0232-tmpfiles-make-purge-hard-to-mis-use.patch
rename to SOURCES/0253-tmpfiles-make-purge-hard-to-mis-use.patch
index 205a35bfb2ed548f2704e52b38e675e7210cafeb..04e0e57ce911ecc67e665d7c50c545bfdfddad86 100644
--- a/SOURCES/0232-tmpfiles-make-purge-hard-to-mis-use.patch
+++ b/SOURCES/0253-tmpfiles-make-purge-hard-to-mis-use.patch
@@ -1,4 +1,4 @@
-From 8c1b874414f2f619412adaecdc5a349e1ff634ba Mon Sep 17 00:00:00 2001
+From bbd480dc658d26fdd35c9635a08b5380aaccdcad Mon Sep 17 00:00:00 2001
 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
 Date: Tue, 18 Jun 2024 20:32:10 +0200
 Subject: [PATCH] tmpfiles: make --purge hard to (mis-)use
@@ -13,7 +13,7 @@ Related: RHEL-40924
  1 file changed, 17 insertions(+)
 
 diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
-index bff05cda6f..9190f604a5 100644
+index b699a1e5be..563bf01b45 100644
 --- a/src/tmpfiles/tmpfiles.c
 +++ b/src/tmpfiles/tmpfiles.c
 @@ -4213,6 +4213,7 @@ static int parse_argv(int argc, char *argv[]) {
diff --git a/SOURCES/0233-fedora-use-system-auth-in-pam-systemd-user.patch b/SOURCES/0254-fedora-use-system-auth-in-pam-systemd-user.patch
similarity index 93%
rename from SOURCES/0233-fedora-use-system-auth-in-pam-systemd-user.patch
rename to SOURCES/0254-fedora-use-system-auth-in-pam-systemd-user.patch
index e12eaa39a6e69969cf13696693370d0d2279a5df..83342e66f7ef966a793cfb7bfe5f2f1d8de08914 100644
--- a/SOURCES/0233-fedora-use-system-auth-in-pam-systemd-user.patch
+++ b/SOURCES/0254-fedora-use-system-auth-in-pam-systemd-user.patch
@@ -1,4 +1,4 @@
-From 98b19314de99112cf315a2894562639dcadbe320 Mon Sep 17 00:00:00 2001
+From 32882ddc3e34baeeb1fd65c2ed783f10463ccc8f Mon Sep 17 00:00:00 2001
 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
 Date: Wed, 14 Dec 2022 22:24:53 +0100
 Subject: [PATCH] fedora: use system-auth in pam systemd-user
diff --git a/SOURCES/0234-net-naming-scheme-start-rhel10-naming-and-include-rh.patch b/SOURCES/0255-net-naming-scheme-start-rhel10-naming-and-include-rh.patch
similarity index 99%
rename from SOURCES/0234-net-naming-scheme-start-rhel10-naming-and-include-rh.patch
rename to SOURCES/0255-net-naming-scheme-start-rhel10-naming-and-include-rh.patch
index c651d7f2f4c2f3e54dbb771f52eec22b40104203..1bd881c5bf3117ce516eaecf2506cb04fe7c965e 100644
--- a/SOURCES/0234-net-naming-scheme-start-rhel10-naming-and-include-rh.patch
+++ b/SOURCES/0255-net-naming-scheme-start-rhel10-naming-and-include-rh.patch
@@ -1,4 +1,4 @@
-From 8263ecf730ea5ab77caa8467c5c28f24f4a865a3 Mon Sep 17 00:00:00 2001
+From fda607614c4854678e1bfe1c27e82996e86a59fb Mon Sep 17 00:00:00 2001
 From: Jan Macku <jamacku@redhat.com>
 Date: Tue, 25 Jun 2024 14:00:45 +0200
 Subject: [PATCH] net-naming-scheme: start rhel10 naming and include rhel8 and
diff --git a/SOURCES/0235-rules-copy-40-redhat.rules-from-RHEL-9.patch b/SOURCES/0256-rules-copy-40-redhat.rules-from-RHEL-9.patch
similarity index 98%
rename from SOURCES/0235-rules-copy-40-redhat.rules-from-RHEL-9.patch
rename to SOURCES/0256-rules-copy-40-redhat.rules-from-RHEL-9.patch
index 46aa919fd353a89f8894038d007f991ec0c9024e..230c544596e2a493cf5401e531edffacb4bd665e 100644
--- a/SOURCES/0235-rules-copy-40-redhat.rules-from-RHEL-9.patch
+++ b/SOURCES/0256-rules-copy-40-redhat.rules-from-RHEL-9.patch
@@ -1,4 +1,4 @@
-From 564e24369d0c1ddc8536d577550331e5b8a0d0e0 Mon Sep 17 00:00:00 2001
+From d1043fe3a970d6396d4df91aff7714f5e3010830 Mon Sep 17 00:00:00 2001
 From: Jan Macku <jamacku@redhat.com>
 Date: Wed, 12 Jun 2024 14:23:30 +0200
 Subject: [PATCH] rules: copy 40-redhat.rules from RHEL 9
diff --git a/SOURCES/0236-logind-set-RemoveIPC-to-false-by-default.patch b/SOURCES/0257-logind-set-RemoveIPC-to-false-by-default.patch
similarity index 96%
rename from SOURCES/0236-logind-set-RemoveIPC-to-false-by-default.patch
rename to SOURCES/0257-logind-set-RemoveIPC-to-false-by-default.patch
index deead0760846e255698bf4d29d2d7c23e2e00cde..c28d9ccdade803ea82991ae2214b11b19850e2c4 100644
--- a/SOURCES/0236-logind-set-RemoveIPC-to-false-by-default.patch
+++ b/SOURCES/0257-logind-set-RemoveIPC-to-false-by-default.patch
@@ -1,4 +1,4 @@
-From b3f9d8462a14cef1455dbdd3d89c01c9674a7d0f Mon Sep 17 00:00:00 2001
+From a86ee384de6953b4bfdfd37e083887959d74e9ae Mon Sep 17 00:00:00 2001
 From: rpm-build <rpm-build>
 Date: Wed, 1 Aug 2018 10:58:28 +0200
 Subject: [PATCH] logind: set RemoveIPC to false by default
diff --git a/SOURCES/0237-tmpfiles-don-t-create-resolv.conf-stub-resolv.conf-s.patch b/SOURCES/0258-tmpfiles-don-t-create-resolv.conf-stub-resolv.conf-s.patch
similarity index 95%
rename from SOURCES/0237-tmpfiles-don-t-create-resolv.conf-stub-resolv.conf-s.patch
rename to SOURCES/0258-tmpfiles-don-t-create-resolv.conf-stub-resolv.conf-s.patch
index 7ee2ed5b84ab94a128503e9628673b3d9253214c..0c02ddf91da09d3669d7e9b862035cfbfb693ba6 100644
--- a/SOURCES/0237-tmpfiles-don-t-create-resolv.conf-stub-resolv.conf-s.patch
+++ b/SOURCES/0258-tmpfiles-don-t-create-resolv.conf-stub-resolv.conf-s.patch
@@ -1,4 +1,4 @@
-From 23091e70f1770b23ad650e3977341b834742d909 Mon Sep 17 00:00:00 2001
+From 523094024f847593eb62219b1980cdef44da618d Mon Sep 17 00:00:00 2001
 From: Michal Sekletar <msekleta@redhat.com>
 Date: Thu, 5 Aug 2021 17:11:47 +0200
 Subject: [PATCH] tmpfiles: don't create resolv.conf -> stub-resolv.conf
diff --git a/SOURCES/0238-rc-local-order-after-network-online.target.patch b/SOURCES/0259-rc-local-order-after-network-online.target.patch
similarity index 92%
rename from SOURCES/0238-rc-local-order-after-network-online.target.patch
rename to SOURCES/0259-rc-local-order-after-network-online.target.patch
index 02180eaa475e86765ba119db13b63de810bf46b3..2ff12aacb2101beb4e0f1669df3326fc691aa5e3 100644
--- a/SOURCES/0238-rc-local-order-after-network-online.target.patch
+++ b/SOURCES/0259-rc-local-order-after-network-online.target.patch
@@ -1,4 +1,4 @@
-From 3485ef0a5796a5c72876bdf63156952b0ffea714 Mon Sep 17 00:00:00 2001
+From 2bcaf0f03302e84da5c2c2eaa3e04cb36b597f72 Mon Sep 17 00:00:00 2001
 From: David Tardon <dtardon@redhat.com>
 Date: Thu, 11 Mar 2021 15:48:23 +0100
 Subject: [PATCH] rc-local: order after network-online.target
diff --git a/SOURCES/0239-random-util-increase-random-seed-size-to-1024.patch b/SOURCES/0260-random-util-increase-random-seed-size-to-1024.patch
similarity index 91%
rename from SOURCES/0239-random-util-increase-random-seed-size-to-1024.patch
rename to SOURCES/0260-random-util-increase-random-seed-size-to-1024.patch
index 9b96b84fd05d1377154e920ffb46aed2e5c3aacc..fcb2bcf9d6dbc3d451039c45e5cbd756e711ba07 100644
--- a/SOURCES/0239-random-util-increase-random-seed-size-to-1024.patch
+++ b/SOURCES/0260-random-util-increase-random-seed-size-to-1024.patch
@@ -1,4 +1,4 @@
-From 61b82fbe22fbc6ec00b075df25a878052ad2f6f1 Mon Sep 17 00:00:00 2001
+From e40b94a3e7402147ce78e7224973fdb0d7386db2 Mon Sep 17 00:00:00 2001
 From: David Tardon <dtardon@redhat.com>
 Date: Thu, 15 Jul 2021 11:15:17 +0200
 Subject: [PATCH] random-util: increase random seed size to 1024
diff --git a/SOURCES/0240-journal-don-t-enable-systemd-journald-audit.socket-b.patch b/SOURCES/0261-journal-don-t-enable-systemd-journald-audit.socket-b.patch
similarity index 92%
rename from SOURCES/0240-journal-don-t-enable-systemd-journald-audit.socket-b.patch
rename to SOURCES/0261-journal-don-t-enable-systemd-journald-audit.socket-b.patch
index 838ed88eefa64a4d9dfc36bd2e3e1fe46c5d4075..719cfc7fc6e8151524061bc93097b4d29f9f9262 100644
--- a/SOURCES/0240-journal-don-t-enable-systemd-journald-audit.socket-b.patch
+++ b/SOURCES/0261-journal-don-t-enable-systemd-journald-audit.socket-b.patch
@@ -1,4 +1,4 @@
-From 172467141cad31672cbb23398696cd56814347f7 Mon Sep 17 00:00:00 2001
+From b8cf88743e39a156b6e5d6e51805f25a774988cb Mon Sep 17 00:00:00 2001
 From: Jan Synacek <jsynacek@redhat.com>
 Date: Thu, 2 May 2019 14:11:54 +0200
 Subject: [PATCH] journal: don't enable systemd-journald-audit.socket by
diff --git a/SOURCES/0241-journald.conf-don-t-touch-current-audit-settings.patch b/SOURCES/0262-journald.conf-don-t-touch-current-audit-settings.patch
similarity index 89%
rename from SOURCES/0241-journald.conf-don-t-touch-current-audit-settings.patch
rename to SOURCES/0262-journald.conf-don-t-touch-current-audit-settings.patch
index 53bc8fa6ac4a5d2321d02949888b2e3e27cd049e..171e0dacaff380a52b9be000bc7950d834463f0f 100644
--- a/SOURCES/0241-journald.conf-don-t-touch-current-audit-settings.patch
+++ b/SOURCES/0262-journald.conf-don-t-touch-current-audit-settings.patch
@@ -1,4 +1,4 @@
-From e94102b01e89ce625b4947857d0148165adec1ac Mon Sep 17 00:00:00 2001
+From 0fd88aa06db2982be08817d7b9e461141ef9b5b7 Mon Sep 17 00:00:00 2001
 From: David Tardon <dtardon@redhat.com>
 Date: Thu, 5 Aug 2021 15:26:13 +0200
 Subject: [PATCH] journald.conf: don't touch current audit settings
diff --git a/SOURCES/0242-rules-add-elevator-kernel-command-line-parameter.patch b/SOURCES/0263-rules-add-elevator-kernel-command-line-parameter.patch
similarity index 96%
rename from SOURCES/0242-rules-add-elevator-kernel-command-line-parameter.patch
rename to SOURCES/0263-rules-add-elevator-kernel-command-line-parameter.patch
index 46c821f04c6bdbed552db57bfb5a15f71698c1e8..63e06d29f8b2a5e717ec67a81ce8121a77729bac 100644
--- a/SOURCES/0242-rules-add-elevator-kernel-command-line-parameter.patch
+++ b/SOURCES/0263-rules-add-elevator-kernel-command-line-parameter.patch
@@ -1,4 +1,4 @@
-From b4c80df8978ea29893edb45cd163dfe5d93cbb27 Mon Sep 17 00:00:00 2001
+From 338c2b90dff6f57a197b12f1d0df11f7d842f5bd Mon Sep 17 00:00:00 2001
 From: Lukas Nykryn <lnykryn@redhat.com>
 Date: Tue, 12 Feb 2019 16:58:16 +0100
 Subject: [PATCH] rules: add elevator= kernel command line parameter
diff --git a/SOURCES/0243-pid1-bump-DefaultTasksMax-to-80-of-the-kernel-pid.ma.patch b/SOURCES/0264-pid1-bump-DefaultTasksMax-to-80-of-the-kernel-pid.ma.patch
similarity index 97%
rename from SOURCES/0243-pid1-bump-DefaultTasksMax-to-80-of-the-kernel-pid.ma.patch
rename to SOURCES/0264-pid1-bump-DefaultTasksMax-to-80-of-the-kernel-pid.ma.patch
index 5522fc7e2084141e16c173d010b6257c8c186740..55ea8737a0a39853c5aeb41ee1db3081d94e6682 100644
--- a/SOURCES/0243-pid1-bump-DefaultTasksMax-to-80-of-the-kernel-pid.ma.patch
+++ b/SOURCES/0264-pid1-bump-DefaultTasksMax-to-80-of-the-kernel-pid.ma.patch
@@ -1,4 +1,4 @@
-From 73538e27e83432aae86db0cf3af31e397a4d7c69 Mon Sep 17 00:00:00 2001
+From e81e90faf12aaaa0ea2b7002cced4752226fdc15 Mon Sep 17 00:00:00 2001
 From: rpm-build <rpm-build>
 Date: Wed, 1 Aug 2018 13:19:39 +0200
 Subject: [PATCH] pid1: bump DefaultTasksMax to 80% of the kernel pid.max value
diff --git a/SOURCES/0244-udev-net-setup-link-change-the-default-MACAddressPol.patch b/SOURCES/0265-udev-net-setup-link-change-the-default-MACAddressPol.patch
similarity index 96%
rename from SOURCES/0244-udev-net-setup-link-change-the-default-MACAddressPol.patch
rename to SOURCES/0265-udev-net-setup-link-change-the-default-MACAddressPol.patch
index a14f5fa3e4f7873bbd95273462fb0da858780a32..b45b73c3678900e00fbeb13a1b8375d61c1a61f9 100644
--- a/SOURCES/0244-udev-net-setup-link-change-the-default-MACAddressPol.patch
+++ b/SOURCES/0265-udev-net-setup-link-change-the-default-MACAddressPol.patch
@@ -1,4 +1,4 @@
-From 75e43ad53bce62ad58112cdfcecbc1917250a731 Mon Sep 17 00:00:00 2001
+From 2899425fa34da1b713bcac3568b18a8137cce391 Mon Sep 17 00:00:00 2001
 From: Michal Sekletar <msekleta@redhat.com>
 Date: Tue, 21 Sep 2021 15:01:19 +0200
 Subject: [PATCH] udev/net-setup-link: change the default MACAddressPolicy to
diff --git a/SOURCES/0245-core-decrease-log-level-of-messages-about-use-of-Kil.patch b/SOURCES/0266-core-decrease-log-level-of-messages-about-use-of-Kil.patch
similarity index 96%
rename from SOURCES/0245-core-decrease-log-level-of-messages-about-use-of-Kil.patch
rename to SOURCES/0266-core-decrease-log-level-of-messages-about-use-of-Kil.patch
index bb6f3c5b6398f8ff28c6ea220a7365614c61efcf..306920616966c6a439315faeba1ccb0cd581ac27 100644
--- a/SOURCES/0245-core-decrease-log-level-of-messages-about-use-of-Kil.patch
+++ b/SOURCES/0266-core-decrease-log-level-of-messages-about-use-of-Kil.patch
@@ -1,4 +1,4 @@
-From 54af0d04d5194cdf9a26cbe4fd7c751f7cdae497 Mon Sep 17 00:00:00 2001
+From ddb64e87a3ae6610ea9e2722f7ce8d3e23c715f2 Mon Sep 17 00:00:00 2001
 From: Michal Sekletar <msekleta@redhat.com>
 Date: Tue, 22 Feb 2022 13:24:11 +0100
 Subject: [PATCH] core: decrease log level of messages about use of
diff --git a/SOURCES/0246-taint-remove-unmerged-bin.patch b/SOURCES/0267-taint-remove-unmerged-bin.patch
similarity index 98%
rename from SOURCES/0246-taint-remove-unmerged-bin.patch
rename to SOURCES/0267-taint-remove-unmerged-bin.patch
index 03ba74b75e3b14ad0d8a82e0bb1158adcc29002e..a5aa26886b3cb94d0e3ae0509fc6cf83298d708b 100644
--- a/SOURCES/0246-taint-remove-unmerged-bin.patch
+++ b/SOURCES/0267-taint-remove-unmerged-bin.patch
@@ -1,4 +1,4 @@
-From 17c66b80f5a9bf38a1d4226ab4f54038253b4f93 Mon Sep 17 00:00:00 2001
+From ff7a67e1aa5c71c0f40d7f80922a98884394da63 Mon Sep 17 00:00:00 2001
 From: Lukas Nykryn <lnykryn@redhat.com>
 Date: Mon, 8 Jul 2024 14:44:45 +0200
 Subject: [PATCH] taint: remove unmerged-bin
diff --git a/SOURCES/0247-presets-remove-resolved.patch b/SOURCES/0268-presets-remove-resolved.patch
similarity index 93%
rename from SOURCES/0247-presets-remove-resolved.patch
rename to SOURCES/0268-presets-remove-resolved.patch
index 99ae707c83da443537b7248e70f7af1e0103cdda..c017a3475d67fe6f16eda607c54a3d897ee46350 100644
--- a/SOURCES/0247-presets-remove-resolved.patch
+++ b/SOURCES/0268-presets-remove-resolved.patch
@@ -1,4 +1,4 @@
-From ed45de428287869a531db8a230874fa31db02178 Mon Sep 17 00:00:00 2001
+From fddcb74610ef948369589d470642faa188bc0501 Mon Sep 17 00:00:00 2001
 From: Lukas Nykryn <lnykryn@redhat.com>
 Date: Mon, 8 Jul 2024 13:13:10 +0200
 Subject: [PATCH] presets: remove resolved
diff --git a/SOURCES/0248-ci-run-mkosi-test-only-for-Fedora-and-CentOS-Stream.patch b/SOURCES/0269-ci-run-mkosi-test-only-for-Fedora-and-CentOS-Stream.patch
similarity index 95%
rename from SOURCES/0248-ci-run-mkosi-test-only-for-Fedora-and-CentOS-Stream.patch
rename to SOURCES/0269-ci-run-mkosi-test-only-for-Fedora-and-CentOS-Stream.patch
index 34d3d7401ca1f43928eb334207448aa17604f57f..5415428f492e044f23151b51a2b9e66774be92b8 100644
--- a/SOURCES/0248-ci-run-mkosi-test-only-for-Fedora-and-CentOS-Stream.patch
+++ b/SOURCES/0269-ci-run-mkosi-test-only-for-Fedora-and-CentOS-Stream.patch
@@ -1,4 +1,4 @@
-From d93bd311a97296483c7d99d572545ce38edcaa65 Mon Sep 17 00:00:00 2001
+From 111fdc464b7e470597db4477cedbe54e3c2fb4e8 Mon Sep 17 00:00:00 2001
 From: Jan Macku <jamacku@redhat.com>
 Date: Tue, 16 Jul 2024 10:08:06 +0200
 Subject: [PATCH]  ci: run mkosi test only for Fedora and CentOS Stream
@@ -11,7 +11,7 @@ Related: RHEL-40924
  1 file changed, 2 insertions(+), 34 deletions(-)
 
 diff --git a/.github/workflows/mkosi.yml b/.github/workflows/mkosi.yml
-index d662d65dad..77ccf03717 100644
+index 2b00498243..7a764e82a7 100644
 --- a/.github/workflows/mkosi.yml
 +++ b/.github/workflows/mkosi.yml
 @@ -8,7 +8,7 @@ on:
diff --git a/SOURCES/0249-taint-remove-unused-variable-usr_sbin.patch b/SOURCES/0270-taint-remove-unused-variable-usr_sbin.patch
similarity index 93%
rename from SOURCES/0249-taint-remove-unused-variable-usr_sbin.patch
rename to SOURCES/0270-taint-remove-unused-variable-usr_sbin.patch
index 2bcfd96989d369d1430bccd1493b5aea51c752ba..ae0138cc993a448e3bdeb424028053e32fa3db07 100644
--- a/SOURCES/0249-taint-remove-unused-variable-usr_sbin.patch
+++ b/SOURCES/0270-taint-remove-unused-variable-usr_sbin.patch
@@ -1,4 +1,4 @@
-From 9b4672695dd83f8e5a7fb7ff55c477542907a850 Mon Sep 17 00:00:00 2001
+From 6b3e22ba2834f02d8513d44c65bf95b186deeb40 Mon Sep 17 00:00:00 2001
 From: Jan Macku <jamacku@redhat.com>
 Date: Tue, 16 Jul 2024 10:09:23 +0200
 Subject: [PATCH] taint: remove unused variable `usr_sbin`
diff --git a/SOURCES/0250-packit-drop-the-libarchive-workaround.patch b/SOURCES/0271-packit-drop-the-libarchive-workaround.patch
similarity index 93%
rename from SOURCES/0250-packit-drop-the-libarchive-workaround.patch
rename to SOURCES/0271-packit-drop-the-libarchive-workaround.patch
index d997102bb14c872187b0d0cba3fc54fe002b1aa9..3cb8be9edc32ef45bfa4db0c680151c530a7df90 100644
--- a/SOURCES/0250-packit-drop-the-libarchive-workaround.patch
+++ b/SOURCES/0271-packit-drop-the-libarchive-workaround.patch
@@ -1,4 +1,4 @@
-From 77cb42b21dc039c6c12ebeadfb8433fdd6ba805e Mon Sep 17 00:00:00 2001
+From d2a27c0be47ed2f47a7f4c52d44fd05f8dc92cf2 Mon Sep 17 00:00:00 2001
 From: Frantisek Sumsal <frantisek@sumsal.cz>
 Date: Wed, 17 Jul 2024 12:19:03 +0200
 Subject: [PATCH] packit: drop the libarchive workaround
diff --git a/SOURCES/0251-coredump-by-default-process-and-store-core-files-up-.patch b/SOURCES/0272-coredump-by-default-process-and-store-core-files-up-.patch
similarity index 92%
rename from SOURCES/0251-coredump-by-default-process-and-store-core-files-up-.patch
rename to SOURCES/0272-coredump-by-default-process-and-store-core-files-up-.patch
index 7c26b2edf89341f601f20ae785b0543c75c23377..3a430e47c02ba9e9c847b810459242a5f22d1997 100644
--- a/SOURCES/0251-coredump-by-default-process-and-store-core-files-up-.patch
+++ b/SOURCES/0272-coredump-by-default-process-and-store-core-files-up-.patch
@@ -1,4 +1,4 @@
-From 9e174bfea4f0dc91e3a807d425f090d904beb986 Mon Sep 17 00:00:00 2001
+From 733ed7a01bcb70f20d535f914cc11fbd4149a676 Mon Sep 17 00:00:00 2001
 From: Michal Sekletar <msekleta@redhat.com>
 Date: Fri, 5 Apr 2024 15:56:58 +0200
 Subject: [PATCH] coredump: by default process and store core files up to 1GiB
diff --git a/SOURCES/0252-Avoid-tmp-being-mounted-as-tmpfs-without-the-user-s-.patch b/SOURCES/0273-Avoid-tmp-being-mounted-as-tmpfs-without-the-user-s-.patch
similarity index 92%
rename from SOURCES/0252-Avoid-tmp-being-mounted-as-tmpfs-without-the-user-s-.patch
rename to SOURCES/0273-Avoid-tmp-being-mounted-as-tmpfs-without-the-user-s-.patch
index 726a41225937e230df46a4e87f558c9ac77bcf44..9bd6dd60e9a9c0929fdf7a0f3e4d8f850a88d8c8 100644
--- a/SOURCES/0252-Avoid-tmp-being-mounted-as-tmpfs-without-the-user-s-.patch
+++ b/SOURCES/0273-Avoid-tmp-being-mounted-as-tmpfs-without-the-user-s-.patch
@@ -1,4 +1,4 @@
-From f815901eda09adb11b0957b4243b877d9dc971a4 Mon Sep 17 00:00:00 2001
+From 0f3fae206bb81459e33fc54cfa3c374fbca9bdf3 Mon Sep 17 00:00:00 2001
 From: Jan Synacek <jsynacek@redhat.com>
 Date: Tue, 15 May 2018 09:24:20 +0200
 Subject: [PATCH] Avoid /tmp being mounted as tmpfs without the user's will
diff --git a/SOURCES/0253-unit-don-t-add-Requires-for-tmp.mount.patch b/SOURCES/0274-unit-don-t-add-Requires-for-tmp.mount.patch
similarity index 96%
rename from SOURCES/0253-unit-don-t-add-Requires-for-tmp.mount.patch
rename to SOURCES/0274-unit-don-t-add-Requires-for-tmp.mount.patch
index 0bb8696f2625beff219184c29ed587ed233c1bcb..2c2f85b004cb656d7e36e6b239b96398707690e5 100644
--- a/SOURCES/0253-unit-don-t-add-Requires-for-tmp.mount.patch
+++ b/SOURCES/0274-unit-don-t-add-Requires-for-tmp.mount.patch
@@ -1,4 +1,4 @@
-From 626d6691fe357a848e9910d6497eb9892e85db58 Mon Sep 17 00:00:00 2001
+From 6e50633c85c58faf3f247cdc21ea59edb888b5d0 Mon Sep 17 00:00:00 2001
 From: Lukas Nykryn <lnykryn@redhat.com>
 Date: Mon, 5 Sep 2016 12:47:09 +0200
 Subject: [PATCH] unit: don't add Requires for tmp.mount
diff --git a/SOURCES/0254-units-add-Install-section-to-tmp.mount.patch b/SOURCES/0275-units-add-Install-section-to-tmp.mount.patch
similarity index 90%
rename from SOURCES/0254-units-add-Install-section-to-tmp.mount.patch
rename to SOURCES/0275-units-add-Install-section-to-tmp.mount.patch
index aea9ce6fd93c76a4a0514e9dd2c93683bcbd003a..8c49dbd24919dc0229974a6bbab4dddd0ae6c62a 100644
--- a/SOURCES/0254-units-add-Install-section-to-tmp.mount.patch
+++ b/SOURCES/0275-units-add-Install-section-to-tmp.mount.patch
@@ -1,4 +1,4 @@
-From 34f26684f30b23cf59545b8fba68cbee7655abe0 Mon Sep 17 00:00:00 2001
+From d3105aa57bfea2eceecc450f226c916e4d42886a Mon Sep 17 00:00:00 2001
 From: Jan Synacek <jsynacek@redhat.com>
 Date: Tue, 22 Jan 2019 10:28:42 +0100
 Subject: [PATCH] units: add [Install] section to tmp.mount
diff --git a/SOURCES/0255-units-don-t-enable-tmp.mount-statically-in-local-fs..patch b/SOURCES/0276-units-don-t-enable-tmp.mount-statically-in-local-fs..patch
similarity index 92%
rename from SOURCES/0255-units-don-t-enable-tmp.mount-statically-in-local-fs..patch
rename to SOURCES/0276-units-don-t-enable-tmp.mount-statically-in-local-fs..patch
index 871161f79ea9545b0f80da651f3bd6434ba8f429..ab3d60d0d99ed6e0765a4424479cf53092e6ef4f 100644
--- a/SOURCES/0255-units-don-t-enable-tmp.mount-statically-in-local-fs..patch
+++ b/SOURCES/0276-units-don-t-enable-tmp.mount-statically-in-local-fs..patch
@@ -1,4 +1,4 @@
-From 882020f9dc77c6212ab33cf2edca2e5488aa488b Mon Sep 17 00:00:00 2001
+From 3cc7226bfbfd32be28cef53d49c646d768868930 Mon Sep 17 00:00:00 2001
 From: Michal Sekletar <msekleta@redhat.com>
 Date: Wed, 22 Sep 2021 14:38:00 +0200
 Subject: [PATCH] units: don't enable tmp.mount statically in local-fs.target
diff --git a/SOURCES/0256-netif-naming-scheme-add-rhel-9.5-scheme.patch b/SOURCES/0277-netif-naming-scheme-add-rhel-9.5-scheme.patch
similarity index 97%
rename from SOURCES/0256-netif-naming-scheme-add-rhel-9.5-scheme.patch
rename to SOURCES/0277-netif-naming-scheme-add-rhel-9.5-scheme.patch
index a2ffe37c06fbf929cab290099b875c0e9d455451..3c8ed93618487a7e098c447e960cd755dd8646d8 100644
--- a/SOURCES/0256-netif-naming-scheme-add-rhel-9.5-scheme.patch
+++ b/SOURCES/0277-netif-naming-scheme-add-rhel-9.5-scheme.patch
@@ -1,4 +1,4 @@
-From 761136b13a86095663988d9d1080a9235d5f98f6 Mon Sep 17 00:00:00 2001
+From ab60f607bba1153287a20ab27a440bbcbce51207 Mon Sep 17 00:00:00 2001
 From: Jan Macku <jamacku@redhat.com>
 Date: Thu, 8 Aug 2024 13:12:58 +0200
 Subject: [PATCH] netif-naming-scheme: add rhel-9.5 scheme
diff --git a/SOURCES/0257-netif-naming-scheme-rename-rhel-10.0-to-rhel-10.0.be.patch b/SOURCES/0278-netif-naming-scheme-rename-rhel-10.0-to-rhel-10.0.be.patch
similarity index 97%
rename from SOURCES/0257-netif-naming-scheme-rename-rhel-10.0-to-rhel-10.0.be.patch
rename to SOURCES/0278-netif-naming-scheme-rename-rhel-10.0-to-rhel-10.0.be.patch
index fbc30d5d58c91acfb2b6505bc5822097f306a972..66b54ae9aca6240dd417d2c3745dd307e3930ade 100644
--- a/SOURCES/0257-netif-naming-scheme-rename-rhel-10.0-to-rhel-10.0.be.patch
+++ b/SOURCES/0278-netif-naming-scheme-rename-rhel-10.0-to-rhel-10.0.be.patch
@@ -1,4 +1,4 @@
-From 1bf9dcf0b954a29078a0d81b9d1d0b508353f9f4 Mon Sep 17 00:00:00 2001
+From 36e9a4f8f81753bf7688cf512b26efecb1cdcc73 Mon Sep 17 00:00:00 2001
 From: Lukas Nykryn <lnykryn@redhat.com>
 Date: Thu, 22 Aug 2024 13:42:11 +0200
 Subject: [PATCH] netif-naming-scheme: rename rhel-10.0 to rhel-10.0.beta
diff --git a/SOURCES/0258-net-naming-scheme-disable-NAMING_FIRMWARE_NODE_SUN.patch b/SOURCES/0279-net-naming-scheme-disable-NAMING_FIRMWARE_NODE_SUN.patch
similarity index 94%
rename from SOURCES/0258-net-naming-scheme-disable-NAMING_FIRMWARE_NODE_SUN.patch
rename to SOURCES/0279-net-naming-scheme-disable-NAMING_FIRMWARE_NODE_SUN.patch
index 1669e23dfe7282595116c71f66f33d592a972565..5bfa7109ceaae945182aede53949f349fa8900ed 100644
--- a/SOURCES/0258-net-naming-scheme-disable-NAMING_FIRMWARE_NODE_SUN.patch
+++ b/SOURCES/0279-net-naming-scheme-disable-NAMING_FIRMWARE_NODE_SUN.patch
@@ -1,4 +1,4 @@
-From 30d6ee692d1ec4c914a1dd7718827208121ba623 Mon Sep 17 00:00:00 2001
+From 83dcfb7f301b6131fbc69ea5b4b0b773005b69a3 Mon Sep 17 00:00:00 2001
 From: Lukas Nykryn <lnykryn@redhat.com>
 Date: Thu, 22 Aug 2024 13:47:56 +0200
 Subject: [PATCH] net-naming-scheme: disable NAMING_FIRMWARE_NODE_SUN
diff --git a/SOURCES/0259-netif-naming-scheme-introduce-rhel-10.0-scheme.patch b/SOURCES/0280-netif-naming-scheme-introduce-rhel-10.0-scheme.patch
similarity index 97%
rename from SOURCES/0259-netif-naming-scheme-introduce-rhel-10.0-scheme.patch
rename to SOURCES/0280-netif-naming-scheme-introduce-rhel-10.0-scheme.patch
index 8b4c35db9f2ec2cf4fb11514d2c849d6f06c1719..fbdbe8b935ff14b9ec96e9bb7f9121459d1f4161 100644
--- a/SOURCES/0259-netif-naming-scheme-introduce-rhel-10.0-scheme.patch
+++ b/SOURCES/0280-netif-naming-scheme-introduce-rhel-10.0-scheme.patch
@@ -1,4 +1,4 @@
-From 6233005b0c87d963d0e9920869338b48364fbcf2 Mon Sep 17 00:00:00 2001
+From afc67dabfe5b51fe9fe02438fd14b4fe8ae6eae8 Mon Sep 17 00:00:00 2001
 From: Jan Macku <jamacku@redhat.com>
 Date: Mon, 16 Dec 2024 15:08:50 +0100
 Subject: [PATCH] netif-naming-scheme: introduce rhel-10.0 scheme
diff --git a/SOURCES/0260-udev-net_id-introduce-naming-scheme-for-RHEL-9.6.patch b/SOURCES/0281-udev-net_id-introduce-naming-scheme-for-RHEL-9.6.patch
similarity index 97%
rename from SOURCES/0260-udev-net_id-introduce-naming-scheme-for-RHEL-9.6.patch
rename to SOURCES/0281-udev-net_id-introduce-naming-scheme-for-RHEL-9.6.patch
index 356df6e79f9367e8041dcdeaba912c52b60fd8d5..f46057442b9a9617dd5366c0774b2f2fcb5cc37e 100644
--- a/SOURCES/0260-udev-net_id-introduce-naming-scheme-for-RHEL-9.6.patch
+++ b/SOURCES/0281-udev-net_id-introduce-naming-scheme-for-RHEL-9.6.patch
@@ -1,4 +1,4 @@
-From 4055f81a331d519e557bc1761811e9291a68bc9a Mon Sep 17 00:00:00 2001
+From fa30772d110fbc6fb5f85b13ed99e1f73df6888f Mon Sep 17 00:00:00 2001
 From: Jan Macku <jamacku@redhat.com>
 Date: Mon, 6 Jan 2025 09:09:11 +0100
 Subject: [PATCH] udev/net_id: introduce naming scheme for RHEL-9.6
diff --git a/SOURCES/0261-ci-use-ubuntu-22-04-for-deploy-of-man-pages.patch b/SOURCES/0282-ci-use-ubuntu-22-04-for-deploy-of-man-pages.patch
similarity index 91%
rename from SOURCES/0261-ci-use-ubuntu-22-04-for-deploy-of-man-pages.patch
rename to SOURCES/0282-ci-use-ubuntu-22-04-for-deploy-of-man-pages.patch
index 31583def999e7fcca24ccfe84274d70c683e56b9..727a40827bb9245fb46b3c6128734fa48f7a487a 100644
--- a/SOURCES/0261-ci-use-ubuntu-22-04-for-deploy-of-man-pages.patch
+++ b/SOURCES/0282-ci-use-ubuntu-22-04-for-deploy-of-man-pages.patch
@@ -1,4 +1,4 @@
-From 305b85d3fa788342fb65326fec677f73f739810e Mon Sep 17 00:00:00 2001
+From a2208a909829860b7c0488f8f403a8d4301dce88 Mon Sep 17 00:00:00 2001
 From: Jan Macku <jamacku@redhat.com>
 Date: Tue, 14 Jan 2025 13:26:05 +0100
 Subject: [PATCH] ci: use ubuntu 22:04 for deploy of man pages
diff --git a/SOURCES/0262-ci-fix-Packit.patch b/SOURCES/0283-ci-fix-Packit.patch
similarity index 91%
rename from SOURCES/0262-ci-fix-Packit.patch
rename to SOURCES/0283-ci-fix-Packit.patch
index 397132d5ece09a0ae723f60a6a321555babbcd6f..5d5dd62220780b051933cd151ca30c0730d41dd8 100644
--- a/SOURCES/0262-ci-fix-Packit.patch
+++ b/SOURCES/0283-ci-fix-Packit.patch
@@ -1,4 +1,4 @@
-From 4f52f9d4e24227648967d4f79644fd35a01e1460 Mon Sep 17 00:00:00 2001
+From ed7ade53472721fcde5b324660c89164280ad854 Mon Sep 17 00:00:00 2001
 From: Jan Macku <jamacku@redhat.com>
 Date: Wed, 15 Jan 2025 15:35:00 +0100
 Subject: [PATCH] ci: fix Packit
diff --git a/SOURCES/0263-ci-drop-testing-farm-test.patch b/SOURCES/0284-ci-drop-testing-farm-test.patch
similarity index 90%
rename from SOURCES/0263-ci-drop-testing-farm-test.patch
rename to SOURCES/0284-ci-drop-testing-farm-test.patch
index 3f3fc96ee0ca136400305fe7b77e6c145f64d82c..2c239c8a2b823769a535236d0c3ecdb8140cd041 100644
--- a/SOURCES/0263-ci-drop-testing-farm-test.patch
+++ b/SOURCES/0284-ci-drop-testing-farm-test.patch
@@ -1,4 +1,4 @@
-From d9ea9b2c99571518f1ea3e63fcffd11ecbd3e282 Mon Sep 17 00:00:00 2001
+From ee0b5e44b263718912a1cb8081f6b9127d10836a Mon Sep 17 00:00:00 2001
 From: Jan Macku <jamacku@redhat.com>
 Date: Thu, 16 Jan 2025 14:42:48 +0100
 Subject: [PATCH] ci: drop testing farm test
diff --git a/SOURCES/0264-dbus-stash-the-subscriber-list-when-we-disconenct-fr.patch b/SOURCES/0285-dbus-stash-the-subscriber-list-when-we-disconenct-fr.patch
similarity index 99%
rename from SOURCES/0264-dbus-stash-the-subscriber-list-when-we-disconenct-fr.patch
rename to SOURCES/0285-dbus-stash-the-subscriber-list-when-we-disconenct-fr.patch
index 3be2c821135db55777aa4270bbd0dd956af4713a..a4a4570d21f648f2091c76420ccc659e5436622b 100644
--- a/SOURCES/0264-dbus-stash-the-subscriber-list-when-we-disconenct-fr.patch
+++ b/SOURCES/0285-dbus-stash-the-subscriber-list-when-we-disconenct-fr.patch
@@ -1,4 +1,4 @@
-From bb1289d5263891bddf0568f29d00ac0b95632f9b Mon Sep 17 00:00:00 2001
+From f4d3078bd16a814364e653c1e1c2e53af301f0e7 Mon Sep 17 00:00:00 2001
 From: Ronan Pigott <ronan@rjp.ie>
 Date: Thu, 28 Nov 2024 12:53:32 -0700
 Subject: [PATCH] dbus: stash the subscriber list when we disconenct from the
diff --git a/SOURCES/0265-manager-s-deserialized_subscribed-subscribed_as_strv.patch b/SOURCES/0286-manager-s-deserialized_subscribed-subscribed_as_strv.patch
similarity index 98%
rename from SOURCES/0265-manager-s-deserialized_subscribed-subscribed_as_strv.patch
rename to SOURCES/0286-manager-s-deserialized_subscribed-subscribed_as_strv.patch
index 25872eedc4d60617bcad0845a576709401fc7033..68eeb2609d6c7909414c34a6252a50e76d9b1732 100644
--- a/SOURCES/0265-manager-s-deserialized_subscribed-subscribed_as_strv.patch
+++ b/SOURCES/0286-manager-s-deserialized_subscribed-subscribed_as_strv.patch
@@ -1,4 +1,4 @@
-From e0f31135e2c1929844dca4cb2cc8a5c2a2395013 Mon Sep 17 00:00:00 2001
+From c6e2ecacb40767e3327813808c60653181e32f78 Mon Sep 17 00:00:00 2001
 From: Ronan Pigott <ronan@rjp.ie>
 Date: Wed, 11 Dec 2024 12:47:10 -0700
 Subject: [PATCH] manager: s/deserialized_subscribed/subscribed_as_strv
diff --git a/SOURCES/0266-shared-bus-util-move-bus_message_read_id128-to-bus-m.patch b/SOURCES/0287-shared-bus-util-move-bus_message_read_id128-to-bus-m.patch
similarity index 99%
rename from SOURCES/0266-shared-bus-util-move-bus_message_read_id128-to-bus-m.patch
rename to SOURCES/0287-shared-bus-util-move-bus_message_read_id128-to-bus-m.patch
index b80eb8ef9afb652e0f9613ecb7698778b1ae8582..58d6a8a76f465184cc417d12d9c9b56cdc2eda89 100644
--- a/SOURCES/0266-shared-bus-util-move-bus_message_read_id128-to-bus-m.patch
+++ b/SOURCES/0287-shared-bus-util-move-bus_message_read_id128-to-bus-m.patch
@@ -1,4 +1,4 @@
-From ba46905dd7c33d6e3bcfccfd87cfcc2b4d8b3e52 Mon Sep 17 00:00:00 2001
+From d502fb075bb28704030598e58b93e6b274ef9bb1 Mon Sep 17 00:00:00 2001
 From: Mike Yuan <me@yhndnzj.com>
 Date: Sat, 11 Jan 2025 16:52:05 +0100
 Subject: [PATCH] shared/bus-util: move bus_message_read_id128() to
diff --git a/SOURCES/0267-shared-bus-util-move-bus_message_hash_ops-to-bus-mes.patch b/SOURCES/0288-shared-bus-util-move-bus_message_hash_ops-to-bus-mes.patch
similarity index 98%
rename from SOURCES/0267-shared-bus-util-move-bus_message_hash_ops-to-bus-mes.patch
rename to SOURCES/0288-shared-bus-util-move-bus_message_hash_ops-to-bus-mes.patch
index 113eb6a80fb2fae6c31eb74a812ed290d53fddbf..e7175141cf48cd610f3995a5bbbcb10037e127b6 100644
--- a/SOURCES/0267-shared-bus-util-move-bus_message_hash_ops-to-bus-mes.patch
+++ b/SOURCES/0288-shared-bus-util-move-bus_message_hash_ops-to-bus-mes.patch
@@ -1,4 +1,4 @@
-From 2ea8cc2b4d6a266fbd06b727a3fbc74301930f98 Mon Sep 17 00:00:00 2001
+From 42319407ae279478143e30d9c2878140b23e969c Mon Sep 17 00:00:00 2001
 From: Mike Yuan <me@yhndnzj.com>
 Date: Sat, 11 Jan 2025 17:10:43 +0100
 Subject: [PATCH] shared/bus-util: move bus_message_hash_ops to
diff --git a/SOURCES/0268-shared-bus-util-move-string-set-append-get-funcs-to-.patch b/SOURCES/0289-shared-bus-util-move-string-set-append-get-funcs-to-.patch
similarity index 98%
rename from SOURCES/0268-shared-bus-util-move-string-set-append-get-funcs-to-.patch
rename to SOURCES/0289-shared-bus-util-move-string-set-append-get-funcs-to-.patch
index 761bb87f27358ae10b82260b8c62cbbee7db6319..e8d18f0a5feeab75671d287b4302bd64ef03c87b 100644
--- a/SOURCES/0268-shared-bus-util-move-string-set-append-get-funcs-to-.patch
+++ b/SOURCES/0289-shared-bus-util-move-string-set-append-get-funcs-to-.patch
@@ -1,4 +1,4 @@
-From c53d1e0bdb9a48fa1b902d85848b1bdd252d1606 Mon Sep 17 00:00:00 2001
+From e0c7b4d3ca67508c319fa28ef562dfc0c9982765 Mon Sep 17 00:00:00 2001
 From: Mike Yuan <me@yhndnzj.com>
 Date: Sat, 11 Jan 2025 18:04:37 +0100
 Subject: [PATCH] shared/bus-util: move string set append/get funcs to
diff --git a/SOURCES/0269-shared-serialize-make-input-params-const.patch b/SOURCES/0290-shared-serialize-make-input-params-const.patch
similarity index 97%
rename from SOURCES/0269-shared-serialize-make-input-params-const.patch
rename to SOURCES/0290-shared-serialize-make-input-params-const.patch
index 4e4096d270fac4477cfe016afd87c70e6ec76ede..f16de3e442b135897f9a5e3b7a765ada7fbafc0e 100644
--- a/SOURCES/0269-shared-serialize-make-input-params-const.patch
+++ b/SOURCES/0290-shared-serialize-make-input-params-const.patch
@@ -1,4 +1,4 @@
-From 14c41b05308e6b8911be1d9703fd5aab7b6ee902 Mon Sep 17 00:00:00 2001
+From fb16bc1ebc0f6d3747e52be6238ced202ce2bbb5 Mon Sep 17 00:00:00 2001
 From: Mike Yuan <me@yhndnzj.com>
 Date: Mon, 13 Jan 2025 16:35:13 +0100
 Subject: [PATCH] shared/serialize: make input params const
diff --git a/SOURCES/0270-shared-serialize-introduce-serialize_id128.patch b/SOURCES/0291-shared-serialize-introduce-serialize_id128.patch
similarity index 97%
rename from SOURCES/0270-shared-serialize-introduce-serialize_id128.patch
rename to SOURCES/0291-shared-serialize-introduce-serialize_id128.patch
index 6b7232fbd160960be0029c6c73617183e6ddef30..a598391e63ba9af50824c67901562db90788819e 100644
--- a/SOURCES/0270-shared-serialize-introduce-serialize_id128.patch
+++ b/SOURCES/0291-shared-serialize-introduce-serialize_id128.patch
@@ -1,4 +1,4 @@
-From d59a5e3674de4e7973c10cf3122a75259022ee01 Mon Sep 17 00:00:00 2001
+From 3e782a6a5e9ab272280e1dbd15a433d15ecf8961 Mon Sep 17 00:00:00 2001
 From: Mike Yuan <me@yhndnzj.com>
 Date: Mon, 13 Jan 2025 16:35:58 +0100
 Subject: [PATCH] shared/serialize: introduce serialize_id128()
diff --git a/SOURCES/0271-bus-util-do-not-reset-the-count-returned-by-sd_bus_t.patch b/SOURCES/0292-bus-util-do-not-reset-the-count-returned-by-sd_bus_t.patch
similarity index 96%
rename from SOURCES/0271-bus-util-do-not-reset-the-count-returned-by-sd_bus_t.patch
rename to SOURCES/0292-bus-util-do-not-reset-the-count-returned-by-sd_bus_t.patch
index f5b1e72e30472ea15a83e0e1f6f72cf6f1f5da0d..a64ad5097d9a2a6cc9270f409a9347239f48f449 100644
--- a/SOURCES/0271-bus-util-do-not-reset-the-count-returned-by-sd_bus_t.patch
+++ b/SOURCES/0292-bus-util-do-not-reset-the-count-returned-by-sd_bus_t.patch
@@ -1,4 +1,4 @@
-From 76809cbbc63d43836f16d4d9ba9ccce9582122ee Mon Sep 17 00:00:00 2001
+From 24cb20f7d53015dace0a2a7621c7671ab54b1e81 Mon Sep 17 00:00:00 2001
 From: Mike Yuan <me@yhndnzj.com>
 Date: Sat, 11 Jan 2025 16:26:55 +0100
 Subject: [PATCH] bus-util: do not reset the count returned by
diff --git a/SOURCES/0272-core-manager-use-FOREACH_ARRAY-at-one-more-place.patch b/SOURCES/0293-core-manager-use-FOREACH_ARRAY-at-one-more-place.patch
similarity index 94%
rename from SOURCES/0272-core-manager-use-FOREACH_ARRAY-at-one-more-place.patch
rename to SOURCES/0293-core-manager-use-FOREACH_ARRAY-at-one-more-place.patch
index d6aea1e09d339a46080d4e8bf6d918c91994ad7b..0dd548ab46b2a3518ec5a92cced318c4d1a4e531 100644
--- a/SOURCES/0272-core-manager-use-FOREACH_ARRAY-at-one-more-place.patch
+++ b/SOURCES/0293-core-manager-use-FOREACH_ARRAY-at-one-more-place.patch
@@ -1,4 +1,4 @@
-From 5486bfede7481152ce3b22ed4286791d53fea3b4 Mon Sep 17 00:00:00 2001
+From 66d8a57b8bc706ce0454689562a8f86850ffef5a Mon Sep 17 00:00:00 2001
 From: Mike Yuan <me@yhndnzj.com>
 Date: Mon, 13 Jan 2025 17:06:21 +0100
 Subject: [PATCH] core/manager: use FOREACH_ARRAY at one more place
diff --git a/SOURCES/0273-core-manager-drop-duplicate-bus-track-deserializatio.patch b/SOURCES/0294-core-manager-drop-duplicate-bus-track-deserializatio.patch
similarity index 95%
rename from SOURCES/0273-core-manager-drop-duplicate-bus-track-deserializatio.patch
rename to SOURCES/0294-core-manager-drop-duplicate-bus-track-deserializatio.patch
index dcd055bca8ab84d61dbac544167dc75c8599fbf0..e8a084ac36d20ea38354f765d8fd5a435cafac27 100644
--- a/SOURCES/0273-core-manager-drop-duplicate-bus-track-deserializatio.patch
+++ b/SOURCES/0294-core-manager-drop-duplicate-bus-track-deserializatio.patch
@@ -1,4 +1,4 @@
-From 494158868273df13f4bace55a555683b579e2506 Mon Sep 17 00:00:00 2001
+From ce620175b0cd9e90461058b04700a204531900a5 Mon Sep 17 00:00:00 2001
 From: Mike Yuan <me@yhndnzj.com>
 Date: Sat, 11 Jan 2025 18:38:49 +0100
 Subject: [PATCH] core/manager: drop duplicate bus track deserialization
diff --git a/SOURCES/0274-bus-util-introduce-bus_get_instance_id.patch b/SOURCES/0295-bus-util-introduce-bus_get_instance_id.patch
similarity index 96%
rename from SOURCES/0274-bus-util-introduce-bus_get_instance_id.patch
rename to SOURCES/0295-bus-util-introduce-bus_get_instance_id.patch
index 1971c672ee9d2b2b68f6d58f8d5c1b6fee809b75..a0881eae7d596aa26906a49be2655406858355c6 100644
--- a/SOURCES/0274-bus-util-introduce-bus_get_instance_id.patch
+++ b/SOURCES/0295-bus-util-introduce-bus_get_instance_id.patch
@@ -1,4 +1,4 @@
-From d3c951a20af778bdc065c94ee1d1540730b51e53 Mon Sep 17 00:00:00 2001
+From e92f809870c24f13eee4dbf50d0725eab9c8d8ea Mon Sep 17 00:00:00 2001
 From: Mike Yuan <me@yhndnzj.com>
 Date: Mon, 13 Jan 2025 16:42:34 +0100
 Subject: [PATCH] bus-util: introduce bus_get_instance_id()
diff --git a/SOURCES/0275-core-serialize-API-bus-id-and-validate-before-deseri.patch b/SOURCES/0296-core-serialize-API-bus-id-and-validate-before-deseri.patch
similarity index 99%
rename from SOURCES/0275-core-serialize-API-bus-id-and-validate-before-deseri.patch
rename to SOURCES/0296-core-serialize-API-bus-id-and-validate-before-deseri.patch
index 5ec17174a29185ed47e8335926b426d0c1ac04c9..5c5c5d9ca0636b242668af11ce268b27a99a1b30 100644
--- a/SOURCES/0275-core-serialize-API-bus-id-and-validate-before-deseri.patch
+++ b/SOURCES/0296-core-serialize-API-bus-id-and-validate-before-deseri.patch
@@ -1,4 +1,4 @@
-From 42933b1d439e7197e9fc6bc66a945932105c1a91 Mon Sep 17 00:00:00 2001
+From ec9f1ba4bf2b17aa2d10c1196271ce164f4e7c91 Mon Sep 17 00:00:00 2001
 From: Mike Yuan <me@yhndnzj.com>
 Date: Mon, 13 Jan 2025 17:06:35 +0100
 Subject: [PATCH] core: serialize API bus id and validate before deserializing
diff --git a/SOURCES/0276-core-manager-restore-bus-track-deserialization-clean.patch b/SOURCES/0297-core-manager-restore-bus-track-deserialization-clean.patch
similarity index 94%
rename from SOURCES/0276-core-manager-restore-bus-track-deserialization-clean.patch
rename to SOURCES/0297-core-manager-restore-bus-track-deserialization-clean.patch
index 3bd765518d50573055d522034fab6b293ce9a295..d093c3a690f4da0dcf389bc4f22a09b4ce7f1e62 100644
--- a/SOURCES/0276-core-manager-restore-bus-track-deserialization-clean.patch
+++ b/SOURCES/0297-core-manager-restore-bus-track-deserialization-clean.patch
@@ -1,4 +1,4 @@
-From 18246c12768c55d28281a15dd26cbc777ef1789f Mon Sep 17 00:00:00 2001
+From e67e2c131c1ebc4dd820e2580baac9e7bbf4564c Mon Sep 17 00:00:00 2001
 From: Mike Yuan <me@yhndnzj.com>
 Date: Mon, 13 Jan 2025 17:30:51 +0100
 Subject: [PATCH] core/manager: restore bus track deserialization cleanup in
diff --git a/SOURCES/0277-shared-bus-util-add-missing-set.h-include.patch b/SOURCES/0298-shared-bus-util-add-missing-set.h-include.patch
similarity index 95%
rename from SOURCES/0277-shared-bus-util-add-missing-set.h-include.patch
rename to SOURCES/0298-shared-bus-util-add-missing-set.h-include.patch
index e07a4c077489da18873df3c927f28b6169a26415..2049aa57ad8770a30ad7a43393968e2eff1f4ef7 100644
--- a/SOURCES/0277-shared-bus-util-add-missing-set.h-include.patch
+++ b/SOURCES/0298-shared-bus-util-add-missing-set.h-include.patch
@@ -1,4 +1,4 @@
-From 02bdc612e1c1d9a484c758384ad6375c1ede5e9f Mon Sep 17 00:00:00 2001
+From 7a1733c162f1258a85eef648ed283fffc56ff5c3 Mon Sep 17 00:00:00 2001
 From: Jan Macku <jamacku@redhat.com>
 Date: Wed, 15 Jan 2025 15:06:46 +0100
 Subject: [PATCH] shared/bus-util: add missing `set.h` include
diff --git a/SOURCES/0278-udevadm-test-add-missing-oom-check.patch b/SOURCES/0299-udevadm-test-add-missing-oom-check.patch
similarity index 92%
rename from SOURCES/0278-udevadm-test-add-missing-oom-check.patch
rename to SOURCES/0299-udevadm-test-add-missing-oom-check.patch
index 305054a83cefa14f16b73245ef49c070a41e55c9..8f37cf694b5721a8579cae447709cf5b44793fc5 100644
--- a/SOURCES/0278-udevadm-test-add-missing-oom-check.patch
+++ b/SOURCES/0299-udevadm-test-add-missing-oom-check.patch
@@ -1,4 +1,4 @@
-From 511e1fad5fdac4b078fca5e2347ed5bac582e4b9 Mon Sep 17 00:00:00 2001
+From fdefe7c099925a6432f97d860217e6b1b429c279 Mon Sep 17 00:00:00 2001
 From: Yu Watanabe <watanabe.yu+github@gmail.com>
 Date: Sat, 11 Jan 2025 05:27:44 +0900
 Subject: [PATCH] udevadm-test: add missing oom check
diff --git a/SOURCES/0279-udev-rules-replace-type-func-type-func.patch b/SOURCES/0300-udev-rules-replace-type-func-type-func.patch
similarity index 95%
rename from SOURCES/0279-udev-rules-replace-type-func-type-func.patch
rename to SOURCES/0300-udev-rules-replace-type-func-type-func.patch
index ba2c44602877d4f64c0f201c905ec9311a8fa725..5e7db5d38bc1e04982ca59bfef33a72a722c22a3 100644
--- a/SOURCES/0279-udev-rules-replace-type-func-type-func.patch
+++ b/SOURCES/0300-udev-rules-replace-type-func-type-func.patch
@@ -1,4 +1,4 @@
-From 2c0eb3137cb1a886763b4d254bfe1871d4872a3b Mon Sep 17 00:00:00 2001
+From 24e7457de660efd3e6906c7fa4708d55d7e45f93 Mon Sep 17 00:00:00 2001
 From: Yu Watanabe <watanabe.yu+github@gmail.com>
 Date: Sat, 11 Jan 2025 03:57:34 +0900
 Subject: [PATCH] udev-rules: replace 'type *func()' -> 'type* func()'
diff --git a/SOURCES/0280-udev-rules-do-not-change-maximum-log-level-when-runn.patch b/SOURCES/0301-udev-rules-do-not-change-maximum-log-level-when-runn.patch
similarity index 96%
rename from SOURCES/0280-udev-rules-do-not-change-maximum-log-level-when-runn.patch
rename to SOURCES/0301-udev-rules-do-not-change-maximum-log-level-when-runn.patch
index aaee03234577a26f53701ac1f5ef92fdef721272..f325d332a0bd79b1d6c58a26f44300821885e500 100644
--- a/SOURCES/0280-udev-rules-do-not-change-maximum-log-level-when-runn.patch
+++ b/SOURCES/0301-udev-rules-do-not-change-maximum-log-level-when-runn.patch
@@ -1,4 +1,4 @@
-From dffdf9bcba4cdd2b27b65f210525fd45fc492904 Mon Sep 17 00:00:00 2001
+From 19e40fd51b249a05aae478c733aec343cfc39d54 Mon Sep 17 00:00:00 2001
 From: Yu Watanabe <watanabe.yu+github@gmail.com>
 Date: Sat, 11 Jan 2025 06:07:55 +0900
 Subject: [PATCH] udev-rules: do not change maximum log level when running in
diff --git a/SOURCES/0281-udevadm-test-introduce-v-verbose-option-to-show-verb.patch b/SOURCES/0302-udevadm-test-introduce-v-verbose-option-to-show-verb.patch
similarity index 99%
rename from SOURCES/0281-udevadm-test-introduce-v-verbose-option-to-show-verb.patch
rename to SOURCES/0302-udevadm-test-introduce-v-verbose-option-to-show-verb.patch
index 44c4fecc7fd205503effd69b199174bf3e8bf798..69f02d61d0d946fafde9be8d5f7af220578a6c5b 100644
--- a/SOURCES/0281-udevadm-test-introduce-v-verbose-option-to-show-verb.patch
+++ b/SOURCES/0302-udevadm-test-introduce-v-verbose-option-to-show-verb.patch
@@ -1,4 +1,4 @@
-From 8b8b65c0da68c96900e694d94571abe4d59fe0da Mon Sep 17 00:00:00 2001
+From 17214f471355ed135c503fe64687749b8b0dbe86 Mon Sep 17 00:00:00 2001
 From: Yu Watanabe <watanabe.yu+github@gmail.com>
 Date: Mon, 13 Jan 2025 05:09:15 +0900
 Subject: [PATCH] udevadm-test: introduce -v/--verbose option to show verbose
diff --git a/SOURCES/0282-udev-rules-show-original-token-string-in-log_event_e.patch b/SOURCES/0303-udev-rules-show-original-token-string-in-log_event_e.patch
similarity index 99%
rename from SOURCES/0282-udev-rules-show-original-token-string-in-log_event_e.patch
rename to SOURCES/0303-udev-rules-show-original-token-string-in-log_event_e.patch
index 3c2572936aa377caa92388bdbf609c2190c825f3..894f58ff2ec085b7f49a7141b6d31d373ea2a67e 100644
--- a/SOURCES/0282-udev-rules-show-original-token-string-in-log_event_e.patch
+++ b/SOURCES/0303-udev-rules-show-original-token-string-in-log_event_e.patch
@@ -1,4 +1,4 @@
-From 0286607e910e964c9eb05b719ce37954dd4d9e2b Mon Sep 17 00:00:00 2001
+From cdbd8b3bdec0c3f2ca0258acedc88a0191be176b Mon Sep 17 00:00:00 2001
 From: Yu Watanabe <watanabe.yu+github@gmail.com>
 Date: Mon, 13 Jan 2025 05:12:40 +0900
 Subject: [PATCH] udev-rules: show original token string in log_event_error()
diff --git a/SOURCES/0283-udev-rules-logs-result-of-format-substitution.patch b/SOURCES/0304-udev-rules-logs-result-of-format-substitution.patch
similarity index 99%
rename from SOURCES/0283-udev-rules-logs-result-of-format-substitution.patch
rename to SOURCES/0304-udev-rules-logs-result-of-format-substitution.patch
index b245fa6b955364bfffdc3cab3d0fa52aea5d13d0..923b7d439ec4aa5733374d8a7d864846587b02b1 100644
--- a/SOURCES/0283-udev-rules-logs-result-of-format-substitution.patch
+++ b/SOURCES/0304-udev-rules-logs-result-of-format-substitution.patch
@@ -1,4 +1,4 @@
-From b1d0e76a3a2bde484cb69e2138cbb8d7b966130e Mon Sep 17 00:00:00 2001
+From 5f21939ebe4ca3c23c33383336030b45b72f86b5 Mon Sep 17 00:00:00 2001
 From: Yu Watanabe <watanabe.yu+github@gmail.com>
 Date: Sun, 12 Jan 2025 00:12:52 +0900
 Subject: [PATCH] udev-rules: logs result of format substitution
diff --git a/SOURCES/0284-udev-rules-add-more-trace-logs-for-string-match.patch b/SOURCES/0305-udev-rules-add-more-trace-logs-for-string-match.patch
similarity index 99%
rename from SOURCES/0284-udev-rules-add-more-trace-logs-for-string-match.patch
rename to SOURCES/0305-udev-rules-add-more-trace-logs-for-string-match.patch
index ab9068b6d7980359af5e86ab5bc2ea342e5be039..e3a25e1b83aca9eaa3f2f47e13658a30239298f6 100644
--- a/SOURCES/0284-udev-rules-add-more-trace-logs-for-string-match.patch
+++ b/SOURCES/0305-udev-rules-add-more-trace-logs-for-string-match.patch
@@ -1,4 +1,4 @@
-From 42b0f1bcc8126420d0eb657261a300d506f7c093 Mon Sep 17 00:00:00 2001
+From a10de9d393f4996bc9735e8cd2f10e1edb5c7284 Mon Sep 17 00:00:00 2001
 From: Yu Watanabe <watanabe.yu+github@gmail.com>
 Date: Mon, 13 Jan 2025 04:03:11 +0900
 Subject: [PATCH] udev-rules: add more trace logs for string match
diff --git a/SOURCES/0285-udev-rules-introduce-udev_replace_chars_and_log.patch b/SOURCES/0306-udev-rules-introduce-udev_replace_chars_and_log.patch
similarity index 99%
rename from SOURCES/0285-udev-rules-introduce-udev_replace_chars_and_log.patch
rename to SOURCES/0306-udev-rules-introduce-udev_replace_chars_and_log.patch
index 87aef42dab3841786c4315eb8b722a5b3e4bbff0..88b78c4ec088f644b84bcbdaec8ac68523a0512c 100644
--- a/SOURCES/0285-udev-rules-introduce-udev_replace_chars_and_log.patch
+++ b/SOURCES/0306-udev-rules-introduce-udev_replace_chars_and_log.patch
@@ -1,4 +1,4 @@
-From 93ae29d07b292ee76d0dd82277db54a6ee78eace Mon Sep 17 00:00:00 2001
+From b1983b3bf0a5328edfb999c35a923cbc883ed7d4 Mon Sep 17 00:00:00 2001
 From: Yu Watanabe <watanabe.yu+github@gmail.com>
 Date: Wed, 15 Jan 2025 22:09:05 +0900
 Subject: [PATCH] udev-rules: introduce udev_replace_chars_and_log()
diff --git a/SOURCES/0286-udev-rules-ignore-whole-command-result-if-it-is-too-.patch b/SOURCES/0307-udev-rules-ignore-whole-command-result-if-it-is-too-.patch
similarity index 95%
rename from SOURCES/0286-udev-rules-ignore-whole-command-result-if-it-is-too-.patch
rename to SOURCES/0307-udev-rules-ignore-whole-command-result-if-it-is-too-.patch
index a1278a4d582d3286aa6855fc420b5daa21237132..ea8671cca2b0b4c2aa78eeed980c84b2e6c3a552 100644
--- a/SOURCES/0286-udev-rules-ignore-whole-command-result-if-it-is-too-.patch
+++ b/SOURCES/0307-udev-rules-ignore-whole-command-result-if-it-is-too-.patch
@@ -1,4 +1,4 @@
-From 224d090a512006eccbd1dfc2e669e7ada8f6ebf4 Mon Sep 17 00:00:00 2001
+From c2163f365b7f565358d6f5d9ba78cce087cf4cf9 Mon Sep 17 00:00:00 2001
 From: Yu Watanabe <watanabe.yu+github@gmail.com>
 Date: Wed, 15 Jan 2025 23:43:37 +0900
 Subject: [PATCH] udev-rules: ignore whole command result if it is too long and
diff --git a/SOURCES/0287-udev-rules-update-log-messages.patch b/SOURCES/0308-udev-rules-update-log-messages.patch
similarity index 99%
rename from SOURCES/0287-udev-rules-update-log-messages.patch
rename to SOURCES/0308-udev-rules-update-log-messages.patch
index 2b7a6c8707f6899e1682566d13d24bb6daf06627..57dec0fbf11945b3685c9262c4efce3db2194334 100644
--- a/SOURCES/0287-udev-rules-update-log-messages.patch
+++ b/SOURCES/0308-udev-rules-update-log-messages.patch
@@ -1,4 +1,4 @@
-From 9a88f822a6e604434abc51b9eee4e6087a6e8483 Mon Sep 17 00:00:00 2001
+From ee390c8b143a7aebe76dfdb009d7fcfbd931a6ea Mon Sep 17 00:00:00 2001
 From: Yu Watanabe <watanabe.yu+github@gmail.com>
 Date: Wed, 15 Jan 2025 23:47:05 +0900
 Subject: [PATCH] udev-rules: update log messages
diff --git a/SOURCES/0288-udev-rules-add-trace-logs-for-GOTO-and-parent-condit.patch b/SOURCES/0309-udev-rules-add-trace-logs-for-GOTO-and-parent-condit.patch
similarity index 98%
rename from SOURCES/0288-udev-rules-add-trace-logs-for-GOTO-and-parent-condit.patch
rename to SOURCES/0309-udev-rules-add-trace-logs-for-GOTO-and-parent-condit.patch
index 442c809cb217c6f14d803b7148eeb25d381aadb0..f5d11673b833b99c78d799b233caec35f671c6e2 100644
--- a/SOURCES/0288-udev-rules-add-trace-logs-for-GOTO-and-parent-condit.patch
+++ b/SOURCES/0309-udev-rules-add-trace-logs-for-GOTO-and-parent-condit.patch
@@ -1,4 +1,4 @@
-From fabb5fa7a0f6a7480688488ae8724ec93167b857 Mon Sep 17 00:00:00 2001
+From 2e8cb0b6ed4a75962dcb91fb2737d4c098893618 Mon Sep 17 00:00:00 2001
 From: Yu Watanabe <watanabe.yu+github@gmail.com>
 Date: Mon, 13 Jan 2025 05:18:25 +0900
 Subject: [PATCH] udev-rules: add trace logs for GOTO and parent conditions
diff --git a/SOURCES/0310-udev-move-enums-to-udev-def.h.patch b/SOURCES/0310-udev-move-enums-to-udev-def.h.patch
new file mode 100644
index 0000000000000000000000000000000000000000..e88fd02a662e3c5b41ec566b1c744917672a1831
--- /dev/null
+++ b/SOURCES/0310-udev-move-enums-to-udev-def.h.patch
@@ -0,0 +1,318 @@
+From d7038446b87ee770bc01a288fac81d86723c9838 Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Wed, 4 Dec 2024 06:05:38 +0900
+Subject: [PATCH] udev: move enums to udev-def.h
+
+No functional change, just refactoring and preparation for later
+commits.
+
+(cherry picked from commit 0bdcca5aee60422167065be156990f2a88e0ed95)
+
+Resolves: RHEL-75774
+---
+ src/udev/test-udev-rule-runner.c |  1 +
+ src/udev/udev-builtin.h          | 24 +-------------
+ src/udev/udev-def.h              | 57 ++++++++++++++++++++++++++++++++
+ src/udev/udev-event.c            |  2 ++
+ src/udev/udev-event.h            | 12 ++-----
+ src/udev/udev-format.c           |  1 +
+ src/udev/udev-manager.c          |  1 +
+ src/udev/udev-manager.h          |  3 +-
+ src/udev/udev-rules.c            |  1 +
+ src/udev/udev-rules.h            | 21 +-----------
+ src/udev/udev-spawn.c            |  1 +
+ src/udev/udev-worker.c           |  1 +
+ src/udev/udevadm-test.c          |  1 +
+ src/udev/udevd.c                 |  1 +
+ 14 files changed, 74 insertions(+), 53 deletions(-)
+ create mode 100644 src/udev/udev-def.h
+
+diff --git a/src/udev/test-udev-rule-runner.c b/src/udev/test-udev-rule-runner.c
+index db41813511..d123c8ad1b 100644
+--- a/src/udev/test-udev-rule-runner.c
++++ b/src/udev/test-udev-rule-runner.c
+@@ -25,6 +25,7 @@
+ #include "string-util.h"
+ #include "tests.h"
+ #include "udev-event.h"
++#include "udev-rules.h"
+ #include "udev-spawn.h"
+ #include "version.h"
+ 
+diff --git a/src/udev/udev-builtin.h b/src/udev/udev-builtin.h
+index b4ddba095a..2433dfa4d4 100644
+--- a/src/udev/udev-builtin.h
++++ b/src/udev/udev-builtin.h
+@@ -7,31 +7,9 @@
+ #include "sd-netlink.h"
+ 
+ #include "macro.h"
++#include "udev-def.h"
+ #include "udev-event.h"
+ 
+-typedef enum UdevBuiltinCommand {
+-#if HAVE_BLKID
+-        UDEV_BUILTIN_BLKID,
+-#endif
+-        UDEV_BUILTIN_BTRFS,
+-        UDEV_BUILTIN_HWDB,
+-        UDEV_BUILTIN_INPUT_ID,
+-        UDEV_BUILTIN_KEYBOARD,
+-#if HAVE_KMOD
+-        UDEV_BUILTIN_KMOD,
+-#endif
+-        UDEV_BUILTIN_NET_DRIVER,
+-        UDEV_BUILTIN_NET_ID,
+-        UDEV_BUILTIN_NET_LINK,
+-        UDEV_BUILTIN_PATH_ID,
+-        UDEV_BUILTIN_USB_ID,
+-#if HAVE_ACL
+-        UDEV_BUILTIN_UACCESS,
+-#endif
+-        _UDEV_BUILTIN_MAX,
+-        _UDEV_BUILTIN_INVALID = -EINVAL,
+-} UdevBuiltinCommand;
+-
+ typedef struct UdevBuiltin {
+         const char *name;
+         int (*cmd)(UdevEvent *event, int argc, char *argv[]);
+diff --git a/src/udev/udev-def.h b/src/udev/udev-def.h
+new file mode 100644
+index 0000000000..6ff3feacec
+--- /dev/null
++++ b/src/udev/udev-def.h
+@@ -0,0 +1,57 @@
++/* SPDX-License-Identifier: GPL-2.0-or-later */
++#pragma once
++
++#include <errno.h>
++
++#define UDEV_NAME_SIZE   512
++#define UDEV_PATH_SIZE  1024
++#define UDEV_LINE_SIZE 16384
++
++typedef enum EventMode {
++        EVENT_UDEV_WORKER,
++        EVENT_UDEVADM_TEST,
++        EVENT_UDEVADM_TEST_BUILTIN,
++        EVENT_TEST_RULE_RUNNER,
++        EVENT_TEST_SPAWN,
++        _EVENT_MODE_MAX,
++        _EVENT_MODE_INVALID = -EINVAL,
++} EventMode;
++
++typedef enum UdevRuleEscapeType {
++        ESCAPE_UNSET,
++        ESCAPE_NONE,    /* OPTIONS="string_escape=none" */
++        ESCAPE_REPLACE, /* OPTIONS="string_escape=replace" */
++        _ESCAPE_TYPE_MAX,
++        _ESCAPE_TYPE_INVALID = -EINVAL,
++} UdevRuleEscapeType;
++
++typedef enum ResolveNameTiming {
++        RESOLVE_NAME_NEVER,
++        RESOLVE_NAME_LATE,
++        RESOLVE_NAME_EARLY,
++        _RESOLVE_NAME_TIMING_MAX,
++        _RESOLVE_NAME_TIMING_INVALID = -EINVAL,
++} ResolveNameTiming;
++
++typedef enum UdevBuiltinCommand {
++#if HAVE_BLKID
++        UDEV_BUILTIN_BLKID,
++#endif
++        UDEV_BUILTIN_BTRFS,
++        UDEV_BUILTIN_HWDB,
++        UDEV_BUILTIN_INPUT_ID,
++        UDEV_BUILTIN_KEYBOARD,
++#if HAVE_KMOD
++        UDEV_BUILTIN_KMOD,
++#endif
++        UDEV_BUILTIN_NET_DRIVER,
++        UDEV_BUILTIN_NET_ID,
++        UDEV_BUILTIN_NET_LINK,
++        UDEV_BUILTIN_PATH_ID,
++        UDEV_BUILTIN_USB_ID,
++#if HAVE_ACL
++        UDEV_BUILTIN_UACCESS,
++#endif
++        _UDEV_BUILTIN_MAX,
++        _UDEV_BUILTIN_INVALID = -EINVAL,
++} UdevBuiltinCommand;
+diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
+index 607071a8cf..7fa86ddd84 100644
+--- a/src/udev/udev-event.c
++++ b/src/udev/udev-event.c
+@@ -12,8 +12,10 @@
+ #include "strv.h"
+ #include "udev-event.h"
+ #include "udev-node.h"
++#include "udev-rules.h"
+ #include "udev-trace.h"
+ #include "udev-util.h"
++#include "udev-worker.h"
+ #include "user-util.h"
+ 
+ UdevEvent *udev_event_new(sd_device *dev, UdevWorker *worker, EventMode mode) {
+diff --git a/src/udev/udev-event.h b/src/udev/udev-event.h
+index 22388fe904..88a7cfe497 100644
+--- a/src/udev/udev-event.h
++++ b/src/udev/udev-event.h
+@@ -14,17 +14,11 @@
+ #include "hashmap.h"
+ #include "macro.h"
+ #include "time-util.h"
+-#include "udev-rules.h"
+-#include "udev-worker.h"
++#include "udev-def.h"
+ #include "user-util.h"
+ 
+-typedef enum EventMode {
+-        EVENT_UDEV_WORKER,
+-        EVENT_UDEVADM_TEST,
+-        EVENT_UDEVADM_TEST_BUILTIN,
+-        EVENT_TEST_RULE_RUNNER,
+-        EVENT_TEST_SPAWN,
+-} EventMode;
++typedef struct UdevRules UdevRules;
++typedef struct UdevWorker UdevWorker;
+ 
+ typedef struct UdevEvent {
+         UdevWorker *worker;
+diff --git a/src/udev/udev-format.c b/src/udev/udev-format.c
+index 4bfa6d7a3e..8637d802fc 100644
+--- a/src/udev/udev-format.c
++++ b/src/udev/udev-format.c
+@@ -8,6 +8,7 @@
+ #include "udev-event.h"
+ #include "udev-format.h"
+ #include "udev-util.h"
++#include "udev-worker.h"
+ 
+ typedef enum {
+         FORMAT_SUBST_DEVNODE,
+diff --git a/src/udev/udev-manager.c b/src/udev/udev-manager.c
+index 32bc0db345..5b1135c9e8 100644
+--- a/src/udev/udev-manager.c
++++ b/src/udev/udev-manager.c
+@@ -29,6 +29,7 @@
+ #include "udev-event.h"
+ #include "udev-manager.h"
+ #include "udev-node.h"
++#include "udev-rules.h"
+ #include "udev-spawn.h"
+ #include "udev-trace.h"
+ #include "udev-util.h"
+diff --git a/src/udev/udev-manager.h b/src/udev/udev-manager.h
+index 5921d333d1..5519eb33bb 100644
+--- a/src/udev/udev-manager.h
++++ b/src/udev/udev-manager.h
+@@ -10,9 +10,10 @@
+ #include "macro.h"
+ #include "time-util.h"
+ #include "udev-ctrl.h"
+-#include "udev-rules.h"
++#include "udev-def.h"
+ 
+ typedef struct Event Event;
++typedef struct UdevRules UdevRules;
+ typedef struct Worker Worker;
+ 
+ typedef struct Manager {
+diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c
+index 4f2021b8c4..6345b80cba 100644
+--- a/src/udev/udev-rules.c
++++ b/src/udev/udev-rules.c
+@@ -39,6 +39,7 @@
+ #include "udev-spawn.h"
+ #include "udev-trace.h"
+ #include "udev-util.h"
++#include "udev-worker.h"
+ #include "user-util.h"
+ #include "virt.h"
+ 
+diff --git a/src/udev/udev-rules.h b/src/udev/udev-rules.h
+index 61d517d9da..3bd4b04ab3 100644
+--- a/src/udev/udev-rules.h
++++ b/src/udev/udev-rules.h
+@@ -4,31 +4,12 @@
+ #include "alloc-util.h"
+ #include "hashmap.h"
+ #include "time-util.h"
+-
+-#define UDEV_NAME_SIZE   512
+-#define UDEV_PATH_SIZE  1024
+-#define UDEV_LINE_SIZE 16384
++#include "udev-def.h"
+ 
+ typedef struct UdevRuleFile UdevRuleFile;
+ typedef struct UdevRules UdevRules;
+ typedef struct UdevEvent UdevEvent;
+ 
+-typedef enum {
+-        ESCAPE_UNSET,
+-        ESCAPE_NONE,    /* OPTIONS="string_escape=none" */
+-        ESCAPE_REPLACE, /* OPTIONS="string_escape=replace" */
+-        _ESCAPE_TYPE_MAX,
+-        _ESCAPE_TYPE_INVALID = -EINVAL,
+-} UdevRuleEscapeType;
+-
+-typedef enum ResolveNameTiming {
+-        RESOLVE_NAME_NEVER,
+-        RESOLVE_NAME_LATE,
+-        RESOLVE_NAME_EARLY,
+-        _RESOLVE_NAME_TIMING_MAX,
+-        _RESOLVE_NAME_TIMING_INVALID = -EINVAL,
+-} ResolveNameTiming;
+-
+ int udev_rule_parse_value(char *str, char **ret_value, char **ret_endpos, bool *ret_is_case_insensitive);
+ int udev_rules_parse_file(UdevRules *rules, const char *filename, bool extra_checks, UdevRuleFile **ret);
+ unsigned udev_rule_file_get_issues(UdevRuleFile *rule_file);
+diff --git a/src/udev/udev-spawn.c b/src/udev/udev-spawn.c
+index d2a422f7e8..b95141cf21 100644
+--- a/src/udev/udev-spawn.c
++++ b/src/udev/udev-spawn.c
+@@ -14,6 +14,7 @@
+ #include "udev-event.h"
+ #include "udev-spawn.h"
+ #include "udev-trace.h"
++#include "udev-worker.h"
+ 
+ typedef struct Spawn {
+         sd_device *device;
+diff --git a/src/udev/udev-worker.c b/src/udev/udev-worker.c
+index fc1bfd684c..0c57551a37 100644
+--- a/src/udev/udev-worker.c
++++ b/src/udev/udev-worker.c
+@@ -18,6 +18,7 @@
+ #include "signal-util.h"
+ #include "string-util.h"
+ #include "udev-event.h"
++#include "udev-rules.h"
+ #include "udev-spawn.h"
+ #include "udev-trace.h"
+ #include "udev-util.h"
+diff --git a/src/udev/udevadm-test.c b/src/udev/udevadm-test.c
+index 7f3e534d2b..863eab87a5 100644
+--- a/src/udev/udevadm-test.c
++++ b/src/udev/udevadm-test.c
+@@ -26,6 +26,7 @@
+ #include "udev-builtin.h"
+ #include "udev-event.h"
+ #include "udev-format.h"
++#include "udev-rules.h"
+ #include "udevadm-util.h"
+ #include "udevadm.h"
+ #include "user-util.h"
+diff --git a/src/udev/udevd.c b/src/udev/udevd.c
+index c46fcaa038..bd0cefe8b5 100644
+--- a/src/udev/udevd.c
++++ b/src/udev/udevd.c
+@@ -24,6 +24,7 @@
+ #include "signal-util.h"
+ #include "syslog-util.h"
+ #include "udev-manager.h"
++#include "udev-rules.h"
+ #include "udev-util.h"
+ #include "udevd.h"
+ #include "version.h"
diff --git a/SOURCES/0311-udev-move-listen_fds-to-udev-manager.c.patch b/SOURCES/0311-udev-move-listen_fds-to-udev-manager.c.patch
new file mode 100644
index 0000000000000000000000000000000000000000..434987d721327f6960fb21d4565371c4c27d7b6c
--- /dev/null
+++ b/SOURCES/0311-udev-move-listen_fds-to-udev-manager.c.patch
@@ -0,0 +1,194 @@
+From 3e4a9e13ab88f6656e2f57ac1450832494726713 Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Wed, 4 Dec 2024 05:02:53 +0900
+Subject: [PATCH] udev: move listen_fds() to udev-manager.c
+
+Also
+- drop redundant error message when manager_init() failed,
+- close unexpected fds.
+
+No functional change, just refactoring.
+
+(cherry picked from commit a2840b9599f2c764600c3168017918c2cf213ead)
+
+Resolves: RHEL-75774
+---
+ src/udev/udev-manager.c | 57 ++++++++++++++++++++++++++++++++++++++++-
+ src/udev/udev-manager.h |  2 +-
+ src/udev/udevd.c        | 45 ++------------------------------
+ 3 files changed, 59 insertions(+), 45 deletions(-)
+
+diff --git a/src/udev/udev-manager.c b/src/udev/udev-manager.c
+index 5b1135c9e8..6e1935a731 100644
+--- a/src/udev/udev-manager.c
++++ b/src/udev/udev-manager.c
+@@ -1228,15 +1228,69 @@ void manager_adjust_arguments(Manager *manager) {
+         }
+ }
+ 
+-int manager_init(Manager *manager, int fd_ctrl, int fd_uevent) {
++static int listen_fds(int *ret_ctrl, int *ret_netlink) {
++        _cleanup_strv_free_ char **names = NULL;
++        _cleanup_close_ int ctrl_fd = -EBADF, netlink_fd = -EBADF;
++
++        assert(ret_ctrl);
++        assert(ret_netlink);
++
++        int n = sd_listen_fds_with_names(/* unset_environment = */ true, &names);
++        if (n < 0)
++                return n;
++
++        if (strv_length(names) != (size_t) n)
++                return -EIO;
++
++        for (int i = 0; i < n; i++) {
++                int fd = SD_LISTEN_FDS_START + i;
++
++                if (sd_is_socket(fd, AF_UNIX, SOCK_SEQPACKET, -1) > 0) {
++                        if (ctrl_fd >= 0) {
++                                log_debug("Received multiple seqpacket socket (%s), ignoring.", names[i]);
++                                goto unused;
++                        }
++
++                        ctrl_fd = fd;
++                        continue;
++                }
++
++                if (sd_is_socket(fd, AF_NETLINK, SOCK_RAW, -1) > 0) {
++                        if (netlink_fd >= 0) {
++                                log_debug("Received multiple netlink socket (%s), ignoring.", names[i]);
++                                goto unused;
++                        }
++
++                        netlink_fd = fd;
++                        continue;
++                }
++
++                log_debug("Received unexpected fd (%s), ignoring.", names[i]);
++
++        unused:
++                close_and_notify_warn(fd, names[i]);
++        }
++
++        *ret_ctrl = TAKE_FD(ctrl_fd);
++        *ret_netlink = TAKE_FD(netlink_fd);
++        return 0;
++}
++
++int manager_init(Manager *manager) {
++        _cleanup_close_ int fd_ctrl = -EBADF, fd_uevent = -EBADF;
+         _cleanup_free_ char *cgroup = NULL;
+         int r;
+ 
+         assert(manager);
+ 
++        r = listen_fds(&fd_ctrl, &fd_uevent);
++        if (r < 0)
++                return log_error_errno(r, "Failed to listen on fds: %m");
++
+         r = udev_ctrl_new_from_fd(&manager->ctrl, fd_ctrl);
+         if (r < 0)
+                 return log_error_errno(r, "Failed to initialize udev control socket: %m");
++        TAKE_FD(fd_ctrl);
+ 
+         r = udev_ctrl_enable_receiving(manager->ctrl);
+         if (r < 0)
+@@ -1245,6 +1299,7 @@ int manager_init(Manager *manager, int fd_ctrl, int fd_uevent) {
+         r = device_monitor_new_full(&manager->monitor, MONITOR_GROUP_KERNEL, fd_uevent);
+         if (r < 0)
+                 return log_error_errno(r, "Failed to initialize device monitor: %m");
++        TAKE_FD(fd_uevent);
+ 
+         (void) sd_device_monitor_set_description(manager->monitor, "manager");
+ 
+diff --git a/src/udev/udev-manager.h b/src/udev/udev-manager.h
+index 5519eb33bb..7c20e29594 100644
+--- a/src/udev/udev-manager.h
++++ b/src/udev/udev-manager.h
+@@ -54,7 +54,7 @@ Manager* manager_free(Manager *manager);
+ DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
+ 
+ void manager_adjust_arguments(Manager *manager);
+-int manager_init(Manager *manager, int fd_ctrl, int fd_uevent);
++int manager_init(Manager *manager);
+ int manager_main(Manager *manager);
+ 
+ bool devpath_conflict(const char *a, const char *b);
+diff --git a/src/udev/udevd.c b/src/udev/udevd.c
+index bd0cefe8b5..ef1c07a2ca 100644
+--- a/src/udev/udevd.c
++++ b/src/udev/udevd.c
+@@ -8,8 +8,6 @@
+ #include <getopt.h>
+ #include <unistd.h>
+ 
+-#include "sd-daemon.h"
+-
+ #include "conf-parser.h"
+ #include "env-file.h"
+ #include "errno-util.h"
+@@ -32,40 +30,6 @@
+ static bool arg_debug = false;
+ static int arg_daemonize = false;
+ 
+-static int listen_fds(int *ret_ctrl, int *ret_netlink) {
+-        int ctrl_fd = -EBADF, netlink_fd = -EBADF;
+-
+-        assert(ret_ctrl);
+-        assert(ret_netlink);
+-
+-        int n = sd_listen_fds(true);
+-        if (n < 0)
+-                return n;
+-
+-        for (int fd = SD_LISTEN_FDS_START; fd < n + SD_LISTEN_FDS_START; fd++) {
+-                if (sd_is_socket(fd, AF_UNIX, SOCK_SEQPACKET, -1) > 0) {
+-                        if (ctrl_fd >= 0)
+-                                return -EINVAL;
+-                        ctrl_fd = fd;
+-                        continue;
+-                }
+-
+-                if (sd_is_socket(fd, AF_NETLINK, SOCK_RAW, -1) > 0) {
+-                        if (netlink_fd >= 0)
+-                                return -EINVAL;
+-                        netlink_fd = fd;
+-                        continue;
+-                }
+-
+-                return -EINVAL;
+-        }
+-
+-        *ret_ctrl = ctrl_fd;
+-        *ret_netlink = netlink_fd;
+-
+-        return 0;
+-}
+-
+ static DEFINE_CONFIG_PARSE_ENUM(config_parse_resolve_name_timing, resolve_name_timing, ResolveNameTiming);
+ 
+ static int manager_parse_udev_config(Manager *manager) {
+@@ -287,7 +251,6 @@ static int parse_argv(int argc, char *argv[], Manager *manager) {
+ 
+ int run_udevd(int argc, char *argv[]) {
+         _cleanup_(manager_freep) Manager *manager = NULL;
+-        int fd_ctrl = -EBADF, fd_uevent = -EBADF;
+         int r;
+ 
+         log_setup();
+@@ -331,13 +294,9 @@ int run_udevd(int argc, char *argv[]) {
+         if (r < 0 && r != -EEXIST)
+                 return log_error_errno(r, "Failed to create /run/udev: %m");
+ 
+-        r = listen_fds(&fd_ctrl, &fd_uevent);
+-        if (r < 0)
+-                return log_error_errno(r, "Failed to listen on fds: %m");
+-
+-        r = manager_init(manager, fd_ctrl, fd_uevent);
++        r = manager_init(manager);
+         if (r < 0)
+-                return log_error_errno(r, "Failed to create manager: %m");
++                return r;
+ 
+         if (arg_daemonize) {
+                 pid_t pid;
diff --git a/SOURCES/0312-udev-several-coding-style-fixes.patch b/SOURCES/0312-udev-several-coding-style-fixes.patch
new file mode 100644
index 0000000000000000000000000000000000000000..8708142e46398b3c47b1fda4d4ca879901d0f6d8
--- /dev/null
+++ b/SOURCES/0312-udev-several-coding-style-fixes.patch
@@ -0,0 +1,491 @@
+From 54b98a2405e68ee9cf3d8af27b8b315659a2c656 Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Thu, 5 Dec 2024 00:44:14 +0900
+Subject: [PATCH] udev: several coding style fixes
+
+- use 'type* func()' rather than 'type *func()',
+- merge variable declarations,
+- etc.
+
+(cherry picked from commit 7ab25935f3ce677483cb9044126ac7b4b3680d8d)
+
+Resolves: RHEL-75774
+---
+ src/udev/dmi_memory_id/dmi_memory_id.c |  2 +-
+ src/udev/net/link-config.c             |  2 +-
+ src/udev/net/link-config.h             |  2 +-
+ src/udev/udev-builtin-hwdb.c           |  7 +--
+ src/udev/udev-builtin-input_id.c       | 79 +++++++++++++-------------
+ src/udev/udev-builtin-keyboard.c       |  6 +-
+ src/udev/udev-builtin-path_id.c        | 36 ++++++------
+ src/udev/udev-builtin-usb_id.c         | 30 +++-------
+ src/udev/udev-event.c                  |  4 +-
+ src/udev/udev-event.h                  |  4 +-
+ src/udev/udev-format.c                 |  2 +-
+ src/udev/udev-rules.c                  |  2 +-
+ src/udev/udev-rules.h                  |  2 +-
+ 13 files changed, 75 insertions(+), 103 deletions(-)
+
+diff --git a/src/udev/dmi_memory_id/dmi_memory_id.c b/src/udev/dmi_memory_id/dmi_memory_id.c
+index 71cec5fc47..e62222a307 100644
+--- a/src/udev/dmi_memory_id/dmi_memory_id.c
++++ b/src/udev/dmi_memory_id/dmi_memory_id.c
+@@ -89,7 +89,7 @@ static bool verify_checksum(const uint8_t *buf, size_t len) {
+  * Type-independent Stuff
+  */
+ 
+-static const char *dmi_string(const struct dmi_header *dm, uint8_t s) {
++static const char* dmi_string(const struct dmi_header *dm, uint8_t s) {
+         const char *bp = (const char *) dm->data;
+ 
+         if (s == 0)
+diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c
+index 7787f66981..c2bec61347 100644
+--- a/src/udev/net/link-config.c
++++ b/src/udev/net/link-config.c
+@@ -372,7 +372,7 @@ bool link_config_should_reload(LinkConfigContext *ctx) {
+         return !stats_by_path_equal(ctx->stats_by_path, stats_by_path);
+ }
+ 
+-Link *link_free(Link *link) {
++Link* link_free(Link *link) {
+         if (!link)
+                 return NULL;
+ 
+diff --git a/src/udev/net/link-config.h b/src/udev/net/link-config.h
+index 3152bec72a..5aaa7c51a0 100644
+--- a/src/udev/net/link-config.h
++++ b/src/udev/net/link-config.h
+@@ -103,7 +103,7 @@ int link_config_load(LinkConfigContext *ctx);
+ bool link_config_should_reload(LinkConfigContext *ctx);
+ 
+ int link_new(LinkConfigContext *ctx, sd_netlink **rtnl, sd_device *device, sd_device *device_db_clone, Link **ret);
+-Link *link_free(Link *link);
++Link* link_free(Link *link);
+ DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_free);
+ 
+ int link_get_config(LinkConfigContext *ctx, Link *link);
+diff --git a/src/udev/udev-builtin-hwdb.c b/src/udev/udev-builtin-hwdb.c
+index e33a7febd6..fbee04b4a8 100644
+--- a/src/udev/udev-builtin-hwdb.c
++++ b/src/udev/udev-builtin-hwdb.c
+@@ -50,7 +50,7 @@ int udev_builtin_hwdb_lookup(
+         return n;
+ }
+ 
+-static const char *modalias_usb(sd_device *dev, char *s, size_t size) {
++static const char* modalias_usb(sd_device *dev, char *s, size_t size) {
+         const char *v, *p, *n = NULL;
+         uint16_t vn, pn;
+ 
+@@ -130,10 +130,7 @@ static int builtin_hwdb(UdevEvent *event, int argc, char *argv[]) {
+                 { "lookup-prefix", required_argument, NULL, 'p' },
+                 {}
+         };
+-        const char *filter = NULL;
+-        const char *device = NULL;
+-        const char *subsystem = NULL;
+-        const char *prefix = NULL;
++        const char *filter = NULL, *device = NULL, *subsystem = NULL, *prefix = NULL;
+         _cleanup_(sd_device_unrefp) sd_device *srcdev = NULL;
+         sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
+         int r;
+diff --git a/src/udev/udev-builtin-input_id.c b/src/udev/udev-builtin-input_id.c
+index 876af195e2..c204d656f0 100644
+--- a/src/udev/udev-builtin-input_id.c
++++ b/src/udev/udev-builtin-input_id.c
+@@ -75,15 +75,14 @@ static void extract_info(sd_device *dev, EventMode mode) {
+  */
+ static void get_cap_mask(
+                 sd_device *pdev,
+-                const char* attr,
++                const char *attr,
+                 unsigned long *bitmask,
+                 size_t bitmask_size,
+                 EventMode mode) {
+ 
+         const char *v;
+-        char text[4096];
++        char text[4096], *word;
+         unsigned i;
+-        char* word;
+         unsigned long val;
+         int r;
+ 
+@@ -151,37 +150,36 @@ static struct input_id get_input_id(sd_device *dev) {
+ static bool test_pointers(
+                 sd_device *dev,
+                 const struct input_id *id,
+-                const unsigned long* bitmask_ev,
+-                const unsigned long* bitmask_abs,
+-                const unsigned long* bitmask_key,
+-                const unsigned long* bitmask_rel,
+-                const unsigned long* bitmask_props,
++                const unsigned long *bitmask_ev,
++                const unsigned long *bitmask_abs,
++                const unsigned long *bitmask_key,
++                const unsigned long *bitmask_rel,
++                const unsigned long *bitmask_props,
+                 EventMode mode) {
+ 
+-        bool has_abs_coordinates = false;
+-        bool has_rel_coordinates = false;
+-        bool has_mt_coordinates = false;
+-        size_t num_joystick_axes = 0;
+-        size_t num_joystick_buttons = 0;
+-        bool has_pad_buttons = false;
+-        bool is_direct = false;
+-        bool has_touch = false;
+-        bool has_3d_coordinates = false;
+-        bool has_keys = false;
+-        bool has_stylus = false;
+-        bool has_pen = false;
+-        bool finger_but_no_pen = false;
+-        bool has_mouse_button = false;
+-        bool is_mouse = false;
+-        bool is_abs_mouse = false;
+-        bool is_touchpad = false;
+-        bool is_touchscreen = false;
+-        bool is_tablet = false;
+-        bool is_tablet_pad = false;
+-        bool is_joystick = false;
+-        bool is_accelerometer = false;
+-        bool is_pointing_stick = false;
+-        bool has_wheel = false;
++        size_t num_joystick_axes = 0, num_joystick_buttons = 0;
++        bool has_abs_coordinates = false,
++                has_rel_coordinates = false,
++                has_mt_coordinates = false,
++                has_pad_buttons = false,
++                is_direct = false,
++                has_touch = false,
++                has_3d_coordinates = false,
++                has_keys = false,
++                has_stylus = false,
++                has_pen = false,
++                finger_but_no_pen = false,
++                has_mouse_button = false,
++                is_mouse = false,
++                is_abs_mouse = false,
++                is_touchpad = false,
++                is_touchscreen = false,
++                is_tablet = false,
++                is_tablet_pad = false,
++                is_joystick = false,
++                is_accelerometer = false,
++                is_pointing_stick = false,
++                has_wheel = false;
+ 
+         has_keys = test_bit(EV_KEY, bitmask_ev);
+         has_abs_coordinates = test_bit(ABS_X, bitmask_abs) && test_bit(ABS_Y, bitmask_abs);
+@@ -335,8 +333,8 @@ static bool test_pointers(
+ /* key like devices */
+ static bool test_key(
+                 sd_device *dev,
+-                const unsigned long* bitmask_ev,
+-                const unsigned long* bitmask_key,
++                const unsigned long *bitmask_ev,
++                const unsigned long *bitmask_key,
+                 EventMode mode) {
+ 
+         bool found = false;
+@@ -378,14 +376,13 @@ static bool test_key(
+ 
+ static int builtin_input_id(UdevEvent *event, int argc, char *argv[]) {
+         sd_device *pdev, *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
+-        unsigned long bitmask_ev[NBITS(EV_MAX)];
+-        unsigned long bitmask_abs[NBITS(ABS_MAX)];
+-        unsigned long bitmask_key[NBITS(KEY_MAX)];
+-        unsigned long bitmask_rel[NBITS(REL_MAX)];
+-        unsigned long bitmask_props[NBITS(INPUT_PROP_MAX)];
++        unsigned long bitmask_ev[NBITS(EV_MAX)],
++                bitmask_abs[NBITS(ABS_MAX)],
++                bitmask_key[NBITS(KEY_MAX)],
++                bitmask_rel[NBITS(REL_MAX)],
++                bitmask_props[NBITS(INPUT_PROP_MAX)];
+         const char *sysname;
+-        bool is_pointer;
+-        bool is_key;
++        bool is_pointer, is_key;
+ 
+         /* walk up the parental chain until we find the real input device; the
+          * argument is very likely a subdevice of this, like eventN */
+diff --git a/src/udev/udev-builtin-keyboard.c b/src/udev/udev-builtin-keyboard.c
+index e1e6de0426..1595a8f031 100644
+--- a/src/udev/udev-builtin-keyboard.c
++++ b/src/udev/udev-builtin-keyboard.c
+@@ -20,8 +20,7 @@ static const struct key_name *keyboard_lookup_key(const char *str, GPERF_LEN_TYP
+ static int install_force_release(sd_device *dev, const unsigned *release, unsigned release_count) {
+         sd_device *atkbd;
+         const char *cur;
+-        char codes[4096];
+-        char *s;
++        char *s, codes[4096];
+         size_t l;
+         unsigned i;
+         int r;
+@@ -161,8 +160,7 @@ static int set_trackpoint_sensitivity(sd_device *dev, const char *value) {
+ 
+ static int builtin_keyboard(UdevEvent *event, int argc, char *argv[]) {
+         sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
+-        unsigned release[1024];
+-        unsigned release_count = 0;
++        unsigned release[1024], release_count = 0;
+         _cleanup_close_ int fd = -EBADF;
+         const char *node;
+         int has_abs = -1, r;
+diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c
+index 77abff004e..8ba5f2e358 100644
+--- a/src/udev/udev-builtin-path_id.c
++++ b/src/udev/udev-builtin-path_id.c
+@@ -82,7 +82,7 @@ static int format_lun_number(sd_device *dev, char **path) {
+         return 0;
+ }
+ 
+-static sd_device *skip_subsystem(sd_device *dev, const char *subsys) {
++static sd_device* skip_subsystem(sd_device *dev, const char *subsys) {
+         sd_device *parent;
+ 
+         assert(dev);
+@@ -107,7 +107,7 @@ static sd_device *skip_subsystem(sd_device *dev, const char *subsys) {
+         return dev;
+ }
+ 
+-static sd_device *handle_scsi_fibre_channel(sd_device *parent, char **path) {
++static sd_device* handle_scsi_fibre_channel(sd_device *parent, char **path) {
+         sd_device *targetdev;
+         _cleanup_(sd_device_unrefp) sd_device *fcdev = NULL;
+         const char *port, *sysname;
+@@ -130,7 +130,7 @@ static sd_device *handle_scsi_fibre_channel(sd_device *parent, char **path) {
+         return parent;
+ }
+ 
+-static sd_device *handle_scsi_sas_wide_port(sd_device *parent, char **path) {
++static sd_device* handle_scsi_sas_wide_port(sd_device *parent, char **path) {
+         sd_device *targetdev, *target_parent;
+         _cleanup_(sd_device_unrefp) sd_device *sasdev = NULL;
+         const char *sas_address, *sysname;
+@@ -155,12 +155,10 @@ static sd_device *handle_scsi_sas_wide_port(sd_device *parent, char **path) {
+         return parent;
+ }
+ 
+-static sd_device *handle_scsi_sas(sd_device *parent, char **path) {
++static sd_device* handle_scsi_sas(sd_device *parent, char **path) {
+         sd_device *targetdev, *target_parent, *port, *expander;
+         _cleanup_(sd_device_unrefp) sd_device *target_sasdev = NULL, *expander_sasdev = NULL, *port_sasdev = NULL;
+-        const char *sas_address = NULL;
+-        const char *phy_id;
+-        const char *sysname;
++        const char *sas_address = NULL, *phy_id, *sysname;
+         unsigned num_phys;
+         _cleanup_free_ char *lun = NULL;
+ 
+@@ -216,12 +214,11 @@ static sd_device *handle_scsi_sas(sd_device *parent, char **path) {
+         return parent;
+ }
+ 
+-static sd_device *handle_scsi_iscsi(sd_device *parent, char **path) {
++static sd_device* handle_scsi_iscsi(sd_device *parent, char **path) {
+         sd_device *transportdev;
+         _cleanup_(sd_device_unrefp) sd_device *sessiondev = NULL, *conndev = NULL;
+-        const char *target, *connname, *addr, *port;
++        const char *target, *connname, *addr, *port, *sysname, *sysnum;
+         _cleanup_free_ char *lun = NULL;
+-        const char *sysname, *sysnum;
+ 
+         assert(parent);
+         assert(path);
+@@ -260,7 +257,7 @@ static sd_device *handle_scsi_iscsi(sd_device *parent, char **path) {
+         return parent;
+ }
+ 
+-static sd_device *handle_scsi_ata(sd_device *parent, char **path, char **compat_path) {
++static sd_device* handle_scsi_ata(sd_device *parent, char **path, char **compat_path) {
+         sd_device *targetdev, *target_parent;
+         _cleanup_(sd_device_unrefp) sd_device *atadev = NULL;
+         const char *port_no, *sysname, *name;
+@@ -302,7 +299,7 @@ static sd_device *handle_scsi_ata(sd_device *parent, char **path, char **compat_
+         return parent;
+ }
+ 
+-static sd_device *handle_scsi_default(sd_device *parent, char **path) {
++static sd_device* handle_scsi_default(sd_device *parent, char **path) {
+         sd_device *hostdev;
+         int host, bus, target, lun;
+         const char *name, *base, *pos;
+@@ -376,9 +373,8 @@ static sd_device *handle_scsi_default(sd_device *parent, char **path) {
+         return hostdev;
+ }
+ 
+-static sd_device *handle_scsi_hyperv(sd_device *parent, char **path, size_t guid_str_len) {
+-        sd_device *hostdev;
+-        sd_device *vmbusdev;
++static sd_device* handle_scsi_hyperv(sd_device *parent, char **path, size_t guid_str_len) {
++        sd_device *hostdev, *vmbusdev;
+         const char *guid_str;
+         _cleanup_free_ char *lun = NULL;
+         char guid[39];
+@@ -412,7 +408,7 @@ static sd_device *handle_scsi_hyperv(sd_device *parent, char **path, size_t guid
+         return parent;
+ }
+ 
+-static sd_device *handle_scsi(sd_device *parent, char **path, char **compat_path, bool *supported_parent) {
++static sd_device* handle_scsi(sd_device *parent, char **path, char **compat_path, bool *supported_parent) {
+         const char *id, *name;
+ 
+         if (!device_is_devtype(parent, "scsi_device"))
+@@ -455,7 +451,7 @@ static sd_device *handle_scsi(sd_device *parent, char **path, char **compat_path
+         return handle_scsi_default(parent, path);
+ }
+ 
+-static sd_device *handle_cciss(sd_device *parent, char **path) {
++static sd_device* handle_cciss(sd_device *parent, char **path) {
+         const char *str;
+         unsigned controller, disk;
+ 
+@@ -526,7 +522,7 @@ static int get_usb_revision(sd_device *dev) {
+         }
+ }
+ 
+-static sd_device *handle_usb(sd_device *parent, char **path) {
++static sd_device* handle_usb(sd_device *parent, char **path) {
+         const char *str, *port;
+         int r;
+ 
+@@ -564,7 +560,7 @@ static sd_device *handle_usb(sd_device *parent, char **path) {
+         return parent;
+ }
+ 
+-static sd_device *handle_bcma(sd_device *parent, char **path) {
++static sd_device* handle_bcma(sd_device *parent, char **path) {
+         const char *sysname;
+         unsigned core;
+ 
+@@ -578,7 +574,7 @@ static sd_device *handle_bcma(sd_device *parent, char **path) {
+ }
+ 
+ /* Handle devices of AP bus in System z platform. */
+-static sd_device *handle_ap(sd_device *parent, char **path) {
++static sd_device* handle_ap(sd_device *parent, char **path) {
+         const char *type, *func;
+ 
+         assert(parent);
+diff --git a/src/udev/udev-builtin-usb_id.c b/src/udev/udev-builtin-usb_id.c
+index 2413f9ce9e..9abdec3591 100644
+--- a/src/udev/udev-builtin-usb_id.c
++++ b/src/udev/udev-builtin-usb_id.c
+@@ -225,31 +225,15 @@ static int dev_if_packed_info(sd_device *dev, char *ifs_str, size_t len) {
+  *     is concatenated with the identification with an underscore '_'.
+  */
+ static int builtin_usb_id(UdevEvent *event, int argc, char *argv[]) {
+-        sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
+-        char vendor_str[64] = "";
+-        char vendor_str_enc[256];
+-        const char *vendor_id;
+-        char model_str[64] = "";
+-        char model_str_enc[256];
+-        const char *product_id;
+-        char serial_str[UDEV_NAME_SIZE] = "";
+-        char packed_if_str[UDEV_NAME_SIZE] = "";
+-        char revision_str[64] = "";
+-        char type_str[64] = "";
+-        char instance_str[64] = "";
+-        const char *ifnum = NULL;
+-        const char *driver = NULL;
+-        char serial[256];
+-
+-        sd_device *dev_interface, *dev_usb;
+-        const char *if_class, *if_subclass;
++        sd_device *dev_interface, *dev_usb, *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
++        const char *syspath, *sysname, *interface_syspath, *vendor_id, *product_id,
++                *ifnum = NULL, *driver = NULL, *if_class, *if_subclass;
++        char *s, model_str[64] = "", model_str_enc[256], serial_str[UDEV_NAME_SIZE] = "",
++                packed_if_str[UDEV_NAME_SIZE] = "", revision_str[64] = "", type_str[64] = "",
++                instance_str[64] = "", serial[256], vendor_str[64] = "", vendor_str_enc[256];
+         unsigned if_class_num;
+-        int protocol = 0;
++        int r, protocol = 0;
+         size_t l;
+-        char *s;
+-
+-        const char *syspath, *sysname, *interface_syspath;
+-        int r;
+ 
+         r = sd_device_get_syspath(dev, &syspath);
+         if (r < 0)
+diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
+index 7fa86ddd84..9141a9d2a7 100644
+--- a/src/udev/udev-event.c
++++ b/src/udev/udev-event.c
+@@ -18,7 +18,7 @@
+ #include "udev-worker.h"
+ #include "user-util.h"
+ 
+-UdevEvent *udev_event_new(sd_device *dev, UdevWorker *worker, EventMode mode) {
++UdevEvent* udev_event_new(sd_device *dev, UdevWorker *worker, EventMode mode) {
+         int log_level = worker ? worker->log_level : log_get_max_level();
+         UdevEvent *event;
+ 
+@@ -44,7 +44,7 @@ UdevEvent *udev_event_new(sd_device *dev, UdevWorker *worker, EventMode mode) {
+         return event;
+ }
+ 
+-UdevEvent *udev_event_free(UdevEvent *event) {
++UdevEvent* udev_event_free(UdevEvent *event) {
+         if (!event)
+                 return NULL;
+ 
+diff --git a/src/udev/udev-event.h b/src/udev/udev-event.h
+index 88a7cfe497..186cfa541f 100644
+--- a/src/udev/udev-event.h
++++ b/src/udev/udev-event.h
+@@ -53,8 +53,8 @@ typedef struct UdevEvent {
+         EventMode event_mode;
+ } UdevEvent;
+ 
+-UdevEvent *udev_event_new(sd_device *dev, UdevWorker *worker, EventMode mode);
+-UdevEvent *udev_event_free(UdevEvent *event);
++UdevEvent* udev_event_new(sd_device *dev, UdevWorker *worker, EventMode mode);
++UdevEvent* udev_event_free(UdevEvent *event);
+ DEFINE_TRIVIAL_CLEANUP_FUNC(UdevEvent*, udev_event_free);
+ 
+ int udev_event_execute_rules(UdevEvent *event, UdevRules *rules);
+diff --git a/src/udev/udev-format.c b/src/udev/udev-format.c
+index 8637d802fc..c09ea44d91 100644
+--- a/src/udev/udev-format.c
++++ b/src/udev/udev-format.c
+@@ -58,7 +58,7 @@ static const struct subst_map_entry map[] = {
+            { .name = "sys",      .fmt = 'S', .type = FORMAT_SUBST_SYS           },
+ };
+ 
+-static const char *format_type_to_string(FormatSubstitutionType t) {
++static const char* format_type_to_string(FormatSubstitutionType t) {
+         FOREACH_ELEMENT(entry, map)
+                 if (entry->type == t)
+                         return entry->name;
+diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c
+index 6345b80cba..041c642aa9 100644
+--- a/src/udev/udev-rules.c
++++ b/src/udev/udev-rules.c
+@@ -457,7 +457,7 @@ static UdevRuleFile* udev_rule_file_free(UdevRuleFile *rule_file) {
+ 
+ DEFINE_TRIVIAL_CLEANUP_FUNC(UdevRuleFile*, udev_rule_file_free);
+ 
+-UdevRules *udev_rules_free(UdevRules *rules) {
++UdevRules* udev_rules_free(UdevRules *rules) {
+         if (!rules)
+                 return NULL;
+ 
+diff --git a/src/udev/udev-rules.h b/src/udev/udev-rules.h
+index 3bd4b04ab3..67d7e5b178 100644
+--- a/src/udev/udev-rules.h
++++ b/src/udev/udev-rules.h
+@@ -15,7 +15,7 @@ int udev_rules_parse_file(UdevRules *rules, const char *filename, bool extra_che
+ unsigned udev_rule_file_get_issues(UdevRuleFile *rule_file);
+ UdevRules* udev_rules_new(ResolveNameTiming resolve_name_timing);
+ int udev_rules_load(UdevRules **ret_rules, ResolveNameTiming resolve_name_timing);
+-UdevRules *udev_rules_free(UdevRules *rules);
++UdevRules* udev_rules_free(UdevRules *rules);
+ DEFINE_TRIVIAL_CLEANUP_FUNC(UdevRules*, udev_rules_free);
+ #define udev_rules_free_and_replace(a, b) free_and_replace_full(a, b, udev_rules_free)
+ 
diff --git a/SOURCES/0313-udev-builtin-make-udev_builtin_add_property-and-frie.patch b/SOURCES/0313-udev-builtin-make-udev_builtin_add_property-and-frie.patch
new file mode 100644
index 0000000000000000000000000000000000000000..1ffbb2598650d86ee158d6661bcf2705c8c61e2b
--- /dev/null
+++ b/SOURCES/0313-udev-builtin-make-udev_builtin_add_property-and-frie.patch
@@ -0,0 +1,1259 @@
+From fc5978e7c5913187fba87ae5d71da5de3064f10c Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Thu, 5 Dec 2024 01:17:40 +0900
+Subject: [PATCH] udev-builtin: make udev_builtin_add_property() and friends
+ take UdevEvent*
+
+No functional change, just refactoring.
+
+(cherry picked from commit 036c75ded366bc2e8ae5ef3bf230f20982633d15)
+
+Resolves: RHEL-75774
+---
+ src/udev/net/link-config.c             |  29 +++---
+ src/udev/net/link-config.h             |   4 +-
+ src/udev/udev-builtin-blkid.c          |  70 +++++++-------
+ src/udev/udev-builtin-btrfs.c          |   4 +-
+ src/udev/udev-builtin-hwdb.c           |  21 ++---
+ src/udev/udev-builtin-input_id.c       |  58 ++++++------
+ src/udev/udev-builtin-net_driver.c     |   2 +-
+ src/udev/udev-builtin-net_id.c         | 123 ++++++++++++-------------
+ src/udev/udev-builtin-net_setup_link.c |   8 +-
+ src/udev/udev-builtin-path_id.c        |  18 ++--
+ src/udev/udev-builtin-usb_id.c         |  52 +++++------
+ src/udev/udev-builtin.c                |  26 +++---
+ src/udev/udev-builtin.h                |   9 +-
+ 13 files changed, 211 insertions(+), 213 deletions(-)
+
+diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c
+index c2bec61347..55eeb9de81 100644
+--- a/src/udev/net/link-config.c
++++ b/src/udev/net/link-config.c
+@@ -1001,18 +1001,16 @@ static int link_apply_rps_cpu_mask(Link *link, EventMode mode) {
+         return 0;
+ }
+ 
+-static int link_apply_udev_properties(Link *link, EventMode mode) {
++static int link_apply_udev_properties(Link *link, UdevEvent *event) {
+         LinkConfig *config;
+-        sd_device *device;
+ 
+         assert(link);
+ 
+         config = ASSERT_PTR(link->config);
+-        device = ASSERT_PTR(link->device);
+ 
+         /* 1. apply ImportProperty=. */
+         STRV_FOREACH(p, config->import_properties)
+-                (void) udev_builtin_import_property(device, link->device_db_clone, mode, *p);
++                (void) udev_builtin_import_property(event, *p);
+ 
+         /* 2. apply Property=. */
+         STRV_FOREACH(p, config->properties) {
+@@ -1027,15 +1025,15 @@ static int link_apply_udev_properties(Link *link, EventMode mode) {
+                 if (!key)
+                         return log_oom();
+ 
+-                (void) udev_builtin_add_property(device, mode, key, eq + 1);
++                (void) udev_builtin_add_property(event, key, eq + 1);
+         }
+ 
+         /* 3. apply UnsetProperty=. */
+         STRV_FOREACH(p, config->unset_properties)
+-                (void) udev_builtin_add_property(device, mode, *p, NULL);
++                (void) udev_builtin_add_property(event, *p, NULL);
+ 
+         /* 4. set the default properties. */
+-        (void) udev_builtin_add_property(device, mode, "ID_NET_LINK_FILE", config->filename);
++        (void) udev_builtin_add_property(event, "ID_NET_LINK_FILE", config->filename);
+ 
+         _cleanup_free_ char *joined = NULL;
+         STRV_FOREACH(d, config->dropins) {
+@@ -1049,26 +1047,27 @@ static int link_apply_udev_properties(Link *link, EventMode mode) {
+                         return log_oom();
+         }
+ 
+-        (void) udev_builtin_add_property(device, mode, "ID_NET_LINK_FILE_DROPINS", joined);
++        (void) udev_builtin_add_property(event, "ID_NET_LINK_FILE_DROPINS", joined);
+ 
+         if (link->new_name)
+-                (void) udev_builtin_add_property(device, mode, "ID_NET_NAME", link->new_name);
++                (void) udev_builtin_add_property(event, "ID_NET_NAME", link->new_name);
+ 
+         return 0;
+ }
+ 
+-int link_apply_config(LinkConfigContext *ctx, sd_netlink **rtnl, Link *link, EventMode mode) {
++int link_apply_config(LinkConfigContext *ctx, sd_netlink **rtnl, Link *link, UdevEvent *event) {
+         int r;
+ 
+         assert(ctx);
+         assert(rtnl);
+         assert(link);
++        assert(event);
+ 
+-        r = link_apply_ethtool_settings(link, &ctx->ethtool_fd, mode);
++        r = link_apply_ethtool_settings(link, &ctx->ethtool_fd, event->event_mode);
+         if (r < 0)
+                 return r;
+ 
+-        r = link_apply_rtnl_settings(link, rtnl, mode);
++        r = link_apply_rtnl_settings(link, rtnl, event->event_mode);
+         if (r < 0)
+                 return r;
+ 
+@@ -1080,15 +1079,15 @@ int link_apply_config(LinkConfigContext *ctx, sd_netlink **rtnl, Link *link, Eve
+         if (r < 0)
+                 return r;
+ 
+-        r = link_apply_sr_iov_config(link, rtnl, mode);
++        r = link_apply_sr_iov_config(link, rtnl, event->event_mode);
+         if (r < 0)
+                 return r;
+ 
+-        r = link_apply_rps_cpu_mask(link, mode);
++        r = link_apply_rps_cpu_mask(link, event->event_mode);
+         if (r < 0)
+                 return r;
+ 
+-        return link_apply_udev_properties(link, mode);
++        return link_apply_udev_properties(link, event);
+ }
+ 
+ int config_parse_udev_property(
+diff --git a/src/udev/net/link-config.h b/src/udev/net/link-config.h
+index 5aaa7c51a0..a60e183e4b 100644
+--- a/src/udev/net/link-config.h
++++ b/src/udev/net/link-config.h
+@@ -12,10 +12,10 @@
+ #include "list.h"
+ #include "net-condition.h"
+ #include "netif-naming-scheme.h"
+-#include "udev-event.h"
+ 
+ typedef struct LinkConfigContext LinkConfigContext;
+ typedef struct LinkConfig LinkConfig;
++typedef struct UdevEvent UdevEvent;
+ 
+ typedef enum MACAddressPolicy {
+         MAC_ADDRESS_POLICY_PERSISTENT,
+@@ -107,7 +107,7 @@ Link* link_free(Link *link);
+ DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_free);
+ 
+ int link_get_config(LinkConfigContext *ctx, Link *link);
+-int link_apply_config(LinkConfigContext *ctx, sd_netlink **rtnl, Link *link, EventMode mode);
++int link_apply_config(LinkConfigContext *ctx, sd_netlink **rtnl, Link *link, UdevEvent *event);
+ 
+ const char* mac_address_policy_to_string(MACAddressPolicy p) _const_;
+ MACAddressPolicy mac_address_policy_from_string(const char *p) _pure_;
+diff --git a/src/udev/udev-builtin-blkid.c b/src/udev/udev-builtin-blkid.c
+index ae9a11f45d..73417338f5 100644
+--- a/src/udev/udev-builtin-blkid.c
++++ b/src/udev/udev-builtin-blkid.c
+@@ -34,95 +34,98 @@
+ #include "strxcpyx.h"
+ #include "udev-builtin.h"
+ 
+-static void print_property(sd_device *dev, EventMode mode, const char *name, const char *value) {
++static void print_property(UdevEvent *event, const char *name, const char *value) {
+         char s[256];
+ 
++        assert(event);
++        assert(name);
++
+         s[0] = '\0';
+ 
+         if (streq(name, "TYPE")) {
+-                udev_builtin_add_property(dev, mode, "ID_FS_TYPE", value);
++                udev_builtin_add_property(event, "ID_FS_TYPE", value);
+ 
+         } else if (streq(name, "USAGE")) {
+-                udev_builtin_add_property(dev, mode, "ID_FS_USAGE", value);
++                udev_builtin_add_property(event, "ID_FS_USAGE", value);
+ 
+         } else if (streq(name, "VERSION")) {
+-                udev_builtin_add_property(dev, mode, "ID_FS_VERSION", value);
++                udev_builtin_add_property(event, "ID_FS_VERSION", value);
+ 
+         } else if (streq(name, "UUID")) {
+                 blkid_safe_string(value, s, sizeof(s));
+-                udev_builtin_add_property(dev, mode, "ID_FS_UUID", s);
++                udev_builtin_add_property(event, "ID_FS_UUID", s);
+                 blkid_encode_string(value, s, sizeof(s));
+-                udev_builtin_add_property(dev, mode, "ID_FS_UUID_ENC", s);
++                udev_builtin_add_property(event, "ID_FS_UUID_ENC", s);
+ 
+         } else if (streq(name, "UUID_SUB")) {
+                 blkid_safe_string(value, s, sizeof(s));
+-                udev_builtin_add_property(dev, mode, "ID_FS_UUID_SUB", s);
++                udev_builtin_add_property(event, "ID_FS_UUID_SUB", s);
+                 blkid_encode_string(value, s, sizeof(s));
+-                udev_builtin_add_property(dev, mode, "ID_FS_UUID_SUB_ENC", s);
++                udev_builtin_add_property(event, "ID_FS_UUID_SUB_ENC", s);
+ 
+         } else if (streq(name, "LABEL")) {
+                 blkid_safe_string(value, s, sizeof(s));
+-                udev_builtin_add_property(dev, mode, "ID_FS_LABEL", s);
++                udev_builtin_add_property(event, "ID_FS_LABEL", s);
+                 blkid_encode_string(value, s, sizeof(s));
+-                udev_builtin_add_property(dev, mode, "ID_FS_LABEL_ENC", s);
++                udev_builtin_add_property(event, "ID_FS_LABEL_ENC", s);
+ 
+         } else if (STR_IN_SET(name, "FSSIZE", "FSLASTBLOCK", "FSBLOCKSIZE")) {
+                 strscpyl(s, sizeof(s), "ID_FS_", name + 2, NULL);
+-                udev_builtin_add_property(dev, mode, s, value);
++                udev_builtin_add_property(event, s, value);
+ 
+         } else if (streq(name, "PTTYPE")) {
+-                udev_builtin_add_property(dev, mode, "ID_PART_TABLE_TYPE", value);
++                udev_builtin_add_property(event, "ID_PART_TABLE_TYPE", value);
+ 
+         } else if (streq(name, "PTUUID")) {
+-                udev_builtin_add_property(dev, mode, "ID_PART_TABLE_UUID", value);
++                udev_builtin_add_property(event, "ID_PART_TABLE_UUID", value);
+ 
+         } else if (streq(name, "PART_ENTRY_NAME")) {
+                 blkid_encode_string(value, s, sizeof(s));
+-                udev_builtin_add_property(dev, mode, "ID_PART_ENTRY_NAME", s);
++                udev_builtin_add_property(event, "ID_PART_ENTRY_NAME", s);
+ 
+         } else if (streq(name, "PART_ENTRY_TYPE")) {
+                 blkid_encode_string(value, s, sizeof(s));
+-                udev_builtin_add_property(dev, mode, "ID_PART_ENTRY_TYPE", s);
++                udev_builtin_add_property(event, "ID_PART_ENTRY_TYPE", s);
+ 
+         } else if (startswith(name, "PART_ENTRY_")) {
+                 strscpyl(s, sizeof(s), "ID_", name, NULL);
+-                udev_builtin_add_property(dev, mode, s, value);
++                udev_builtin_add_property(event, s, value);
+ 
+         } else if (streq(name, "SYSTEM_ID")) {
+                 blkid_encode_string(value, s, sizeof(s));
+-                udev_builtin_add_property(dev, mode, "ID_FS_SYSTEM_ID", s);
++                udev_builtin_add_property(event, "ID_FS_SYSTEM_ID", s);
+ 
+         } else if (streq(name, "PUBLISHER_ID")) {
+                 blkid_encode_string(value, s, sizeof(s));
+-                udev_builtin_add_property(dev, mode, "ID_FS_PUBLISHER_ID", s);
++                udev_builtin_add_property(event, "ID_FS_PUBLISHER_ID", s);
+ 
+         } else if (streq(name, "APPLICATION_ID")) {
+                 blkid_encode_string(value, s, sizeof(s));
+-                udev_builtin_add_property(dev, mode, "ID_FS_APPLICATION_ID", s);
++                udev_builtin_add_property(event, "ID_FS_APPLICATION_ID", s);
+ 
+         } else if (streq(name, "BOOT_SYSTEM_ID")) {
+                 blkid_encode_string(value, s, sizeof(s));
+-                udev_builtin_add_property(dev, mode, "ID_FS_BOOT_SYSTEM_ID", s);
++                udev_builtin_add_property(event, "ID_FS_BOOT_SYSTEM_ID", s);
+ 
+         } else if (streq(name, "VOLUME_ID")) {
+                 blkid_encode_string(value, s, sizeof(s));
+-                udev_builtin_add_property(dev, mode, "ID_FS_VOLUME_ID", s);
++                udev_builtin_add_property(event, "ID_FS_VOLUME_ID", s);
+ 
+         } else if (streq(name, "LOGICAL_VOLUME_ID")) {
+                 blkid_encode_string(value, s, sizeof(s));
+-                udev_builtin_add_property(dev, mode, "ID_FS_LOGICAL_VOLUME_ID", s);
++                udev_builtin_add_property(event, "ID_FS_LOGICAL_VOLUME_ID", s);
+ 
+         } else if (streq(name, "VOLUME_SET_ID")) {
+                 blkid_encode_string(value, s, sizeof(s));
+-                udev_builtin_add_property(dev, mode, "ID_FS_VOLUME_SET_ID", s);
++                udev_builtin_add_property(event, "ID_FS_VOLUME_SET_ID", s);
+ 
+         } else if (streq(name, "DATA_PREPARER_ID")) {
+                 blkid_encode_string(value, s, sizeof(s));
+-                udev_builtin_add_property(dev, mode, "ID_FS_DATA_PREPARER_ID", s);
++                udev_builtin_add_property(event, "ID_FS_DATA_PREPARER_ID", s);
+         }
+ }
+ 
+-static int find_gpt_root(sd_device *dev, blkid_probe pr, EventMode mode) {
++static int find_gpt_root(UdevEvent *event, blkid_probe pr) {
+ 
+ #if defined(SD_GPT_ROOT_NATIVE) && ENABLE_EFI
+ 
+@@ -131,6 +134,7 @@ static int find_gpt_root(sd_device *dev, blkid_probe pr, EventMode mode) {
+         sd_id128_t root_id = SD_ID128_NULL;
+         int r;
+ 
++        assert(event);
+         assert(pr);
+ 
+         /* Iterate through the partitions on this disk, and see if the UEFI ESP or XBOOTLDR partition we
+@@ -201,7 +205,7 @@ static int find_gpt_root(sd_device *dev, blkid_probe pr, EventMode mode) {
+         /* We found the ESP/XBOOTLDR on this disk, and also found a root partition, nice! Let's export its
+          * UUID */
+         if (found_esp_or_xbootldr && !sd_id128_is_null(root_id))
+-                udev_builtin_add_property(dev, mode, "ID_PART_GPT_AUTO_ROOT_UUID", SD_ID128_TO_UUID_STRING(root_id));
++                udev_builtin_add_property(event, "ID_PART_GPT_AUTO_ROOT_UUID", SD_ID128_TO_UUID_STRING(root_id));
+ #endif
+ 
+         return 0;
+@@ -421,7 +425,7 @@ static int builtin_blkid(UdevEvent *event, int argc, char *argv[]) {
+                 if (blkid_probe_get_value(pr, i, &name, &data, NULL) < 0)
+                         continue;
+ 
+-                print_property(dev, event->event_mode, name, data);
++                print_property(event, name, data);
+ 
+                 /* Is this a disk with GPT partition table? */
+                 if (streq(name, "PTTYPE") && streq(data, "gpt"))
+@@ -430,11 +434,11 @@ static int builtin_blkid(UdevEvent *event, int argc, char *argv[]) {
+                 /* Is this a partition that matches the root partition
+                  * property inherited from the parent? */
+                 if (root_partition && streq(name, "PART_ENTRY_UUID") && streq(data, root_partition))
+-                        udev_builtin_add_property(dev, event->event_mode, "ID_PART_GPT_AUTO_ROOT", "1");
++                        udev_builtin_add_property(event, "ID_PART_GPT_AUTO_ROOT", "1");
+         }
+ 
+         if (is_gpt)
+-                find_gpt_root(dev, pr, event->event_mode);
++                find_gpt_root(event, pr);
+ 
+         r = read_loopback_backing_inode(
+                         dev,
+@@ -445,8 +449,8 @@ static int builtin_blkid(UdevEvent *event, int argc, char *argv[]) {
+         if (r < 0)
+                 log_device_debug_errno(dev, r, "Failed to read loopback backing inode, ignoring: %m");
+         else if (r > 0) {
+-                udev_builtin_add_propertyf(dev, event->event_mode, "ID_LOOP_BACKING_DEVICE", DEVNUM_FORMAT_STR, DEVNUM_FORMAT_VAL(backing_devno));
+-                udev_builtin_add_propertyf(dev, event->event_mode, "ID_LOOP_BACKING_INODE", "%" PRIu64, (uint64_t) backing_inode);
++                udev_builtin_add_propertyf(event, "ID_LOOP_BACKING_DEVICE", DEVNUM_FORMAT_STR, DEVNUM_FORMAT_VAL(backing_devno));
++                udev_builtin_add_propertyf(event, "ID_LOOP_BACKING_INODE", "%" PRIu64, (uint64_t) backing_inode);
+ 
+                 if (backing_fname) {
+                         /* In the worst case blkid_encode_string() will blow up to 4x the string
+@@ -457,8 +461,8 @@ static int builtin_blkid(UdevEvent *event, int argc, char *argv[]) {
+                         assert(strlen(backing_fname) < ELEMENTSOF(encoded) / 4);
+                         blkid_encode_string(backing_fname, encoded, ELEMENTSOF(encoded));
+ 
+-                        udev_builtin_add_property(dev, event->event_mode, "ID_LOOP_BACKING_FILENAME", backing_fname);
+-                        udev_builtin_add_property(dev, event->event_mode, "ID_LOOP_BACKING_FILENAME_ENC", encoded);
++                        udev_builtin_add_property(event, "ID_LOOP_BACKING_FILENAME", backing_fname);
++                        udev_builtin_add_property(event, "ID_LOOP_BACKING_FILENAME_ENC", encoded);
+                 }
+         }
+ 
+diff --git a/src/udev/udev-builtin-btrfs.c b/src/udev/udev-builtin-btrfs.c
+index fe030d05b9..f7d42c1ed0 100644
+--- a/src/udev/udev-builtin-btrfs.c
++++ b/src/udev/udev-builtin-btrfs.c
+@@ -27,7 +27,7 @@ static int builtin_btrfs(UdevEvent *event, int argc, char *argv[]) {
+                         /* Driver not installed? Then we aren't ready. This is useful in initrds that lack
+                          * btrfs.ko. After the host transition (where btrfs.ko will hopefully become
+                          * available) the device can be retriggered and will then be considered ready. */
+-                        udev_builtin_add_property(dev, event->event_mode, "ID_BTRFS_READY", "0");
++                        udev_builtin_add_property(event, "ID_BTRFS_READY", "0");
+                         return 0;
+                 }
+ 
+@@ -39,7 +39,7 @@ static int builtin_btrfs(UdevEvent *event, int argc, char *argv[]) {
+         if (r < 0)
+                 return log_device_debug_errno(dev, errno, "Failed to call BTRFS_IOC_DEVICES_READY: %m");
+ 
+-        udev_builtin_add_property(dev, event->event_mode, "ID_BTRFS_READY", one_zero(r == 0));
++        udev_builtin_add_property(event, "ID_BTRFS_READY", one_zero(r == 0));
+         return 0;
+ }
+ 
+diff --git a/src/udev/udev-builtin-hwdb.c b/src/udev/udev-builtin-hwdb.c
+index fbee04b4a8..b499d92479 100644
+--- a/src/udev/udev-builtin-hwdb.c
++++ b/src/udev/udev-builtin-hwdb.c
+@@ -18,11 +18,10 @@
+ static sd_hwdb *hwdb;
+ 
+ int udev_builtin_hwdb_lookup(
+-                sd_device *dev,
++                UdevEvent *event,
+                 const char *prefix,
+                 const char *modalias,
+-                const char *filter,
+-                EventMode mode) {
++                const char *filter) {
+ 
+         _cleanup_free_ char *lookup = NULL;
+         const char *key, *value;
+@@ -42,7 +41,7 @@ int udev_builtin_hwdb_lookup(
+                 if (filter && fnmatch(filter, key, FNM_NOESCAPE) != 0)
+                         continue;
+ 
+-                r = udev_builtin_add_property(dev, mode, key, value);
++                r = udev_builtin_add_property(event, key, value);
+                 if (r < 0)
+                         return r;
+                 n++;
+@@ -69,18 +68,18 @@ static const char* modalias_usb(sd_device *dev, char *s, size_t size) {
+ }
+ 
+ static int udev_builtin_hwdb_search(
+-                sd_device *dev,
++                UdevEvent *event,
+                 sd_device *srcdev,
+                 const char *subsystem,
+                 const char *prefix,
+-                const char *filter,
+-                EventMode mode) {
++                const char *filter) {
+ 
++        sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
+         char s[LINE_MAX];
+         bool last = false;
+         int r = 0;
+ 
+-        assert(dev);
++        assert(event);
+ 
+         if (!srcdev)
+                 srcdev = dev;
+@@ -108,7 +107,7 @@ static int udev_builtin_hwdb_search(
+ 
+                 log_device_debug(dev, "hwdb modalias key: \"%s\"", modalias);
+ 
+-                r = udev_builtin_hwdb_lookup(dev, prefix, modalias, filter, mode);
++                r = udev_builtin_hwdb_lookup(event, prefix, modalias, filter);
+                 if (r > 0)
+                         break;
+ 
+@@ -166,7 +165,7 @@ static int builtin_hwdb(UdevEvent *event, int argc, char *argv[]) {
+ 
+         /* query a specific key given as argument */
+         if (argv[optind]) {
+-                r = udev_builtin_hwdb_lookup(dev, prefix, argv[optind], filter, event->event_mode);
++                r = udev_builtin_hwdb_lookup(event, prefix, argv[optind], filter);
+                 if (r < 0)
+                         return log_device_debug_errno(dev, r, "Failed to look up hwdb: %m");
+                 if (r == 0)
+@@ -181,7 +180,7 @@ static int builtin_hwdb(UdevEvent *event, int argc, char *argv[]) {
+                         return log_device_debug_errno(dev, r, "Failed to create sd_device object '%s': %m", device);
+         }
+ 
+-        r = udev_builtin_hwdb_search(dev, srcdev, subsystem, prefix, filter, event->event_mode);
++        r = udev_builtin_hwdb_search(event, srcdev, subsystem, prefix, filter);
+         if (r < 0)
+                 return log_device_debug_errno(dev, r, "Failed to look up hwdb: %m");
+         if (r == 0)
+diff --git a/src/udev/udev-builtin-input_id.c b/src/udev/udev-builtin-input_id.c
+index c204d656f0..509edee8aa 100644
+--- a/src/udev/udev-builtin-input_id.c
++++ b/src/udev/udev-builtin-input_id.c
+@@ -44,12 +44,15 @@ static int abs_size_mm(const struct input_absinfo *absinfo) {
+         return (absinfo->maximum - absinfo->minimum) / absinfo->resolution;
+ }
+ 
+-static void extract_info(sd_device *dev, EventMode mode) {
++static void extract_info(UdevEvent *event) {
+         char width[DECIMAL_STR_MAX(int)], height[DECIMAL_STR_MAX(int)];
+         struct input_absinfo xabsinfo = {}, yabsinfo = {};
+         _cleanup_close_ int fd = -EBADF;
+ 
+-        fd = sd_device_open(dev, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
++        assert(event);
++        assert(event->dev);
++
++        fd = sd_device_open(event->dev, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
+         if (fd < 0)
+                 return;
+ 
+@@ -63,8 +66,8 @@ static void extract_info(sd_device *dev, EventMode mode) {
+         xsprintf(width, "%d", abs_size_mm(&xabsinfo));
+         xsprintf(height, "%d", abs_size_mm(&yabsinfo));
+ 
+-        udev_builtin_add_property(dev, mode, "ID_INPUT_WIDTH_MM", width);
+-        udev_builtin_add_property(dev, mode, "ID_INPUT_HEIGHT_MM", height);
++        udev_builtin_add_property(event, "ID_INPUT_WIDTH_MM", width);
++        udev_builtin_add_property(event, "ID_INPUT_HEIGHT_MM", height);
+ }
+ 
+ /*
+@@ -148,15 +151,15 @@ static struct input_id get_input_id(sd_device *dev) {
+ 
+ /* pointer devices */
+ static bool test_pointers(
+-                sd_device *dev,
++                UdevEvent *event,
+                 const struct input_id *id,
+                 const unsigned long *bitmask_ev,
+                 const unsigned long *bitmask_abs,
+                 const unsigned long *bitmask_key,
+                 const unsigned long *bitmask_rel,
+-                const unsigned long *bitmask_props,
+-                EventMode mode) {
++                const unsigned long *bitmask_props) {
+ 
++        sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
+         size_t num_joystick_axes = 0, num_joystick_buttons = 0;
+         bool has_abs_coordinates = false,
+                 has_rel_coordinates = false,
+@@ -190,7 +193,7 @@ static bool test_pointers(
+                 is_accelerometer = true;
+ 
+         if (is_accelerometer) {
+-                udev_builtin_add_property(dev, mode, "ID_INPUT_ACCELEROMETER", "1");
++                udev_builtin_add_property(event, "ID_INPUT_ACCELEROMETER", "1");
+                 return true;
+         }
+ 
+@@ -313,30 +316,30 @@ static bool test_pointers(
+         }
+ 
+         if (is_pointing_stick)
+-                udev_builtin_add_property(dev, mode, "ID_INPUT_POINTINGSTICK", "1");
++                udev_builtin_add_property(event, "ID_INPUT_POINTINGSTICK", "1");
+         if (is_mouse || is_abs_mouse)
+-                udev_builtin_add_property(dev, mode, "ID_INPUT_MOUSE", "1");
++                udev_builtin_add_property(event, "ID_INPUT_MOUSE", "1");
+         if (is_touchpad)
+-                udev_builtin_add_property(dev, mode, "ID_INPUT_TOUCHPAD", "1");
++                udev_builtin_add_property(event, "ID_INPUT_TOUCHPAD", "1");
+         if (is_touchscreen)
+-                udev_builtin_add_property(dev, mode, "ID_INPUT_TOUCHSCREEN", "1");
++                udev_builtin_add_property(event, "ID_INPUT_TOUCHSCREEN", "1");
+         if (is_joystick)
+-                udev_builtin_add_property(dev, mode, "ID_INPUT_JOYSTICK", "1");
++                udev_builtin_add_property(event, "ID_INPUT_JOYSTICK", "1");
+         if (is_tablet)
+-                udev_builtin_add_property(dev, mode, "ID_INPUT_TABLET", "1");
++                udev_builtin_add_property(event, "ID_INPUT_TABLET", "1");
+         if (is_tablet_pad)
+-                udev_builtin_add_property(dev, mode, "ID_INPUT_TABLET_PAD", "1");
++                udev_builtin_add_property(event, "ID_INPUT_TABLET_PAD", "1");
+ 
+         return is_tablet || is_mouse || is_abs_mouse || is_touchpad || is_touchscreen || is_joystick || is_pointing_stick;
+ }
+ 
+ /* key like devices */
+ static bool test_key(
+-                sd_device *dev,
++                UdevEvent *event,
+                 const unsigned long *bitmask_ev,
+-                const unsigned long *bitmask_key,
+-                EventMode mode) {
++                const unsigned long *bitmask_key) {
+ 
++        sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
+         bool found = false;
+ 
+         /* do we have any KEY_* capability? */
+@@ -362,12 +365,12 @@ static bool test_key(
+                         }
+ 
+         if (found)
+-                udev_builtin_add_property(dev, mode, "ID_INPUT_KEY", "1");
++                udev_builtin_add_property(event, "ID_INPUT_KEY", "1");
+ 
+         /* the first 32 bits are ESC, numbers, and Q to D; if we have all of
+          * those, consider it a full keyboard; do not test KEY_RESERVED, though */
+         if (FLAGS_SET(bitmask_key[0], 0xFFFFFFFE)) {
+-                udev_builtin_add_property(dev, mode, "ID_INPUT_KEYBOARD", "1");
++                udev_builtin_add_property(event, "ID_INPUT_KEYBOARD", "1");
+                 return true;
+         }
+ 
+@@ -404,28 +407,27 @@ static int builtin_input_id(UdevEvent *event, int argc, char *argv[]) {
+ 
+                 /* Use this as a flag that input devices were detected, so that this
+                  * program doesn't need to be called more than once per device */
+-                udev_builtin_add_property(dev, event->event_mode, "ID_INPUT", "1");
++                udev_builtin_add_property(event, "ID_INPUT", "1");
+                 get_cap_mask(pdev, "capabilities/ev", bitmask_ev, sizeof(bitmask_ev), event->event_mode);
+                 get_cap_mask(pdev, "capabilities/abs", bitmask_abs, sizeof(bitmask_abs), event->event_mode);
+                 get_cap_mask(pdev, "capabilities/rel", bitmask_rel, sizeof(bitmask_rel), event->event_mode);
+                 get_cap_mask(pdev, "capabilities/key", bitmask_key, sizeof(bitmask_key), event->event_mode);
+                 get_cap_mask(pdev, "properties", bitmask_props, sizeof(bitmask_props), event->event_mode);
+-                is_pointer = test_pointers(dev, &id, bitmask_ev, bitmask_abs,
++                is_pointer = test_pointers(event, &id, bitmask_ev, bitmask_abs,
+                                            bitmask_key, bitmask_rel,
+-                                           bitmask_props, event->event_mode);
+-                is_key = test_key(dev, bitmask_ev, bitmask_key, event->event_mode);
++                                           bitmask_props);
++                is_key = test_key(event, bitmask_ev, bitmask_key);
+                 /* Some evdev nodes have only a scrollwheel */
+                 if (!is_pointer && !is_key && test_bit(EV_REL, bitmask_ev) &&
+                     (test_bit(REL_WHEEL, bitmask_rel) || test_bit(REL_HWHEEL, bitmask_rel)))
+-                        udev_builtin_add_property(dev, event->event_mode, "ID_INPUT_KEY", "1");
++                        udev_builtin_add_property(event, "ID_INPUT_KEY", "1");
+                 if (test_bit(EV_SW, bitmask_ev))
+-                        udev_builtin_add_property(dev, event->event_mode, "ID_INPUT_SWITCH", "1");
+-
++                        udev_builtin_add_property(event, "ID_INPUT_SWITCH", "1");
+         }
+ 
+         if (sd_device_get_sysname(dev, &sysname) >= 0 &&
+             startswith(sysname, "event"))
+-                extract_info(dev, event->event_mode);
++                extract_info(event);
+ 
+         return 0;
+ }
+diff --git a/src/udev/udev-builtin-net_driver.c b/src/udev/udev-builtin-net_driver.c
+index 90a9e8d22f..5e35b39ee4 100644
+--- a/src/udev/udev-builtin-net_driver.c
++++ b/src/udev/udev-builtin-net_driver.c
+@@ -32,7 +32,7 @@ static int builtin_net_driver_set_driver(UdevEvent *event, int argc, char **argv
+         if (r < 0)
+                 return log_device_warning_errno(dev, r, "Failed to get driver for '%s': %m", sysname);
+ 
+-        return udev_builtin_add_property(event->dev, event->event_mode, "ID_NET_DRIVER", driver);
++        return udev_builtin_add_property(event, "ID_NET_DRIVER", driver);
+ }
+ 
+ const UdevBuiltin udev_builtin_net_driver = {
+diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c
+index 09c04b9a7f..96e792bcde 100644
+--- a/src/udev/udev-builtin-net_id.c
++++ b/src/udev/udev-builtin-net_id.c
+@@ -299,12 +299,12 @@ static int pci_get_onboard_index(sd_device *dev, unsigned *ret) {
+         return 0;
+ }
+ 
+-static int names_pci_onboard(sd_device *dev, sd_device *pci_dev, const char *prefix, const char *suffix, EventMode mode) {
++static int names_pci_onboard(UdevEvent *event, sd_device *pci_dev, const char *prefix, const char *suffix) {
++        sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
+         _cleanup_free_ char *port = NULL;
+         unsigned idx = 0;  /* avoid false maybe-uninitialized warning */
+         int r;
+ 
+-        assert(dev);
+         assert(pci_dev);
+         assert(prefix);
+ 
+@@ -319,7 +319,7 @@ static int names_pci_onboard(sd_device *dev, sd_device *pci_dev, const char *pre
+ 
+         char str[ALTIFNAMSIZ];
+         if (snprintf_ok(str, sizeof str, "%so%u%s%s", prefix, idx, strempty(port), strempty(suffix)))
+-                udev_builtin_add_property(dev, mode, "ID_NET_NAME_ONBOARD", str);
++                udev_builtin_add_property(event, "ID_NET_NAME_ONBOARD", str);
+ 
+         log_device_debug(dev, "PCI onboard index identifier: index=%u port=%s %s %s",
+                          idx, strna(port),
+@@ -328,11 +328,11 @@ static int names_pci_onboard(sd_device *dev, sd_device *pci_dev, const char *pre
+         return 0;
+ }
+ 
+-static int names_pci_onboard_label(sd_device *dev, sd_device *pci_dev, const char *prefix, EventMode mode) {
++static int names_pci_onboard_label(UdevEvent *event, sd_device *pci_dev, const char *prefix) {
++        sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
+         const char *label;
+         int r;
+ 
+-        assert(dev);
+         assert(prefix);
+ 
+         /* retrieve on-board label from firmware */
+@@ -344,7 +344,7 @@ static int names_pci_onboard_label(sd_device *dev, sd_device *pci_dev, const cha
+         if (snprintf_ok(str, sizeof str, "%s%s",
+                         naming_scheme_has(NAMING_LABEL_NOPREFIX) ? "" : prefix,
+                         label))
+-                udev_builtin_add_property(dev, mode, "ID_NET_LABEL_ONBOARD", str);
++                udev_builtin_add_property(event, "ID_NET_LABEL_ONBOARD", str);
+ 
+         log_device_debug(dev, "Onboard label from PCI device: %s", label);
+         return 0;
+@@ -666,13 +666,13 @@ static int get_pci_slot_specifiers(
+         return 0;
+ }
+ 
+-static int names_pci_slot(sd_device *dev, sd_device *pci_dev, const char *prefix, const char *suffix, EventMode mode) {
++static int names_pci_slot(UdevEvent *event, sd_device *pci_dev, const char *prefix, const char *suffix) {
++        sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
+         _cleanup_free_ char *domain = NULL, *bus_and_slot = NULL, *func = NULL, *port = NULL;
+         uint32_t slot = 0;  /* avoid false maybe-uninitialized warning */
+         char str[ALTIFNAMSIZ];
+         int r;
+ 
+-        assert(dev);
+         assert(pci_dev);
+         assert(prefix);
+ 
+@@ -687,7 +687,7 @@ static int names_pci_slot(sd_device *dev, sd_device *pci_dev, const char *prefix
+         /* compose a name based on the raw kernel's PCI bus, slot numbers */
+         if (snprintf_ok(str, sizeof str, "%s%s%s%s%s%s",
+                         prefix, strempty(domain), bus_and_slot, strempty(func), strempty(port), strempty(suffix)))
+-                udev_builtin_add_property(dev, mode, "ID_NET_NAME_PATH", str);
++                udev_builtin_add_property(event, "ID_NET_NAME_PATH", str);
+ 
+         log_device_debug(dev, "PCI path identifier: domain=%s bus_and_slot=%s func=%s port=%s %s %s",
+                          strna(domain), bus_and_slot, strna(func), strna(port),
+@@ -706,7 +706,7 @@ static int names_pci_slot(sd_device *dev, sd_device *pci_dev, const char *prefix
+ 
+         if (snprintf_ok(str, sizeof str, "%s%ss%"PRIu32"%s%s%s",
+                         prefix, strempty(domain), slot, strempty(func), strempty(port), strempty(suffix)))
+-                udev_builtin_add_property(dev, mode, "ID_NET_NAME_SLOT", str);
++                udev_builtin_add_property(event, "ID_NET_NAME_SLOT", str);
+ 
+         log_device_debug(dev, "PCI slot identifier: domain=%s slot=%"PRIu32" func=%s port=%s %s %s",
+                          strna(domain), slot, strna(func), strna(port),
+@@ -715,12 +715,12 @@ static int names_pci_slot(sd_device *dev, sd_device *pci_dev, const char *prefix
+         return 0;
+ }
+ 
+-static int names_vio(sd_device *dev, const char *prefix, EventMode mode) {
++static int names_vio(UdevEvent *event, const char *prefix) {
++        sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
+         _cleanup_free_ char *s = NULL;
+         unsigned slotid;
+         int r;
+ 
+-        assert(dev);
+         assert(prefix);
+ 
+         /* get ibmveth/ibmvnic slot-based names. */
+@@ -754,20 +754,20 @@ static int names_vio(sd_device *dev, const char *prefix, EventMode mode) {
+ 
+         char str[ALTIFNAMSIZ];
+         if (snprintf_ok(str, sizeof str, "%sv%u", prefix, slotid))
+-                udev_builtin_add_property(dev, mode, "ID_NET_NAME_SLOT", str);
++                udev_builtin_add_property(event, "ID_NET_NAME_SLOT", str);
+         log_device_debug(dev, "Vio slot identifier: slotid=%u %s %s",
+                          slotid, special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), str + strlen(prefix));
+         return 0;
+ }
+ 
+-static int names_platform(sd_device *dev, const char *prefix, EventMode mode) {
++static int names_platform(UdevEvent *event, const char *prefix) {
++        sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
+         _cleanup_free_ char *p = NULL;
+         const char *validchars;
+         char *vendor, *model_str, *instance_str;
+         unsigned model, instance;
+         int r;
+ 
+-        assert(dev);
+         assert(prefix);
+ 
+         /* get ACPI path names for ARM64 platform devices */
+@@ -816,18 +816,18 @@ static int names_platform(sd_device *dev, const char *prefix, EventMode mode) {
+ 
+         char str[ALTIFNAMSIZ];
+         if (snprintf_ok(str, sizeof str, "%sa%s%xi%u", prefix, vendor, model, instance))
+-                udev_builtin_add_property(dev, mode, "ID_NET_NAME_PATH", str);
++                udev_builtin_add_property(event, "ID_NET_NAME_PATH", str);
+         log_device_debug(dev, "Platform identifier: vendor=%s model=%x instance=%u %s %s",
+                          vendor, model, instance, special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), str + strlen(prefix));
+         return 0;
+ }
+ 
+-static int names_devicetree(sd_device *dev, const char *prefix, EventMode mode) {
++static int names_devicetree(UdevEvent *event, const char *prefix) {
++        sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
+         _cleanup_(sd_device_unrefp) sd_device *aliases_dev = NULL, *ofnode_dev = NULL, *devicetree_dev = NULL;
+         const char *ofnode_path, *ofnode_syspath, *devicetree_syspath;
+         int r;
+ 
+-        assert(dev);
+         assert(prefix);
+ 
+         if (!naming_scheme_has(NAMING_DEVICETREE_ALIASES))
+@@ -923,7 +923,7 @@ static int names_devicetree(sd_device *dev, const char *prefix, EventMode mode)
+ 
+                 char str[ALTIFNAMSIZ];
+                 if (snprintf_ok(str, sizeof str, "%sd%u", prefix, i))
+-                        udev_builtin_add_property(dev, mode, "ID_NET_NAME_ONBOARD", str);
++                        udev_builtin_add_property(event, "ID_NET_NAME_ONBOARD", str);
+                 log_device_debug(dev, "DeviceTree identifier: alias_index=%u %s \"%s\"",
+                                  i, special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), str + strlen(prefix));
+                 return 0;
+@@ -932,12 +932,11 @@ static int names_devicetree(sd_device *dev, const char *prefix, EventMode mode)
+         return -ENOENT;
+ }
+ 
+-static int names_pci(sd_device *dev, const char *prefix, EventMode mode) {
++static int names_pci(UdevEvent *event, const char *prefix) {
++        sd_device *parent, *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
+         _cleanup_(sd_device_unrefp) sd_device *physfn_pcidev = NULL;
+         _cleanup_free_ char *virtfn_suffix = NULL;
+-        sd_device *parent;
+ 
+-        assert(dev);
+         assert(prefix);
+ 
+         /* check if our direct parent is a PCI device with no other bus in-between */
+@@ -949,10 +948,10 @@ static int names_pci(sd_device *dev, const char *prefix, EventMode mode) {
+             get_virtfn_info(parent, &physfn_pcidev, &virtfn_suffix) >= 0)
+                 parent = physfn_pcidev;
+         else
+-                (void) names_pci_onboard_label(dev, parent, prefix, mode);
++                (void) names_pci_onboard_label(event, parent, prefix);
+ 
+-        (void) names_pci_onboard(dev, parent, prefix, virtfn_suffix, mode);
+-        (void) names_pci_slot(dev, parent, prefix, virtfn_suffix, mode);
++        (void) names_pci_onboard(event, parent, prefix, virtfn_suffix);
++        (void) names_pci_slot(event, parent, prefix, virtfn_suffix);
+         return 0;
+ }
+ 
+@@ -1015,12 +1014,11 @@ static int get_usb_specifier(sd_device *dev, char **ret) {
+         return 0;
+ }
+ 
+-static int names_usb(sd_device *dev, const char *prefix, EventMode mode) {
++static int names_usb(UdevEvent *event, const char *prefix) {
++        sd_device *usbdev, *pcidev, *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
+         _cleanup_free_ char *suffix = NULL;
+-        sd_device *usbdev, *pcidev;
+         int r;
+ 
+-        assert(dev);
+         assert(prefix);
+ 
+         /* USB device */
+@@ -1036,7 +1034,7 @@ static int names_usb(sd_device *dev, const char *prefix, EventMode mode) {
+         /* If the USB bus is on PCI bus, then suffix the USB specifier to the name based on the PCI bus. */
+         r = sd_device_get_parent_with_subsystem_devtype(usbdev, "pci", NULL, &pcidev);
+         if (r >= 0)
+-                return names_pci_slot(dev, pcidev, prefix, suffix, mode);
++                return names_pci_slot(event, pcidev, prefix, suffix);
+ 
+         if (r != -ENOENT || !naming_scheme_has(NAMING_USB_HOST))
+                 return log_device_debug_errno(usbdev, r, "Failed to get parent PCI bus: %m");
+@@ -1044,7 +1042,7 @@ static int names_usb(sd_device *dev, const char *prefix, EventMode mode) {
+         /* Otherwise, e.g. on-chip asics that have USB ports, use the USB specifier as is. */
+         char str[ALTIFNAMSIZ];
+         if (snprintf_ok(str, sizeof str, "%s%s", prefix, suffix))
+-                udev_builtin_add_property(dev, mode, "ID_NET_NAME_PATH", str);
++                udev_builtin_add_property(event, "ID_NET_NAME_PATH", str);
+ 
+         return 0;
+ }
+@@ -1079,12 +1077,11 @@ static int get_bcma_specifier(sd_device *dev, char **ret) {
+         return 0;
+ }
+ 
+-static int names_bcma(sd_device *dev, const char *prefix, EventMode mode) {
++static int names_bcma(UdevEvent *event, const char *prefix) {
++        sd_device *bcmadev, *pcidev, *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
+         _cleanup_free_ char *suffix = NULL;
+-        sd_device *bcmadev, *pcidev;
+         int r;
+ 
+-        assert(dev);
+         assert(prefix);
+ 
+         r = sd_device_get_parent_with_subsystem_devtype(dev, "bcma", NULL, &bcmadev);
+@@ -1099,16 +1096,15 @@ static int names_bcma(sd_device *dev, const char *prefix, EventMode mode) {
+         if (r < 0)
+                 return r;
+ 
+-        return names_pci_slot(dev, pcidev, prefix, suffix, mode);
++        return names_pci_slot(event, pcidev, prefix, suffix);
+ }
+ 
+-static int names_ccw(sd_device *dev, const char *prefix, EventMode mode) {
+-        sd_device *cdev;
++static int names_ccw(UdevEvent *event, const char *prefix) {
++        sd_device *cdev, *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
+         const char *bus_id;
+         size_t bus_id_start, bus_id_len;
+         int r;
+ 
+-        assert(dev);
+         assert(prefix);
+ 
+         /* get path names for Linux on System z network devices */
+@@ -1144,17 +1140,17 @@ static int names_ccw(sd_device *dev, const char *prefix, EventMode mode) {
+         /* Use the CCW bus-ID as network device name */
+         char str[ALTIFNAMSIZ];
+         if (snprintf_ok(str, sizeof str, "%sc%s", prefix, bus_id))
+-                udev_builtin_add_property(dev, mode, "ID_NET_NAME_PATH", str);
++                udev_builtin_add_property(event, "ID_NET_NAME_PATH", str);
+         log_device_debug(dev, "CCW identifier: ccw_busid=%s %s \"%s\"",
+                          bus_id, special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), str + strlen(prefix));
+         return 0;
+ }
+ 
+ /* IEEE Organizationally Unique Identifier vendor string */
+-static int ieee_oui(sd_device *dev, const struct hw_addr_data *hw_addr, EventMode mode) {
++static int ieee_oui(UdevEvent *event, const struct hw_addr_data *hw_addr) {
+         char str[32];
+ 
+-        assert(dev);
++        assert(event);
+         assert(hw_addr);
+ 
+         if (hw_addr->length != 6)
+@@ -1174,16 +1170,16 @@ static int ieee_oui(sd_device *dev, const struct hw_addr_data *hw_addr, EventMod
+                  hw_addr->bytes[4],
+                  hw_addr->bytes[5]);
+ 
+-        return udev_builtin_hwdb_lookup(dev, NULL, str, NULL, mode);
++        return udev_builtin_hwdb_lookup(event, NULL, str, NULL);
+ }
+ 
+-static int names_mac(sd_device *dev, const char *prefix, EventMode mode) {
++static int names_mac(UdevEvent *event, const char *prefix) {
++        sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
+         unsigned iftype, assign_type;
+         struct hw_addr_data hw_addr;
+         const char *s;
+         int r;
+ 
+-        assert(dev);
+         assert(prefix);
+ 
+         r = device_get_sysattr_unsigned_filtered(dev, "type", &iftype);
+@@ -1221,22 +1217,21 @@ static int names_mac(sd_device *dev, const char *prefix, EventMode mode) {
+ 
+         char str[ALTIFNAMSIZ];
+         xsprintf(str, "%sx%s", prefix, HW_ADDR_TO_STR_FULL(&hw_addr, HW_ADDR_TO_STRING_NO_COLON));
+-        udev_builtin_add_property(dev, mode, "ID_NET_NAME_MAC", str);
++        udev_builtin_add_property(event, "ID_NET_NAME_MAC", str);
+         log_device_debug(dev, "MAC address identifier: hw_addr=%s %s %s",
+                          HW_ADDR_TO_STR(&hw_addr),
+                          special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), str + strlen(prefix));
+ 
+-        (void) ieee_oui(dev, &hw_addr, mode);
++        (void) ieee_oui(event, &hw_addr);
+         return 0;
+ }
+ 
+-static int names_netdevsim(sd_device *dev, const char *prefix, EventMode mode) {
+-        sd_device *netdevsimdev;
++static int names_netdevsim(UdevEvent *event, const char *prefix) {
++        sd_device *netdevsimdev, *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
+         const char *sysnum, *phys_port_name;
+         unsigned addr;
+         int r;
+ 
+-        assert(dev);
+         assert(prefix);
+ 
+         /* get netdevsim path names */
+@@ -1265,19 +1260,19 @@ static int names_netdevsim(sd_device *dev, const char *prefix, EventMode mode) {
+ 
+         char str[ALTIFNAMSIZ];
+         if (snprintf_ok(str, sizeof str, "%si%un%s", prefix, addr, phys_port_name))
+-                udev_builtin_add_property(dev, mode, "ID_NET_NAME_PATH", str);
++                udev_builtin_add_property(event, "ID_NET_NAME_PATH", str);
+         log_device_debug(dev, "Netdevsim identifier: address=%u, port_name=%s %s %s",
+                          addr, phys_port_name, special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), str + strlen(prefix));
+         return 0;
+ }
+ 
+-static int names_xen(sd_device *dev, const char *prefix, EventMode mode) {
++static int names_xen(UdevEvent *event, const char *prefix) {
++        sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
+         _cleanup_free_ char *vif = NULL;
+         const char *p;
+         unsigned id;
+         int r;
+ 
+-        assert(dev);
+         assert(prefix);
+ 
+         /* get xen vif "slot" based names. */
+@@ -1305,7 +1300,7 @@ static int names_xen(sd_device *dev, const char *prefix, EventMode mode) {
+ 
+         char str[ALTIFNAMSIZ];
+         if (snprintf_ok(str, sizeof str, "%sX%u", prefix, id))
+-                udev_builtin_add_property(dev, mode, "ID_NET_NAME_SLOT", str);
++                udev_builtin_add_property(event, "ID_NET_NAME_SLOT", str);
+         log_device_debug(dev, "Xen identifier: id=%u %s %s",
+                          id, special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), str + strlen(prefix));
+         return 0;
+@@ -1383,18 +1378,18 @@ static int builtin_net_id(UdevEvent *event, int argc, char *argv[]) {
+                 return 0;
+         }
+ 
+-        udev_builtin_add_property(dev, event->event_mode, "ID_NET_NAMING_SCHEME", naming_scheme()->name);
+-
+-        (void) names_mac(dev, prefix, event->event_mode);
+-        (void) names_devicetree(dev, prefix, event->event_mode);
+-        (void) names_ccw(dev, prefix, event->event_mode);
+-        (void) names_vio(dev, prefix, event->event_mode);
+-        (void) names_platform(dev, prefix, event->event_mode);
+-        (void) names_netdevsim(dev, prefix, event->event_mode);
+-        (void) names_xen(dev, prefix, event->event_mode);
+-        (void) names_pci(dev, prefix, event->event_mode);
+-        (void) names_usb(dev, prefix, event->event_mode);
+-        (void) names_bcma(dev, prefix, event->event_mode);
++        udev_builtin_add_property(event, "ID_NET_NAMING_SCHEME", naming_scheme()->name);
++
++        (void) names_mac(event, prefix);
++        (void) names_devicetree(event, prefix);
++        (void) names_ccw(event, prefix);
++        (void) names_vio(event, prefix);
++        (void) names_platform(event, prefix);
++        (void) names_netdevsim(event, prefix);
++        (void) names_xen(event, prefix);
++        (void) names_pci(event, prefix);
++        (void) names_usb(event, prefix);
++        (void) names_bcma(event, prefix);
+ 
+         return 0;
+ }
+diff --git a/src/udev/udev-builtin-net_setup_link.c b/src/udev/udev-builtin-net_setup_link.c
+index 8cfcaa932f..4500a69c68 100644
+--- a/src/udev/udev-builtin-net_setup_link.c
++++ b/src/udev/udev-builtin-net_setup_link.c
+@@ -30,13 +30,13 @@ static int builtin_net_setup_link(UdevEvent *event, int argc, char **argv) {
+                                  device_action_to_string(action));
+ 
+                 /* Import previously assigned .link file name. */
+-                (void) udev_builtin_import_property(dev, event->dev_db_clone, event->event_mode, "ID_NET_LINK_FILE");
+-                (void) udev_builtin_import_property(dev, event->dev_db_clone, event->event_mode, "ID_NET_LINK_FILE_DROPINS");
++                (void) udev_builtin_import_property(event, "ID_NET_LINK_FILE");
++                (void) udev_builtin_import_property(event, "ID_NET_LINK_FILE_DROPINS");
+ 
+                 /* Set ID_NET_NAME= with the current interface name. */
+                 const char *value;
+                 if (sd_device_get_sysname(dev, &value) >= 0)
+-                        (void) udev_builtin_add_property(dev, event->event_mode, "ID_NET_NAME", value);
++                        (void) udev_builtin_add_property(event, "ID_NET_NAME", value);
+ 
+                 return 0;
+         }
+@@ -59,7 +59,7 @@ static int builtin_net_setup_link(UdevEvent *event, int argc, char **argv) {
+                 return log_device_error_errno(dev, r, "Failed to get link config: %m");
+         }
+ 
+-        r = link_apply_config(ctx, &event->rtnl, link, event->event_mode);
++        r = link_apply_config(ctx, &event->rtnl, link, event);
+         if (r == -ENODEV)
+                 log_device_debug_errno(dev, r, "Link vanished while applying configuration, ignoring.");
+         else if (r < 0)
+diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c
+index 8ba5f2e358..d6ea471482 100644
+--- a/src/udev/udev-builtin-path_id.c
++++ b/src/udev/udev-builtin-path_id.c
+@@ -639,10 +639,10 @@ static int find_real_nvme_parent(sd_device *dev, sd_device **ret) {
+         return 0;
+ }
+ 
+-static void add_id_with_usb_revision(sd_device *dev, EventMode mode, char *path) {
++static void add_id_with_usb_revision(UdevEvent *event, char *path) {
+         char *p;
+ 
+-        assert(dev);
++        assert(event);
+         assert(path);
+ 
+         /* When the path contains the USB revision, let's adds ID_PATH_WITH_USB_REVISION property and
+@@ -656,13 +656,13 @@ static void add_id_with_usb_revision(sd_device *dev, EventMode mode, char *path)
+         if (p[1] != '-')
+                 return;
+ 
+-        (void) udev_builtin_add_property(dev, mode, "ID_PATH_WITH_USB_REVISION", path);
++        (void) udev_builtin_add_property(event, "ID_PATH_WITH_USB_REVISION", path);
+ 
+         /* Drop the USB revision specifier for backward compatibility. */
+         memmove(p - 1, p + 1, strlen(p + 1) + 1);
+ }
+ 
+-static void add_id_tag(sd_device *dev, EventMode mode, const char *path) {
++static void add_id_tag(UdevEvent *event, const char *path) {
+         char tag[UDEV_NAME_SIZE];
+         size_t i = 0;
+ 
+@@ -690,7 +690,7 @@ static void add_id_tag(sd_device *dev, EventMode mode, const char *path) {
+                 i--;
+         tag[i] = '\0';
+ 
+-        (void) udev_builtin_add_property(dev, mode, "ID_PATH_TAG", tag);
++        (void) udev_builtin_add_property(event, "ID_PATH_TAG", tag);
+ }
+ 
+ static int builtin_path_id(UdevEvent *event, int argc, char *argv[]) {
+@@ -848,11 +848,11 @@ static int builtin_path_id(UdevEvent *event, int argc, char *argv[]) {
+         if (device_in_subsystem(dev, "block") && !supported_transport)
+                 return -ENOENT;
+ 
+-        add_id_with_usb_revision(dev, event->event_mode, path);
++        add_id_with_usb_revision(event, path);
+ 
+-        (void) udev_builtin_add_property(dev, event->event_mode, "ID_PATH", path);
++        (void) udev_builtin_add_property(event, "ID_PATH", path);
+ 
+-        add_id_tag(dev, event->event_mode, path);
++        add_id_tag(event, path);
+ 
+         /*
+          * Compatible link generation for ATA devices
+@@ -860,7 +860,7 @@ static int builtin_path_id(UdevEvent *event, int argc, char *argv[]) {
+          * ID_PATH_ATA_COMPAT
+          */
+         if (compat_path)
+-                (void) udev_builtin_add_property(dev, event->event_mode, "ID_PATH_ATA_COMPAT", compat_path);
++                (void) udev_builtin_add_property(event, "ID_PATH_ATA_COMPAT", compat_path);
+ 
+         return 0;
+ }
+diff --git a/src/udev/udev-builtin-usb_id.c b/src/udev/udev-builtin-usb_id.c
+index 9abdec3591..7148c80194 100644
+--- a/src/udev/udev-builtin-usb_id.c
++++ b/src/udev/udev-builtin-usb_id.c
+@@ -413,55 +413,55 @@ fallback:
+         if (sd_device_get_property_value(dev, "ID_BUS", NULL) >= 0)
+                 log_device_debug(dev, "ID_BUS property is already set, setting only properties prefixed with \"ID_USB_\".");
+         else {
+-                udev_builtin_add_property(dev, event->event_mode, "ID_BUS", "usb");
++                udev_builtin_add_property(event, "ID_BUS", "usb");
+ 
+-                udev_builtin_add_property(dev, event->event_mode, "ID_MODEL", model_str);
+-                udev_builtin_add_property(dev, event->event_mode, "ID_MODEL_ENC", model_str_enc);
+-                udev_builtin_add_property(dev, event->event_mode, "ID_MODEL_ID", product_id);
++                udev_builtin_add_property(event, "ID_MODEL", model_str);
++                udev_builtin_add_property(event, "ID_MODEL_ENC", model_str_enc);
++                udev_builtin_add_property(event, "ID_MODEL_ID", product_id);
+ 
+-                udev_builtin_add_property(dev, event->event_mode, "ID_SERIAL", serial);
++                udev_builtin_add_property(event, "ID_SERIAL", serial);
+                 if (!isempty(serial_str))
+-                        udev_builtin_add_property(dev, event->event_mode, "ID_SERIAL_SHORT", serial_str);
++                        udev_builtin_add_property(event, "ID_SERIAL_SHORT", serial_str);
+ 
+-                udev_builtin_add_property(dev, event->event_mode, "ID_VENDOR", vendor_str);
+-                udev_builtin_add_property(dev, event->event_mode, "ID_VENDOR_ENC", vendor_str_enc);
+-                udev_builtin_add_property(dev, event->event_mode, "ID_VENDOR_ID", vendor_id);
++                udev_builtin_add_property(event, "ID_VENDOR", vendor_str);
++                udev_builtin_add_property(event, "ID_VENDOR_ENC", vendor_str_enc);
++                udev_builtin_add_property(event, "ID_VENDOR_ID", vendor_id);
+ 
+-                udev_builtin_add_property(dev, event->event_mode, "ID_REVISION", revision_str);
++                udev_builtin_add_property(event, "ID_REVISION", revision_str);
+ 
+                 if (!isempty(type_str))
+-                        udev_builtin_add_property(dev, event->event_mode, "ID_TYPE", type_str);
++                        udev_builtin_add_property(event, "ID_TYPE", type_str);
+ 
+                 if (!isempty(instance_str))
+-                        udev_builtin_add_property(dev, event->event_mode, "ID_INSTANCE", instance_str);
++                        udev_builtin_add_property(event, "ID_INSTANCE", instance_str);
+         }
+ 
+         /* Also export the same values in the above by prefixing ID_USB_. */
+-        udev_builtin_add_property(dev, event->event_mode, "ID_USB_MODEL", model_str);
+-        udev_builtin_add_property(dev, event->event_mode, "ID_USB_MODEL_ENC", model_str_enc);
+-        udev_builtin_add_property(dev, event->event_mode, "ID_USB_MODEL_ID", product_id);
+-        udev_builtin_add_property(dev, event->event_mode, "ID_USB_SERIAL", serial);
++        udev_builtin_add_property(event, "ID_USB_MODEL", model_str);
++        udev_builtin_add_property(event, "ID_USB_MODEL_ENC", model_str_enc);
++        udev_builtin_add_property(event, "ID_USB_MODEL_ID", product_id);
++        udev_builtin_add_property(event, "ID_USB_SERIAL", serial);
+         if (!isempty(serial_str))
+-                udev_builtin_add_property(dev, event->event_mode, "ID_USB_SERIAL_SHORT", serial_str);
++                udev_builtin_add_property(event, "ID_USB_SERIAL_SHORT", serial_str);
+ 
+-        udev_builtin_add_property(dev, event->event_mode, "ID_USB_VENDOR", vendor_str);
+-        udev_builtin_add_property(dev, event->event_mode, "ID_USB_VENDOR_ENC", vendor_str_enc);
+-        udev_builtin_add_property(dev, event->event_mode, "ID_USB_VENDOR_ID", vendor_id);
++        udev_builtin_add_property(event, "ID_USB_VENDOR", vendor_str);
++        udev_builtin_add_property(event, "ID_USB_VENDOR_ENC", vendor_str_enc);
++        udev_builtin_add_property(event, "ID_USB_VENDOR_ID", vendor_id);
+ 
+-        udev_builtin_add_property(dev, event->event_mode, "ID_USB_REVISION", revision_str);
++        udev_builtin_add_property(event, "ID_USB_REVISION", revision_str);
+ 
+         if (!isempty(type_str))
+-                udev_builtin_add_property(dev, event->event_mode, "ID_USB_TYPE", type_str);
++                udev_builtin_add_property(event, "ID_USB_TYPE", type_str);
+ 
+         if (!isempty(instance_str))
+-                udev_builtin_add_property(dev, event->event_mode, "ID_USB_INSTANCE", instance_str);
++                udev_builtin_add_property(event, "ID_USB_INSTANCE", instance_str);
+ 
+         if (!isempty(packed_if_str))
+-                udev_builtin_add_property(dev, event->event_mode, "ID_USB_INTERFACES", packed_if_str);
++                udev_builtin_add_property(event, "ID_USB_INTERFACES", packed_if_str);
+         if (ifnum)
+-                udev_builtin_add_property(dev, event->event_mode, "ID_USB_INTERFACE_NUM", ifnum);
++                udev_builtin_add_property(event, "ID_USB_INTERFACE_NUM", ifnum);
+         if (driver)
+-                udev_builtin_add_property(dev, event->event_mode, "ID_USB_DRIVER", driver);
++                udev_builtin_add_property(event, "ID_USB_DRIVER", driver);
+         return 0;
+ }
+ 
+diff --git a/src/udev/udev-builtin.c b/src/udev/udev-builtin.c
+index 69401aa2e0..2118c2f3df 100644
+--- a/src/udev/udev-builtin.c
++++ b/src/udev/udev-builtin.c
+@@ -120,10 +120,10 @@ int udev_builtin_run(UdevEvent *event, UdevBuiltinCommand cmd, const char *comma
+         return builtins[cmd]->cmd(event, strv_length(argv), argv);
+ }
+ 
+-int udev_builtin_add_property(sd_device *dev, EventMode mode, const char *key, const char *val) {
++int udev_builtin_add_property(UdevEvent *event, const char *key, const char *val) {
++        sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
+         int r;
+ 
+-        assert(dev);
+         assert(key);
+ 
+         r = device_add_property(dev, key, val);
+@@ -131,18 +131,18 @@ int udev_builtin_add_property(sd_device *dev, EventMode mode, const char *key, c
+                 return log_device_debug_errno(dev, r, "Failed to add property '%s%s%s'",
+                                               key, val ? "=" : "", strempty(val));
+ 
+-        if (mode == EVENT_UDEVADM_TEST_BUILTIN)
++        if (event->event_mode == EVENT_UDEVADM_TEST_BUILTIN)
+                 printf("%s=%s\n", key, strempty(val));
+ 
+         return 0;
+ }
+ 
+-int udev_builtin_add_propertyf(sd_device *dev, EventMode mode, const char *key, const char *valf, ...) {
++int udev_builtin_add_propertyf(UdevEvent *event, const char *key, const char *valf, ...) {
+         _cleanup_free_ char *val = NULL;
+         va_list ap;
+         int r;
+ 
+-        assert(dev);
++        assert(event);
+         assert(key);
+         assert(valf);
+ 
+@@ -152,26 +152,26 @@ int udev_builtin_add_propertyf(sd_device *dev, EventMode mode, const char *key,
+         if (r < 0)
+                 return log_oom_debug();
+ 
+-        return udev_builtin_add_property(dev, mode, key, val);
++        return udev_builtin_add_property(event, key, val);
+ }
+ 
+-int udev_builtin_import_property(sd_device *dev, sd_device *src, EventMode mode, const char *key) {
++int udev_builtin_import_property(UdevEvent *event, const char *key) {
+         const char *val;
+         int r;
+ 
+-        assert(dev);
+-        assert(key);
++        assert(event);
++        assert(event->dev);
+ 
+-        if (!src)
++        if (!event->dev_db_clone)
+                 return 0;
+ 
+-        r = sd_device_get_property_value(src, key, &val);
++        r = sd_device_get_property_value(event->dev_db_clone, key, &val);
+         if (r == -ENOENT)
+                 return 0;
+         if (r < 0)
+-                return log_device_debug_errno(src, r, "Failed to get property \"%s\", ignoring: %m", key);
++                return log_device_debug_errno(event->dev_db_clone, r, "Failed to get property \"%s\", ignoring: %m", key);
+ 
+-        r = udev_builtin_add_property(dev, mode, key, val);
++        r = udev_builtin_add_property(event, key, val);
+         if (r < 0)
+                 return r;
+ 
+diff --git a/src/udev/udev-builtin.h b/src/udev/udev-builtin.h
+index 2433dfa4d4..8c2016e5f0 100644
+--- a/src/udev/udev-builtin.h
++++ b/src/udev/udev-builtin.h
+@@ -60,8 +60,7 @@ bool udev_builtin_run_once(UdevBuiltinCommand cmd);
+ int udev_builtin_run(UdevEvent *event, UdevBuiltinCommand cmd, const char *command);
+ void udev_builtin_list(void);
+ bool udev_builtin_should_reload(void);
+-int udev_builtin_add_property(sd_device *dev, EventMode mode, const char *key, const char *val);
+-int udev_builtin_add_propertyf(sd_device *dev, EventMode mode, const char *key, const char *valf, ...) _printf_(4, 5);
+-int udev_builtin_import_property(sd_device *dev, sd_device *src, EventMode mode, const char *key);
+-int udev_builtin_hwdb_lookup(sd_device *dev, const char *prefix, const char *modalias,
+-                             const char *filter, EventMode mode);
++int udev_builtin_add_property(UdevEvent *event, const char *key, const char *val);
++int udev_builtin_add_propertyf(UdevEvent *event, const char *key, const char *valf, ...) _printf_(3, 4);
++int udev_builtin_import_property(UdevEvent *event, const char *key);
++int udev_builtin_hwdb_lookup(UdevEvent *event, const char *prefix, const char *modalias, const char *filter);
diff --git a/SOURCES/0314-udev-introduce-reference-counter-for-UdevEvent.patch b/SOURCES/0314-udev-introduce-reference-counter-for-UdevEvent.patch
new file mode 100644
index 0000000000000000000000000000000000000000..3d6a76b4cce2258152d73c2c7b8367304477d753
--- /dev/null
+++ b/SOURCES/0314-udev-introduce-reference-counter-for-UdevEvent.patch
@@ -0,0 +1,143 @@
+From 9702ed206cb97d6b437965abaf139a2628055e75 Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Thu, 5 Dec 2024 03:12:03 +0900
+Subject: [PATCH] udev: introduce reference counter for UdevEvent
+
+No functional change, preparation for later commits.
+
+(cherry picked from commit 4a90166488a4018effbf471df5e057f901f0b52d)
+
+Resolves: RHEL-75774
+---
+ src/udev/test-udev-rule-runner.c | 2 +-
+ src/udev/test-udev-spawn.c       | 2 +-
+ src/udev/udev-event.c            | 5 ++++-
+ src/udev/udev-event.h            | 8 +++++---
+ src/udev/udev-worker.c           | 2 +-
+ src/udev/udevadm-test-builtin.c  | 2 +-
+ src/udev/udevadm-test.c          | 2 +-
+ 7 files changed, 14 insertions(+), 9 deletions(-)
+
+diff --git a/src/udev/test-udev-rule-runner.c b/src/udev/test-udev-rule-runner.c
+index d123c8ad1b..9a04abf590 100644
+--- a/src/udev/test-udev-rule-runner.c
++++ b/src/udev/test-udev-rule-runner.c
+@@ -89,7 +89,7 @@ static int fake_filesystems(void) {
+ 
+ static int run(int argc, char *argv[]) {
+         _cleanup_(udev_rules_freep) UdevRules *rules = NULL;
+-        _cleanup_(udev_event_freep) UdevEvent *event = NULL;
++        _cleanup_(udev_event_unrefp) UdevEvent *event = NULL;
+         _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
+         const char *devpath, *devname, *action;
+         int r;
+diff --git a/src/udev/test-udev-spawn.c b/src/udev/test-udev-spawn.c
+index a6079e3c61..a2b9aad3a7 100644
+--- a/src/udev/test-udev-spawn.c
++++ b/src/udev/test-udev-spawn.c
+@@ -12,7 +12,7 @@
+ 
+ static void test_event_spawn_core(bool with_pidfd, const char *cmd, char *result_buf, size_t buf_size) {
+         _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
+-        _cleanup_(udev_event_freep) UdevEvent *event = NULL;
++        _cleanup_(udev_event_unrefp) UdevEvent *event = NULL;
+ 
+         assert_se(setenv("SYSTEMD_PIDFD", yes_no(with_pidfd), 1) >= 0);
+ 
+diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
+index 9141a9d2a7..6a7c34b162 100644
+--- a/src/udev/udev-event.c
++++ b/src/udev/udev-event.c
+@@ -29,6 +29,7 @@ UdevEvent* udev_event_new(sd_device *dev, UdevWorker *worker, EventMode mode) {
+                 return NULL;
+ 
+         *event = (UdevEvent) {
++                .n_ref = 1,
+                 .worker = worker,
+                 .rtnl = worker ? sd_netlink_ref(worker->rtnl) : NULL,
+                 .dev = sd_device_ref(dev),
+@@ -44,7 +45,7 @@ UdevEvent* udev_event_new(sd_device *dev, UdevWorker *worker, EventMode mode) {
+         return event;
+ }
+ 
+-UdevEvent* udev_event_free(UdevEvent *event) {
++static UdevEvent* udev_event_free(UdevEvent *event) {
+         if (!event)
+                 return NULL;
+ 
+@@ -60,6 +61,8 @@ UdevEvent* udev_event_free(UdevEvent *event) {
+         return mfree(event);
+ }
+ 
++DEFINE_TRIVIAL_REF_UNREF_FUNC(UdevEvent, udev_event, udev_event_free);
++
+ static int device_rename(sd_device *device, const char *name) {
+         _cleanup_free_ char *new_syspath = NULL;
+         const char *s;
+diff --git a/src/udev/udev-event.h b/src/udev/udev-event.h
+index 186cfa541f..11e2c700e6 100644
+--- a/src/udev/udev-event.h
++++ b/src/udev/udev-event.h
+@@ -21,9 +21,10 @@ typedef struct UdevRules UdevRules;
+ typedef struct UdevWorker UdevWorker;
+ 
+ typedef struct UdevEvent {
++        unsigned n_ref;
++
+         UdevWorker *worker;
+         sd_netlink *rtnl;
+-
+         sd_device *dev;
+         sd_device *dev_parent;
+         sd_device *dev_db_clone;
+@@ -54,8 +55,9 @@ typedef struct UdevEvent {
+ } UdevEvent;
+ 
+ UdevEvent* udev_event_new(sd_device *dev, UdevWorker *worker, EventMode mode);
+-UdevEvent* udev_event_free(UdevEvent *event);
+-DEFINE_TRIVIAL_CLEANUP_FUNC(UdevEvent*, udev_event_free);
++UdevEvent* udev_event_ref(UdevEvent *event);
++UdevEvent* udev_event_unref(UdevEvent *event);
++DEFINE_TRIVIAL_CLEANUP_FUNC(UdevEvent*, udev_event_unref);
+ 
+ int udev_event_execute_rules(UdevEvent *event, UdevRules *rules);
+ 
+diff --git a/src/udev/udev-worker.c b/src/udev/udev-worker.c
+index 0c57551a37..44287e4774 100644
+--- a/src/udev/udev-worker.c
++++ b/src/udev/udev-worker.c
+@@ -171,7 +171,7 @@ static int worker_mark_block_device_read_only(sd_device *dev) {
+ }
+ 
+ static int worker_process_device(UdevWorker *worker, sd_device *dev) {
+-        _cleanup_(udev_event_freep) UdevEvent *udev_event = NULL;
++        _cleanup_(udev_event_unrefp) UdevEvent *udev_event = NULL;
+         _cleanup_close_ int fd_lock = -EBADF;
+         int r;
+ 
+diff --git a/src/udev/udevadm-test-builtin.c b/src/udev/udevadm-test-builtin.c
+index 5815f2cc78..382897efd4 100644
+--- a/src/udev/udevadm-test-builtin.c
++++ b/src/udev/udevadm-test-builtin.c
+@@ -74,7 +74,7 @@ static int parse_argv(int argc, char *argv[]) {
+ }
+ 
+ int builtin_main(int argc, char *argv[], void *userdata) {
+-        _cleanup_(udev_event_freep) UdevEvent *event = NULL;
++        _cleanup_(udev_event_unrefp) UdevEvent *event = NULL;
+         _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
+         UdevBuiltinCommand cmd;
+         int r;
+diff --git a/src/udev/udevadm-test.c b/src/udev/udevadm-test.c
+index 863eab87a5..09d1150dd7 100644
+--- a/src/udev/udevadm-test.c
++++ b/src/udev/udevadm-test.c
+@@ -99,7 +99,7 @@ static int parse_argv(int argc, char *argv[]) {
+ 
+ int test_main(int argc, char *argv[], void *userdata) {
+         _cleanup_(udev_rules_freep) UdevRules *rules = NULL;
+-        _cleanup_(udev_event_freep) UdevEvent *event = NULL;
++        _cleanup_(udev_event_unrefp) UdevEvent *event = NULL;
+         _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
+         sigset_t mask, sigmask_orig;
+         int r;
diff --git a/SOURCES/0315-udev-net-make-Link-object-take-reference-to-UdevEven.patch b/SOURCES/0315-udev-net-make-Link-object-take-reference-to-UdevEven.patch
new file mode 100644
index 0000000000000000000000000000000000000000..6899e284f7b54b76212782bb1f86146a00910990
--- /dev/null
+++ b/SOURCES/0315-udev-net-make-Link-object-take-reference-to-UdevEven.patch
@@ -0,0 +1,447 @@
+From f4fb3eb1a5c51cf8828720c7c4ee7e03e6eb9726 Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Thu, 5 Dec 2024 03:12:42 +0900
+Subject: [PATCH] udev/net: make Link object take reference to UdevEvent
+
+No functional change, just refactoring.
+
+(cherry picked from commit ab70e42999d9587aac025d2d15da3490d401cb1a)
+
+Resolves: RHEL-75774
+---
+ src/udev/net/link-config.c             | 132 ++++++++++---------------
+ src/udev/net/link-config.h             |  20 ++--
+ src/udev/udev-builtin-net_setup_link.c |   6 +-
+ 3 files changed, 66 insertions(+), 92 deletions(-)
+
+diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c
+index 55eeb9de81..7d4e334503 100644
+--- a/src/udev/net/link-config.c
++++ b/src/udev/net/link-config.c
+@@ -376,21 +376,18 @@ Link* link_free(Link *link) {
+         if (!link)
+                 return NULL;
+ 
+-        sd_device_unref(link->device);
+-        sd_device_unref(link->device_db_clone);
++        udev_event_unref(link->event);
+         free(link->kind);
+-        strv_free(link->altnames);
+         return mfree(link);
+ }
+ 
+-int link_new(LinkConfigContext *ctx, sd_netlink **rtnl, sd_device *device, sd_device *device_db_clone, Link **ret) {
++int link_new(LinkConfigContext *ctx, UdevEvent *event, Link **ret) {
++        sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
+         _cleanup_(link_freep) Link *link = NULL;
+         int r;
+ 
+         assert(ctx);
+-        assert(rtnl);
+-        assert(device);
+-        assert(device_db_clone);
++        assert(event);
+         assert(ret);
+ 
+         link = new(Link, 1);
+@@ -398,31 +395,30 @@ int link_new(LinkConfigContext *ctx, sd_netlink **rtnl, sd_device *device, sd_de
+                 return -ENOMEM;
+ 
+         *link = (Link) {
+-                .device = sd_device_ref(device),
+-                .device_db_clone = sd_device_ref(device_db_clone),
++                .event = udev_event_ref(event),
+         };
+ 
+-        r = sd_device_get_sysname(device, &link->ifname);
++        r = sd_device_get_sysname(dev, &link->ifname);
+         if (r < 0)
+                 return r;
+ 
+-        r = sd_device_get_ifindex(device, &link->ifindex);
++        r = sd_device_get_ifindex(dev, &link->ifindex);
+         if (r < 0)
+                 return r;
+ 
+-        r = sd_device_get_action(device, &link->action);
++        r = sd_device_get_action(dev, &link->action);
+         if (r < 0)
+                 return r;
+ 
+-        r = device_unsigned_attribute(device, "name_assign_type", &link->name_assign_type);
++        r = device_unsigned_attribute(dev, "name_assign_type", &link->name_assign_type);
+         if (r < 0)
+                 log_link_debug_errno(link, r, "Failed to get \"name_assign_type\" attribute, ignoring: %m");
+ 
+-        r = device_unsigned_attribute(device, "addr_assign_type", &link->addr_assign_type);
++        r = device_unsigned_attribute(dev, "addr_assign_type", &link->addr_assign_type);
+         if (r < 0)
+                 log_link_debug_errno(link, r, "Failed to get \"addr_assign_type\" attribute, ignoring: %m");
+ 
+-        r = rtnl_get_link_info(rtnl, link->ifindex, &link->iftype, &link->flags,
++        r = rtnl_get_link_info(&event->rtnl, link->ifindex, &link->iftype, &link->flags,
+                                &link->kind, &link->hw_addr, &link->permanent_hw_addr);
+         if (r < 0)
+                 return r;
+@@ -433,7 +429,7 @@ int link_new(LinkConfigContext *ctx, sd_netlink **rtnl, sd_device *device, sd_de
+                         log_link_debug_errno(link, r, "Failed to get permanent hardware address, ignoring: %m");
+         }
+ 
+-        r = sd_device_get_property_value(link->device, "ID_NET_DRIVER", &link->driver);
++        r = sd_device_get_property_value(dev, "ID_NET_DRIVER", &link->driver);
+         if (r < 0 && r != -ENOENT)
+                 log_link_debug_errno(link, r, "Failed to get driver, ignoring: %m");
+ 
+@@ -454,7 +450,7 @@ int link_get_config(LinkConfigContext *ctx, Link *link) {
+         LIST_FOREACH(configs, config, ctx->configs) {
+                 r = net_match_config(
+                                 &config->match,
+-                                link->device,
++                                link->event->dev,
+                                 &link->hw_addr,
+                                 &link->permanent_hw_addr,
+                                 link->driver,
+@@ -483,23 +479,19 @@ int link_get_config(LinkConfigContext *ctx, Link *link) {
+         return -ENOENT;
+ }
+ 
+-static int link_apply_ethtool_settings(Link *link, int *ethtool_fd, EventMode mode) {
+-        LinkConfig *config;
+-        const char *name;
++static int link_apply_ethtool_settings(Link *link, int *ethtool_fd) {
++        LinkConfig *config = ASSERT_PTR(ASSERT_PTR(link)->config);
++        const char *name = ASSERT_PTR(link->ifname);
+         int r;
+ 
+-        assert(link);
+-        assert(link->config);
++        assert(link->event);
+         assert(ethtool_fd);
+ 
+-        if (mode != EVENT_UDEV_WORKER) {
++        if (link->event->event_mode != EVENT_UDEV_WORKER) {
+                 log_link_debug(link, "Running in test mode, skipping application of ethtool settings.");
+                 return 0;
+         }
+ 
+-        config = link->config;
+-        name = link->ifname;
+-
+         r = ethtool_set_glinksettings(ethtool_fd, name,
+                                       config->autonegotiation, config->advertise,
+                                       config->speed, config->duplex, config->port, config->mdi);
+@@ -589,7 +581,8 @@ static int link_generate_new_hw_addr(Link *link, struct hw_addr_data *ret) {
+ 
+         assert(link);
+         assert(link->config);
+-        assert(link->device);
++        assert(link->event);
++        assert(link->event->dev);
+         assert(ret);
+ 
+         if (link->hw_addr.length == 0)
+@@ -655,7 +648,7 @@ static int link_generate_new_hw_addr(Link *link, struct hw_addr_data *ret) {
+         else {
+                 uint64_t result;
+ 
+-                r = net_get_unique_predictable_data(link->device,
++                r = net_get_unique_predictable_data(link->event->dev,
+                                                     naming_scheme_has(NAMING_STABLE_VIRTUAL_MACS),
+                                                     &result);
+                 if (r < 0)
+@@ -689,25 +682,21 @@ finalize:
+         return 0;
+ }
+ 
+-static int link_apply_rtnl_settings(Link *link, sd_netlink **rtnl, EventMode mode) {
++static int link_apply_rtnl_settings(Link *link) {
+         struct hw_addr_data hw_addr = {};
+-        LinkConfig *config;
++        LinkConfig *config = ASSERT_PTR(ASSERT_PTR(link)->config);
+         int r;
+ 
+-        assert(link);
+-        assert(link->config);
+-        assert(rtnl);
++        assert(link->event);
+ 
+-        if (mode != EVENT_UDEV_WORKER) {
++        if (link->event->event_mode != EVENT_UDEV_WORKER) {
+                 log_link_debug(link, "Running in test mode, skipping application of rtnl settings.");
+                 return 0;
+         }
+ 
+-        config = link->config;
+-
+         (void) link_generate_new_hw_addr(link, &hw_addr);
+ 
+-        r = rtnl_set_link_properties(rtnl, link->ifindex, config->alias, &hw_addr,
++        r = rtnl_set_link_properties(&link->event->rtnl, link->ifindex, config->alias, &hw_addr,
+                                      config->txqueues, config->rxqueues, config->txqueuelen,
+                                      config->mtu, config->gso_max_size, config->gso_max_segments);
+         if (r < 0)
+@@ -741,15 +730,8 @@ static bool enable_name_policy(void) {
+ }
+ 
+ static int link_generate_new_name(Link *link) {
+-        LinkConfig *config;
+-        sd_device *device;
+-
+-        assert(link);
+-        assert(link->config);
+-        assert(link->device);
+-
+-        config = link->config;
+-        device = link->device;
++        LinkConfig *config = ASSERT_PTR(ASSERT_PTR(link)->config);;
++        sd_device *device = ASSERT_PTR(ASSERT_PTR(link->event)->dev);
+ 
+         if (link->action != SD_DEVICE_ADD) {
+                 log_link_debug(link, "Not applying Name= and NamePolicy= on '%s' uevent.",
+@@ -822,14 +804,11 @@ no_rename:
+ 
+ static int link_generate_alternative_names(Link *link) {
+         _cleanup_strv_free_ char **altnames = NULL;
+-        LinkConfig *config;
+-        sd_device *device;
++        LinkConfig *config = ASSERT_PTR(ASSERT_PTR(link)->config);
++        sd_device *device = ASSERT_PTR(ASSERT_PTR(link->event)->dev);
+         int r;
+ 
+-        assert(link);
+-        config = ASSERT_PTR(link->config);
+-        device = ASSERT_PTR(link->device);
+-        assert(!link->altnames);
++        assert(!ASSERT_PTR(link->event)->altnames);
+ 
+         if (link->action != SD_DEVICE_ADD) {
+                 log_link_debug(link, "Not applying AlternativeNames= and AlternativeNamesPolicy= on '%s' uevent.",
+@@ -873,7 +852,7 @@ static int link_generate_alternative_names(Link *link) {
+                         }
+                 }
+ 
+-        link->altnames = TAKE_PTR(altnames);
++        link->event->altnames = TAKE_PTR(altnames);
+         return 0;
+ }
+ 
+@@ -906,28 +885,28 @@ static int sr_iov_configure(Link *link, sd_netlink **rtnl, SRIOV *sr_iov) {
+         return 0;
+ }
+ 
+-static int link_apply_sr_iov_config(Link *link, sd_netlink **rtnl, EventMode mode) {
++static int link_apply_sr_iov_config(Link *link) {
+         SRIOV *sr_iov;
+         uint32_t n;
+         int r;
+ 
+         assert(link);
+         assert(link->config);
+-        assert(link->device);
++        assert(ASSERT_PTR(link->event)->dev);
+ 
+-        if (mode != EVENT_UDEV_WORKER) {
++        if (link->event->event_mode != EVENT_UDEV_WORKER) {
+                 log_link_debug(link, "Running in test mode, skipping application of SR-IOV settings.");
+                 return 0;
+         }
+ 
+-        r = sr_iov_set_num_vfs(link->device, link->config->sr_iov_num_vfs, link->config->sr_iov_by_section);
++        r = sr_iov_set_num_vfs(link->event->dev, link->config->sr_iov_num_vfs, link->config->sr_iov_by_section);
+         if (r < 0)
+                 log_link_warning_errno(link, r, "Failed to set the number of SR-IOV virtual functions, ignoring: %m");
+ 
+         if (ordered_hashmap_isempty(link->config->sr_iov_by_section))
+                 return 0;
+ 
+-        r = sr_iov_get_num_vfs(link->device, &n);
++        r = sr_iov_get_num_vfs(link->event->dev, &n);
+         if (r < 0) {
+                 log_link_warning_errno(link, r, "Failed to get the number of SR-IOV virtual functions, ignoring [SR-IOV] sections: %m");
+                 return 0;
+@@ -943,7 +922,7 @@ static int link_apply_sr_iov_config(Link *link, sd_netlink **rtnl, EventMode mod
+                         continue;
+                 }
+ 
+-                r = sr_iov_configure(link, rtnl, sr_iov);
++                r = sr_iov_configure(link, &link->event->rtnl, sr_iov);
+                 if (r < 0)
+                         log_link_warning_errno(link, r,
+                                                "Failed to configure SR-IOV virtual function %"PRIu32", ignoring: %m",
+@@ -953,15 +932,15 @@ static int link_apply_sr_iov_config(Link *link, sd_netlink **rtnl, EventMode mod
+         return 0;
+ }
+ 
+-static int link_apply_rps_cpu_mask(Link *link, EventMode mode) {
++static int link_apply_rps_cpu_mask(Link *link) {
+         _cleanup_free_ char *mask_str = NULL;
+         LinkConfig *config;
+         int r;
+ 
+-        assert(link);
+-        config = ASSERT_PTR(link->config);
++        config = ASSERT_PTR(ASSERT_PTR(link)->config);
++        assert(ASSERT_PTR(link->event)->dev);
+ 
+-        if (mode != EVENT_UDEV_WORKER) {
++        if (link->event->event_mode != EVENT_UDEV_WORKER) {
+                 log_link_debug(link, "Running in test mode, skipping application of RPS setting.");
+                 return 0;
+         }
+@@ -977,7 +956,7 @@ static int link_apply_rps_cpu_mask(Link *link, EventMode mode) {
+         log_link_debug(link, "Applying RPS CPU mask: %s", mask_str);
+ 
+         /* Currently, this will set CPU mask to all rx queue of matched device. */
+-        FOREACH_DEVICE_SYSATTR(link->device, attr) {
++        FOREACH_DEVICE_SYSATTR(link->event->dev, attr) {
+                 const char *c;
+ 
+                 c = path_startswith(attr, "queues/");
+@@ -993,7 +972,7 @@ static int link_apply_rps_cpu_mask(Link *link, EventMode mode) {
+                 if (!path_equal(c, "/rps_cpus"))
+                         continue;
+ 
+-                r = sd_device_set_sysattr_value(link->device, attr, mask_str);
++                r = sd_device_set_sysattr_value(link->event->dev, attr, mask_str);
+                 if (r < 0)
+                         log_link_warning_errno(link, r, "Failed to write %s sysfs attribute, ignoring: %m", attr);
+         }
+@@ -1001,12 +980,9 @@ static int link_apply_rps_cpu_mask(Link *link, EventMode mode) {
+         return 0;
+ }
+ 
+-static int link_apply_udev_properties(Link *link, UdevEvent *event) {
+-        LinkConfig *config;
+-
+-        assert(link);
+-
+-        config = ASSERT_PTR(link->config);
++static int link_apply_udev_properties(Link *link) {
++        LinkConfig *config = ASSERT_PTR(ASSERT_PTR(link)->config);
++        UdevEvent *event = ASSERT_PTR(link->event);
+ 
+         /* 1. apply ImportProperty=. */
+         STRV_FOREACH(p, config->import_properties)
+@@ -1055,19 +1031,17 @@ static int link_apply_udev_properties(Link *link, UdevEvent *event) {
+         return 0;
+ }
+ 
+-int link_apply_config(LinkConfigContext *ctx, sd_netlink **rtnl, Link *link, UdevEvent *event) {
++int link_apply_config(LinkConfigContext *ctx, Link *link) {
+         int r;
+ 
+         assert(ctx);
+-        assert(rtnl);
+         assert(link);
+-        assert(event);
+ 
+-        r = link_apply_ethtool_settings(link, &ctx->ethtool_fd, event->event_mode);
++        r = link_apply_ethtool_settings(link, &ctx->ethtool_fd);
+         if (r < 0)
+                 return r;
+ 
+-        r = link_apply_rtnl_settings(link, rtnl, event->event_mode);
++        r = link_apply_rtnl_settings(link);
+         if (r < 0)
+                 return r;
+ 
+@@ -1079,15 +1053,15 @@ int link_apply_config(LinkConfigContext *ctx, sd_netlink **rtnl, Link *link, Ude
+         if (r < 0)
+                 return r;
+ 
+-        r = link_apply_sr_iov_config(link, rtnl, event->event_mode);
++        r = link_apply_sr_iov_config(link);
+         if (r < 0)
+                 return r;
+ 
+-        r = link_apply_rps_cpu_mask(link, event->event_mode);
++        r = link_apply_rps_cpu_mask(link);
+         if (r < 0)
+                 return r;
+ 
+-        return link_apply_udev_properties(link, event);
++        return link_apply_udev_properties(link);
+ }
+ 
+ int config_parse_udev_property(
+diff --git a/src/udev/net/link-config.h b/src/udev/net/link-config.h
+index a60e183e4b..fd796bbaa5 100644
+--- a/src/udev/net/link-config.h
++++ b/src/udev/net/link-config.h
+@@ -26,16 +26,15 @@ typedef enum MACAddressPolicy {
+ } MACAddressPolicy;
+ 
+ typedef struct Link {
+-        int ifindex;
+-        const char *ifname;
+-        const char *new_name;
+-        char **altnames;
+-
++        UdevEvent *event;
+         LinkConfig *config;
+-        sd_device *device;
+-        sd_device *device_db_clone;
++
++        /* from sd_device */
++        const char *ifname;
++        int ifindex;
+         sd_device_action_t action;
+ 
++        /* from rtnl */
+         char *kind;
+         const char *driver;
+         uint16_t iftype;
+@@ -44,6 +43,9 @@ typedef struct Link {
+         struct hw_addr_data permanent_hw_addr;
+         unsigned name_assign_type;
+         unsigned addr_assign_type;
++
++        /* generated name */
++        const char *new_name;
+ } Link;
+ 
+ struct LinkConfig {
+@@ -102,12 +104,12 @@ int link_load_one(LinkConfigContext *ctx, const char *filename);
+ int link_config_load(LinkConfigContext *ctx);
+ bool link_config_should_reload(LinkConfigContext *ctx);
+ 
+-int link_new(LinkConfigContext *ctx, sd_netlink **rtnl, sd_device *device, sd_device *device_db_clone, Link **ret);
++int link_new(LinkConfigContext *ctx, UdevEvent *event, Link **ret);
+ Link* link_free(Link *link);
+ DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_free);
+ 
+ int link_get_config(LinkConfigContext *ctx, Link *link);
+-int link_apply_config(LinkConfigContext *ctx, sd_netlink **rtnl, Link *link, UdevEvent *event);
++int link_apply_config(LinkConfigContext *ctx, Link *link);
+ 
+ const char* mac_address_policy_to_string(MACAddressPolicy p) _const_;
+ MACAddressPolicy mac_address_policy_from_string(const char *p) _pure_;
+diff --git a/src/udev/udev-builtin-net_setup_link.c b/src/udev/udev-builtin-net_setup_link.c
+index 4500a69c68..572e171e07 100644
+--- a/src/udev/udev-builtin-net_setup_link.c
++++ b/src/udev/udev-builtin-net_setup_link.c
+@@ -41,7 +41,7 @@ static int builtin_net_setup_link(UdevEvent *event, int argc, char **argv) {
+                 return 0;
+         }
+ 
+-        r = link_new(ctx, &event->rtnl, dev, event->dev_db_clone, &link);
++        r = link_new(ctx, event, &link);
+         if (r == -ENODEV) {
+                 log_device_debug_errno(dev, r, "Link vanished while getting information, ignoring.");
+                 return 0;
+@@ -59,14 +59,12 @@ static int builtin_net_setup_link(UdevEvent *event, int argc, char **argv) {
+                 return log_device_error_errno(dev, r, "Failed to get link config: %m");
+         }
+ 
+-        r = link_apply_config(ctx, &event->rtnl, link, event);
++        r = link_apply_config(ctx, link);
+         if (r == -ENODEV)
+                 log_device_debug_errno(dev, r, "Link vanished while applying configuration, ignoring.");
+         else if (r < 0)
+                 log_device_warning_errno(dev, r, "Could not apply link configuration, ignoring: %m");
+ 
+-        event->altnames = TAKE_PTR(link->altnames);
+-
+         return 0;
+ }
+ 
diff --git a/SOURCES/0316-udev-move-parsers-for-config-file-kerenel-command-li.patch b/SOURCES/0316-udev-move-parsers-for-config-file-kerenel-command-li.patch
new file mode 100644
index 0000000000000000000000000000000000000000..a4976a5a65157ffacea0fb05566df095d03ea92e
--- /dev/null
+++ b/SOURCES/0316-udev-move-parsers-for-config-file-kerenel-command-li.patch
@@ -0,0 +1,764 @@
+From ce2b557c15680ec67accc5242d34dc651c2be3e7 Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Wed, 4 Dec 2024 02:33:47 +0900
+Subject: [PATCH] udev: move parsers for config file, kerenel command line, and
+ positional arguments to udev-config.c
+
+No functional change, just refactoring and preparation for later
+commits.
+
+(cherry picked from commit 394a678aec3b8bba0f0b1a8d7b9427c62468fe68)
+
+Resolves: RHEL-75774
+---
+ src/udev/meson.build    |   1 +
+ src/udev/udev-config.c  | 311 ++++++++++++++++++++++++++++++++++++++++
+ src/udev/udev-config.h  |  11 ++
+ src/udev/udev-manager.c |  49 +------
+ src/udev/udev-manager.h |   1 -
+ src/udev/udevd.c        | 250 +-------------------------------
+ 6 files changed, 326 insertions(+), 297 deletions(-)
+ create mode 100644 src/udev/udev-config.c
+ create mode 100644 src/udev/udev-config.h
+
+diff --git a/src/udev/meson.build b/src/udev/meson.build
+index 921dfac39c..d7acbae6bb 100644
+--- a/src/udev/meson.build
++++ b/src/udev/meson.build
+@@ -19,6 +19,7 @@ udevadm_sources = files(
+ 
+ libudevd_core_sources = files(
+         'net/link-config.c',
++        'udev-config.c',
+         'udev-ctrl.c',
+         'udev-event.c',
+         'udev-format.c',
+diff --git a/src/udev/udev-config.c b/src/udev/udev-config.c
+new file mode 100644
+index 0000000000..b774e7676e
+--- /dev/null
++++ b/src/udev/udev-config.c
+@@ -0,0 +1,311 @@
++/* SPDX-License-Identifier: GPL-2.0-or-later */
++
++#include <getopt.h>
++#include <unistd.h>
++
++#include "conf-parser.h"
++#include "cpu-set-util.h"
++#include "limits-util.h"
++#include "parse-util.h"
++#include "pretty-print.h"
++#include "proc-cmdline.h"
++#include "signal-util.h"
++#include "syslog-util.h"
++#include "udev-config.h"
++#include "udev-manager.h"
++#include "udev-rules.h"
++#include "udev-util.h"
++#include "udev-worker.h"
++#include "version.h"
++
++#define WORKER_NUM_MAX UINT64_C(2048)
++
++static bool arg_debug = false;
++bool arg_daemonize = false;
++
++static DEFINE_CONFIG_PARSE_ENUM(config_parse_resolve_name_timing, resolve_name_timing, ResolveNameTiming);
++
++static int manager_parse_udev_config(Manager *manager) {
++        int r, log_val = -1;
++
++        assert(manager);
++
++        const ConfigTableItem config_table[] = {
++                { NULL, "udev_log",       config_parse_log_level,           0, &log_val                      },
++                { NULL, "children_max",   config_parse_unsigned,            0, &manager->children_max        },
++                { NULL, "exec_delay",     config_parse_sec,                 0, &manager->exec_delay_usec     },
++                { NULL, "event_timeout",  config_parse_sec,                 0, &manager->timeout_usec        },
++                { NULL, "resolve_names",  config_parse_resolve_name_timing, 0, &manager->resolve_name_timing },
++                { NULL, "timeout_signal", config_parse_signal,              0, &manager->timeout_signal      },
++                {}
++        };
++
++        r = udev_parse_config_full(config_table);
++        if (r < 0)
++                return r;
++
++        if (log_val >= 0)
++                log_set_max_level(log_val);
++
++        return 0;
++}
++
++/*
++ * read the kernel command line, in case we need to get into debug mode
++ *   udev.log_level=<level>                    syslog priority
++ *   udev.children_max=<number of workers>     events are fully serialized if set to 1
++ *   udev.exec_delay=<number of seconds>       delay execution of every executed program
++ *   udev.event_timeout=<number of seconds>    seconds to wait before terminating an event
++ *   udev.blockdev_read_only<=bool>            mark all block devices read-only when they appear
++ */
++static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
++        Manager *manager = ASSERT_PTR(data);
++        int r;
++
++        assert(key);
++
++        if (proc_cmdline_key_streq(key, "udev.log_level") ||
++            proc_cmdline_key_streq(key, "udev.log_priority")) { /* kept for backward compatibility */
++
++                if (proc_cmdline_value_missing(key, value))
++                        return 0;
++
++                r = log_level_from_string(value);
++                if (r >= 0)
++                        manager->log_level = r;
++
++        } else if (proc_cmdline_key_streq(key, "udev.event_timeout")) {
++
++                if (proc_cmdline_value_missing(key, value))
++                        return 0;
++
++                r = parse_sec(value, &manager->timeout_usec);
++
++        } else if (proc_cmdline_key_streq(key, "udev.children_max")) {
++
++                if (proc_cmdline_value_missing(key, value))
++                        return 0;
++
++                r = safe_atou(value, &manager->children_max);
++
++        } else if (proc_cmdline_key_streq(key, "udev.exec_delay")) {
++
++                if (proc_cmdline_value_missing(key, value))
++                        return 0;
++
++                r = parse_sec(value, &manager->exec_delay_usec);
++
++        } else if (proc_cmdline_key_streq(key, "udev.timeout_signal")) {
++
++                if (proc_cmdline_value_missing(key, value))
++                        return 0;
++
++                r = signal_from_string(value);
++                if (r > 0)
++                        manager->timeout_signal = r;
++
++        } else if (proc_cmdline_key_streq(key, "udev.blockdev_read_only")) {
++
++                if (!value)
++                        manager->blockdev_read_only = true;
++                else {
++                        r = parse_boolean(value);
++                        if (r < 0)
++                                log_warning_errno(r, "Failed to parse udev.blockdev-read-only argument, ignoring: %s", value);
++                        else
++                                manager->blockdev_read_only = r;
++                }
++
++                if (manager->blockdev_read_only)
++                        log_notice("All physical block devices will be marked read-only.");
++
++                return 0;
++
++        } else {
++                if (startswith(key, "udev."))
++                        log_warning("Unknown udev kernel command line option \"%s\", ignoring.", key);
++
++                return 0;
++        }
++
++        if (r < 0)
++                log_warning_errno(r, "Failed to parse \"%s=%s\", ignoring: %m", key, value);
++
++        return 0;
++}
++
++static int help(void) {
++        _cleanup_free_ char *link = NULL;
++        int r;
++
++        r = terminal_urlify_man("systemd-udevd.service", "8", &link);
++        if (r < 0)
++                return log_oom();
++
++        printf("%s [OPTIONS...]\n\n"
++               "Rule-based manager for device events and files.\n\n"
++               "  -h --help                   Print this message\n"
++               "  -V --version                Print version of the program\n"
++               "  -d --daemon                 Detach and run in the background\n"
++               "  -D --debug                  Enable debug output\n"
++               "  -c --children-max=INT       Set maximum number of workers\n"
++               "  -e --exec-delay=SECONDS     Seconds to wait before executing RUN=\n"
++               "  -t --event-timeout=SECONDS  Seconds to wait before terminating an event\n"
++               "  -N --resolve-names=early|late|never\n"
++               "                              When to resolve users and groups\n"
++               "\nSee the %s for details.\n",
++               program_invocation_short_name,
++               link);
++
++        return 0;
++}
++
++static int parse_argv(int argc, char *argv[], Manager *manager) {
++        enum {
++                ARG_TIMEOUT_SIGNAL,
++        };
++
++        static const struct option options[] = {
++                { "daemon",             no_argument,            NULL, 'd'                 },
++                { "debug",              no_argument,            NULL, 'D'                 },
++                { "children-max",       required_argument,      NULL, 'c'                 },
++                { "exec-delay",         required_argument,      NULL, 'e'                 },
++                { "event-timeout",      required_argument,      NULL, 't'                 },
++                { "resolve-names",      required_argument,      NULL, 'N'                 },
++                { "help",               no_argument,            NULL, 'h'                 },
++                { "version",            no_argument,            NULL, 'V'                 },
++                { "timeout-signal",     required_argument,      NULL,  ARG_TIMEOUT_SIGNAL },
++                {}
++        };
++
++        int c, r;
++
++        assert(argc >= 0);
++        assert(argv);
++        assert(manager);
++
++        while ((c = getopt_long(argc, argv, "c:de:Dt:N:hV", options, NULL)) >= 0) {
++                switch (c) {
++
++                case 'd':
++                        arg_daemonize = true;
++                        break;
++                case 'c':
++                        r = safe_atou(optarg, &manager->children_max);
++                        if (r < 0)
++                                log_warning_errno(r, "Failed to parse --children-max= value '%s', ignoring: %m", optarg);
++                        break;
++                case 'e':
++                        r = parse_sec(optarg, &manager->exec_delay_usec);
++                        if (r < 0)
++                                log_warning_errno(r, "Failed to parse --exec-delay= value '%s', ignoring: %m", optarg);
++                        break;
++                case ARG_TIMEOUT_SIGNAL:
++                        r = signal_from_string(optarg);
++                        if (r <= 0)
++                                log_warning_errno(r, "Failed to parse --timeout-signal= value '%s', ignoring: %m", optarg);
++                        else
++                                manager->timeout_signal = r;
++
++                        break;
++                case 't':
++                        r = parse_sec(optarg, &manager->timeout_usec);
++                        if (r < 0)
++                                log_warning_errno(r, "Failed to parse --event-timeout= value '%s', ignoring: %m", optarg);
++                        break;
++                case 'D':
++                        arg_debug = true;
++                        break;
++                case 'N': {
++                        ResolveNameTiming t;
++
++                        t = resolve_name_timing_from_string(optarg);
++                        if (t < 0)
++                                log_warning("Invalid --resolve-names= value '%s', ignoring.", optarg);
++                        else
++                                manager->resolve_name_timing = t;
++                        break;
++                }
++                case 'h':
++                        return help();
++                case 'V':
++                        printf("%s\n", GIT_VERSION);
++                        return 0;
++                case '?':
++                        return -EINVAL;
++                default:
++                        assert_not_reached();
++
++                }
++        }
++
++        return 1;
++}
++
++void manager_set_default_children_max(Manager *manager) {
++        uint64_t cpu_limit, mem_limit, cpu_count = 1;
++        int r;
++
++        assert(manager);
++
++        if (manager->children_max != 0)
++                return;
++
++        r = cpus_in_affinity_mask();
++        if (r < 0)
++                log_warning_errno(r, "Failed to determine number of local CPUs, ignoring: %m");
++        else
++                cpu_count = r;
++
++        cpu_limit = cpu_count * 2 + 16;
++        mem_limit = MAX(physical_memory() / (128*1024*1024), UINT64_C(10));
++
++        manager->children_max = MIN3(cpu_limit, mem_limit, WORKER_NUM_MAX);
++        log_debug("Set children_max to %u", manager->children_max);
++}
++
++static void manager_adjust_config(Manager *manager) {
++        assert(manager);
++
++        if (manager->timeout_usec < MIN_WORKER_TIMEOUT_USEC) {
++                log_debug("Timeout (%s) for processing event is too small, using the default: %s",
++                          FORMAT_TIMESPAN(manager->timeout_usec, 1),
++                          FORMAT_TIMESPAN(DEFAULT_WORKER_TIMEOUT_USEC, 1));
++
++                manager->timeout_usec = DEFAULT_WORKER_TIMEOUT_USEC;
++        }
++
++        if (manager->exec_delay_usec >= manager->timeout_usec) {
++                log_debug("Delay (%s) for executing RUN= commands is too large compared with the timeout (%s) for event execution, ignoring the delay.",
++                          FORMAT_TIMESPAN(manager->exec_delay_usec, 1),
++                          FORMAT_TIMESPAN(manager->timeout_usec, 1));
++
++                manager->exec_delay_usec = 0;
++        }
++
++        manager_set_default_children_max(manager);
++}
++
++int manager_load(Manager *manager, int argc, char *argv[]) {
++        int r;
++
++        assert(manager);
++
++        manager_parse_udev_config(manager);
++
++        r = parse_argv(argc, argv, manager);
++        if (r <= 0)
++                return r;
++
++        r = proc_cmdline_parse(parse_proc_cmdline_item, manager, PROC_CMDLINE_STRIP_RD_PREFIX);
++        if (r < 0)
++                log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
++
++        if (arg_debug) {
++                log_set_target(LOG_TARGET_CONSOLE);
++                log_set_max_level(LOG_DEBUG);
++        }
++
++        manager_adjust_config(manager);
++        return 1;
++}
+diff --git a/src/udev/udev-config.h b/src/udev/udev-config.h
+new file mode 100644
+index 0000000000..9a8a18821f
+--- /dev/null
++++ b/src/udev/udev-config.h
+@@ -0,0 +1,11 @@
++/* SPDX-License-Identifier: GPL-2.0-or-later */
++#pragma once
++
++#include <stdbool.h>
++
++extern bool arg_daemonize;
++
++typedef struct Manager Manager;
++
++int manager_load(Manager *manager, int argc, char *argv[]);
++void manager_set_default_children_max(Manager *manager);
+diff --git a/src/udev/udev-manager.c b/src/udev/udev-manager.c
+index 6e1935a731..23a57dbed3 100644
+--- a/src/udev/udev-manager.c
++++ b/src/udev/udev-manager.c
+@@ -3,7 +3,6 @@
+ #include "blockdev-util.h"
+ #include "cgroup-util.h"
+ #include "common-signal.h"
+-#include "cpu-set-util.h"
+ #include "daemon-util.h"
+ #include "device-monitor-private.h"
+ #include "device-private.h"
+@@ -15,7 +14,6 @@
+ #include "hashmap.h"
+ #include "inotify-util.h"
+ #include "iovec-util.h"
+-#include "limits-util.h"
+ #include "list.h"
+ #include "mkdir.h"
+ #include "process-util.h"
+@@ -25,6 +23,7 @@
+ #include "string-util.h"
+ #include "syslog-util.h"
+ #include "udev-builtin.h"
++#include "udev-config.h"
+ #include "udev-ctrl.h"
+ #include "udev-event.h"
+ #include "udev-manager.h"
+@@ -36,8 +35,6 @@
+ #include "udev-watch.h"
+ #include "udev-worker.h"
+ 
+-#define WORKER_NUM_MAX UINT64_C(2048)
+-
+ #define EVENT_RETRY_INTERVAL_USEC (200 * USEC_PER_MSEC)
+ #define EVENT_RETRY_TIMEOUT_USEC  (3 * USEC_PER_MINUTE)
+ 
+@@ -845,28 +842,6 @@ static int on_worker(sd_event_source *s, int fd, uint32_t revents, void *userdat
+         return 1;
+ }
+ 
+-static void manager_set_default_children_max(Manager *manager) {
+-        uint64_t cpu_limit, mem_limit, cpu_count = 1;
+-        int r;
+-
+-        assert(manager);
+-
+-        if (manager->children_max != 0)
+-                return;
+-
+-        r = cpus_in_affinity_mask();
+-        if (r < 0)
+-                log_warning_errno(r, "Failed to determine number of local CPUs, ignoring: %m");
+-        else
+-                cpu_count = r;
+-
+-        cpu_limit = cpu_count * 2 + 16;
+-        mem_limit = MAX(physical_memory() / (128*1024*1024), UINT64_C(10));
+-
+-        manager->children_max = MIN3(cpu_limit, mem_limit, WORKER_NUM_MAX);
+-        log_debug("Set children_max to %u", manager->children_max);
+-}
+-
+ /* receive the udevd message from userspace */
+ static int on_ctrl_msg(UdevCtrl *uctrl, UdevCtrlMessageType type, const UdevCtrlMessageValue *value, void *userdata) {
+         Manager *manager = ASSERT_PTR(userdata);
+@@ -1208,26 +1183,6 @@ Manager* manager_new(void) {
+         return manager;
+ }
+ 
+-void manager_adjust_arguments(Manager *manager) {
+-        assert(manager);
+-
+-        if (manager->timeout_usec < MIN_WORKER_TIMEOUT_USEC) {
+-                log_debug("Timeout (%s) for processing event is too small, using the default: %s",
+-                          FORMAT_TIMESPAN(manager->timeout_usec, 1),
+-                          FORMAT_TIMESPAN(DEFAULT_WORKER_TIMEOUT_USEC, 1));
+-
+-                manager->timeout_usec = DEFAULT_WORKER_TIMEOUT_USEC;
+-        }
+-
+-        if (manager->exec_delay_usec >= manager->timeout_usec) {
+-                log_debug("Delay (%s) for executing RUN= commands is too large compared with the timeout (%s) for event execution, ignoring the delay.",
+-                          FORMAT_TIMESPAN(manager->exec_delay_usec, 1),
+-                          FORMAT_TIMESPAN(manager->timeout_usec, 1));
+-
+-                manager->exec_delay_usec = 0;
+-        }
+-}
+-
+ static int listen_fds(int *ret_ctrl, int *ret_netlink) {
+         _cleanup_strv_free_ char **names = NULL;
+         _cleanup_close_ int ctrl_fd = -EBADF, netlink_fd = -EBADF;
+@@ -1319,8 +1274,6 @@ int manager_init(Manager *manager) {
+ int manager_main(Manager *manager) {
+         int fd_worker, r;
+ 
+-        manager_set_default_children_max(manager);
+-
+         /* unnamed socket from workers to the main daemon */
+         r = socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, manager->worker_watch);
+         if (r < 0)
+diff --git a/src/udev/udev-manager.h b/src/udev/udev-manager.h
+index 7c20e29594..14b458bcdb 100644
+--- a/src/udev/udev-manager.h
++++ b/src/udev/udev-manager.h
+@@ -53,7 +53,6 @@ Manager* manager_new(void);
+ Manager* manager_free(Manager *manager);
+ DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
+ 
+-void manager_adjust_arguments(Manager *manager);
+ int manager_init(Manager *manager);
+ int manager_main(Manager *manager);
+ 
+diff --git a/src/udev/udevd.c b/src/udev/udevd.c
+index ef1c07a2ca..018a3cd6e7 100644
+--- a/src/udev/udevd.c
++++ b/src/udev/udevd.c
+@@ -5,250 +5,17 @@
+  * Copyright © 2009 Scott James Remnant <scott@netsplit.com>
+  */
+ 
+-#include <getopt.h>
+-#include <unistd.h>
+-
+-#include "conf-parser.h"
+-#include "env-file.h"
+ #include "errno-util.h"
+ #include "fd-util.h"
+ #include "mkdir.h"
+-#include "parse-util.h"
+-#include "pretty-print.h"
+-#include "proc-cmdline.h"
+ #include "process-util.h"
+ #include "rlimit-util.h"
+ #include "selinux-util.h"
+-#include "signal-util.h"
+-#include "syslog-util.h"
++#include "udev-config.h"
+ #include "udev-manager.h"
+-#include "udev-rules.h"
+-#include "udev-util.h"
+ #include "udevd.h"
+ #include "version.h"
+ 
+-static bool arg_debug = false;
+-static int arg_daemonize = false;
+-
+-static DEFINE_CONFIG_PARSE_ENUM(config_parse_resolve_name_timing, resolve_name_timing, ResolveNameTiming);
+-
+-static int manager_parse_udev_config(Manager *manager) {
+-        int r, log_val = -1;
+-
+-        assert(manager);
+-
+-        const ConfigTableItem config_table[] = {
+-                { NULL, "udev_log",       config_parse_log_level,           0, &log_val                      },
+-                { NULL, "children_max",   config_parse_unsigned,            0, &manager->children_max        },
+-                { NULL, "exec_delay",     config_parse_sec,                 0, &manager->exec_delay_usec     },
+-                { NULL, "event_timeout",  config_parse_sec,                 0, &manager->timeout_usec        },
+-                { NULL, "resolve_names",  config_parse_resolve_name_timing, 0, &manager->resolve_name_timing },
+-                { NULL, "timeout_signal", config_parse_signal,              0, &manager->timeout_signal      },
+-                {}
+-        };
+-
+-        r = udev_parse_config_full(config_table);
+-        if (r < 0)
+-                return r;
+-
+-        if (log_val >= 0)
+-                log_set_max_level(log_val);
+-
+-        return 0;
+-}
+-
+-/*
+- * read the kernel command line, in case we need to get into debug mode
+- *   udev.log_level=<level>                    syslog priority
+- *   udev.children_max=<number of workers>     events are fully serialized if set to 1
+- *   udev.exec_delay=<number of seconds>       delay execution of every executed program
+- *   udev.event_timeout=<number of seconds>    seconds to wait before terminating an event
+- *   udev.blockdev_read_only<=bool>            mark all block devices read-only when they appear
+- */
+-static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
+-        Manager *manager = ASSERT_PTR(data);
+-        int r;
+-
+-        assert(key);
+-
+-        if (proc_cmdline_key_streq(key, "udev.log_level") ||
+-            proc_cmdline_key_streq(key, "udev.log_priority")) { /* kept for backward compatibility */
+-
+-                if (proc_cmdline_value_missing(key, value))
+-                        return 0;
+-
+-                r = log_level_from_string(value);
+-                if (r >= 0)
+-                        log_set_max_level(r);
+-
+-        } else if (proc_cmdline_key_streq(key, "udev.event_timeout")) {
+-
+-                if (proc_cmdline_value_missing(key, value))
+-                        return 0;
+-
+-                r = parse_sec(value, &manager->timeout_usec);
+-
+-        } else if (proc_cmdline_key_streq(key, "udev.children_max")) {
+-
+-                if (proc_cmdline_value_missing(key, value))
+-                        return 0;
+-
+-                r = safe_atou(value, &manager->children_max);
+-
+-        } else if (proc_cmdline_key_streq(key, "udev.exec_delay")) {
+-
+-                if (proc_cmdline_value_missing(key, value))
+-                        return 0;
+-
+-                r = parse_sec(value, &manager->exec_delay_usec);
+-
+-        } else if (proc_cmdline_key_streq(key, "udev.timeout_signal")) {
+-
+-                if (proc_cmdline_value_missing(key, value))
+-                        return 0;
+-
+-                r = signal_from_string(value);
+-                if (r > 0)
+-                        manager->timeout_signal = r;
+-
+-        } else if (proc_cmdline_key_streq(key, "udev.blockdev_read_only")) {
+-
+-                if (!value)
+-                        manager->blockdev_read_only = true;
+-                else {
+-                        r = parse_boolean(value);
+-                        if (r < 0)
+-                                log_warning_errno(r, "Failed to parse udev.blockdev-read-only argument, ignoring: %s", value);
+-                        else
+-                                manager->blockdev_read_only = r;
+-                }
+-
+-                if (manager->blockdev_read_only)
+-                        log_notice("All physical block devices will be marked read-only.");
+-
+-                return 0;
+-
+-        } else {
+-                if (startswith(key, "udev."))
+-                        log_warning("Unknown udev kernel command line option \"%s\", ignoring.", key);
+-
+-                return 0;
+-        }
+-
+-        if (r < 0)
+-                log_warning_errno(r, "Failed to parse \"%s=%s\", ignoring: %m", key, value);
+-
+-        return 0;
+-}
+-
+-static int help(void) {
+-        _cleanup_free_ char *link = NULL;
+-        int r;
+-
+-        r = terminal_urlify_man("systemd-udevd.service", "8", &link);
+-        if (r < 0)
+-                return log_oom();
+-
+-        printf("%s [OPTIONS...]\n\n"
+-               "Rule-based manager for device events and files.\n\n"
+-               "  -h --help                   Print this message\n"
+-               "  -V --version                Print version of the program\n"
+-               "  -d --daemon                 Detach and run in the background\n"
+-               "  -D --debug                  Enable debug output\n"
+-               "  -c --children-max=INT       Set maximum number of workers\n"
+-               "  -e --exec-delay=SECONDS     Seconds to wait before executing RUN=\n"
+-               "  -t --event-timeout=SECONDS  Seconds to wait before terminating an event\n"
+-               "  -N --resolve-names=early|late|never\n"
+-               "                              When to resolve users and groups\n"
+-               "\nSee the %s for details.\n",
+-               program_invocation_short_name,
+-               link);
+-
+-        return 0;
+-}
+-
+-static int parse_argv(int argc, char *argv[], Manager *manager) {
+-        enum {
+-                ARG_TIMEOUT_SIGNAL,
+-        };
+-
+-        static const struct option options[] = {
+-                { "daemon",             no_argument,            NULL, 'd'                 },
+-                { "debug",              no_argument,            NULL, 'D'                 },
+-                { "children-max",       required_argument,      NULL, 'c'                 },
+-                { "exec-delay",         required_argument,      NULL, 'e'                 },
+-                { "event-timeout",      required_argument,      NULL, 't'                 },
+-                { "resolve-names",      required_argument,      NULL, 'N'                 },
+-                { "help",               no_argument,            NULL, 'h'                 },
+-                { "version",            no_argument,            NULL, 'V'                 },
+-                { "timeout-signal",     required_argument,      NULL,  ARG_TIMEOUT_SIGNAL },
+-                {}
+-        };
+-
+-        int c, r;
+-
+-        assert(argc >= 0);
+-        assert(argv);
+-        assert(manager);
+-
+-        while ((c = getopt_long(argc, argv, "c:de:Dt:N:hV", options, NULL)) >= 0) {
+-                switch (c) {
+-
+-                case 'd':
+-                        arg_daemonize = true;
+-                        break;
+-                case 'c':
+-                        r = safe_atou(optarg, &manager->children_max);
+-                        if (r < 0)
+-                                log_warning_errno(r, "Failed to parse --children-max= value '%s', ignoring: %m", optarg);
+-                        break;
+-                case 'e':
+-                        r = parse_sec(optarg, &manager->exec_delay_usec);
+-                        if (r < 0)
+-                                log_warning_errno(r, "Failed to parse --exec-delay= value '%s', ignoring: %m", optarg);
+-                        break;
+-                case ARG_TIMEOUT_SIGNAL:
+-                        r = signal_from_string(optarg);
+-                        if (r <= 0)
+-                                log_warning_errno(r, "Failed to parse --timeout-signal= value '%s', ignoring: %m", optarg);
+-                        else
+-                                manager->timeout_signal = r;
+-
+-                        break;
+-                case 't':
+-                        r = parse_sec(optarg, &manager->timeout_usec);
+-                        if (r < 0)
+-                                log_warning_errno(r, "Failed to parse --event-timeout= value '%s', ignoring: %m", optarg);
+-                        break;
+-                case 'D':
+-                        arg_debug = true;
+-                        break;
+-                case 'N': {
+-                        ResolveNameTiming t;
+-
+-                        t = resolve_name_timing_from_string(optarg);
+-                        if (t < 0)
+-                                log_warning("Invalid --resolve-names= value '%s', ignoring.", optarg);
+-                        else
+-                                manager->resolve_name_timing = t;
+-                        break;
+-                }
+-                case 'h':
+-                        return help();
+-                case 'V':
+-                        printf("%s\n", GIT_VERSION);
+-                        return 0;
+-                case '?':
+-                        return -EINVAL;
+-                default:
+-                        assert_not_reached();
+-
+-                }
+-        }
+-
+-        return 1;
+-}
+-
+ int run_udevd(int argc, char *argv[]) {
+         _cleanup_(manager_freep) Manager *manager = NULL;
+         int r;
+@@ -259,23 +26,10 @@ int run_udevd(int argc, char *argv[]) {
+         if (!manager)
+                 return log_oom();
+ 
+-        manager_parse_udev_config(manager);
+-
+-        r = parse_argv(argc, argv, manager);
++        r = manager_load(manager, argc, argv);
+         if (r <= 0)
+                 return r;
+ 
+-        r = proc_cmdline_parse(parse_proc_cmdline_item, manager, PROC_CMDLINE_STRIP_RD_PREFIX);
+-        if (r < 0)
+-                log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
+-
+-        if (arg_debug) {
+-                log_set_target(LOG_TARGET_CONSOLE);
+-                log_set_max_level(LOG_DEBUG);
+-        }
+-
+-        manager_adjust_arguments(manager);
+-
+         r = must_be_root();
+         if (r < 0)
+                 return r;
diff --git a/SOURCES/0317-udev-config-introduce-UdevConfig.patch b/SOURCES/0317-udev-config-introduce-UdevConfig.patch
new file mode 100644
index 0000000000000000000000000000000000000000..b931b8fa235defd46edc1321d0bb5dd335194f5a
--- /dev/null
+++ b/SOURCES/0317-udev-config-introduce-UdevConfig.patch
@@ -0,0 +1,629 @@
+From 623edeade94ef18f503ccac4296629b31bdd7515 Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Wed, 4 Dec 2024 02:26:02 +0900
+Subject: [PATCH] udev-config: introduce UdevConfig
+
+Then, save configurations by their source: udev.conf, command line
+arguments, kernel command line options, and udev control.
+
+Preparation to support reloading udev.conf in a later commit.
+
+(cherry picked from commit 04fa5c1580ad388af3477ecfd7d4aa7d7f5cee30)
+
+Resolves: RHEL-75774
+---
+ src/udev/udev-config.c  | 142 ++++++++++++++++++++++++----------------
+ src/udev/udev-config.h  |  21 +++++-
+ src/udev/udev-event.c   |   2 +-
+ src/udev/udev-manager.c |  40 +++++------
+ src/udev/udev-manager.h |  13 ++--
+ src/udev/udev-spawn.c   |  14 ++--
+ src/udev/udev-worker.c  |   4 +-
+ src/udev/udev-worker.h  |   7 +-
+ 8 files changed, 142 insertions(+), 101 deletions(-)
+
+diff --git a/src/udev/udev-config.c b/src/udev/udev-config.c
+index b774e7676e..eced080547 100644
+--- a/src/udev/udev-config.c
++++ b/src/udev/udev-config.c
+@@ -25,29 +25,20 @@ bool arg_daemonize = false;
+ 
+ static DEFINE_CONFIG_PARSE_ENUM(config_parse_resolve_name_timing, resolve_name_timing, ResolveNameTiming);
+ 
+-static int manager_parse_udev_config(Manager *manager) {
+-        int r, log_val = -1;
+-
+-        assert(manager);
++static void manager_parse_udev_config(UdevConfig *config) {
++        assert(config);
+ 
+         const ConfigTableItem config_table[] = {
+-                { NULL, "udev_log",       config_parse_log_level,           0, &log_val                      },
+-                { NULL, "children_max",   config_parse_unsigned,            0, &manager->children_max        },
+-                { NULL, "exec_delay",     config_parse_sec,                 0, &manager->exec_delay_usec     },
+-                { NULL, "event_timeout",  config_parse_sec,                 0, &manager->timeout_usec        },
+-                { NULL, "resolve_names",  config_parse_resolve_name_timing, 0, &manager->resolve_name_timing },
+-                { NULL, "timeout_signal", config_parse_signal,              0, &manager->timeout_signal      },
++                { NULL, "udev_log",       config_parse_log_level,           0, &config->log_level           },
++                { NULL, "children_max",   config_parse_unsigned,            0, &config->children_max        },
++                { NULL, "exec_delay",     config_parse_sec,                 0, &config->exec_delay_usec     },
++                { NULL, "event_timeout",  config_parse_sec,                 0, &config->timeout_usec        },
++                { NULL, "resolve_names",  config_parse_resolve_name_timing, 0, &config->resolve_name_timing },
++                { NULL, "timeout_signal", config_parse_signal,              0, &config->timeout_signal      },
+                 {}
+         };
+ 
+-        r = udev_parse_config_full(config_table);
+-        if (r < 0)
+-                return r;
+-
+-        if (log_val >= 0)
+-                log_set_max_level(log_val);
+-
+-        return 0;
++        (void) udev_parse_config_full(config_table);
+ }
+ 
+ /*
+@@ -59,7 +50,7 @@ static int manager_parse_udev_config(Manager *manager) {
+  *   udev.blockdev_read_only<=bool>            mark all block devices read-only when they appear
+  */
+ static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
+-        Manager *manager = ASSERT_PTR(data);
++        UdevConfig *config = ASSERT_PTR(data);
+         int r;
+ 
+         assert(key);
+@@ -72,28 +63,28 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
+ 
+                 r = log_level_from_string(value);
+                 if (r >= 0)
+-                        manager->log_level = r;
++                        config->log_level = r;
+ 
+         } else if (proc_cmdline_key_streq(key, "udev.event_timeout")) {
+ 
+                 if (proc_cmdline_value_missing(key, value))
+                         return 0;
+ 
+-                r = parse_sec(value, &manager->timeout_usec);
++                r = parse_sec(value, &config->timeout_usec);
+ 
+         } else if (proc_cmdline_key_streq(key, "udev.children_max")) {
+ 
+                 if (proc_cmdline_value_missing(key, value))
+                         return 0;
+ 
+-                r = safe_atou(value, &manager->children_max);
++                r = safe_atou(value, &config->children_max);
+ 
+         } else if (proc_cmdline_key_streq(key, "udev.exec_delay")) {
+ 
+                 if (proc_cmdline_value_missing(key, value))
+                         return 0;
+ 
+-                r = parse_sec(value, &manager->exec_delay_usec);
++                r = parse_sec(value, &config->exec_delay_usec);
+ 
+         } else if (proc_cmdline_key_streq(key, "udev.timeout_signal")) {
+ 
+@@ -102,21 +93,21 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
+ 
+                 r = signal_from_string(value);
+                 if (r > 0)
+-                        manager->timeout_signal = r;
++                        config->timeout_signal = r;
+ 
+         } else if (proc_cmdline_key_streq(key, "udev.blockdev_read_only")) {
+ 
+                 if (!value)
+-                        manager->blockdev_read_only = true;
++                        config->blockdev_read_only = true;
+                 else {
+                         r = parse_boolean(value);
+                         if (r < 0)
+                                 log_warning_errno(r, "Failed to parse udev.blockdev-read-only argument, ignoring: %s", value);
+                         else
+-                                manager->blockdev_read_only = r;
++                                config->blockdev_read_only = r;
+                 }
+ 
+-                if (manager->blockdev_read_only)
++                if (config->blockdev_read_only)
+                         log_notice("All physical block devices will be marked read-only.");
+ 
+                 return 0;
+@@ -160,7 +151,7 @@ static int help(void) {
+         return 0;
+ }
+ 
+-static int parse_argv(int argc, char *argv[], Manager *manager) {
++static int parse_argv(int argc, char *argv[], UdevConfig *config) {
+         enum {
+                 ARG_TIMEOUT_SIGNAL,
+         };
+@@ -182,7 +173,7 @@ static int parse_argv(int argc, char *argv[], Manager *manager) {
+ 
+         assert(argc >= 0);
+         assert(argv);
+-        assert(manager);
++        assert(config);
+ 
+         while ((c = getopt_long(argc, argv, "c:de:Dt:N:hV", options, NULL)) >= 0) {
+                 switch (c) {
+@@ -191,12 +182,12 @@ static int parse_argv(int argc, char *argv[], Manager *manager) {
+                         arg_daemonize = true;
+                         break;
+                 case 'c':
+-                        r = safe_atou(optarg, &manager->children_max);
++                        r = safe_atou(optarg, &config->children_max);
+                         if (r < 0)
+                                 log_warning_errno(r, "Failed to parse --children-max= value '%s', ignoring: %m", optarg);
+                         break;
+                 case 'e':
+-                        r = parse_sec(optarg, &manager->exec_delay_usec);
++                        r = parse_sec(optarg, &config->exec_delay_usec);
+                         if (r < 0)
+                                 log_warning_errno(r, "Failed to parse --exec-delay= value '%s', ignoring: %m", optarg);
+                         break;
+@@ -205,16 +196,17 @@ static int parse_argv(int argc, char *argv[], Manager *manager) {
+                         if (r <= 0)
+                                 log_warning_errno(r, "Failed to parse --timeout-signal= value '%s', ignoring: %m", optarg);
+                         else
+-                                manager->timeout_signal = r;
++                                config->timeout_signal = r;
+ 
+                         break;
+                 case 't':
+-                        r = parse_sec(optarg, &manager->timeout_usec);
++                        r = parse_sec(optarg, &config->timeout_usec);
+                         if (r < 0)
+                                 log_warning_errno(r, "Failed to parse --event-timeout= value '%s', ignoring: %m", optarg);
+                         break;
+                 case 'D':
+                         arg_debug = true;
++                        config->log_level = LOG_DEBUG;
+                         break;
+                 case 'N': {
+                         ResolveNameTiming t;
+@@ -223,7 +215,7 @@ static int parse_argv(int argc, char *argv[], Manager *manager) {
+                         if (t < 0)
+                                 log_warning("Invalid --resolve-names= value '%s', ignoring.", optarg);
+                         else
+-                                manager->resolve_name_timing = t;
++                                config->resolve_name_timing = t;
+                         break;
+                 }
+                 case 'h':
+@@ -242,13 +234,50 @@ static int parse_argv(int argc, char *argv[], Manager *manager) {
+         return 1;
+ }
+ 
+-void manager_set_default_children_max(Manager *manager) {
++#define MERGE_NON_NEGATIVE(name, default_value)                                              \
++        manager->config.name =                                                               \
++                manager->config_by_control.name >= 0 ? manager->config_by_control.name :     \
++                manager->config_by_kernel.name >= 0 ? manager->config_by_kernel.name :       \
++                manager->config_by_command.name >= 0 ? manager->config_by_command.name :     \
++                manager->config_by_udev_conf.name >= 0 ? manager->config_by_udev_conf.name : \
++                default_value;
++
++#define MERGE_NON_ZERO(name, default_value)                             \
++        manager->config.name =                                          \
++                manager->config_by_control.name ?:                      \
++                manager->config_by_kernel.name ?:                       \
++                manager->config_by_command.name ?:                      \
++                manager->config_by_udev_conf.name ?:                    \
++                default_value;
++
++#define MERGE_BOOL(name) \
++        manager->config.name =                                          \
++                manager->config_by_control.name ||                      \
++                manager->config_by_kernel.name ||                       \
++                manager->config_by_command.name ||                      \
++                manager->config_by_udev_conf.name;
++
++static void manager_merge_config(Manager *manager) {
++        assert(manager);
++
++        /* udev.conf has the lowest priority, then followed by command line arguments, kernel command line
++           options, and values set by udev control. */
++
++        MERGE_NON_NEGATIVE(log_level, log_get_max_level());
++        MERGE_NON_NEGATIVE(resolve_name_timing, RESOLVE_NAME_EARLY);
++        MERGE_NON_ZERO(exec_delay_usec, 0);
++        MERGE_NON_ZERO(timeout_usec, DEFAULT_WORKER_TIMEOUT_USEC);
++        MERGE_NON_ZERO(timeout_signal, SIGKILL);
++        MERGE_BOOL(blockdev_read_only);
++}
++
++void udev_config_set_default_children_max(UdevConfig *config) {
+         uint64_t cpu_limit, mem_limit, cpu_count = 1;
+         int r;
+ 
+-        assert(manager);
++        assert(config);
+ 
+-        if (manager->children_max != 0)
++        if (config->children_max != 0)
+                 return;
+ 
+         r = cpus_in_affinity_mask();
+@@ -260,30 +289,30 @@ void manager_set_default_children_max(Manager *manager) {
+         cpu_limit = cpu_count * 2 + 16;
+         mem_limit = MAX(physical_memory() / (128*1024*1024), UINT64_C(10));
+ 
+-        manager->children_max = MIN3(cpu_limit, mem_limit, WORKER_NUM_MAX);
+-        log_debug("Set children_max to %u", manager->children_max);
++        config->children_max = MIN3(cpu_limit, mem_limit, WORKER_NUM_MAX);
++        log_debug("Set children_max to %u", config->children_max);
+ }
+ 
+-static void manager_adjust_config(Manager *manager) {
+-        assert(manager);
++static void manager_adjust_config(UdevConfig *config) {
++        assert(config);
+ 
+-        if (manager->timeout_usec < MIN_WORKER_TIMEOUT_USEC) {
++        if (config->timeout_usec < MIN_WORKER_TIMEOUT_USEC) {
+                 log_debug("Timeout (%s) for processing event is too small, using the default: %s",
+-                          FORMAT_TIMESPAN(manager->timeout_usec, 1),
++                          FORMAT_TIMESPAN(config->timeout_usec, 1),
+                           FORMAT_TIMESPAN(DEFAULT_WORKER_TIMEOUT_USEC, 1));
+ 
+-                manager->timeout_usec = DEFAULT_WORKER_TIMEOUT_USEC;
++                config->timeout_usec = DEFAULT_WORKER_TIMEOUT_USEC;
+         }
+ 
+-        if (manager->exec_delay_usec >= manager->timeout_usec) {
++        if (config->exec_delay_usec >= config->timeout_usec) {
+                 log_debug("Delay (%s) for executing RUN= commands is too large compared with the timeout (%s) for event execution, ignoring the delay.",
+-                          FORMAT_TIMESPAN(manager->exec_delay_usec, 1),
+-                          FORMAT_TIMESPAN(manager->timeout_usec, 1));
++                          FORMAT_TIMESPAN(config->exec_delay_usec, 1),
++                          FORMAT_TIMESPAN(config->timeout_usec, 1));
+ 
+-                manager->exec_delay_usec = 0;
++                config->exec_delay_usec = 0;
+         }
+ 
+-        manager_set_default_children_max(manager);
++        udev_config_set_default_children_max(config);
+ }
+ 
+ int manager_load(Manager *manager, int argc, char *argv[]) {
+@@ -291,21 +320,22 @@ int manager_load(Manager *manager, int argc, char *argv[]) {
+ 
+         assert(manager);
+ 
+-        manager_parse_udev_config(manager);
++        manager_parse_udev_config(&manager->config_by_udev_conf);
+ 
+-        r = parse_argv(argc, argv, manager);
++        r = parse_argv(argc, argv, &manager->config_by_command);
+         if (r <= 0)
+                 return r;
+ 
+-        r = proc_cmdline_parse(parse_proc_cmdline_item, manager, PROC_CMDLINE_STRIP_RD_PREFIX);
++        r = proc_cmdline_parse(parse_proc_cmdline_item, &manager->config_by_kernel, PROC_CMDLINE_STRIP_RD_PREFIX);
+         if (r < 0)
+                 log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
+ 
+-        if (arg_debug) {
++        manager_merge_config(manager);
++
++        if (arg_debug)
+                 log_set_target(LOG_TARGET_CONSOLE);
+-                log_set_max_level(LOG_DEBUG);
+-        }
+ 
+-        manager_adjust_config(manager);
++        log_set_max_level(manager->config.log_level);
++        manager_adjust_config(&manager->config);
+         return 1;
+ }
+diff --git a/src/udev/udev-config.h b/src/udev/udev-config.h
+index 9a8a18821f..3b0997eeb0 100644
+--- a/src/udev/udev-config.h
++++ b/src/udev/udev-config.h
+@@ -3,9 +3,28 @@
+ 
+ #include <stdbool.h>
+ 
++#include "time-util.h"
++#include "udev-def.h"
++
+ extern bool arg_daemonize;
+ 
+ typedef struct Manager Manager;
+ 
++typedef struct UdevConfig {
++        int log_level;
++        ResolveNameTiming resolve_name_timing;
++        unsigned children_max;
++        usec_t exec_delay_usec;
++        usec_t timeout_usec;
++        int timeout_signal;
++        bool blockdev_read_only;
++} UdevConfig;
++
++#define UDEV_CONFIG_INIT                                             \
++        (UdevConfig) {                                               \
++                .log_level = -1,                                     \
++                .resolve_name_timing = _RESOLVE_NAME_TIMING_INVALID, \
++        }
++
+ int manager_load(Manager *manager, int argc, char *argv[]);
+-void manager_set_default_children_max(Manager *manager);
++void udev_config_set_default_children_max(UdevConfig *c);
+diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
+index 6a7c34b162..e3661f5bf8 100644
+--- a/src/udev/udev-event.c
++++ b/src/udev/udev-event.c
+@@ -19,7 +19,7 @@
+ #include "user-util.h"
+ 
+ UdevEvent* udev_event_new(sd_device *dev, UdevWorker *worker, EventMode mode) {
+-        int log_level = worker ? worker->log_level : log_get_max_level();
++        int log_level = worker ? worker->config.log_level : log_get_max_level();
+         UdevEvent *event;
+ 
+         assert(dev);
+diff --git a/src/udev/udev-manager.c b/src/udev/udev-manager.c
+index 23a57dbed3..7f7079bcd2 100644
+--- a/src/udev/udev-manager.c
++++ b/src/udev/udev-manager.c
+@@ -240,7 +240,7 @@ static void notify_ready(Manager *manager) {
+ 
+         r = sd_notifyf(/* unset= */ false,
+                        "READY=1\n"
+-                       "STATUS=Processing with %u children at max", manager->children_max);
++                       "STATUS=Processing with %u children at max", manager->config.children_max);
+         if (r < 0)
+                 log_warning_errno(r, "Failed to send readiness notification, ignoring: %m");
+ }
+@@ -278,7 +278,7 @@ static void manager_reload(Manager *manager, bool force) {
+                 udev_builtin_exit();
+                 udev_builtin_init();
+ 
+-                r = udev_rules_load(&rules, manager->resolve_name_timing);
++                r = udev_rules_load(&rules, manager->config.resolve_name_timing);
+                 if (r < 0)
+                         log_warning_errno(r, "Failed to read udev rules, using the previously loaded rules, ignoring: %m");
+                 else
+@@ -303,7 +303,7 @@ static int on_event_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
+         assert(event->manager);
+         assert(event->worker);
+ 
+-        kill_and_sigcont(event->worker->pid, event->manager->timeout_signal);
++        kill_and_sigcont(event->worker->pid, event->manager->config.timeout_signal);
+         event->worker->state = WORKER_KILLED;
+ 
+         log_device_error(event->dev, "Worker ["PID_FMT"] processing SEQNUM=%"PRIu64" killed", event->worker->pid, event->seqnum);
+@@ -363,7 +363,7 @@ static void worker_attach_event(Worker *worker, Event *event) {
+         event->worker = worker;
+ 
+         (void) sd_event_add_time_relative(e, &event->timeout_warning_event, CLOCK_MONOTONIC,
+-                                          udev_warn_timeout(manager->timeout_usec), USEC_PER_SEC,
++                                          udev_warn_timeout(manager->config.timeout_usec), USEC_PER_SEC,
+                                           on_event_timeout_warning, event);
+ 
+         /* Manager.timeout_usec is also used as the timeout for running programs specified in
+@@ -371,7 +371,7 @@ static void worker_attach_event(Worker *worker, Event *event) {
+          * kills a worker, to make it possible that the worker detects timed out of spawned programs,
+          * kills them, and finalizes the event. */
+         (void) sd_event_add_time_relative(e, &event->timeout_event, CLOCK_MONOTONIC,
+-                                          usec_add(manager->timeout_usec, extra_timeout_usec()), USEC_PER_SEC,
++                                          usec_add(manager->config.timeout_usec, extra_timeout_usec()), USEC_PER_SEC,
+                                           on_event_timeout, event);
+ }
+ 
+@@ -405,11 +405,7 @@ static int worker_spawn(Manager *manager, Event *event) {
+                         .rules = TAKE_PTR(manager->rules),
+                         .pipe_fd = TAKE_FD(manager->worker_watch[WRITE_END]),
+                         .inotify_fd = TAKE_FD(manager->inotify_fd),
+-                        .exec_delay_usec = manager->exec_delay_usec,
+-                        .timeout_usec = manager->timeout_usec,
+-                        .timeout_signal = manager->timeout_signal,
+-                        .log_level = manager->log_level,
+-                        .blockdev_read_only = manager->blockdev_read_only,
++                        .config = manager->config,
+                 };
+ 
+                 /* Worker process */
+@@ -458,10 +454,10 @@ static int event_run(Event *event) {
+                 return 1; /* event is now processing. */
+         }
+ 
+-        if (hashmap_size(manager->workers) >= manager->children_max) {
++        if (hashmap_size(manager->workers) >= manager->config.children_max) {
+                 /* Avoid spamming the debug logs if the limit is already reached and
+                  * many events still need to be processed */
+-                if (log_children_max_reached && manager->children_max > 1) {
++                if (log_children_max_reached && manager->config.children_max > 1) {
+                         log_debug("Maximum number (%u) of children reached.", hashmap_size(manager->workers));
+                         log_children_max_reached = false;
+                 }
+@@ -863,7 +859,7 @@ static int on_ctrl_msg(UdevCtrl *uctrl, UdevCtrlMessageType type, const UdevCtrl
+                         break;
+ 
+                 log_set_max_level(value->intval);
+-                manager->log_level = value->intval;
++                manager->config.log_level = manager->config_by_control.log_level = value->intval;
+                 manager_kill_workers(manager, false);
+                 break;
+         case UDEV_CTRL_STOP_EXEC_QUEUE:
+@@ -934,10 +930,11 @@ static int on_ctrl_msg(UdevCtrl *uctrl, UdevCtrlMessageType type, const UdevCtrl
+                 }
+ 
+                 log_debug("Received udev control message (SET_MAX_CHILDREN), setting children_max=%i", value->intval);
+-                manager->children_max = value->intval;
++                manager->config_by_control.children_max = value->intval;
+ 
+                 /* When 0 is specified, determine the maximum based on the system resources. */
+-                manager_set_default_children_max(manager);
++                udev_config_set_default_children_max(&manager->config_by_control);
++                manager->config.children_max = manager->config_by_control.children_max;
+ 
+                 notify_ready(manager);
+                 break;
+@@ -1174,10 +1171,11 @@ Manager* manager_new(void) {
+         *manager = (Manager) {
+                 .inotify_fd = -EBADF,
+                 .worker_watch = EBADF_PAIR,
+-                .log_level = LOG_INFO,
+-                .resolve_name_timing = RESOLVE_NAME_EARLY,
+-                .timeout_usec = DEFAULT_WORKER_TIMEOUT_USEC,
+-                .timeout_signal = SIGKILL,
++                .config_by_udev_conf = UDEV_CONFIG_INIT,
++                .config_by_command = UDEV_CONFIG_INIT,
++                .config_by_kernel = UDEV_CONFIG_INIT,
++                .config_by_control = UDEV_CONFIG_INIT,
++                .config = UDEV_CONFIG_INIT,
+         };
+ 
+         return manager;
+@@ -1258,8 +1256,6 @@ int manager_init(Manager *manager) {
+ 
+         (void) sd_device_monitor_set_description(manager->monitor, "manager");
+ 
+-        manager->log_level = log_get_max_level();
+-
+         r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &cgroup);
+         if (r < 0)
+                 log_debug_errno(r, "Failed to get cgroup, ignoring: %m");
+@@ -1365,7 +1361,7 @@ int manager_main(Manager *manager) {
+ 
+         udev_builtin_init();
+ 
+-        r = udev_rules_load(&manager->rules, manager->resolve_name_timing);
++        r = udev_rules_load(&manager->rules, manager->config.resolve_name_timing);
+         if (r < 0)
+                 return log_error_errno(r, "Failed to read udev rules: %m");
+ 
+diff --git a/src/udev/udev-manager.h b/src/udev/udev-manager.h
+index 14b458bcdb..13c7242ea8 100644
+--- a/src/udev/udev-manager.h
++++ b/src/udev/udev-manager.h
+@@ -9,6 +9,7 @@
+ #include "hashmap.h"
+ #include "macro.h"
+ #include "time-util.h"
++#include "udev-config.h"
+ #include "udev-ctrl.h"
+ #include "udev-def.h"
+ 
+@@ -21,7 +22,6 @@ typedef struct Manager {
+         Hashmap *workers;
+         LIST_HEAD(Event, events);
+         char *cgroup;
+-        int log_level;
+ 
+         UdevRules *rules;
+         Hashmap *properties;
+@@ -38,12 +38,11 @@ typedef struct Manager {
+ 
+         usec_t last_usec;
+ 
+-        ResolveNameTiming resolve_name_timing;
+-        unsigned children_max;
+-        usec_t exec_delay_usec;
+-        usec_t timeout_usec;
+-        int timeout_signal;
+-        bool blockdev_read_only;
++        UdevConfig config_by_udev_conf;
++        UdevConfig config_by_command;
++        UdevConfig config_by_kernel;
++        UdevConfig config_by_control;
++        UdevConfig config;
+ 
+         bool stop_exec_queue;
+         bool exit;
+diff --git a/src/udev/udev-spawn.c b/src/udev/udev-spawn.c
+index b95141cf21..2d0f6455a5 100644
+--- a/src/udev/udev-spawn.c
++++ b/src/udev/udev-spawn.c
+@@ -240,8 +240,8 @@ int udev_event_spawn(
+                 return 0;
+         }
+ 
+-        int timeout_signal = event->worker ? event->worker->timeout_signal : SIGKILL;
+-        usec_t timeout_usec = event->worker ? event->worker->timeout_usec : DEFAULT_WORKER_TIMEOUT_USEC;
++        int timeout_signal = event->worker ? event->worker->config.timeout_signal : SIGKILL;
++        usec_t timeout_usec = event->worker ? event->worker->config.timeout_usec : DEFAULT_WORKER_TIMEOUT_USEC;
+         usec_t now_usec = now(CLOCK_MONOTONIC);
+         usec_t age_usec = usec_sub_unsigned(now_usec, event->birth_usec);
+         usec_t cmd_timeout_usec = usec_sub_unsigned(timeout_usec, age_usec);
+@@ -349,20 +349,20 @@ void udev_event_execute_run(UdevEvent *event) {
+                         if (r < 0)
+                                 log_device_debug_errno(event->dev, r, "Failed to run built-in command \"%s\", ignoring: %m", command);
+                 } else {
+-                        if (event->worker && event->worker->exec_delay_usec > 0) {
++                        if (event->worker && event->worker->config.exec_delay_usec > 0) {
+                                 usec_t now_usec = now(CLOCK_MONOTONIC);
+                                 usec_t age_usec = usec_sub_unsigned(now_usec, event->birth_usec);
+ 
+-                                if (event->worker->exec_delay_usec >= usec_sub_unsigned(event->worker->timeout_usec, age_usec)) {
++                                if (event->worker->config.exec_delay_usec >= usec_sub_unsigned(event->worker->config.timeout_usec, age_usec)) {
+                                         log_device_warning(event->dev,
+                                                            "Cannot delay execution of \"%s\" for %s, skipping.",
+-                                                           command, FORMAT_TIMESPAN(event->worker->exec_delay_usec, USEC_PER_SEC));
++                                                           command, FORMAT_TIMESPAN(event->worker->config.exec_delay_usec, USEC_PER_SEC));
+                                         continue;
+                                 }
+ 
+                                 log_device_debug(event->dev, "Delaying execution of \"%s\" for %s.",
+-                                                 command, FORMAT_TIMESPAN(event->worker->exec_delay_usec, USEC_PER_SEC));
+-                                (void) usleep_safe(event->worker->exec_delay_usec);
++                                                 command, FORMAT_TIMESPAN(event->worker->config.exec_delay_usec, USEC_PER_SEC));
++                                (void) usleep_safe(event->worker->config.exec_delay_usec);
+                         }
+ 
+                         log_device_debug(event->dev, "Running command \"%s\"", command);
+diff --git a/src/udev/udev-worker.c b/src/udev/udev-worker.c
+index 44287e4774..fc9072e5fd 100644
+--- a/src/udev/udev-worker.c
++++ b/src/udev/udev-worker.c
+@@ -195,7 +195,7 @@ static int worker_process_device(UdevWorker *worker, sd_device *dev) {
+         if (r < 0)
+                 return r;
+ 
+-        if (worker->blockdev_read_only)
++        if (worker->config.blockdev_read_only)
+                 (void) worker_mark_block_device_read_only(dev);
+ 
+         /* Disable watch during event processing. */
+@@ -322,7 +322,7 @@ static int worker_device_monitor_handler(sd_device_monitor *monitor, sd_device *
+                 log_device_warning_errno(dev, r, "Failed to send signal to main daemon, ignoring: %m");
+ 
+         /* Reset the log level, as it might be changed by "OPTIONS=log_level=". */
+-        log_set_max_level(worker->log_level);
++        log_set_max_level(worker->config.log_level);
+ 
+         return 1;
+ }
+diff --git a/src/udev/udev-worker.h b/src/udev/udev-worker.h
+index e9aefc5b04..d9dd88d472 100644
+--- a/src/udev/udev-worker.h
++++ b/src/udev/udev-worker.h
+@@ -10,6 +10,7 @@
+ #include "errno-list.h"
+ #include "hashmap.h"
+ #include "time-util.h"
++#include "udev-config.h"
+ 
+ #define DEFAULT_WORKER_TIMEOUT_USEC (3 * USEC_PER_MINUTE)
+ #define MIN_WORKER_TIMEOUT_USEC     (1 * USEC_PER_MSEC)
+@@ -27,11 +28,7 @@ typedef struct UdevWorker {
+         int pipe_fd;
+         int inotify_fd; /* Do not close! */
+ 
+-        usec_t exec_delay_usec;
+-        usec_t timeout_usec;
+-        int timeout_signal;
+-        int log_level;
+-        bool blockdev_read_only;
++        UdevConfig config;
+ } UdevWorker;
+ 
+ /* passed from worker to main process */
diff --git a/SOURCES/0318-udev-reload-.rules-files-and-builtins-only-when-nece.patch b/SOURCES/0318-udev-reload-.rules-files-and-builtins-only-when-nece.patch
new file mode 100644
index 0000000000000000000000000000000000000000..31effe3fa97ab251c286888f29a7fd092f6dd27c
--- /dev/null
+++ b/SOURCES/0318-udev-reload-.rules-files-and-builtins-only-when-nece.patch
@@ -0,0 +1,136 @@
+From 8224a238bb1ddd9328ba6d0c5aabb972dd49a06c Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Wed, 4 Dec 2024 04:31:31 +0900
+Subject: [PATCH] udev: reload .rules files and builtins only when necessary
+
+Previously, even if e.g. .rules files are unchanged, all .rules files
+are reloaded when other kind of config files like .link files or
+.hwdb.bin are changed, vice versa.
+
+(cherry picked from commit 0f72af536f957b5755551de5f1815baef8f377b7)
+
+Resolves: RHEL-75774
+---
+ src/udev/udev-builtin.c | 23 ++++++++++++++++++++---
+ src/udev/udev-builtin.h |  3 ++-
+ src/udev/udev-def.h     | 23 +++++++++++++++++++++++
+ src/udev/udev-manager.c | 15 +++++++++------
+ 4 files changed, 54 insertions(+), 10 deletions(-)
+
+diff --git a/src/udev/udev-builtin.c b/src/udev/udev-builtin.c
+index 2118c2f3df..3d22ddf945 100644
+--- a/src/udev/udev-builtin.c
++++ b/src/udev/udev-builtin.c
+@@ -54,11 +54,28 @@ void udev_builtin_exit(void) {
+         initialized = false;
+ }
+ 
+-bool udev_builtin_should_reload(void) {
++UdevReloadFlags udev_builtin_should_reload(void) {
++        UdevReloadFlags flags = 0;
++
+         for (UdevBuiltinCommand i = 0; i < _UDEV_BUILTIN_MAX; i++)
+                 if (builtins[i] && builtins[i]->should_reload && builtins[i]->should_reload())
+-                        return true;
+-        return false;
++                        flags |= 1u << i;
++
++        if (flags != 0)
++                flags |= UDEV_RELOAD_KILL_WORKERS;
++
++        return flags;
++}
++
++void udev_builtin_reload(UdevReloadFlags flags) {
++        for (UdevBuiltinCommand i = 0; i < _UDEV_BUILTIN_MAX; i++) {
++                if (!FLAGS_SET(flags, 1u << i) || !builtins[i])
++                        continue;
++                if (builtins[i]->exit)
++                        builtins[i]->exit();
++                if (builtins[i]->init)
++                        builtins[i]->init();
++        }
+ }
+ 
+ void udev_builtin_list(void) {
+diff --git a/src/udev/udev-builtin.h b/src/udev/udev-builtin.h
+index 8c2016e5f0..3b5f3bd120 100644
+--- a/src/udev/udev-builtin.h
++++ b/src/udev/udev-builtin.h
+@@ -59,7 +59,8 @@ const char* udev_builtin_name(UdevBuiltinCommand cmd);
+ bool udev_builtin_run_once(UdevBuiltinCommand cmd);
+ int udev_builtin_run(UdevEvent *event, UdevBuiltinCommand cmd, const char *command);
+ void udev_builtin_list(void);
+-bool udev_builtin_should_reload(void);
++UdevReloadFlags udev_builtin_should_reload(void);
++void udev_builtin_reload(UdevReloadFlags flags);
+ int udev_builtin_add_property(UdevEvent *event, const char *key, const char *val);
+ int udev_builtin_add_propertyf(UdevEvent *event, const char *key, const char *valf, ...) _printf_(3, 4);
+ int udev_builtin_import_property(UdevEvent *event, const char *key);
+diff --git a/src/udev/udev-def.h b/src/udev/udev-def.h
+index 6ff3feacec..9d9fc78247 100644
+--- a/src/udev/udev-def.h
++++ b/src/udev/udev-def.h
+@@ -55,3 +55,26 @@ typedef enum UdevBuiltinCommand {
+         _UDEV_BUILTIN_MAX,
+         _UDEV_BUILTIN_INVALID = -EINVAL,
+ } UdevBuiltinCommand;
++
++typedef enum UdevReloadFlags {
++#if HAVE_BLKID
++        UDEV_RELOAD_BUILTIN_BLKID    = 1u << UDEV_BUILTIN_BLKID,
++#endif
++        UDEV_RELOAD_BUILTIN_BTRFS    = 1u << UDEV_BUILTIN_BTRFS,
++        UDEV_RELOAD_BUILTIN_HWDB     = 1u << UDEV_BUILTIN_HWDB,
++        UDEV_RELOAD_BUILTIN_INPUT_ID = 1u << UDEV_BUILTIN_INPUT_ID,
++        UDEV_RELOAD_BUILTIN_KEYBOARD = 1u << UDEV_BUILTIN_KEYBOARD,
++#if HAVE_KMOD
++        UDEV_RELOAD_BUILTIN_KMOD     = 1u << UDEV_BUILTIN_KMOD,
++#endif
++        UDEV_RELOAD_BUILTIN_DRIVER   = 1u << UDEV_BUILTIN_NET_DRIVER,
++        UDEV_RELOAD_BUILTIN_NET_ID   = 1u << UDEV_BUILTIN_NET_ID,
++        UDEV_RELOAD_BUILTIN_NET_LINK = 1u << UDEV_BUILTIN_NET_LINK,
++        UDEV_RELOAD_BUILTIN_PATH_ID  = 1u << UDEV_BUILTIN_PATH_ID,
++        UDEV_RELOAD_BUILTIN_USB_ID   = 1u << UDEV_BUILTIN_USB_ID,
++#if HAVE_ACL
++        UDEV_RELOAD_BUILTIN_UACCESS  = 1u << UDEV_BUILTIN_UACCESS,
++#endif
++        UDEV_RELOAD_KILL_WORKERS     = 1u << (_UDEV_BUILTIN_MAX + 0),
++        UDEV_RELOAD_RULES            = 1u << (_UDEV_BUILTIN_MAX + 1),
++} UdevReloadFlags;
+diff --git a/src/udev/udev-manager.c b/src/udev/udev-manager.c
+index 7f7079bcd2..c691b8ebed 100644
+--- a/src/udev/udev-manager.c
++++ b/src/udev/udev-manager.c
+@@ -262,22 +262,25 @@ static void manager_reload(Manager *manager, bool force) {
+         /* Reload SELinux label database, to make the child inherit the up-to-date database. */
+         mac_selinux_maybe_reload();
+ 
+-        /* Nothing changed. It is not necessary to reload. */
+-        if (!udev_rules_should_reload(manager->rules) && !udev_builtin_should_reload()) {
+-
++        UdevReloadFlags flags = udev_builtin_should_reload();
++        if (udev_rules_should_reload(manager->rules))
++                flags |= UDEV_RELOAD_RULES | UDEV_RELOAD_KILL_WORKERS;
++        if (flags == 0) {
++                /* Nothing changed. It is not necessary to reload. */
+                 if (!force)
+                         return;
+ 
+                 /* If we eat this up, then tell our service manager to just continue */
+                 (void) notify_reloading_full("Skipping configuration reloading, nothing changed.");
+-        } else {
++        } else
+                 (void) notify_reloading();
+ 
++        if (FLAGS_SET(flags, UDEV_RELOAD_KILL_WORKERS))
+                 manager_kill_workers(manager, false);
+ 
+-                udev_builtin_exit();
+-                udev_builtin_init();
++        udev_builtin_reload(flags);
+ 
++        if (FLAGS_SET(flags, UDEV_RELOAD_RULES)) {
+                 r = udev_rules_load(&rules, manager->config.resolve_name_timing);
+                 if (r < 0)
+                         log_warning_errno(r, "Failed to read udev rules, using the previously loaded rules, ignoring: %m");
diff --git a/SOURCES/0319-udev-also-reload-udev.conf-when-explicitly-requested.patch b/SOURCES/0319-udev-also-reload-udev.conf-when-explicitly-requested.patch
new file mode 100644
index 0000000000000000000000000000000000000000..946f84e2ff908b4eb72e53e91e899adf4169094d
--- /dev/null
+++ b/SOURCES/0319-udev-also-reload-udev.conf-when-explicitly-requested.patch
@@ -0,0 +1,87 @@
+From 1ac71b3069f39c3b1e681eab90419ef500659cbe Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Wed, 4 Dec 2024 04:29:13 +0900
+Subject: [PATCH] udev: also reload udev.conf when explicitly requested
+
+When reloading is explicitly requested, e.g. by 'udevadm control --reload',
+then also reload udev.conf.
+
+(cherry picked from commit e95861d909e17d56eddc20331a62f67f0d37d950)
+
+Resolves: RHEL-75774
+---
+ src/udev/udev-config.c  | 24 ++++++++++++++++++++++++
+ src/udev/udev-config.h  |  1 +
+ src/udev/udev-manager.c | 16 ++++++++--------
+ 3 files changed, 33 insertions(+), 8 deletions(-)
+
+diff --git a/src/udev/udev-config.c b/src/udev/udev-config.c
+index eced080547..891cf92535 100644
+--- a/src/udev/udev-config.c
++++ b/src/udev/udev-config.c
+@@ -339,3 +339,27 @@ int manager_load(Manager *manager, int argc, char *argv[]) {
+         manager_adjust_config(&manager->config);
+         return 1;
+ }
++
++UdevReloadFlags manager_reload_config(Manager *manager) {
++        assert(manager);
++
++        UdevConfig old = manager->config;
++
++        manager->config_by_udev_conf = UDEV_CONFIG_INIT;
++        manager_parse_udev_config(&manager->config_by_udev_conf);
++        manager_merge_config(manager);
++        log_set_max_level(manager->config.log_level);
++        manager_adjust_config(&manager->config);
++
++        if (manager->config.resolve_name_timing != old.resolve_name_timing)
++                return UDEV_RELOAD_RULES | UDEV_RELOAD_KILL_WORKERS;
++
++        if (manager->config.log_level != old.log_level ||
++            manager->config.exec_delay_usec != old.exec_delay_usec ||
++            manager->config.timeout_usec != old.timeout_usec ||
++            manager->config.timeout_signal != old.timeout_signal ||
++            manager->config.blockdev_read_only != old.blockdev_read_only)
++                return UDEV_RELOAD_KILL_WORKERS;
++
++        return 0;
++}
+diff --git a/src/udev/udev-config.h b/src/udev/udev-config.h
+index 3b0997eeb0..1c7a74b106 100644
+--- a/src/udev/udev-config.h
++++ b/src/udev/udev-config.h
+@@ -27,4 +27,5 @@ typedef struct UdevConfig {
+         }
+ 
+ int manager_load(Manager *manager, int argc, char *argv[]);
++UdevReloadFlags manager_reload_config(Manager *manager);
+ void udev_config_set_default_children_max(UdevConfig *c);
+diff --git a/src/udev/udev-manager.c b/src/udev/udev-manager.c
+index c691b8ebed..4fc316e106 100644
+--- a/src/udev/udev-manager.c
++++ b/src/udev/udev-manager.c
+@@ -265,15 +265,15 @@ static void manager_reload(Manager *manager, bool force) {
+         UdevReloadFlags flags = udev_builtin_should_reload();
+         if (udev_rules_should_reload(manager->rules))
+                 flags |= UDEV_RELOAD_RULES | UDEV_RELOAD_KILL_WORKERS;
+-        if (flags == 0) {
+-                /* Nothing changed. It is not necessary to reload. */
+-                if (!force)
+-                        return;
++        if (flags == 0 && !force)
++                /* Neither .rules files nor config files for builtins e.g. .link files changed. It is not
++                 * necessary to reload configs. Note, udev.conf is not checked in the above, hence reloaded
++                 * when explicitly requested or at least one .rules file or friend is updated. */
++                return;
+ 
+-                /* If we eat this up, then tell our service manager to just continue */
+-                (void) notify_reloading_full("Skipping configuration reloading, nothing changed.");
+-        } else
+-                (void) notify_reloading();
++        (void) notify_reloading();
++
++        flags |= manager_reload_config(manager);
+ 
+         if (FLAGS_SET(flags, UDEV_RELOAD_KILL_WORKERS))
+                 manager_kill_workers(manager, false);
diff --git a/SOURCES/0320-TEST-17-use-udevadm-control-reload-or-systemctl-relo.patch b/SOURCES/0320-TEST-17-use-udevadm-control-reload-or-systemctl-relo.patch
new file mode 100644
index 0000000000000000000000000000000000000000..34e429e9d6f203cf6393ab4a7a8f1eb94992503a
--- /dev/null
+++ b/SOURCES/0320-TEST-17-use-udevadm-control-reload-or-systemctl-relo.patch
@@ -0,0 +1,61 @@
+From 37735cbe018e1596c74ccca47acb4c1a96e82fc6 Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Wed, 4 Dec 2024 06:34:43 +0900
+Subject: [PATCH] TEST-17: use 'udevadm control --reload' or 'systemctl reload
+ systemd-udevd.service' for reloading udev.conf
+
+These should be equivalent. For coverage, one subtest uses systemctl and
+another uses udevadm.
+
+(cherry picked from commit ced0ef3b35faadc5c8c07f6dd24f69bd836d8399)
+
+Resolves: RHEL-75774
+---
+ test/units/TEST-17-UDEV.03.sh                   | 4 ++--
+ test/units/TEST-17-UDEV.device_is_processing.sh | 4 ++--
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/test/units/TEST-17-UDEV.03.sh b/test/units/TEST-17-UDEV.03.sh
+index d6b3162258..56ecf49e3b 100755
+--- a/test/units/TEST-17-UDEV.03.sh
++++ b/test/units/TEST-17-UDEV.03.sh
+@@ -27,7 +27,7 @@ event_timeout=10
+ timeout_signal=SIGABRT
+ EOF
+ 
+-    systemctl restart systemd-udevd.service
++    systemctl reload systemd-udevd.service
+ }
+ 
+ # shellcheck disable=SC2317
+@@ -40,7 +40,7 @@ teardown() {
+ 
+     rm -rf "$TMPDIR"
+     rm -f "$TEST_RULE" "$TEST_CONF"
+-    systemctl restart systemd-udevd.service
++    systemctl reload systemd-udevd.service
+ }
+ 
+ run_test_timeout() {
+diff --git a/test/units/TEST-17-UDEV.device_is_processing.sh b/test/units/TEST-17-UDEV.device_is_processing.sh
+index 88e4b5a6bd..d3b48e780e 100755
+--- a/test/units/TEST-17-UDEV.device_is_processing.sh
++++ b/test/units/TEST-17-UDEV.device_is_processing.sh
+@@ -18,7 +18,7 @@ at_exit() {
+     # Forcibly kills sleep command invoked by the udev rule before restarting,
+     # otherwise systemctl restart below will takes longer.
+     killall -KILL sleep
+-    systemctl restart systemd-udevd.service
++    udevadm control --reload
+     ip link del "$IFNAME"
+ }
+ 
+@@ -36,7 +36,7 @@ cat >/run/udev/rules.d/99-testsuite.rules <<EOF
+ SUBSYSTEM=="net", ACTION=="change", KERNEL=="${IFNAME}", OPTIONS="log_level=debug", RUN+="/usr/bin/sleep 1000"
+ EOF
+ 
+-systemctl restart systemd-udevd.service
++udevadm control --reload
+ 
+ ip link add "$IFNAME" type dummy
+ IFINDEX=$(ip -json link show "$IFNAME" | jq '.[].ifindex')
diff --git a/SOURCES/0321-udevd-add-missing-header-for-glibc-2.34.patch b/SOURCES/0321-udevd-add-missing-header-for-glibc-2.34.patch
new file mode 100644
index 0000000000000000000000000000000000000000..89331976dc7b2b52caae815bffe34ab288638fb0
--- /dev/null
+++ b/SOURCES/0321-udevd-add-missing-header-for-glibc-2.34.patch
@@ -0,0 +1,45 @@
+From 858ec72ef75569f4febb7ea95d433a9414faff0b Mon Sep 17 00:00:00 2001
+From: Antonio Alvarez Feijoo <antonio.feijoo@suse.com>
+Date: Thu, 26 Dec 2024 11:02:55 +0100
+Subject: [PATCH] udevd: add missing header for glibc < 2.34
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+```
+[77/1697] Compiling C object udevadm.p/src_udev_udevd.c.o
+FAILED: udevadm.p/src_udev_udevd.c.o
+cc -Iudevadm.p -I. -I.. -Isrc/basic -I../src/basic -Isrc/fundamental -I../src/fundamental -Isrc/systemd -I../src/systemd -I../src/libsystemd/sd-bus -I../src/libsystemd/sd-device -I../src/libsystemd/sd-event -I../src/libsystemd/sd-hwdb -I../src/libsystemd/sd-id128 -I../src/libsystemd/sd-journal -I../src/libsystemd/sd-json -I../src/libsystemd/sd-netlink -I../src/libsystemd/sd-network -I../src/libsystemd/sd-path -I../src/libsystemd/sd-resolve -I../src/libsystemd/sd-varlink -Isrc/shared -I../src/shared -I/usr/include/blkid -I/usr/include/kmod -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wextra -std=gnu11 -O0 -g -Wno-missing-field-initializers -Wno-unused-parameter -Wno-nonnull-compare -Warray-bounds -Warray-bounds=2 -Wdate-time -Wendif-labels -Werror=format=2 -Werror=format-signedness -Werror=implicit-function-declaration -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -Werror=missing-declarations -Werror=missing-prototypes -Werror=overflow -Werror=override-init -Werror=return-type -Werror=shift-count-overflow -Werror=shift-overflow=2 -Werror=undef -Wfloat-equal -Wimplicit-fallthrough=5 -Winit-self -Wlogical-op -Wmissing-include-dirs -Wmissing-noreturn -Wnested-externs -Wold-style-definition -Wpointer-arith -Wredundant-decls -Wshadow -Wstrict-aliasing=2 -Wstrict-prototypes -Wsuggest-attribute=noreturn -Wunused-function -Wwrite-strings -Wzero-length-bounds -fdiagnostics-show-option -fno-common -fstack-protector -fstack-protector-strong --param=ssp-buffer-size=4 -Wno-unused-result -Werror=shadow -fno-strict-aliasing -fvisibility=hidden -fno-omit-frame-pointer -include config.h -pthread -MD -MQ udevadm.p/src_udev_udevd.c.o -MF udevadm.p/src_udev_udevd.c.o.d -o udevadm.p/src_udev_udevd.c.o -c ../src/udev/udevd.c
+../src/udev/udevd.c: In function ‘run_udevd’:
+../src/udev/udevd.c:67:23: error: implicit declaration of function ‘fork’ [-Werror=implicit-function-declaration]
+   67 |                 pid = fork();
+      |                       ^~~~
+../src/udev/udevd.c:75:24: error: implicit declaration of function ‘setsid’; did you mean ‘setbit’? [-Werror=implicit-function-declaration]
+   75 |                 (void) setsid();
+      |                        ^~~~~~
+      |                        setbit
+../src/udev/udevd.c:75:24: warning: nested extern declaration of ‘setsid’ [-Wnested-externs]
+```
+
+Follow-up for 394a678aec3b8bba0f0b1a8d7b9427c62468fe68
+
+(cherry picked from commit 7cb72bdaeba6069eca99a4292b26dc5eb81bb67a)
+
+Resolves: RHEL-75774
+---
+ src/udev/udevd.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/src/udev/udevd.c b/src/udev/udevd.c
+index 018a3cd6e7..8f0e5cc0d6 100644
+--- a/src/udev/udevd.c
++++ b/src/udev/udevd.c
+@@ -5,6 +5,8 @@
+  * Copyright © 2009 Scott James Remnant <scott@netsplit.com>
+  */
+ 
++#include <unistd.h>
++
+ #include "errno-util.h"
+ #include "fd-util.h"
+ #include "mkdir.h"
diff --git a/SOURCES/0322-meson-sort-source-files.patch b/SOURCES/0322-meson-sort-source-files.patch
new file mode 100644
index 0000000000000000000000000000000000000000..99c76e9bcfb16d7096298c4f87b5c72682432d4d
--- /dev/null
+++ b/SOURCES/0322-meson-sort-source-files.patch
@@ -0,0 +1,50 @@
+From b2c1e85214ee2d0d483ff54b0afade9738327c0d Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Sun, 22 Dec 2024 01:36:54 +0900
+Subject: [PATCH] meson: sort source files
+
+(cherry picked from commit 8567f1342bbaaacfc08e18513c943b3586ea4a6e)
+
+Resolves: RHEL-75774
+---
+ src/udev/meson.build | 20 ++++++++++----------
+ 1 file changed, 10 insertions(+), 10 deletions(-)
+
+diff --git a/src/udev/meson.build b/src/udev/meson.build
+index d7acbae6bb..54e12a45e4 100644
+--- a/src/udev/meson.build
++++ b/src/udev/meson.build
+@@ -19,16 +19,6 @@ udevadm_sources = files(
+ 
+ libudevd_core_sources = files(
+         'net/link-config.c',
+-        'udev-config.c',
+-        'udev-ctrl.c',
+-        'udev-event.c',
+-        'udev-format.c',
+-        'udev-manager.c',
+-        'udev-node.c',
+-        'udev-rules.c',
+-        'udev-spawn.c',
+-        'udev-watch.c',
+-        'udev-worker.c',
+         'udev-builtin-btrfs.c',
+         'udev-builtin-hwdb.c',
+         'udev-builtin-input_id.c',
+@@ -39,6 +29,16 @@ libudevd_core_sources = files(
+         'udev-builtin-path_id.c',
+         'udev-builtin-usb_id.c',
+         'udev-builtin.c',
++        'udev-config.c',
++        'udev-ctrl.c',
++        'udev-event.c',
++        'udev-format.c',
++        'udev-manager.c',
++        'udev-node.c',
++        'udev-rules.c',
++        'udev-spawn.c',
++        'udev-watch.c',
++        'udev-worker.c',
+ )
+ 
+ if conf.get('HAVE_KMOD') == 1
diff --git a/SOURCES/0323-sd-json-introduce-json_dispatch_log_level.patch b/SOURCES/0323-sd-json-introduce-json_dispatch_log_level.patch
new file mode 100644
index 0000000000000000000000000000000000000000..c1df18eb86e8e09f7a4e7a379688461bee8db8bb
--- /dev/null
+++ b/SOURCES/0323-sd-json-introduce-json_dispatch_log_level.patch
@@ -0,0 +1,107 @@
+From 4c3468fa6ab0a993f4bc15b503061bbbeedd19e7 Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Sat, 4 Jan 2025 13:57:30 +0900
+Subject: [PATCH] sd-json: introduce json_dispatch_log_level()
+
+Then, use it in io.systemd.service.SetLogLevel method.
+
+(cherry picked from commit 93081be64b858afea32079a8b32212a36b64de84)
+
+Resolves: RHEL-75774
+---
+ src/libsystemd/sd-json/json-util.c      | 20 ++++++++++++++++++++
+ src/libsystemd/sd-json/json-util.h      |  1 +
+ src/shared/varlink-io.systemd.service.c | 12 ++++--------
+ 3 files changed, 25 insertions(+), 8 deletions(-)
+
+diff --git a/src/libsystemd/sd-json/json-util.c b/src/libsystemd/sd-json/json-util.c
+index 67e50e6c51..1b22084d40 100644
+--- a/src/libsystemd/sd-json/json-util.c
++++ b/src/libsystemd/sd-json/json-util.c
+@@ -327,6 +327,26 @@ int json_dispatch_ifindex(const char *name, sd_json_variant *variant, sd_json_di
+         return 0;
+ }
+ 
++int json_dispatch_log_level(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata) {
++        int *log_level = ASSERT_PTR(userdata), r, t;
++
++        if (sd_json_variant_is_null(variant)) {
++                *log_level = -1;
++                return 0;
++        }
++
++        r = sd_json_dispatch_int(name, variant, flags, &t);
++        if (r < 0)
++                return r;
++
++        /* If SD_JSON_RELAX is set allow a zero interface index, otherwise refuse. */
++        if (LOG_PRI(t) != t)
++                return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a valid log level.", strna(name));
++
++        *log_level = t;
++        return 0;
++}
++
+ int json_variant_new_devnum(sd_json_variant **ret, dev_t devnum) {
+         if (devnum == 0)
+                 return sd_json_variant_new_null(ret);
+diff --git a/src/libsystemd/sd-json/json-util.h b/src/libsystemd/sd-json/json-util.h
+index b3b4941dcc..9a2b7b5ff2 100644
+--- a/src/libsystemd/sd-json/json-util.h
++++ b/src/libsystemd/sd-json/json-util.h
+@@ -119,6 +119,7 @@ int json_dispatch_path(const char *name, sd_json_variant *variant, sd_json_dispa
+ int json_dispatch_pidref(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata);
+ int json_dispatch_devnum(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata);
+ int json_dispatch_ifindex(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata);
++int json_dispatch_log_level(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata);
+ int json_dispatch_strv_environment(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata);
+ 
+ static inline int json_variant_unbase64_iovec(sd_json_variant *v, struct iovec *ret) {
+diff --git a/src/shared/varlink-io.systemd.service.c b/src/shared/varlink-io.systemd.service.c
+index 666778bd41..62cfc9b637 100644
+--- a/src/shared/varlink-io.systemd.service.c
++++ b/src/shared/varlink-io.systemd.service.c
+@@ -2,7 +2,7 @@
+ 
+ #include <unistd.h>
+ 
+-#include "macro.h"
++#include "json-util.h"
+ #include "varlink-io.systemd.service.h"
+ 
+ static SD_VARLINK_DEFINE_METHOD(Ping);
+@@ -33,13 +33,12 @@ int varlink_method_ping(sd_varlink *link, sd_json_variant *parameters, sd_varlin
+ 
+ int varlink_method_set_log_level(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
+         static const sd_json_dispatch_field dispatch_table[] = {
+-                { "level", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_int64, 0, SD_JSON_MANDATORY },
++                { "level", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_log_level, 0, SD_JSON_MANDATORY },
+                 {}
+         };
+ 
+-        int64_t level;
++        int r, level;
+         uid_t uid;
+-        int r;
+ 
+         assert(link);
+         assert(parameters);
+@@ -53,9 +52,6 @@ int varlink_method_set_log_level(sd_varlink *link, sd_json_variant *parameters,
+         if (r != 0)
+                 return r;
+ 
+-        if (LOG_PRI(level) != level)
+-                return sd_varlink_error_invalid_parameter(link, parameters);
+-
+         r = sd_varlink_get_peer_uid(link, &uid);
+         if (r < 0)
+                 return r;
+@@ -63,7 +59,7 @@ int varlink_method_set_log_level(sd_varlink *link, sd_json_variant *parameters,
+         if (uid != getuid() && uid != 0)
+                 return sd_varlink_error(link, SD_VARLINK_ERROR_PERMISSION_DENIED, parameters);
+ 
+-        log_debug("Received io.systemd.service.SetLogLevel(%" PRIi64 ")", level);
++        log_debug("Received io.systemd.service.SetLogLevel(%i)", level);
+ 
+         log_set_max_level(level);
+ 
diff --git a/SOURCES/0324-varlink-invert-uid-check-to-reduce-call-of-getuid.patch b/SOURCES/0324-varlink-invert-uid-check-to-reduce-call-of-getuid.patch
new file mode 100644
index 0000000000000000000000000000000000000000..0e44a088eb8f66486761b04f3e3e38c4ffacd7f3
--- /dev/null
+++ b/SOURCES/0324-varlink-invert-uid-check-to-reduce-call-of-getuid.patch
@@ -0,0 +1,25 @@
+From 2f84b078931b287b117c4aa3e21aa8a30b8fcd9b Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Sun, 22 Dec 2024 01:34:04 +0900
+Subject: [PATCH] varlink: invert uid check to reduce call of getuid()
+
+(cherry picked from commit 4ea611b8a4fa42bc782e2dc5d9c0bb470bb91683)
+
+Resolves: RHEL-75774
+---
+ src/shared/varlink-io.systemd.service.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/shared/varlink-io.systemd.service.c b/src/shared/varlink-io.systemd.service.c
+index 62cfc9b637..06e32f9bf6 100644
+--- a/src/shared/varlink-io.systemd.service.c
++++ b/src/shared/varlink-io.systemd.service.c
+@@ -56,7 +56,7 @@ int varlink_method_set_log_level(sd_varlink *link, sd_json_variant *parameters,
+         if (r < 0)
+                 return r;
+ 
+-        if (uid != getuid() && uid != 0)
++        if (uid != 0 && uid != getuid())
+                 return sd_varlink_error(link, SD_VARLINK_ERROR_PERMISSION_DENIED, parameters);
+ 
+         log_debug("Received io.systemd.service.SetLogLevel(%i)", level);
diff --git a/SOURCES/0325-string-util-modernize-split_pair.patch b/SOURCES/0325-string-util-modernize-split_pair.patch
new file mode 100644
index 0000000000000000000000000000000000000000..7b28cc47d3ac6137d981f5b72b3d92d41fcc57f8
--- /dev/null
+++ b/SOURCES/0325-string-util-modernize-split_pair.patch
@@ -0,0 +1,118 @@
+From 30c1127bfa58f94c98e2fc5a10bc6c272c72d017 Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Sun, 22 Dec 2024 03:34:43 +0900
+Subject: [PATCH] string-util: modernize split_pair()
+
+- use _cleanup_free_ attribute,
+- rename output arguments,
+- trigger assertion when an empty separator is passed.
+
+(cherry picked from commit ac3f3026a99772fbe8d485b56de0a5819513a2c1)
+
+Resolves: RHEL-75774
+---
+ src/basic/string-util.c     | 28 ++++++++++------------------
+ src/basic/string-util.h     |  2 +-
+ src/test/test-string-util.c | 23 ++++++++++++-----------
+ 3 files changed, 23 insertions(+), 30 deletions(-)
+
+diff --git a/src/basic/string-util.c b/src/basic/string-util.c
+index 171a368059..7122d5145e 100644
+--- a/src/basic/string-util.c
++++ b/src/basic/string-util.c
+@@ -1044,34 +1044,26 @@ char* strrep(const char *s, unsigned n) {
+         return r;
+ }
+ 
+-int split_pair(const char *s, const char *sep, char **l, char **r) {
+-        char *x, *a, *b;
+-
++int split_pair(const char *s, const char *sep, char **ret_first, char **ret_second) {
+         assert(s);
+-        assert(sep);
+-        assert(l);
+-        assert(r);
+-
+-        if (isempty(sep))
+-                return -EINVAL;
++        assert(!isempty(sep));
++        assert(ret_first);
++        assert(ret_second);
+ 
+-        x = strstr(s, sep);
++        const char *x = strstr(s, sep);
+         if (!x)
+                 return -EINVAL;
+ 
+-        a = strndup(s, x - s);
++        _cleanup_free_ char *a = strndup(s, x - s);
+         if (!a)
+                 return -ENOMEM;
+ 
+-        b = strdup(x + strlen(sep));
+-        if (!b) {
+-                free(a);
++        _cleanup_free_ char *b = strdup(x + strlen(sep));
++        if (!b)
+                 return -ENOMEM;
+-        }
+-
+-        *l = a;
+-        *r = b;
+ 
++        *ret_first = TAKE_PTR(a);
++        *ret_second = TAKE_PTR(b);
+         return 0;
+ }
+ 
+diff --git a/src/basic/string-util.h b/src/basic/string-util.h
+index cc6aa183c0..a1592b6e6d 100644
+--- a/src/basic/string-util.h
++++ b/src/basic/string-util.h
+@@ -214,7 +214,7 @@ char* strrep(const char *s, unsigned n);
+                 _d_;                                                    \
+         })
+ 
+-int split_pair(const char *s, const char *sep, char **l, char **r);
++int split_pair(const char *s, const char *sep, char **ret_first, char **ret_second);
+ 
+ int free_and_strdup(char **p, const char *s);
+ static inline int free_and_strdup_warn(char **p, const char *s) {
+diff --git a/src/test/test-string-util.c b/src/test/test-string-util.c
+index 999d3bacb8..b692af6cc0 100644
+--- a/src/test/test-string-util.c
++++ b/src/test/test-string-util.c
+@@ -572,21 +572,22 @@ TEST(in_charset) {
+ TEST(split_pair) {
+         _cleanup_free_ char *a = NULL, *b = NULL;
+ 
+-        assert_se(split_pair("", "", &a, &b) == -EINVAL);
+-        assert_se(split_pair("foo=bar", "", &a, &b) == -EINVAL);
+-        assert_se(split_pair("", "=", &a, &b) == -EINVAL);
+-        assert_se(split_pair("foo=bar", "=", &a, &b) >= 0);
++        ASSERT_SIGNAL(split_pair("", NULL, &a, &b), SIGABRT);
++        ASSERT_SIGNAL(split_pair("", "", &a, &b), SIGABRT);
++        ASSERT_SIGNAL(split_pair("foo=bar", "", &a, &b), SIGABRT);
++        ASSERT_SIGNAL(split_pair(NULL, "=", &a, &b), SIGABRT);
++        ASSERT_ERROR(split_pair("", "=", &a, &b), EINVAL);
++        ASSERT_OK(split_pair("foo=bar", "=", &a, &b));
+         ASSERT_STREQ(a, "foo");
+         ASSERT_STREQ(b, "bar");
+-        free(a);
+-        free(b);
+-        assert_se(split_pair("==", "==", &a, &b) >= 0);
++        a = mfree(a);
++        b = mfree(b);
++        ASSERT_OK(split_pair("==", "==", &a, &b));
+         ASSERT_STREQ(a, "");
+         ASSERT_STREQ(b, "");
+-        free(a);
+-        free(b);
+-
+-        assert_se(split_pair("===", "==", &a, &b) >= 0);
++        a = mfree(a);
++        b = mfree(b);
++        ASSERT_OK(split_pair("===", "==", &a, &b));
+         ASSERT_STREQ(a, "");
+         ASSERT_STREQ(b, "=");
+ }
diff --git a/SOURCES/0326-udev-split-manager_init-and-manager_main-into-small-.patch b/SOURCES/0326-udev-split-manager_init-and-manager_main-into-small-.patch
new file mode 100644
index 0000000000000000000000000000000000000000..388a6ad13f15545598a2bddcc62d267a6e874f05
--- /dev/null
+++ b/SOURCES/0326-udev-split-manager_init-and-manager_main-into-small-.patch
@@ -0,0 +1,310 @@
+From b6876d46a4695c0626db089170ea28cb263d3cdb Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Sun, 22 Dec 2024 00:11:38 +0900
+Subject: [PATCH] udev: split manager_init() and manager_main() into small
+ pieces
+
+No functional change, just refactoring.
+
+Co-authored-by: David Tardon <dtardon@redhat.com>
+(cherry picked from commit 0079651876aa5df73fd787b272e91ae4a7898853)
+
+Resolves: RHEL-75774
+---
+ src/udev/udev-manager.c | 217 +++++++++++++++++++++++++++++-----------
+ 1 file changed, 161 insertions(+), 56 deletions(-)
+
+diff --git a/src/udev/udev-manager.c b/src/udev/udev-manager.c
+index 4fc316e106..d9bd9d6d7b 100644
+--- a/src/udev/udev-manager.c
++++ b/src/udev/udev-manager.c
+@@ -1232,32 +1232,66 @@ static int listen_fds(int *ret_ctrl, int *ret_netlink) {
+         return 0;
+ }
+ 
+-int manager_init(Manager *manager) {
+-        _cleanup_close_ int fd_ctrl = -EBADF, fd_uevent = -EBADF;
+-        _cleanup_free_ char *cgroup = NULL;
++static int manager_init_ctrl(Manager *manager, int fd_ctrl) {
++        _cleanup_(udev_ctrl_unrefp) UdevCtrl *ctrl = NULL;
++        _cleanup_close_ int fd = fd_ctrl;
+         int r;
+ 
+         assert(manager);
+ 
+-        r = listen_fds(&fd_ctrl, &fd_uevent);
+-        if (r < 0)
+-                return log_error_errno(r, "Failed to listen on fds: %m");
++        /* This consumes passed file descriptor. */
+ 
+-        r = udev_ctrl_new_from_fd(&manager->ctrl, fd_ctrl);
++        r = udev_ctrl_new_from_fd(&ctrl, fd);
+         if (r < 0)
+                 return log_error_errno(r, "Failed to initialize udev control socket: %m");
+-        TAKE_FD(fd_ctrl);
++        TAKE_FD(fd);
+ 
+-        r = udev_ctrl_enable_receiving(manager->ctrl);
++        r = udev_ctrl_enable_receiving(ctrl);
+         if (r < 0)
+                 return log_error_errno(r, "Failed to bind udev control socket: %m");
+ 
+-        r = device_monitor_new_full(&manager->monitor, MONITOR_GROUP_KERNEL, fd_uevent);
++        manager->ctrl = TAKE_PTR(ctrl);
++        return 0;
++}
++
++static int manager_init_device_monitor(Manager *manager, int fd_uevent) {
++        _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor = NULL;
++        _cleanup_close_ int fd = fd_uevent;
++        int r;
++
++        assert(manager);
++
++        /* This consumes passed file descriptor. */
++
++        r = device_monitor_new_full(&monitor, MONITOR_GROUP_KERNEL, fd);
+         if (r < 0)
+                 return log_error_errno(r, "Failed to initialize device monitor: %m");
+-        TAKE_FD(fd_uevent);
++        TAKE_FD(fd);
++
++        (void) sd_device_monitor_set_description(monitor, "manager");
++
++        manager->monitor = TAKE_PTR(monitor);
++        return 0;
++}
+ 
+-        (void) sd_device_monitor_set_description(manager->monitor, "manager");
++int manager_init(Manager *manager) {
++        _cleanup_close_ int fd_ctrl = -EBADF, fd_uevent = -EBADF;
++        _cleanup_free_ char *cgroup = NULL;
++        int r;
++
++        assert(manager);
++
++        r = listen_fds(&fd_ctrl, &fd_uevent);
++        if (r < 0)
++                return log_error_errno(r, "Failed to listen on fds: %m");
++
++        r = manager_init_ctrl(manager, TAKE_FD(fd_ctrl));
++        if (r < 0)
++                return r;
++
++        r = manager_init_device_monitor(manager, TAKE_FD(fd_uevent));
++        if (r < 0)
++                return r;
+ 
+         r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &cgroup);
+         if (r < 0)
+@@ -1270,95 +1304,166 @@ int manager_init(Manager *manager) {
+         return 0;
+ }
+ 
+-int manager_main(Manager *manager) {
+-        int fd_worker, r;
++static int manager_start_ctrl(Manager *manager) {
++        int r;
++
++        assert(manager);
++        assert(manager->ctrl);
++
++        r = udev_ctrl_attach_event(manager->ctrl, manager->event);
++        if (r < 0)
++                return log_error_errno(r, "Failed to attach event to udev control: %m");
++
++        r = udev_ctrl_start(manager->ctrl, on_ctrl_msg, manager);
++        if (r < 0)
++                return log_error_errno(r, "Failed to start udev control: %m");
++
++        /* This needs to be after the inotify and uevent handling, to make sure that the ping is send back
++         * after fully processing the pending uevents (including the synthetic ones we may create due to
++         * inotify events). */
++        r = sd_event_source_set_priority(udev_ctrl_get_event_source(manager->ctrl), SD_EVENT_PRIORITY_IDLE);
++        if (r < 0)
++                return log_error_errno(r, "Failed to set IDLE event priority for udev control event source: %m");
++
++        return 0;
++}
++
++static int manager_start_device_monitor(Manager *manager) {
++        int r;
++
++        assert(manager);
++        assert(manager->monitor);
++
++        r = sd_device_monitor_attach_event(manager->monitor, manager->event);
++        if (r < 0)
++                return log_error_errno(r, "Failed to attach event to device monitor: %m");
++
++        r = sd_device_monitor_start(manager->monitor, on_uevent, manager);
++        if (r < 0)
++                return log_error_errno(r, "Failed to start device monitor: %m");
++
++        return 0;
++}
++
++static int manager_start_inotify(Manager *manager) {
++        _cleanup_(sd_event_source_unrefp) sd_event_source *s = NULL;
++        _cleanup_close_ int fd = -EBADF;
++        int r;
++
++        assert(manager);
++        assert(manager->event);
++
++        fd = inotify_init1(IN_CLOEXEC);
++        if (fd < 0)
++                return log_error_errno(errno, "Failed to create inotify descriptor: %m");
++
++        udev_watch_restore(fd);
++
++        r = sd_event_add_io(manager->event, &s, fd, EPOLLIN, on_inotify, manager);
++        if (r < 0)
++                return log_error_errno(r, "Failed to create inotify event source: %m");
++
++        (void) sd_event_source_set_description(s, "manager-inotify");
++
++        manager->inotify_fd = TAKE_FD(fd);
++        manager->inotify_event = TAKE_PTR(s);
++        return 0;
++}
++
++static int manager_start_worker_event(Manager *manager) {
++        int r;
++
++        assert(manager);
++        assert(manager->event);
+ 
+         /* unnamed socket from workers to the main daemon */
+         r = socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, manager->worker_watch);
+         if (r < 0)
+                 return log_error_errno(errno, "Failed to create socketpair for communicating with workers: %m");
+ 
+-        fd_worker = manager->worker_watch[READ_END];
+-
+-        r = setsockopt_int(fd_worker, SOL_SOCKET, SO_PASSCRED, true);
++        r = setsockopt_int(manager->worker_watch[READ_END], SOL_SOCKET, SO_PASSCRED, true);
+         if (r < 0)
+                 return log_error_errno(r, "Failed to enable SO_PASSCRED: %m");
+ 
+-        manager->inotify_fd = inotify_init1(IN_CLOEXEC);
+-        if (manager->inotify_fd < 0)
+-                return log_error_errno(errno, "Failed to create inotify descriptor: %m");
++        r = sd_event_add_io(manager->event, NULL, manager->worker_watch[READ_END], EPOLLIN, on_worker, manager);
++        if (r < 0)
++                return log_error_errno(r, "Failed to create worker event source: %m");
+ 
+-        udev_watch_restore(manager->inotify_fd);
++        return 0;
++}
++
++static int manager_setup_event(Manager *manager) {
++        _cleanup_(sd_event_unrefp) sd_event *e = NULL;
++        int r;
++
++        assert(manager);
+ 
+         /* block SIGCHLD for listening child events. */
+         assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD) >= 0);
+ 
+-        r = sd_event_default(&manager->event);
++        r = sd_event_default(&e);
+         if (r < 0)
+                 return log_error_errno(r, "Failed to allocate event loop: %m");
+ 
+-        r = sd_event_add_signal(manager->event, NULL, SIGINT | SD_EVENT_SIGNAL_PROCMASK, on_sigterm, manager);
++        r = sd_event_add_signal(e, /* ret_event_source = */ NULL, SIGINT | SD_EVENT_SIGNAL_PROCMASK, on_sigterm, manager);
+         if (r < 0)
+                 return log_error_errno(r, "Failed to create SIGINT event source: %m");
+ 
+-        r = sd_event_add_signal(manager->event, NULL, SIGTERM | SD_EVENT_SIGNAL_PROCMASK, on_sigterm, manager);
++        r = sd_event_add_signal(e, /* ret_event_source = */ NULL, SIGTERM | SD_EVENT_SIGNAL_PROCMASK, on_sigterm, manager);
+         if (r < 0)
+                 return log_error_errno(r, "Failed to create SIGTERM event source: %m");
+ 
+-        r = sd_event_add_signal(manager->event, NULL, SIGHUP | SD_EVENT_SIGNAL_PROCMASK, on_sighup, manager);
++        r = sd_event_add_signal(e, /* ret_event_source = */ NULL, SIGHUP | SD_EVENT_SIGNAL_PROCMASK, on_sighup, manager);
+         if (r < 0)
+                 return log_error_errno(r, "Failed to create SIGHUP event source: %m");
+ 
+-        r = sd_event_set_watchdog(manager->event, true);
++        r = sd_event_add_post(e, /* ret_event_source = */ NULL, on_post, manager);
+         if (r < 0)
+-                return log_error_errno(r, "Failed to create watchdog event source: %m");
++                return log_error_errno(r, "Failed to create post event source: %m");
+ 
+-        r = udev_ctrl_attach_event(manager->ctrl, manager->event);
++        /* Eventually, we probably want to do more here on memory pressure, for example, kill idle workers immediately */
++        r = sd_event_add_memory_pressure(e, /* ret_event_source= */ NULL, /* callback= */ NULL, /* userdata= */ NULL);
+         if (r < 0)
+-                return log_error_errno(r, "Failed to attach event to udev control: %m");
++                log_full_errno(ERRNO_IS_NOT_SUPPORTED(r) || ERRNO_IS_PRIVILEGE(r) || (r == -EHOSTDOWN) ? LOG_DEBUG : LOG_WARNING, r,
++                               "Failed to allocate memory pressure watch, ignoring: %m");
+ 
+-        r = udev_ctrl_start(manager->ctrl, on_ctrl_msg, manager);
++        r = sd_event_add_signal(e, /* ret_event_source= */ NULL,
++                                (SIGRTMIN+18) | SD_EVENT_SIGNAL_PROCMASK, sigrtmin18_handler, /* userdata= */ NULL);
+         if (r < 0)
+-                return log_error_errno(r, "Failed to start udev control: %m");
++                return log_error_errno(r, "Failed to allocate SIGRTMIN+18 event source, ignoring: %m");
+ 
+-        /* This needs to be after the inotify and uevent handling, to make sure
+-         * that the ping is send back after fully processing the pending uevents
+-         * (including the synthetic ones we may create due to inotify events).
+-         */
+-        r = sd_event_source_set_priority(udev_ctrl_get_event_source(manager->ctrl), SD_EVENT_PRIORITY_IDLE);
++        r = sd_event_set_watchdog(e, true);
+         if (r < 0)
+-                return log_error_errno(r, "Failed to set IDLE event priority for udev control event source: %m");
++                return log_error_errno(r, "Failed to create watchdog event source: %m");
+ 
+-        r = sd_event_add_io(manager->event, &manager->inotify_event, manager->inotify_fd, EPOLLIN, on_inotify, manager);
+-        if (r < 0)
+-                return log_error_errno(r, "Failed to create inotify event source: %m");
++        manager->event = TAKE_PTR(e);
++        return 0;
++}
+ 
+-        r = sd_device_monitor_attach_event(manager->monitor, manager->event);
+-        if (r < 0)
+-                return log_error_errno(r, "Failed to attach event to device monitor: %m");
++int manager_main(Manager *manager) {
++        int r;
+ 
+-        r = sd_device_monitor_start(manager->monitor, on_uevent, manager);
++        assert(manager);
++
++        r = manager_setup_event(manager);
+         if (r < 0)
+-                return log_error_errno(r, "Failed to start device monitor: %m");
++                return r;
+ 
+-        r = sd_event_add_io(manager->event, NULL, fd_worker, EPOLLIN, on_worker, manager);
++        r = manager_start_ctrl(manager);
+         if (r < 0)
+-                return log_error_errno(r, "Failed to create worker event source: %m");
++                return r;
+ 
+-        r = sd_event_add_post(manager->event, NULL, on_post, manager);
++        r = manager_start_device_monitor(manager);
+         if (r < 0)
+-                return log_error_errno(r, "Failed to create post event source: %m");
++                return r;
+ 
+-        /* Eventually, we probably want to do more here on memory pressure, for example, kill idle workers immediately */
+-        r = sd_event_add_memory_pressure(manager->event, /* ret_event_source= */ NULL, /* callback= */ NULL, /* userdata= */ NULL);
++        r = manager_start_inotify(manager);
+         if (r < 0)
+-                log_full_errno(ERRNO_IS_NOT_SUPPORTED(r) || ERRNO_IS_PRIVILEGE(r) || (r == -EHOSTDOWN) ? LOG_DEBUG : LOG_WARNING, r,
+-                               "Failed to allocate memory pressure watch, ignoring: %m");
++                return r;
+ 
+-        r = sd_event_add_signal(manager->event, /* ret_event_source= */ NULL,
+-                                (SIGRTMIN+18) | SD_EVENT_SIGNAL_PROCMASK, sigrtmin18_handler, /* userdata= */ NULL);
++        r = manager_start_worker_event(manager);
+         if (r < 0)
+-                return log_error_errno(r, "Failed to allocate SIGRTMIN+18 event source, ignoring: %m");
++                return r;
+ 
+         manager->last_usec = now(CLOCK_MONOTONIC);
+ 
diff --git a/SOURCES/0327-udev-config-split-on_ctrl_msg-into-small-pieces.patch b/SOURCES/0327-udev-config-split-on_ctrl_msg-into-small-pieces.patch
new file mode 100644
index 0000000000000000000000000000000000000000..642910a83ff45ea6f0b67ab1e39b24b8438c2e3a
--- /dev/null
+++ b/SOURCES/0327-udev-config-split-on_ctrl_msg-into-small-pieces.patch
@@ -0,0 +1,262 @@
+From d03f5018a7015594b9af864779a3e06d0f407192 Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Sun, 22 Dec 2024 01:48:37 +0900
+Subject: [PATCH] udev-config: split on_ctrl_msg() into small pieces
+
+No functional change, just refactroing and preparation for later
+commits.
+
+(cherry picked from commit b358833ee91551d5d70a4fd754187a0259e2c62f)
+
+Resolves: RHEL-75774
+---
+ src/udev/udev-config.c  | 78 ++++++++++++++++++++++++++++++++++++++++-
+ src/udev/udev-config.h  |  5 ++-
+ src/udev/udev-manager.c | 59 ++++---------------------------
+ src/udev/udev-manager.h |  4 +++
+ 4 files changed, 91 insertions(+), 55 deletions(-)
+
+diff --git a/src/udev/udev-config.c b/src/udev/udev-config.c
+index 891cf92535..d511691ab2 100644
+--- a/src/udev/udev-config.c
++++ b/src/udev/udev-config.c
+@@ -271,7 +271,7 @@ static void manager_merge_config(Manager *manager) {
+         MERGE_BOOL(blockdev_read_only);
+ }
+ 
+-void udev_config_set_default_children_max(UdevConfig *config) {
++static void udev_config_set_default_children_max(UdevConfig *config) {
+         uint64_t cpu_limit, mem_limit, cpu_count = 1;
+         int r;
+ 
+@@ -293,6 +293,30 @@ void udev_config_set_default_children_max(UdevConfig *config) {
+         log_debug("Set children_max to %u", config->children_max);
+ }
+ 
++void manager_set_children_max(Manager *manager, unsigned n) {
++        assert(manager);
++
++        manager->config_by_control.children_max = n;
++        /* When 0 is specified, determine the maximum based on the system resources. */
++        udev_config_set_default_children_max(&manager->config_by_control);
++        manager->config.children_max = manager->config_by_control.children_max;
++
++        notify_ready(manager);
++}
++
++void manager_set_log_level(Manager *manager, int log_level) {
++        assert(manager);
++        assert(LOG_PRI(log_level) == log_level);
++
++        int old = log_get_max_level();
++
++        log_set_max_level(log_level);
++        manager->config.log_level = manager->config_by_control.log_level = log_level;
++
++        if (log_level != old)
++                manager_kill_workers(manager, /* force = */ false);
++}
++
+ static void manager_adjust_config(UdevConfig *config) {
+         assert(config);
+ 
+@@ -315,6 +339,58 @@ static void manager_adjust_config(UdevConfig *config) {
+         udev_config_set_default_children_max(config);
+ }
+ 
++static int manager_set_environment_one(Manager *manager, const char *s) {
++        int r;
++
++        assert(manager);
++        assert(s);
++
++        _cleanup_free_ char *key = NULL, *value = NULL;
++        r = split_pair(s, "=", &key, &value);
++        if (r < 0)
++                return r;
++
++        if (isempty(value)) {
++                _cleanup_free_ char *old_key = NULL, *old_value = NULL;
++                old_value = hashmap_remove2(manager->properties, key, (void**) &old_key);
++                return !!old_value;
++        }
++
++        if (streq_ptr(value, hashmap_get(manager->properties, key)))
++                return 0;
++
++        _cleanup_free_ char *old_key = NULL, *old_value = NULL;
++        old_value = hashmap_get2(manager->properties, key, (void**) &old_key);
++
++        r = hashmap_ensure_replace(&manager->properties, &string_hash_ops, key, value);
++        if (r < 0) {
++                assert(!old_key);
++                assert(!old_value);
++                return r;
++        }
++
++        TAKE_PTR(key);
++        TAKE_PTR(value);
++        return 1;
++}
++
++void manager_set_environment(Manager *manager, char * const *v) {
++        bool changed = false;
++        int r;
++
++        assert(manager);
++
++        STRV_FOREACH(s, v) {
++                r = manager_set_environment_one(manager, *s);
++                if (r < 0)
++                        log_debug_errno(r, "Failed to update environment '%s', ignoring: %m", *s);
++                changed = changed || r > 0;
++        }
++
++        if (changed)
++                manager_kill_workers(manager, /* force = */ false);
++}
++
+ int manager_load(Manager *manager, int argc, char *argv[]) {
+         int r;
+ 
+diff --git a/src/udev/udev-config.h b/src/udev/udev-config.h
+index 1c7a74b106..68bb1ea98c 100644
+--- a/src/udev/udev-config.h
++++ b/src/udev/udev-config.h
+@@ -26,6 +26,9 @@ typedef struct UdevConfig {
+                 .resolve_name_timing = _RESOLVE_NAME_TIMING_INVALID, \
+         }
+ 
++void manager_set_children_max(Manager *manager, unsigned n);
++void manager_set_log_level(Manager *manager, int log_level);
++void manager_set_environment(Manager *manager, char * const *v);
++
+ int manager_load(Manager *manager, int argc, char *argv[]);
+ UdevReloadFlags manager_reload_config(Manager *manager);
+-void udev_config_set_default_children_max(UdevConfig *c);
+diff --git a/src/udev/udev-manager.c b/src/udev/udev-manager.c
+index d9bd9d6d7b..2c87e8bb9e 100644
+--- a/src/udev/udev-manager.c
++++ b/src/udev/udev-manager.c
+@@ -194,7 +194,7 @@ static int worker_new(Worker **ret, Manager *manager, sd_device_monitor *worker_
+         return 0;
+ }
+ 
+-static void manager_kill_workers(Manager *manager, bool force) {
++void manager_kill_workers(Manager *manager, bool force) {
+         Worker *worker;
+ 
+         assert(manager);
+@@ -233,7 +233,7 @@ static void manager_exit(Manager *manager) {
+         manager_kill_workers(manager, true);
+ }
+ 
+-static void notify_ready(Manager *manager) {
++void notify_ready(Manager *manager) {
+         int r;
+ 
+         assert(manager);
+@@ -844,7 +844,6 @@ static int on_worker(sd_event_source *s, int fd, uint32_t revents, void *userdat
+ /* receive the udevd message from userspace */
+ static int on_ctrl_msg(UdevCtrl *uctrl, UdevCtrlMessageType type, const UdevCtrlMessageValue *value, void *userdata) {
+         Manager *manager = ASSERT_PTR(userdata);
+-        int r;
+ 
+         assert(value);
+ 
+@@ -857,13 +856,7 @@ static int on_ctrl_msg(UdevCtrl *uctrl, UdevCtrlMessageType type, const UdevCtrl
+ 
+                 log_debug("Received udev control message (SET_LOG_LEVEL), setting log_level=%i", value->intval);
+ 
+-                r = log_get_max_level();
+-                if (r == value->intval)
+-                        break;
+-
+-                log_set_max_level(value->intval);
+-                manager->config.log_level = manager->config_by_control.log_level = value->intval;
+-                manager_kill_workers(manager, false);
++                manager_set_log_level(manager, value->intval);
+                 break;
+         case UDEV_CTRL_STOP_EXEC_QUEUE:
+                 log_debug("Received udev control message (STOP_EXEC_QUEUE)");
+@@ -879,8 +872,6 @@ static int on_ctrl_msg(UdevCtrl *uctrl, UdevCtrlMessageType type, const UdevCtrl
+                 manager_reload(manager, /* force = */ true);
+                 break;
+         case UDEV_CTRL_SET_ENV: {
+-                _unused_ _cleanup_free_ char *old_val = NULL, *old_key = NULL;
+-                _cleanup_free_ char *key = NULL, *val = NULL;
+                 const char *eq;
+ 
+                 eq = strchr(value->buf, '=');
+@@ -889,41 +880,8 @@ static int on_ctrl_msg(UdevCtrl *uctrl, UdevCtrlMessageType type, const UdevCtrl
+                         return 1;
+                 }
+ 
+-                key = strndup(value->buf, eq - value->buf);
+-                if (!key) {
+-                        log_oom();
+-                        return 1;
+-                }
+-
+-                old_val = hashmap_remove2(manager->properties, key, (void **) &old_key);
+-
+-                r = hashmap_ensure_allocated(&manager->properties, &string_hash_ops);
+-                if (r < 0) {
+-                        log_oom();
+-                        return 1;
+-                }
+-
+-                eq++;
+-                if (isempty(eq))
+-                        log_debug("Received udev control message (ENV), unsetting '%s'", key);
+-                else {
+-                        val = strdup(eq);
+-                        if (!val) {
+-                                log_oom();
+-                                return 1;
+-                        }
+-
+-                        log_debug("Received udev control message (ENV), setting '%s=%s'", key, val);
+-
+-                        r = hashmap_put(manager->properties, key, val);
+-                        if (r < 0) {
+-                                log_oom();
+-                                return 1;
+-                        }
+-                }
+-
+-                key = val = NULL;
+-                manager_kill_workers(manager, false);
++                log_debug("Received udev control message(SET_ENV, %s)", value->buf);
++                manager_set_environment(manager, STRV_MAKE(value->buf));
+                 break;
+         }
+         case UDEV_CTRL_SET_CHILDREN_MAX:
+@@ -933,13 +891,8 @@ static int on_ctrl_msg(UdevCtrl *uctrl, UdevCtrlMessageType type, const UdevCtrl
+                 }
+ 
+                 log_debug("Received udev control message (SET_MAX_CHILDREN), setting children_max=%i", value->intval);
+-                manager->config_by_control.children_max = value->intval;
+-
+-                /* When 0 is specified, determine the maximum based on the system resources. */
+-                udev_config_set_default_children_max(&manager->config_by_control);
+-                manager->config.children_max = manager->config_by_control.children_max;
+ 
+-                notify_ready(manager);
++                manager_set_children_max(manager, value->intval);
+                 break;
+         case UDEV_CTRL_PING:
+                 log_debug("Received udev control message (PING)");
+diff --git a/src/udev/udev-manager.h b/src/udev/udev-manager.h
+index 13c7242ea8..05f9a8b709 100644
+--- a/src/udev/udev-manager.h
++++ b/src/udev/udev-manager.h
+@@ -55,4 +55,8 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
+ int manager_init(Manager *manager);
+ int manager_main(Manager *manager);
+ 
++void notify_ready(Manager *manager);
++
++void manager_kill_workers(Manager *manager, bool force);
++
+ bool devpath_conflict(const char *a, const char *b);
diff --git a/SOURCES/0328-udev-introduce-udev_property_name_is_valid-and-frien.patch b/SOURCES/0328-udev-introduce-udev_property_name_is_valid-and-frien.patch
new file mode 100644
index 0000000000000000000000000000000000000000..37ecd1fa4ff9555e6c1343925636496daa39792a
--- /dev/null
+++ b/SOURCES/0328-udev-introduce-udev_property_name_is_valid-and-frien.patch
@@ -0,0 +1,68 @@
+From 1ffd9f7e201e155e3301445a9db00dffabe1827a Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Sat, 4 Jan 2025 21:07:41 +0900
+Subject: [PATCH] udev: introduce udev_property_name_is_valid() and friends
+
+(cherry picked from commit 4c547d216aad4a61d58a6962d0256da3c6ae6a71)
+
+Resolves: RHEL-75774
+---
+ src/udev/net/link-config.c | 7 ++-----
+ src/udev/udev-def.h        | 8 ++++++++
+ 2 files changed, 10 insertions(+), 5 deletions(-)
+
+diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c
+index 7d4e334503..5a4b7261bb 100644
+--- a/src/udev/net/link-config.c
++++ b/src/udev/net/link-config.c
+@@ -15,7 +15,6 @@
+ #include "creds-util.h"
+ #include "device-private.h"
+ #include "device-util.h"
+-#include "env-util.h"
+ #include "escape.h"
+ #include "ethtool-util.h"
+ #include "fd-util.h"
+@@ -1111,8 +1110,7 @@ int config_parse_udev_property(
+                         continue;
+                 }
+ 
+-                /* The restriction for udev property is not clear. Let's apply the one for environment variable here. */
+-                if (!env_assignment_is_valid(resolved)) {
++                if (!udev_property_assignment_is_valid(resolved)) {
+                         log_syntax(unit, LOG_WARNING, filename, line, 0,
+                                    "Invalid udev property, ignoring assignment: %s", word);
+                         continue;
+@@ -1181,8 +1179,7 @@ int config_parse_udev_property_name(
+                         continue;
+                 }
+ 
+-                /* The restriction for udev property is not clear. Let's apply the one for environment variable here. */
+-                if (!env_name_is_valid(resolved)) {
++                if (!udev_property_name_is_valid(resolved)) {
+                         log_syntax(unit, LOG_WARNING, filename, line, 0,
+                                    "Invalid udev property name, ignoring assignment: %s", resolved);
+                         continue;
+diff --git a/src/udev/udev-def.h b/src/udev/udev-def.h
+index 9d9fc78247..ed231764bc 100644
+--- a/src/udev/udev-def.h
++++ b/src/udev/udev-def.h
+@@ -3,6 +3,8 @@
+ 
+ #include <errno.h>
+ 
++#include "env-util.h"
++
+ #define UDEV_NAME_SIZE   512
+ #define UDEV_PATH_SIZE  1024
+ #define UDEV_LINE_SIZE 16384
+@@ -78,3 +80,9 @@ typedef enum UdevReloadFlags {
+         UDEV_RELOAD_KILL_WORKERS     = 1u << (_UDEV_BUILTIN_MAX + 0),
+         UDEV_RELOAD_RULES            = 1u << (_UDEV_BUILTIN_MAX + 1),
+ } UdevReloadFlags;
++
++/* udev properties are conceptually close to environment variables. Let's validate names, values, and
++ * assignments in the same way. */
++#define udev_property_name_is_valid(x)       env_name_is_valid(x)
++#define udev_property_value_is_valid(x)      env_value_is_valid(x)
++#define udev_property_assignment_is_valid(x) env_assignment_is_valid(x)
diff --git a/SOURCES/0329-udev-ctrl-refuse-ENV-control-message-with-invalid-en.patch b/SOURCES/0329-udev-ctrl-refuse-ENV-control-message-with-invalid-en.patch
new file mode 100644
index 0000000000000000000000000000000000000000..3b64be179cd716043efb8057c404fe5216480b71
--- /dev/null
+++ b/SOURCES/0329-udev-ctrl-refuse-ENV-control-message-with-invalid-en.patch
@@ -0,0 +1,47 @@
+From 618742f92e739fc800d066b17bccd1e44cfc6981 Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Sun, 22 Dec 2024 06:34:33 +0900
+Subject: [PATCH] udev-ctrl: refuse ENV control message with invalid
+ environment assignment
+
+Previously, udevd accepts an arbitrary pair of key and value.
+Let's make the environment variable assignment more strict for safety.
+
+Note, we already refuse environment variables with the same way in
+net/link-config.c.
+
+(cherry picked from commit bbb0dbe6b1fad7c8d8250f5dff334a2de8766559)
+
+Resolves: RHEL-75774
+---
+ src/udev/udev-manager.c | 12 ++++--------
+ 1 file changed, 4 insertions(+), 8 deletions(-)
+
+diff --git a/src/udev/udev-manager.c b/src/udev/udev-manager.c
+index 2c87e8bb9e..83b0a90ccf 100644
+--- a/src/udev/udev-manager.c
++++ b/src/udev/udev-manager.c
+@@ -871,19 +871,15 @@ static int on_ctrl_msg(UdevCtrl *uctrl, UdevCtrlMessageType type, const UdevCtrl
+                 log_debug("Received udev control message (RELOAD)");
+                 manager_reload(manager, /* force = */ true);
+                 break;
+-        case UDEV_CTRL_SET_ENV: {
+-                const char *eq;
+-
+-                eq = strchr(value->buf, '=');
+-                if (!eq) {
+-                        log_error("Invalid key format '%s'", value->buf);
+-                        return 1;
++        case UDEV_CTRL_SET_ENV:
++                if (!udev_property_assignment_is_valid(value->buf)) {
++                        log_debug("Received invalid udev control message(SET_ENV, %s), ignoring.", value->buf);
++                        break;
+                 }
+ 
+                 log_debug("Received udev control message(SET_ENV, %s)", value->buf);
+                 manager_set_environment(manager, STRV_MAKE(value->buf));
+                 break;
+-        }
+         case UDEV_CTRL_SET_CHILDREN_MAX:
+                 if (value->intval < 0) {
+                         log_debug("Received invalid udev control message (SET_MAX_CHILDREN, %i), ignoring.", value->intval);
diff --git a/SOURCES/0330-varlink-add-comments-for-io.systemd.service-interfac.patch b/SOURCES/0330-varlink-add-comments-for-io.systemd.service-interfac.patch
new file mode 100644
index 0000000000000000000000000000000000000000..7499d4a730641075272684873077aa79e4f988e1
--- /dev/null
+++ b/SOURCES/0330-varlink-add-comments-for-io.systemd.service-interfac.patch
@@ -0,0 +1,35 @@
+From b0559cceb8b4dd37db4b8dd5e7870fcc784fe8d0 Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Sat, 4 Jan 2025 21:51:09 +0900
+Subject: [PATCH] varlink: add comments for io.systemd.service interface
+
+(cherry picked from commit 8252b74f2dda823ac8d4ff9e9b49f9c981136375)
+
+Resolves: RHEL-75774
+---
+ src/shared/varlink-io.systemd.service.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/src/shared/varlink-io.systemd.service.c b/src/shared/varlink-io.systemd.service.c
+index 06e32f9bf6..f34d5cfead 100644
+--- a/src/shared/varlink-io.systemd.service.c
++++ b/src/shared/varlink-io.systemd.service.c
+@@ -11,13 +11,18 @@ static SD_VARLINK_DEFINE_METHOD(Reload);
+ 
+ static SD_VARLINK_DEFINE_METHOD(
+                 SetLogLevel,
++                SD_VARLINK_FIELD_COMMENT("The maximum log level."),
+                 SD_VARLINK_DEFINE_INPUT(level, SD_VARLINK_INT, 0));
+ 
+ SD_VARLINK_DEFINE_INTERFACE(
+                 io_systemd_service,
+                 "io.systemd.service",
++                SD_VARLINK_INTERFACE_COMMENT("An interface to control basic properties of systemd services."),
++                SD_VARLINK_SYMBOL_COMMENT("Checks if the service is running."),
+                 &vl_method_Ping,
++                SD_VARLINK_SYMBOL_COMMENT("Reloads configurations."),
+                 &vl_method_Reload,
++                SD_VARLINK_SYMBOL_COMMENT("Sets the maximum log level."),
+                 &vl_method_SetLogLevel);
+ 
+ int varlink_method_ping(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
diff --git a/SOURCES/0331-sd-varlink-introduce-sd_varlink_get_current_method.patch b/SOURCES/0331-sd-varlink-introduce-sd_varlink_get_current_method.patch
new file mode 100644
index 0000000000000000000000000000000000000000..82a183127a4ffb88064aa0212708e5ae703b12cf
--- /dev/null
+++ b/SOURCES/0331-sd-varlink-introduce-sd_varlink_get_current_method.patch
@@ -0,0 +1,69 @@
+From d0199162ba3426385535ff7bcef1955c8fc54e9b Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Sat, 4 Jan 2025 21:18:42 +0900
+Subject: [PATCH] sd-varlink: introduce sd_varlink_get_current_method()
+
+(cherry picked from commit ffe292330337b4c78932cde808463752196f531f)
+
+Resolves: RHEL-75774
+---
+ src/libsystemd/libsystemd.sym          |  5 +++++
+ src/libsystemd/sd-varlink/sd-varlink.c | 19 +++++++++++++++++++
+ src/systemd/sd-varlink.h               |  1 +
+ 3 files changed, 25 insertions(+)
+
+diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym
+index a76dc7e4ae..4dbe4e3c76 100644
+--- a/src/libsystemd/libsystemd.sym
++++ b/src/libsystemd/libsystemd.sym
+@@ -1059,3 +1059,8 @@ global:
+         sd_device_monitor_get_timeout;
+         sd_device_monitor_receive;
+ } LIBSYSTEMD_256;
++
++LIBSYSTEMD_258 {
++global:
++        sd_varlink_get_current_method;
++} LIBSYSTEMD_257;
+diff --git a/src/libsystemd/sd-varlink/sd-varlink.c b/src/libsystemd/sd-varlink/sd-varlink.c
+index 7038cba5db..5f3b17199d 100644
+--- a/src/libsystemd/sd-varlink/sd-varlink.c
++++ b/src/libsystemd/sd-varlink/sd-varlink.c
+@@ -1542,6 +1542,25 @@ _public_ int sd_varlink_dispatch_again(sd_varlink *v) {
+         return 0;
+ }
+ 
++_public_ int sd_varlink_get_current_method(sd_varlink *v, const char **ret) {
++        assert_return(v, -EINVAL);
++
++        if (!v->current)
++                return -ENODATA;
++
++        sd_json_variant *p = sd_json_variant_by_key(v->current, "method");
++        if (!p)
++                return -ENODATA;
++
++        const char *s = sd_json_variant_string(p);
++        if (!s)
++                return -ENODATA;
++
++        if (ret)
++                *ret = s;
++        return 0;
++}
++
+ _public_ int sd_varlink_get_current_parameters(sd_varlink *v, sd_json_variant **ret) {
+         sd_json_variant *p;
+ 
+diff --git a/src/systemd/sd-varlink.h b/src/systemd/sd-varlink.h
+index 17cf8b7386..9401d417b2 100644
+--- a/src/systemd/sd-varlink.h
++++ b/src/systemd/sd-varlink.h
+@@ -176,6 +176,7 @@ int sd_varlink_notifyb(sd_varlink *v, ...);
+ int sd_varlink_dispatch_again(sd_varlink *v);
+ 
+ /* Get the currently processed incoming message */
++int sd_varlink_get_current_method(sd_varlink *v, const char **ret);
+ int sd_varlink_get_current_parameters(sd_varlink *v, sd_json_variant **ret);
+ 
+ /* Parsing incoming data via json_dispatch() and generate a nice error on parse errors */
diff --git a/SOURCES/0332-TEST-17-UDEV-wait-for-udevd-being-restarted-after-ex.patch b/SOURCES/0332-TEST-17-UDEV-wait-for-udevd-being-restarted-after-ex.patch
new file mode 100644
index 0000000000000000000000000000000000000000..12887b0285426b7d1bf139ee030abbab021e1268
--- /dev/null
+++ b/SOURCES/0332-TEST-17-UDEV-wait-for-udevd-being-restarted-after-ex.patch
@@ -0,0 +1,35 @@
+From c7ac125cac1a0efcbd5f7e63433d8652887c0714 Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Tue, 7 Jan 2025 20:23:02 +0900
+Subject: [PATCH] TEST-17-UDEV: wait for udevd being restarted after exit
+ control command
+
+Also wait for created devices being processed before running tests.
+
+(cherry picked from commit d5c4c4d45c6075f5a1dde024d7a4717b71f369a2)
+
+Resolves: RHEL-75774
+---
+ test/units/TEST-17-UDEV.10.sh | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/test/units/TEST-17-UDEV.10.sh b/test/units/TEST-17-UDEV.10.sh
+index 6820e76679..be342b3468 100755
+--- a/test/units/TEST-17-UDEV.10.sh
++++ b/test/units/TEST-17-UDEV.10.sh
+@@ -28,9 +28,15 @@ blk="$(mktemp)"
+ dd if=/dev/zero of="$blk" bs=1M count=1
+ loopdev="$(losetup --show -f "$blk")"
+ 
++# Wait for devices created in the above being processed.
++udevadm settle --timeout 30
++
+ udevadm -h
+ 
++INVOCATION_ID=$(systemctl show --property InvocationID --value systemd-udevd.service)
+ udevadm control -e
++# Wait for systemd-udevd.service being restarted.
++timeout 30 bash -ec "while [[ \"\$(systemctl show --property InvocationID --value systemd-udevd.service)\" == \"$INVOCATION_ID\" ]]; do sleep .5; done"
+ udevadm control -l emerg
+ udevadm control -l alert
+ udevadm control -l crit
diff --git a/SOURCES/0333-udev-make-worker-event-source-take-file-descriptor.patch b/SOURCES/0333-udev-make-worker-event-source-take-file-descriptor.patch
new file mode 100644
index 0000000000000000000000000000000000000000..d24922a9ec0c21a97e1162abdad43701e06785b8
--- /dev/null
+++ b/SOURCES/0333-udev-make-worker-event-source-take-file-descriptor.patch
@@ -0,0 +1,102 @@
+From d5f7f864605262d432c7dfeb09d785f7c38463a4 Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Sun, 22 Dec 2024 00:14:52 +0900
+Subject: [PATCH] udev: make worker event source take file descriptor
+
+No functional change, just refactoring.
+
+(cherry picked from commit 77eb6f73053a71ddd7e9156a409b138eb87c4cd6)
+
+Resolves: RHEL-75774
+---
+ src/udev/udev-manager.c | 27 +++++++++++++++++++++------
+ src/udev/udev-manager.h |  2 +-
+ 2 files changed, 22 insertions(+), 7 deletions(-)
+
+diff --git a/src/udev/udev-manager.c b/src/udev/udev-manager.c
+index 83b0a90ccf..1768da5a38 100644
+--- a/src/udev/udev-manager.c
++++ b/src/udev/udev-manager.c
+@@ -144,7 +144,7 @@ Manager* manager_free(Manager *manager) {
+         event_queue_cleanup(manager, EVENT_UNDEF);
+ 
+         safe_close(manager->inotify_fd);
+-        safe_close_pair(manager->worker_watch);
++        safe_close(manager->worker_notify_fd);
+ 
+         sd_device_monitor_unref(manager->monitor);
+         udev_ctrl_unref(manager->ctrl);
+@@ -406,7 +406,7 @@ static int worker_spawn(Manager *manager, Event *event) {
+                         .monitor = TAKE_PTR(worker_monitor),
+                         .properties = TAKE_PTR(manager->properties),
+                         .rules = TAKE_PTR(manager->rules),
+-                        .pipe_fd = TAKE_FD(manager->worker_watch[WRITE_END]),
++                        .pipe_fd = TAKE_FD(manager->worker_notify_fd),
+                         .inotify_fd = TAKE_FD(manager->inotify_fd),
+                         .config = manager->config,
+                 };
+@@ -1122,7 +1122,7 @@ Manager* manager_new(void) {
+ 
+         *manager = (Manager) {
+                 .inotify_fd = -EBADF,
+-                .worker_watch = EBADF_PAIR,
++                .worker_notify_fd = -EBADF,
+                 .config_by_udev_conf = UDEV_CONFIG_INIT,
+                 .config_by_command = UDEV_CONFIG_INIT,
+                 .config_by_kernel = UDEV_CONFIG_INIT,
+@@ -1320,24 +1320,39 @@ static int manager_start_inotify(Manager *manager) {
+ }
+ 
+ static int manager_start_worker_event(Manager *manager) {
++        _cleanup_(sd_event_source_unrefp) sd_event_source *s = NULL;
++        _cleanup_close_pair_ int pair[2] = EBADF_PAIR;
+         int r;
+ 
+         assert(manager);
+         assert(manager->event);
+ 
+         /* unnamed socket from workers to the main daemon */
+-        r = socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, manager->worker_watch);
++        r = socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, pair);
+         if (r < 0)
+                 return log_error_errno(errno, "Failed to create socketpair for communicating with workers: %m");
+ 
+-        r = setsockopt_int(manager->worker_watch[READ_END], SOL_SOCKET, SO_PASSCRED, true);
++        r = setsockopt_int(pair[READ_END], SOL_SOCKET, SO_PASSCRED, true);
+         if (r < 0)
+                 return log_error_errno(r, "Failed to enable SO_PASSCRED: %m");
+ 
+-        r = sd_event_add_io(manager->event, NULL, manager->worker_watch[READ_END], EPOLLIN, on_worker, manager);
++        r = sd_event_add_io(manager->event, &s, pair[READ_END], EPOLLIN, on_worker, manager);
+         if (r < 0)
+                 return log_error_errno(r, "Failed to create worker event source: %m");
+ 
++        (void) sd_event_source_set_description(s, "manager-worker-event");
++
++        r = sd_event_source_set_io_fd_own(s, true);
++        if (r < 0)
++                return log_error_errno(r, "Failed to make worker event source own file descriptor: %m");
++
++        TAKE_FD(pair[READ_END]);
++
++        r = sd_event_source_set_floating(s, true);
++        if (r < 0)
++                return log_error_errno(r, "Failed to make worker event source floating: %m");
++
++        manager->worker_notify_fd = TAKE_FD(pair[WRITE_END]);
+         return 0;
+ }
+ 
+diff --git a/src/udev/udev-manager.h b/src/udev/udev-manager.h
+index 05f9a8b709..2690d59bf3 100644
+--- a/src/udev/udev-manager.h
++++ b/src/udev/udev-manager.h
+@@ -28,7 +28,7 @@ typedef struct Manager {
+ 
+         sd_device_monitor *monitor;
+         UdevCtrl *ctrl;
+-        int worker_watch[2];
++        int worker_notify_fd;
+ 
+         /* used by udev-watch */
+         int inotify_fd;
diff --git a/SOURCES/0334-udev-dump-split-out-dump_event-from-udevadm-test.c.patch b/SOURCES/0334-udev-dump-split-out-dump_event-from-udevadm-test.c.patch
new file mode 100644
index 0000000000000000000000000000000000000000..0079b6d7d42ab0ddab66ce10ddca73318947a6b9
--- /dev/null
+++ b/SOURCES/0334-udev-dump-split-out-dump_event-from-udevadm-test.c.patch
@@ -0,0 +1,269 @@
+From 2583cd4e5b2f06b9d0dcf5faa4d2e2245560448f Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Sat, 11 Jan 2025 15:56:27 +0900
+Subject: [PATCH] udev-dump: split out dump_event() from udevadm-test.c
+
+(cherry picked from commit 91d9f8f834354a0d541a94e65e389309e32cba9d)
+
+Resolves: RHEL-75774
+---
+ src/udev/meson.build    |  1 +
+ src/udev/udev-dump.c    | 96 +++++++++++++++++++++++++++++++++++++++++
+ src/udev/udev-dump.h    |  8 ++++
+ src/udev/udevadm-test.c | 94 +---------------------------------------
+ 4 files changed, 107 insertions(+), 92 deletions(-)
+ create mode 100644 src/udev/udev-dump.c
+ create mode 100644 src/udev/udev-dump.h
+
+diff --git a/src/udev/meson.build b/src/udev/meson.build
+index 54e12a45e4..171bbd2b70 100644
+--- a/src/udev/meson.build
++++ b/src/udev/meson.build
+@@ -31,6 +31,7 @@ libudevd_core_sources = files(
+         'udev-builtin.c',
+         'udev-config.c',
+         'udev-ctrl.c',
++        'udev-dump.c',
+         'udev-event.c',
+         'udev-format.c',
+         'udev-manager.c',
+diff --git a/src/udev/udev-dump.c b/src/udev/udev-dump.c
+new file mode 100644
+index 0000000000..5900eef8af
+--- /dev/null
++++ b/src/udev/udev-dump.c
+@@ -0,0 +1,96 @@
++/* SPDX-License-Identifier: GPL-2.0-or-later */
++
++#include "ansi-color.h"
++#include "device-private.h"
++#include "device-util.h"
++#include "format-util.h"
++#include "fs-util.h"
++#include "udev-builtin.h"
++#include "udev-dump.h"
++#include "udev-event.h"
++#include "user-util.h"
++
++void dump_event(UdevEvent *event, FILE *f) {
++        sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
++
++        if (!f)
++                f = stdout;
++
++        fprintf(f, "%sProperties:%s\n", ansi_highlight(), ansi_normal());
++        FOREACH_DEVICE_PROPERTY(dev, key, value)
++                fprintf(f, "  %s=%s\n", key, value);
++
++        if (sd_device_get_tag_first(dev)) {
++                fprintf(f, "%sTags:%s\n", ansi_highlight(), ansi_normal());
++                FOREACH_DEVICE_TAG(dev, tag)
++                        fprintf(f, "  %s\n", tag);
++        }
++
++        if (sd_device_get_devnum(dev, NULL) >= 0) {
++
++                if (sd_device_get_devlink_first(dev)) {
++                        int prio;
++                        device_get_devlink_priority(dev, &prio);
++                        fprintf(f, "%sDevice node symlinks:%s (priority=%i)\n", ansi_highlight(), ansi_normal(), prio);
++                        FOREACH_DEVICE_DEVLINK(dev, devlink)
++                                fprintf(f, "  %s\n", devlink);
++                }
++
++                fprintf(f, "%sInotify watch:%s\n  %s\n", ansi_highlight(), ansi_normal(), enabled_disabled(event->inotify_watch));
++
++                uid_t uid = event->uid;
++                if (!uid_is_valid(uid))
++                        (void) device_get_devnode_uid(dev, &uid);
++                if (uid_is_valid(uid)) {
++                        _cleanup_free_ char *user = uid_to_name(uid);
++                        fprintf(f, "%sDevice node owner:%s\n  %s (uid="UID_FMT")\n", ansi_highlight(), ansi_normal(), strna(user), uid);
++                }
++
++                gid_t gid = event->gid;
++                if (!gid_is_valid(uid))
++                        (void) device_get_devnode_gid(dev, &gid);
++                if (gid_is_valid(gid)) {
++                        _cleanup_free_ char *group = gid_to_name(gid);
++                        fprintf(f, "%sDevice node group:%s\n  %s (gid="GID_FMT")\n", ansi_highlight(), ansi_normal(), strna(group), gid);
++                }
++
++                mode_t mode = event->mode;
++                if (mode == MODE_INVALID)
++                        (void) device_get_devnode_mode(dev, &mode);
++                if (mode != MODE_INVALID)
++                        fprintf(f, "%sDevice node permission:%s\n  %04o\n", ansi_highlight(), ansi_normal(), mode);
++
++                if (!ordered_hashmap_isempty(event->seclabel_list)) {
++                        const char *name, *label;
++                        fprintf(f, "%sDevice node security label:%s\n", ansi_highlight(), ansi_normal());
++                        ORDERED_HASHMAP_FOREACH_KEY(label, name, event->seclabel_list)
++                                fprintf(f, "  %s : %s\n", name, label);
++                }
++        }
++
++        if (sd_device_get_ifindex(dev, NULL) >= 0) {
++                if (!isempty(event->name))
++                        fprintf(f, "%sNetwork interface name:%s\n  %s\n", ansi_highlight(), ansi_normal(), event->name);
++
++                if (!strv_isempty(event->altnames)) {
++                        bool space = true;
++                        fprintf(f, "%sAlternative interface names:%s", ansi_highlight(), ansi_normal());
++                        fputstrv(f, event->altnames, "\n  ", &space);
++                        fputs("\n", f);
++                }
++        }
++
++        if (!ordered_hashmap_isempty(event->run_list)) {
++                void *val;
++                const char *command;
++                fprintf(f, "%sQueued commands:%s\n", ansi_highlight(), ansi_normal());
++                ORDERED_HASHMAP_FOREACH_KEY(val, command, event->run_list) {
++                        UdevBuiltinCommand builtin_cmd = PTR_TO_UDEV_BUILTIN_CMD(val);
++
++                        if (builtin_cmd != _UDEV_BUILTIN_INVALID)
++                                fprintf(f, "  RUN{builtin} : %s\n", command);
++                        else
++                                fprintf(f, "  RUN{program} : %s\n", command);
++                }
++        }
++}
+diff --git a/src/udev/udev-dump.h b/src/udev/udev-dump.h
+new file mode 100644
+index 0000000000..6e3f1368ce
+--- /dev/null
++++ b/src/udev/udev-dump.h
+@@ -0,0 +1,8 @@
++/* SPDX-License-Identifier: GPL-2.0-or-later */
++#pragma once
++
++#include <stdio.h>
++
++typedef struct UdevEvent UdevEvent;
++
++void dump_event(UdevEvent *event, FILE *f);
+diff --git a/src/udev/udevadm-test.c b/src/udev/udevadm-test.c
+index 09d1150dd7..5ceb6a5f28 100644
+--- a/src/udev/udevadm-test.c
++++ b/src/udev/udevadm-test.c
+@@ -3,33 +3,19 @@
+  * Copyright © 2003-2004 Greg Kroah-Hartman <greg@kroah.com>
+  */
+ 
+-#include <errno.h>
+ #include <getopt.h>
+ #include <signal.h>
+-#include <stddef.h>
+ #include <stdio.h>
+-#include <stdlib.h>
+-#include <sys/signalfd.h>
+-#include <unistd.h>
+ 
+ #include "sd-device.h"
+ 
+-#include "ansi-color.h"
+ #include "device-private.h"
+-#include "device-util.h"
+-#include "format-util.h"
+-#include "path-util.h"
+-#include "string-util.h"
+-#include "strv.h"
+-#include "strxcpyx.h"
+-#include "terminal-util.h"
+ #include "udev-builtin.h"
++#include "udev-dump.h"
+ #include "udev-event.h"
+-#include "udev-format.h"
+ #include "udev-rules.h"
+ #include "udevadm-util.h"
+ #include "udevadm.h"
+-#include "user-util.h"
+ 
+ static sd_device_action_t arg_action = SD_DEVICE_ADD;
+ static ResolveNameTiming arg_resolve_name_timing = RESOLVE_NAME_EARLY;
+@@ -153,83 +139,7 @@ int test_main(int argc, char *argv[], void *userdata) {
+         puts("Processing udev rules done.");
+ 
+         puts("");
+-        printf("%sProperties:%s\n", ansi_highlight(), ansi_normal());
+-        FOREACH_DEVICE_PROPERTY(dev, key, value)
+-                printf("  %s=%s\n", key, value);
+-
+-        if (sd_device_get_tag_first(dev)) {
+-                printf("%sTags:%s\n", ansi_highlight(), ansi_normal());
+-                FOREACH_DEVICE_TAG(dev, tag)
+-                        printf("  %s\n", tag);
+-        }
+-
+-        if (sd_device_get_devnum(dev, NULL) >= 0) {
+-
+-                if (sd_device_get_devlink_first(dev)) {
+-                        int prio;
+-                        device_get_devlink_priority(dev, &prio);
+-                        printf("%sDevice node symlinks:%s (priority=%i)\n", ansi_highlight(), ansi_normal(), prio);
+-                        FOREACH_DEVICE_DEVLINK(dev, devlink)
+-                                printf("  %s\n", devlink);
+-                }
+-
+-                printf("%sInotify watch:%s\n  %s\n", ansi_highlight(), ansi_normal(), enabled_disabled(event->inotify_watch));
+-
+-                uid_t uid = event->uid;
+-                if (!uid_is_valid(uid))
+-                        (void) device_get_devnode_uid(dev, &uid);
+-                if (uid_is_valid(uid)) {
+-                        _cleanup_free_ char *user = uid_to_name(uid);
+-                        printf("%sDevice node owner:%s\n  %s (uid="UID_FMT")\n", ansi_highlight(), ansi_normal(), strna(user), uid);
+-                }
+-
+-                gid_t gid = event->gid;
+-                if (!gid_is_valid(gid))
+-                        (void) device_get_devnode_gid(dev, &gid);
+-                if (gid_is_valid(gid)) {
+-                        _cleanup_free_ char *group = gid_to_name(gid);
+-                        printf("%sDevice node group:%s\n  %s (gid="GID_FMT")\n", ansi_highlight(), ansi_normal(), strna(group), gid);
+-                }
+-
+-                mode_t mode = event->mode;
+-                if (mode == MODE_INVALID)
+-                        (void) device_get_devnode_mode(dev, &mode);
+-                if (mode != MODE_INVALID)
+-                        printf("%sDevice node permission:%s\n  %04o\n", ansi_highlight(), ansi_normal(), mode);
+-
+-                if (!ordered_hashmap_isempty(event->seclabel_list)) {
+-                        const char *name, *label;
+-                        printf("%sDevice node security label:%s\n", ansi_highlight(), ansi_normal());
+-                        ORDERED_HASHMAP_FOREACH_KEY(label, name, event->seclabel_list)
+-                                printf("  %s : %s\n", name, label);
+-                }
+-        }
+-
+-        if (sd_device_get_ifindex(dev, NULL) >= 0) {
+-                if (!isempty(event->name))
+-                        printf("%sNetwork interface name:%s\n  %s\n", ansi_highlight(), ansi_normal(), event->name);
+-
+-                if (!strv_isempty(event->altnames)) {
+-                        bool space = true;
+-                        printf("%sAlternative interface names:%s", ansi_highlight(), ansi_normal());
+-                        fputstrv(stdout, event->altnames, "\n  ", &space);
+-                        puts("");
+-                }
+-        }
+-
+-        if (!ordered_hashmap_isempty(event->run_list)) {
+-                void *val;
+-                const char *command;
+-                printf("%sQueued commands:%s\n", ansi_highlight(), ansi_normal());
+-                ORDERED_HASHMAP_FOREACH_KEY(val, command, event->run_list) {
+-                        UdevBuiltinCommand builtin_cmd = PTR_TO_UDEV_BUILTIN_CMD(val);
+-
+-                        if (builtin_cmd != _UDEV_BUILTIN_INVALID)
+-                                printf("  RUN{builtin} : %s\n", command);
+-                        else
+-                                printf("  RUN{program} : %s\n", command);
+-                }
+-        }
++        dump_event(event, NULL);
+ 
+         r = 0;
+ out:
diff --git a/SOURCES/0335-udev-rules-introduce-OPTIONS-dump-token.patch b/SOURCES/0335-udev-rules-introduce-OPTIONS-dump-token.patch
new file mode 100644
index 0000000000000000000000000000000000000000..e3b0f7a15385f50687677670852dd629e049648b
--- /dev/null
+++ b/SOURCES/0335-udev-rules-introduce-OPTIONS-dump-token.patch
@@ -0,0 +1,107 @@
+From 3c4bb5e072ce6fa02976bd43d038c1b5b4c392c3 Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Sat, 11 Jan 2025 17:00:17 +0900
+Subject: [PATCH] udev-rules: introduce OPTIONS="dump" token
+
+Should be useful for debugging.
+
+(cherry picked from commit b4ffb776696bdd3a7345f73956ce7551f6b449ff)
+
+Resolves: RHEL-75774
+---
+ man/udev.xml          |  9 +++++++++
+ src/udev/udev-rules.c | 33 ++++++++++++++++++++++++++++++++-
+ 2 files changed, 41 insertions(+), 1 deletion(-)
+
+diff --git a/man/udev.xml b/man/udev.xml
+index e6c0e23ed4..27ebdfc114 100644
+--- a/man/udev.xml
++++ b/man/udev.xml
+@@ -720,6 +720,15 @@ SUBSYSTEM=="net", OPTIONS="log_level=debug"</programlisting></para>
+                     <xi:include href="version-info.xml" xpointer="v248"/>
+                   </listitem>
+                 </varlistentry>
++                <varlistentry>
++                  <term><option>dump</option></term>
++                  <listitem>
++                    <para>Dump the status of the event currently processing. It may be useful for debugging
++                    udev rules by inserting this option.</para>
++
++                    <xi:include href="version-info.xml" xpointer="v258"/>
++                  </listitem>
++                </varlistentry>
+               </variablelist>
+             </listitem>
+           </varlistentry>
+diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c
+index 041c642aa9..d94fc6fdbd 100644
+--- a/src/udev/udev-rules.c
++++ b/src/udev/udev-rules.c
+@@ -18,6 +18,7 @@
+ #include "fs-util.h"
+ #include "glob-util.h"
+ #include "list.h"
++#include "memstream-util.h"
+ #include "mkdir.h"
+ #include "netif-naming-scheme.h"
+ #include "nulstr-util.h"
+@@ -32,6 +33,7 @@
+ #include "sysctl-util.h"
+ #include "syslog-util.h"
+ #include "udev-builtin.h"
++#include "udev-dump.h"
+ #include "udev-event.h"
+ #include "udev-format.h"
+ #include "udev-node.h"
+@@ -117,6 +119,7 @@ typedef enum {
+ #define _TK_A_MIN _TK_M_MAX
+ 
+         /* lvalues which take one of assign operators */
++        TK_A_OPTIONS_DUMP,                  /* no argument */
+         TK_A_OPTIONS_STRING_ESCAPE_NONE,    /* no argument */
+         TK_A_OPTIONS_STRING_ESCAPE_REPLACE, /* no argument */
+         TK_A_OPTIONS_DB_PERSIST,            /* no argument */
+@@ -991,7 +994,9 @@ static int parse_token(
+                 if (op == OP_ADD)
+                         op = OP_ASSIGN;
+ 
+-                if (streq(value, "string_escape=none"))
++                if (streq(value, "dump"))
++                        r = rule_line_add_token(rule_line, TK_A_OPTIONS_DUMP, op, NULL, NULL, /* is_case_insensitive = */ false, token_str);
++                else if (streq(value, "string_escape=none"))
+                         r = rule_line_add_token(rule_line, TK_A_OPTIONS_STRING_ESCAPE_NONE, op, NULL, NULL, /* is_case_insensitive = */ false, token_str);
+                 else if (streq(value, "string_escape=replace"))
+                         r = rule_line_add_token(rule_line, TK_A_OPTIONS_STRING_ESCAPE_REPLACE, op, NULL, NULL, /* is_case_insensitive = */ false, token_str);
+@@ -2551,6 +2556,32 @@ static int udev_rule_apply_token_to_event(
+         case TK_M_RESULT:
+                 return token_match_string(event, token, event->program_result, /* log_result = */ true);
+ 
++        case TK_A_OPTIONS_DUMP: {
++                log_event_info(event, token, "Dumping current state:");
++
++                if (event->event_mode == EVENT_UDEV_WORKER) {
++                        _cleanup_(memstream_done) MemStream m = {};
++                        FILE *f = memstream_init(&m);
++                        if (!f)
++                                return log_oom();
++
++                        dump_event(event, f);
++
++                        _cleanup_free_ char *buf = NULL;
++                        r = memstream_finalize(&m, &buf, NULL);
++                        if (r < 0)
++                                log_event_warning_errno(event, token, r, "Failed to finalize memory stream, ignoring: %m");
++                        else
++                                log_info("%s", buf);
++                } else {
++                        puts("============================");
++                        dump_event(event, NULL);
++                        puts("============================");
++                }
++
++                log_event_info(event, token, "DONE");
++                return true;
++        }
+         case TK_A_OPTIONS_STRING_ESCAPE_NONE:
+                 event->esc = ESCAPE_NONE;
+                 return log_event_done(event, token);
diff --git a/SOURCES/0336-udev-control-move-setting-of-log-level-to-manager_ad.patch b/SOURCES/0336-udev-control-move-setting-of-log-level-to-manager_ad.patch
new file mode 100644
index 0000000000000000000000000000000000000000..ed5deaa14d6bb543d9cef54c749637ef4d323161
--- /dev/null
+++ b/SOURCES/0336-udev-control-move-setting-of-log-level-to-manager_ad.patch
@@ -0,0 +1,44 @@
+From 31fd7f6077e1400450b57c4a1357d476e79b76d8 Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Tue, 21 Jan 2025 04:03:05 +0900
+Subject: [PATCH] udev-control: move setting of log level to
+ manager_adjust_config()
+
+No functional change, just refactoring.
+
+(cherry picked from commit b5a10b2127207c6ddb64ed05d01bc211ccef2981)
+
+Resolves: RHEL-75774
+---
+ src/udev/udev-config.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/udev/udev-config.c b/src/udev/udev-config.c
+index d511691ab2..86a99a5381 100644
+--- a/src/udev/udev-config.c
++++ b/src/udev/udev-config.c
+@@ -320,6 +320,8 @@ void manager_set_log_level(Manager *manager, int log_level) {
+ static void manager_adjust_config(UdevConfig *config) {
+         assert(config);
+ 
++        log_set_max_level(config->log_level);
++
+         if (config->timeout_usec < MIN_WORKER_TIMEOUT_USEC) {
+                 log_debug("Timeout (%s) for processing event is too small, using the default: %s",
+                           FORMAT_TIMESPAN(config->timeout_usec, 1),
+@@ -411,7 +413,6 @@ int manager_load(Manager *manager, int argc, char *argv[]) {
+         if (arg_debug)
+                 log_set_target(LOG_TARGET_CONSOLE);
+ 
+-        log_set_max_level(manager->config.log_level);
+         manager_adjust_config(&manager->config);
+         return 1;
+ }
+@@ -424,7 +425,6 @@ UdevReloadFlags manager_reload_config(Manager *manager) {
+         manager->config_by_udev_conf = UDEV_CONFIG_INIT;
+         manager_parse_udev_config(&manager->config_by_udev_conf);
+         manager_merge_config(manager);
+-        log_set_max_level(manager->config.log_level);
+         manager_adjust_config(&manager->config);
+ 
+         if (manager->config.resolve_name_timing != old.resolve_name_timing)
diff --git a/SOURCES/0337-udev-config-allow-to-enable-trace-logging-through-ke.patch b/SOURCES/0337-udev-config-allow-to-enable-trace-logging-through-ke.patch
new file mode 100644
index 0000000000000000000000000000000000000000..433cda0cd2787424cb55d25c840b62ccd18a91cd
--- /dev/null
+++ b/SOURCES/0337-udev-config-allow-to-enable-trace-logging-through-ke.patch
@@ -0,0 +1,158 @@
+From 72d1239a7505c29375bd78e1ff6126305505b533 Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Sun, 12 Jan 2025 01:35:48 +0900
+Subject: [PATCH] udev-config: allow to enable trace logging through kernel
+ command line
+
+This adds udev.trace[=BOOL] kernel command line option to control trace
+logging.
+
+(cherry picked from commit 695c592a034d98be9c10840c9c89b44013b330a2)
+
+Resolves: RHEL-75774
+---
+ man/kernel-command-line.xml   |  2 ++
+ man/systemd-udevd.service.xml | 10 +++++++++
+ src/udev/udev-config.c        | 41 ++++++++++++++++++++++++++++++-----
+ src/udev/udev-config.h        |  1 +
+ src/udev/udev-worker.c        |  1 +
+ 5 files changed, 49 insertions(+), 6 deletions(-)
+
+diff --git a/man/kernel-command-line.xml b/man/kernel-command-line.xml
+index baa7122204..0a4c8cf11b 100644
+--- a/man/kernel-command-line.xml
++++ b/man/kernel-command-line.xml
+@@ -306,6 +306,8 @@
+       <varlistentry>
+         <term><varname>udev.log_level=</varname></term>
+         <term><varname>rd.udev.log_level=</varname></term>
++        <term><varname>udev.trace=</varname></term>
++        <term><varname>rd.udev.trace=</varname></term>
+         <term><varname>udev.children_max=</varname></term>
+         <term><varname>rd.udev.children_max=</varname></term>
+         <term><varname>udev.exec_delay=</varname></term>
+diff --git a/man/systemd-udevd.service.xml b/man/systemd-udevd.service.xml
+index c781765e1c..2a825a52a2 100644
+--- a/man/systemd-udevd.service.xml
++++ b/man/systemd-udevd.service.xml
+@@ -165,6 +165,16 @@
+         <xi:include href="version-info.xml" xpointer="v247"/>
+         </listitem>
+       </varlistentry>
++      <varlistentry>
++        <term><varname>udev.trace[=<replaceable>BOOL</replaceable>]</varname></term>
++        <term><varname>rd.udev.trace[=<replaceable>BOOL</replaceable>]</varname></term>
++        <listitem>
++          <para>Enable/disable trace logging. When enabled, <varname>udev.log_level=</varname> will be
++          ignored, and <literal>debug</literal> level is assumed.</para>
++
++          <xi:include href="version-info.xml" xpointer="v258"/>
++        </listitem>
++      </varlistentry>
+       <varlistentry>
+         <term><varname>udev.children_max=</varname></term>
+         <term><varname>rd.udev.children_max=</varname></term>
+diff --git a/src/udev/udev-config.c b/src/udev/udev-config.c
+index 86a99a5381..9c806baec2 100644
+--- a/src/udev/udev-config.c
++++ b/src/udev/udev-config.c
+@@ -112,6 +112,20 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
+ 
+                 return 0;
+ 
++        } else if (proc_cmdline_key_streq(key, "udev.trace")) {
++
++                if (!value)
++                        config->trace = true;
++                else {
++                        r = parse_boolean(value);
++                        if (r < 0)
++                                log_warning_errno(r, "Failed to parse udev.trace argument, ignoring: %s", value);
++                        else
++                                config->trace = r;
++                }
++
++                return 0;
++
+         } else {
+                 if (startswith(key, "udev."))
+                         log_warning("Unknown udev kernel command line option \"%s\", ignoring.", key);
+@@ -257,13 +271,24 @@ static int parse_argv(int argc, char *argv[], UdevConfig *config) {
+                 manager->config_by_command.name ||                      \
+                 manager->config_by_udev_conf.name;
+ 
++static void manager_merge_config_log_level(Manager *manager) {
++        assert(manager);
++
++        MERGE_BOOL(trace);
++
++        if (manager->config.trace)
++                manager->config.log_level = LOG_DEBUG;
++        else
++                MERGE_NON_NEGATIVE(log_level, log_get_max_level());
++}
++
+ static void manager_merge_config(Manager *manager) {
+         assert(manager);
+ 
+         /* udev.conf has the lowest priority, then followed by command line arguments, kernel command line
+            options, and values set by udev control. */
+ 
+-        MERGE_NON_NEGATIVE(log_level, log_get_max_level());
++        manager_merge_config_log_level(manager);
+         MERGE_NON_NEGATIVE(resolve_name_timing, RESOLVE_NAME_EARLY);
+         MERGE_NON_ZERO(exec_delay_usec, 0);
+         MERGE_NON_ZERO(timeout_usec, DEFAULT_WORKER_TIMEOUT_USEC);
+@@ -310,11 +335,14 @@ void manager_set_log_level(Manager *manager, int log_level) {
+ 
+         int old = log_get_max_level();
+ 
+-        log_set_max_level(log_level);
+-        manager->config.log_level = manager->config_by_control.log_level = log_level;
++        manager->config_by_control.log_level = log_level;
++        manager_merge_config_log_level(manager);
+ 
+-        if (log_level != old)
+-                manager_kill_workers(manager, /* force = */ false);
++        if (manager->config.log_level == old)
++                return;
++
++        log_set_max_level(manager->config.log_level);
++        manager_kill_workers(manager, /* force = */ false);
+ }
+ 
+ static void manager_adjust_config(UdevConfig *config) {
+@@ -434,7 +462,8 @@ UdevReloadFlags manager_reload_config(Manager *manager) {
+             manager->config.exec_delay_usec != old.exec_delay_usec ||
+             manager->config.timeout_usec != old.timeout_usec ||
+             manager->config.timeout_signal != old.timeout_signal ||
+-            manager->config.blockdev_read_only != old.blockdev_read_only)
++            manager->config.blockdev_read_only != old.blockdev_read_only ||
++            manager->config.trace != old.trace)
+                 return UDEV_RELOAD_KILL_WORKERS;
+ 
+         return 0;
+diff --git a/src/udev/udev-config.h b/src/udev/udev-config.h
+index 68bb1ea98c..9e8a48dae2 100644
+--- a/src/udev/udev-config.h
++++ b/src/udev/udev-config.h
+@@ -18,6 +18,7 @@ typedef struct UdevConfig {
+         usec_t timeout_usec;
+         int timeout_signal;
+         bool blockdev_read_only;
++        bool trace;
+ } UdevConfig;
+ 
+ #define UDEV_CONFIG_INIT                                             \
+diff --git a/src/udev/udev-worker.c b/src/udev/udev-worker.c
+index fc9072e5fd..b26bf3b980 100644
+--- a/src/udev/udev-worker.c
++++ b/src/udev/udev-worker.c
+@@ -183,6 +183,7 @@ static int worker_process_device(UdevWorker *worker, sd_device *dev) {
+         udev_event = udev_event_new(dev, worker, EVENT_UDEV_WORKER);
+         if (!udev_event)
+                 return -ENOMEM;
++        udev_event->trace = worker->config.trace;
+ 
+         /* If this is a block device and the device is locked currently via the BSD advisory locks,
+          * someone else is using it exclusively. We don't run our udev rules now to not interfere.
diff --git a/SOURCES/0338-udev-dump-voidify-one-function-call.patch b/SOURCES/0338-udev-dump-voidify-one-function-call.patch
new file mode 100644
index 0000000000000000000000000000000000000000..af11eb5b6549d934b7de0ec47403e778a6aa989d
--- /dev/null
+++ b/SOURCES/0338-udev-dump-voidify-one-function-call.patch
@@ -0,0 +1,29 @@
+From cde8350ec4085cada729256d3be46e25a6a55aa5 Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Thu, 23 Jan 2025 01:48:04 +0900
+Subject: [PATCH] udev-dump: voidify one function call
+
+Fixes CID#1590377.
+
+(cherry picked from commit f3cbd4da121bd4df8483376fce71663d7bf38937)
+
+Resolves: RHEL-75774
+---
+ src/udev/udev-dump.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/udev/udev-dump.c b/src/udev/udev-dump.c
+index 5900eef8af..26e65979eb 100644
+--- a/src/udev/udev-dump.c
++++ b/src/udev/udev-dump.c
+@@ -29,8 +29,8 @@ void dump_event(UdevEvent *event, FILE *f) {
+         if (sd_device_get_devnum(dev, NULL) >= 0) {
+ 
+                 if (sd_device_get_devlink_first(dev)) {
+-                        int prio;
+-                        device_get_devlink_priority(dev, &prio);
++                        int prio = 0;
++                        (void) device_get_devlink_priority(dev, &prio);
+                         fprintf(f, "%sDevice node symlinks:%s (priority=%i)\n", ansi_highlight(), ansi_normal(), prio);
+                         FOREACH_DEVICE_DEVLINK(dev, devlink)
+                                 fprintf(f, "  %s\n", devlink);
diff --git a/SOURCES/0339-udev-dump-also-show-written-sysfs-attributes-and-sys.patch b/SOURCES/0339-udev-dump-also-show-written-sysfs-attributes-and-sys.patch
new file mode 100644
index 0000000000000000000000000000000000000000..8bc15d1088fb8314a79246a341beb02b3ad18a1c
--- /dev/null
+++ b/SOURCES/0339-udev-dump-also-show-written-sysfs-attributes-and-sys.patch
@@ -0,0 +1,159 @@
+From c95b80ea2e851cc0eecba15c452f83683beae56d Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Sat, 11 Jan 2025 16:38:02 +0900
+Subject: [PATCH] udev-dump: also show written sysfs attributes and sysctl
+ entries
+
+This should be useful to know what is changed by processing an event.
+
+(cherry picked from commit 9ddcccfad7c09e7f69527e0b25781925149ad046)
+
+Resolves: RHEL-75774
+---
+ src/udev/udev-dump.c  | 34 ++++++++++++++++++++++++++++++++++
+ src/udev/udev-dump.h  |  2 ++
+ src/udev/udev-event.c |  2 ++
+ src/udev/udev-event.h |  2 ++
+ src/udev/udev-rules.c | 28 ++++++++++++++++++++++++----
+ 5 files changed, 64 insertions(+), 4 deletions(-)
+
+diff --git a/src/udev/udev-dump.c b/src/udev/udev-dump.c
+index 26e65979eb..918c966c4e 100644
+--- a/src/udev/udev-dump.c
++++ b/src/udev/udev-dump.c
+@@ -10,12 +10,46 @@
+ #include "udev-event.h"
+ #include "user-util.h"
+ 
++static void event_cache_written_value(Hashmap **values, const char *attr, const char *value) {
++        assert(values);
++
++        _unused_ _cleanup_free_ void *key = NULL;
++        free(hashmap_remove2(*values, attr, &key));
++
++        if (hashmap_put_strdup_full(values, &path_hash_ops_free_free, attr, value) < 0)
++                log_oom_debug();
++}
++
++void event_cache_written_sysattr(UdevEvent *event, const char *attr, const char *value) {
++        event_cache_written_value(&event->written_sysattrs, attr, value);
++}
++
++void event_cache_written_sysctl(UdevEvent *event, const char *attr, const char *value) {
++        event_cache_written_value(&event->written_sysctls, attr, value);
++}
++
+ void dump_event(UdevEvent *event, FILE *f) {
+         sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
+ 
+         if (!f)
+                 f = stdout;
+ 
++        if (!hashmap_isempty(event->written_sysattrs)) {
++                const char *key, *value;
++
++                fprintf(f, "%sWritten sysfs attributes:%s\n", ansi_highlight(), ansi_normal());
++                HASHMAP_FOREACH_KEY(value, key, event->written_sysattrs)
++                        fprintf(f, "  %s : %s\n", key, value);
++        }
++
++        if (!hashmap_isempty(event->written_sysctls)) {
++                const char *key, *value;
++
++                fprintf(f, "%sWritten sysctl entries:%s\n", ansi_highlight(), ansi_normal());
++                HASHMAP_FOREACH_KEY(value, key, event->written_sysctls)
++                        fprintf(f, "  %s : %s\n", key, value);
++        }
++
+         fprintf(f, "%sProperties:%s\n", ansi_highlight(), ansi_normal());
+         FOREACH_DEVICE_PROPERTY(dev, key, value)
+                 fprintf(f, "  %s=%s\n", key, value);
+diff --git a/src/udev/udev-dump.h b/src/udev/udev-dump.h
+index 6e3f1368ce..514f8267a7 100644
+--- a/src/udev/udev-dump.h
++++ b/src/udev/udev-dump.h
+@@ -5,4 +5,6 @@
+ 
+ typedef struct UdevEvent UdevEvent;
+ 
++void event_cache_written_sysattr(UdevEvent *event, const char *attr, const char *value);
++void event_cache_written_sysctl(UdevEvent *event, const char *attr, const char *value);
+ void dump_event(UdevEvent *event, FILE *f);
+diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
+index e3661f5bf8..fc4c9f9fd1 100644
+--- a/src/udev/udev-event.c
++++ b/src/udev/udev-event.c
+@@ -54,6 +54,8 @@ static UdevEvent* udev_event_free(UdevEvent *event) {
+         sd_netlink_unref(event->rtnl);
+         ordered_hashmap_free_free_key(event->run_list);
+         ordered_hashmap_free_free_free(event->seclabel_list);
++        hashmap_free(event->written_sysattrs);
++        hashmap_free(event->written_sysctls);
+         free(event->program_result);
+         free(event->name);
+         strv_free(event->altnames);
+diff --git a/src/udev/udev-event.h b/src/udev/udev-event.h
+index 11e2c700e6..d18fb0978b 100644
+--- a/src/udev/udev-event.h
++++ b/src/udev/udev-event.h
+@@ -36,6 +36,8 @@ typedef struct UdevEvent {
+         gid_t gid;
+         OrderedHashmap *seclabel_list;
+         OrderedHashmap *run_list;
++        Hashmap *written_sysattrs;
++        Hashmap *written_sysctls;
+         usec_t birth_usec;
+         unsigned builtin_run;
+         unsigned builtin_ret;
+diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c
+index d94fc6fdbd..dfe521378f 100644
+--- a/src/udev/udev-rules.c
++++ b/src/udev/udev-rules.c
+@@ -2949,11 +2949,19 @@ static int udev_rule_apply_token_to_event(
+                                               WRITE_STRING_FILE_VERIFY_IGNORE_NEWLINE);
+                         if (r < 0)
+                                 log_event_error_errno(event, token, r, "Failed to write \"%s\" to sysfs attribute \"%s\", ignoring: %m", value, buf);
+-                        else
++                        else {
++                                event_cache_written_sysattr(event, buf, value);
+                                 log_event_done(event, token);
+-                } else
++                        }
++                } else {
+                         log_event_debug(event, token, "Running in test mode, skipping writing \"%s\" to sysfs attribute \"%s\".", value, buf);
+ 
++                        r = verify_regular_at(AT_FDCWD, buf, /* follow = */ false);
++                        if (r < 0 && !ERRNO_IS_NEG_PRIVILEGE(r))
++                                log_event_error_errno(event, token, r, "Failed to verify sysfs attribute \"%s\" is a regular file: %m", buf);
++                        else
++                                event_cache_written_sysattr(event, buf, value);
++                }
+                 return true;
+         }
+         case TK_A_SYSCTL: {
+@@ -2972,11 +2980,23 @@ static int udev_rule_apply_token_to_event(
+                         r = sysctl_write(buf, value);
+                         if (r < 0)
+                                 log_event_error_errno(event, token, r, "Failed to write \"%s\" to sysctl entry \"%s\", ignoring: %m", value, buf);
+-                        else
++                        else {
++                                event_cache_written_sysctl(event, buf, value);
+                                 log_event_done(event, token);
+-                } else
++                        }
++                } else {
+                         log_event_debug(event, token, "Running in test mode, skipping writing \"%s\" to sysctl entry \"%s\".", value, buf);
+ 
++                        _cleanup_free_ char *path = path_join("/proc/sys/", buf);
++                        if (!path)
++                                return log_oom();
++
++                        r = verify_regular_at(AT_FDCWD, path, /* follow = */ true);
++                        if (r < 0 && !ERRNO_IS_NEG_PRIVILEGE(r))
++                                log_event_error_errno(event, token, r, "Failed to verify sysctl entry \"%s\" is a regular file: %m", buf);
++                        else
++                                event_cache_written_sysctl(event, buf, value);
++                }
+                 return true;
+         }
+         case TK_A_RUN_BUILTIN:
diff --git a/SOURCES/0340-udevadm-test-allow-to-specify-extra-directories-to-l.patch b/SOURCES/0340-udevadm-test-allow-to-specify-extra-directories-to-l.patch
new file mode 100644
index 0000000000000000000000000000000000000000..4a1cb0b113f8eb15ca4a484efd03b6e40de0e320
--- /dev/null
+++ b/SOURCES/0340-udevadm-test-allow-to-specify-extra-directories-to-l.patch
@@ -0,0 +1,255 @@
+From 5921b074c97620053b63d37adcb665b17ace5238 Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Sat, 11 Jan 2025 17:54:43 +0900
+Subject: [PATCH] udevadm-test: allow to specify extra directories to load udev
+ rules files
+
+This adds -D/--extra-rules-dir=DIR switch for 'udevadm test' command.
+When specified, udev rules files in the specified directory will be also
+loaded. This may be useful for debugging udev rules by copying some udev
+rules files to a temporary directory.
+
+(cherry picked from commit c1b7db56e583dbe98e9c605df45a7f7b09c9751f)
+
+Resolves: RHEL-75774
+---
+ man/udevadm.xml                  | 15 ++++++++++++++
+ shell-completion/bash/udevadm    |  5 ++++-
+ shell-completion/zsh/_udevadm    |  1 +
+ src/udev/test-udev-rule-runner.c |  2 +-
+ src/udev/udev-manager.c          |  4 ++--
+ src/udev/udev-rules.c            | 16 ++++++++++++---
+ src/udev/udev-rules.h            |  2 +-
+ src/udev/udevadm-test.c          | 34 +++++++++++++++++++++++++-------
+ 8 files changed, 64 insertions(+), 15 deletions(-)
+
+diff --git a/man/udevadm.xml b/man/udevadm.xml
+index caa41bd204..79907b30c3 100644
+--- a/man/udevadm.xml
++++ b/man/udevadm.xml
+@@ -869,6 +869,21 @@
+             <xi:include href="version-info.xml" xpointer="v209"/>
+           </listitem>
+         </varlistentry>
++        <varlistentry>
++          <term><option>-D <replaceable>DIR</replaceable></option></term>
++          <term><option>--extra-rules-dir=<replaceable>DIR</replaceable></option></term>
++          <listitem>
++            <para>Also load udev rules files from the specified directory. This option can be specified
++            multiple times. It may be useful for debugging udev rules by copying some udev rules files to a
++            temporary directory, editing them, and specifying the directory with this option. Files found in
++            the specified directories have a higher priority than rules files in the default
++            <filename>udev/rules.d</filename> directories used by <command>systemd-udevd</command>. See
++            <citerefentry><refentrytitle>udev</refentrytitle><manvolnum>7</manvolnum></citerefentry> for more
++            details about the search paths.</para>
++
++            <xi:include href="version-info.xml" xpointer="v258"/>
++          </listitem>
++        </varlistentry>
+         <varlistentry>
+           <term><option>-v</option></term>
+           <term><option>--verbose</option></term>
+diff --git a/shell-completion/bash/udevadm b/shell-completion/bash/udevadm
+index af3a0b9058..76ed04bb7a 100644
+--- a/shell-completion/bash/udevadm
++++ b/shell-completion/bash/udevadm
+@@ -70,7 +70,7 @@ _udevadm() {
+         [MONITOR_STANDALONE]='-k --kernel -u --udev -p --property'
+         [MONITOR_ARG]='-s --subsystem-match -t --tag-match'
+         [TEST_STANDALONE]='-v --verbose'
+-        [TEST_ARG]='-a --action -N --resolve-names'
++        [TEST_ARG]='-a --action -N --resolve-names -D --extra-rules-dir'
+         [TEST_BUILTIN]='-a --action'
+         [VERIFY]='-N --resolve-names --root --no-summary --no-style'
+         [WAIT]='-t --timeout --initialized=no --removed --settle'
+@@ -225,6 +225,9 @@ _udevadm() {
+                     -N|--resolve-names)
+                         comps='early late never'
+                         ;;
++                    -D|--extra-rules-dir)
++                        comps=''
++                        compopt -o dirnames
+                 esac
+             elif [[ $cur = -* ]]; then
+                 comps="${OPTS[COMMON]} ${OPTS[TEST_ARG]} ${OPTS[TEST_STANDALONE]}"
+diff --git a/shell-completion/zsh/_udevadm b/shell-completion/zsh/_udevadm
+index 5c3d3c93ef..792b3e479d 100644
+--- a/shell-completion/zsh/_udevadm
++++ b/shell-completion/zsh/_udevadm
+@@ -87,6 +87,7 @@ _udevadm_test(){
+         '(-)'{-V,--version}'[Show package version]' \
+         '--action=[The action string.]:actions:(add change remove move online offline bind unbind)' \
+         '--subsystem=[The subsystem string.]' \
++        '(-D --extra-rules-dir=)'{-D,--extra-rules-dir=}'[Also load rules from the directory.]' \
+         '(-v --verbose)'{-v,--verbose}'[Show verbose logs.]' \
+         '*::devpath:_files -P /sys/ -W /sys'
+ }
+diff --git a/src/udev/test-udev-rule-runner.c b/src/udev/test-udev-rule-runner.c
+index 9a04abf590..9ad446aa2d 100644
+--- a/src/udev/test-udev-rule-runner.c
++++ b/src/udev/test-udev-rule-runner.c
+@@ -136,7 +136,7 @@ static int run(int argc, char *argv[]) {
+                 usleep_safe(us);
+         }
+ 
+-        assert_se(udev_rules_load(&rules, RESOLVE_NAME_EARLY) == 0);
++        assert_se(udev_rules_load(&rules, RESOLVE_NAME_EARLY, /* extra = */ NULL) == 0);
+ 
+         const char *syspath = strjoina("/sys", devpath);
+         r = device_new_from_synthetic_event(&dev, syspath, action);
+diff --git a/src/udev/udev-manager.c b/src/udev/udev-manager.c
+index 1768da5a38..2c71698bf6 100644
+--- a/src/udev/udev-manager.c
++++ b/src/udev/udev-manager.c
+@@ -281,7 +281,7 @@ static void manager_reload(Manager *manager, bool force) {
+         udev_builtin_reload(flags);
+ 
+         if (FLAGS_SET(flags, UDEV_RELOAD_RULES)) {
+-                r = udev_rules_load(&rules, manager->config.resolve_name_timing);
++                r = udev_rules_load(&rules, manager->config.resolve_name_timing, /* extra = */ NULL);
+                 if (r < 0)
+                         log_warning_errno(r, "Failed to read udev rules, using the previously loaded rules, ignoring: %m");
+                 else
+@@ -1433,7 +1433,7 @@ int manager_main(Manager *manager) {
+ 
+         udev_builtin_init();
+ 
+-        r = udev_rules_load(&manager->rules, manager->config.resolve_name_timing);
++        r = udev_rules_load(&manager->rules, manager->config.resolve_name_timing, /* extra = */ NULL);
+         if (r < 0)
+                 return log_error_errno(r, "Failed to read udev rules: %m");
+ 
+diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c
+index dfe521378f..ec4660968c 100644
+--- a/src/udev/udev-rules.c
++++ b/src/udev/udev-rules.c
+@@ -1778,16 +1778,26 @@ UdevRules* udev_rules_new(ResolveNameTiming resolve_name_timing) {
+         return rules;
+ }
+ 
+-int udev_rules_load(UdevRules **ret_rules, ResolveNameTiming resolve_name_timing) {
++int udev_rules_load(UdevRules **ret_rules, ResolveNameTiming resolve_name_timing, char * const *extra) {
+         _cleanup_(udev_rules_freep) UdevRules *rules = NULL;
+-        _cleanup_strv_free_ char **files = NULL;
++        _cleanup_strv_free_ char **files = NULL, **directories = NULL;
+         int r;
+ 
+         rules = udev_rules_new(resolve_name_timing);
+         if (!rules)
+                 return -ENOMEM;
+ 
+-        r = conf_files_list_strv(&files, ".rules", NULL, 0, RULES_DIRS);
++        if (!strv_isempty(extra)) {
++                directories = strv_copy(extra);
++                if (!directories)
++                        return -ENOMEM;
++        }
++
++        r = strv_extend_strv(&directories, CONF_PATHS_STRV("udev/rules.d"), /* filter_duplicates = */ false);
++        if (r < 0)
++                return r;
++
++        r = conf_files_list_strv(&files, ".rules", NULL, 0, (const char* const*) directories);
+         if (r < 0)
+                 return log_debug_errno(r, "Failed to enumerate rules files: %m");
+ 
+diff --git a/src/udev/udev-rules.h b/src/udev/udev-rules.h
+index 67d7e5b178..62dac5ba73 100644
+--- a/src/udev/udev-rules.h
++++ b/src/udev/udev-rules.h
+@@ -14,7 +14,7 @@ int udev_rule_parse_value(char *str, char **ret_value, char **ret_endpos, bool *
+ int udev_rules_parse_file(UdevRules *rules, const char *filename, bool extra_checks, UdevRuleFile **ret);
+ unsigned udev_rule_file_get_issues(UdevRuleFile *rule_file);
+ UdevRules* udev_rules_new(ResolveNameTiming resolve_name_timing);
+-int udev_rules_load(UdevRules **ret_rules, ResolveNameTiming resolve_name_timing);
++int udev_rules_load(UdevRules **ret_rules, ResolveNameTiming resolve_name_timing, char * const *extra);
+ UdevRules* udev_rules_free(UdevRules *rules);
+ DEFINE_TRIVIAL_CLEANUP_FUNC(UdevRules*, udev_rules_free);
+ #define udev_rules_free_and_replace(a, b) free_and_replace_full(a, b, udev_rules_free)
+diff --git a/src/udev/udevadm-test.c b/src/udev/udevadm-test.c
+index 5ceb6a5f28..c3f56d2d81 100644
+--- a/src/udev/udevadm-test.c
++++ b/src/udev/udevadm-test.c
+@@ -10,6 +10,9 @@
+ #include "sd-device.h"
+ 
+ #include "device-private.h"
++#include "parse-argument.h"
++#include "static-destruct.h"
++#include "strv.h"
+ #include "udev-builtin.h"
+ #include "udev-dump.h"
+ #include "udev-event.h"
+@@ -20,8 +23,11 @@
+ static sd_device_action_t arg_action = SD_DEVICE_ADD;
+ static ResolveNameTiming arg_resolve_name_timing = RESOLVE_NAME_EARLY;
+ static const char *arg_syspath = NULL;
++static char **arg_extra_rules_dir = NULL;
+ static bool arg_verbose = false;
+ 
++STATIC_DESTRUCTOR_REGISTER(arg_extra_rules_dir, strv_freep);
++
+ static int help(void) {
+ 
+         printf("%s test [OPTIONS] DEVPATH\n\n"
+@@ -30,6 +36,7 @@ static int help(void) {
+                "  -V --version                         Show package version\n"
+                "  -a --action=ACTION|help              Set action string\n"
+                "  -N --resolve-names=early|late|never  When to resolve names\n"
++               "  -D --extra-rules-dir=DIR             Also load rules from the directory\n"
+                "  -v --verbose                         Show verbose logs\n",
+                program_invocation_short_name);
+ 
+@@ -38,17 +45,18 @@ static int help(void) {
+ 
+ static int parse_argv(int argc, char *argv[]) {
+         static const struct option options[] = {
+-                { "action",        required_argument, NULL, 'a' },
+-                { "resolve-names", required_argument, NULL, 'N' },
+-                { "verbose",       no_argument,       NULL, 'v' },
+-                { "version",       no_argument,       NULL, 'V' },
+-                { "help",          no_argument,       NULL, 'h' },
++                { "action",          required_argument, NULL, 'a' },
++                { "resolve-names",   required_argument, NULL, 'N' },
++                { "extra-rules-dir", required_argument, NULL, 'D' },
++                { "verbose",         no_argument,       NULL, 'v' },
++                { "version",         no_argument,       NULL, 'V' },
++                { "help",            no_argument,       NULL, 'h' },
+                 {}
+         };
+ 
+         int r, c;
+ 
+-        while ((c = getopt_long(argc, argv, "a:N:vVh", options, NULL)) >= 0)
++        while ((c = getopt_long(argc, argv, "a:N:D:vVh", options, NULL)) >= 0)
+                 switch (c) {
+                 case 'a':
+                         r = parse_device_action(optarg, &arg_action);
+@@ -63,6 +71,18 @@ static int parse_argv(int argc, char *argv[]) {
+                                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                                        "--resolve-names= must be early, late or never");
+                         break;
++                case 'D': {
++                        _cleanup_free_ char *p = NULL;
++
++                        r = parse_path_argument(optarg, /* suppress_root = */ false, &p);
++                        if (r < 0)
++                                return r;
++
++                        r = strv_consume(&arg_extra_rules_dir, TAKE_PTR(p));
++                        if (r < 0)
++                                return log_oom();
++                        break;
++                }
+                 case 'v':
+                         arg_verbose = true;
+                         break;
+@@ -108,7 +128,7 @@ int test_main(int argc, char *argv[], void *userdata) {
+         puts("Loading builtins done.");
+ 
+         puts("\nLoading udev rules files...");
+-        r = udev_rules_load(&rules, arg_resolve_name_timing);
++        r = udev_rules_load(&rules, arg_resolve_name_timing, arg_extra_rules_dir);
+         if (r < 0) {
+                 log_error_errno(r, "Failed to read udev rules: %m");
+                 goto out;
diff --git a/SOURCES/0341-shell-completion-udevadm-add-net_driver.patch b/SOURCES/0341-shell-completion-udevadm-add-net_driver.patch
new file mode 100644
index 0000000000000000000000000000000000000000..df549aed1d04303bc942ab9a0cf28ec2acb7e184
--- /dev/null
+++ b/SOURCES/0341-shell-completion-udevadm-add-net_driver.patch
@@ -0,0 +1,41 @@
+From 631e0ca15fd5073199653c6591a65575b9978e0d Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Tue, 7 Jan 2025 17:39:12 +0900
+Subject: [PATCH] shell-completion/udevadm: add net_driver
+
+Follow-up for 2b5b25f123ceb89b3ff45b2380db1c8a88b046d9.
+
+(cherry picked from commit c3d526d765ee41905661c034c348c915a2f49625)
+
+Resolves: RHEL-75774
+---
+ shell-completion/bash/udevadm | 2 +-
+ shell-completion/zsh/_udevadm | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/shell-completion/bash/udevadm b/shell-completion/bash/udevadm
+index 76ed04bb7a..496eac5fd7 100644
+--- a/shell-completion/bash/udevadm
++++ b/shell-completion/bash/udevadm
+@@ -78,7 +78,7 @@ _udevadm() {
+     )
+ 
+     local verbs=(info trigger settle control monitor test-builtin test verify wait lock)
+-    local builtins=(blkid btrfs hwdb input_id keyboard kmod net_id net_setup_link path_id usb_id uaccess)
++    local builtins=(blkid btrfs hwdb input_id keyboard kmod net_driver net_id net_setup_link path_id uaccess usb_id)
+ 
+     for ((i=0; i < COMP_CWORD; i++)); do
+         if __contains_word "${COMP_WORDS[i]}" "${verbs[@]}"; then
+diff --git a/shell-completion/zsh/_udevadm b/shell-completion/zsh/_udevadm
+index 792b3e479d..63db11cea9 100644
+--- a/shell-completion/zsh/_udevadm
++++ b/shell-completion/zsh/_udevadm
+@@ -99,7 +99,7 @@ _udevadm_test-builtin(){
+         '(- *)'{-h,--help}'[Print help]' \
+         '(- *)'{-V,--version}'[Print version of the program]' \
+         '--action=[The action string.]:actions:(add change remove move online offline bind unbind)' \
+-        '*::builtins:(blkid btrfs hwdb input_id net_id net_setup_link kmod path_id usb_id uaccess)'
++        '*::builtins:(blkid btrfs hwdb input_id net_driver net_id net_setup_link kmod path_id uaccess usb_id)'
+     elif  (( CURRENT == 3 )); then
+         _arguments \
+             '--action=[The action string.]:actions:(add change remove move online offline bind unbind)' \
diff --git a/SOURCES/0342-udev-sort-builtins.patch b/SOURCES/0342-udev-sort-builtins.patch
new file mode 100644
index 0000000000000000000000000000000000000000..ffa1fcc5f206d07291609c4a75de12fd4369a370
--- /dev/null
+++ b/SOURCES/0342-udev-sort-builtins.patch
@@ -0,0 +1,76 @@
+From 2cfdc83a3c0eb749448d63d072fb00f42d63084c Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Tue, 7 Jan 2025 17:41:41 +0900
+Subject: [PATCH] udev: sort builtins
+
+Then, 'udevadm test-builtin --help' lists builtins alphabetically.
+
+(cherry picked from commit 86a08e70a83330bc003432cf0d00ff5341acf0a0)
+
+Resolves: RHEL-75774
+---
+ src/udev/udev-builtin.c | 2 +-
+ src/udev/udev-builtin.h | 2 +-
+ src/udev/udev-def.h     | 4 ++--
+ 3 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/src/udev/udev-builtin.c b/src/udev/udev-builtin.c
+index 3d22ddf945..fc6ecc095b 100644
+--- a/src/udev/udev-builtin.c
++++ b/src/udev/udev-builtin.c
+@@ -26,10 +26,10 @@ static const UdevBuiltin *const builtins[_UDEV_BUILTIN_MAX] = {
+         [UDEV_BUILTIN_NET_ID] = &udev_builtin_net_id,
+         [UDEV_BUILTIN_NET_LINK] = &udev_builtin_net_setup_link,
+         [UDEV_BUILTIN_PATH_ID] = &udev_builtin_path_id,
+-        [UDEV_BUILTIN_USB_ID] = &udev_builtin_usb_id,
+ #if HAVE_ACL
+         [UDEV_BUILTIN_UACCESS] = &udev_builtin_uaccess,
+ #endif
++        [UDEV_BUILTIN_USB_ID] = &udev_builtin_usb_id,
+ };
+ 
+ void udev_builtin_init(void) {
+diff --git a/src/udev/udev-builtin.h b/src/udev/udev-builtin.h
+index 3b5f3bd120..83cf103ab5 100644
+--- a/src/udev/udev-builtin.h
++++ b/src/udev/udev-builtin.h
+@@ -47,10 +47,10 @@ extern const UdevBuiltin udev_builtin_net_driver;
+ extern const UdevBuiltin udev_builtin_net_id;
+ extern const UdevBuiltin udev_builtin_net_setup_link;
+ extern const UdevBuiltin udev_builtin_path_id;
+-extern const UdevBuiltin udev_builtin_usb_id;
+ #if HAVE_ACL
+ extern const UdevBuiltin udev_builtin_uaccess;
+ #endif
++extern const UdevBuiltin udev_builtin_usb_id;
+ 
+ void udev_builtin_init(void);
+ void udev_builtin_exit(void);
+diff --git a/src/udev/udev-def.h b/src/udev/udev-def.h
+index ed231764bc..c157c487cf 100644
+--- a/src/udev/udev-def.h
++++ b/src/udev/udev-def.h
+@@ -50,10 +50,10 @@ typedef enum UdevBuiltinCommand {
+         UDEV_BUILTIN_NET_ID,
+         UDEV_BUILTIN_NET_LINK,
+         UDEV_BUILTIN_PATH_ID,
+-        UDEV_BUILTIN_USB_ID,
+ #if HAVE_ACL
+         UDEV_BUILTIN_UACCESS,
+ #endif
++        UDEV_BUILTIN_USB_ID,
+         _UDEV_BUILTIN_MAX,
+         _UDEV_BUILTIN_INVALID = -EINVAL,
+ } UdevBuiltinCommand;
+@@ -73,10 +73,10 @@ typedef enum UdevReloadFlags {
+         UDEV_RELOAD_BUILTIN_NET_ID   = 1u << UDEV_BUILTIN_NET_ID,
+         UDEV_RELOAD_BUILTIN_NET_LINK = 1u << UDEV_BUILTIN_NET_LINK,
+         UDEV_RELOAD_BUILTIN_PATH_ID  = 1u << UDEV_BUILTIN_PATH_ID,
+-        UDEV_RELOAD_BUILTIN_USB_ID   = 1u << UDEV_BUILTIN_USB_ID,
+ #if HAVE_ACL
+         UDEV_RELOAD_BUILTIN_UACCESS  = 1u << UDEV_BUILTIN_UACCESS,
+ #endif
++        UDEV_RELOAD_BUILTIN_USB_ID   = 1u << UDEV_BUILTIN_USB_ID,
+         UDEV_RELOAD_KILL_WORKERS     = 1u << (_UDEV_BUILTIN_MAX + 0),
+         UDEV_RELOAD_RULES            = 1u << (_UDEV_BUILTIN_MAX + 1),
+ } UdevReloadFlags;
diff --git a/SOURCES/0343-udev-rules-log-the-first-line-number-when-continued.patch b/SOURCES/0343-udev-rules-log-the-first-line-number-when-continued.patch
new file mode 100644
index 0000000000000000000000000000000000000000..d8e9ead1c40c438f72756db0da3568c1356f62cc
--- /dev/null
+++ b/SOURCES/0343-udev-rules-log-the-first-line-number-when-continued.patch
@@ -0,0 +1,64 @@
+From 962169813b50b3497574e21bed4692046f23affe Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Sat, 11 Jan 2025 03:45:38 +0900
+Subject: [PATCH] udev-rules: log the first line number when continued
+
+(cherry picked from commit 8e0f023548fae141acc6e3fb2a2ae4de4a284960)
+
+Resolves: RHEL-75774
+---
+ src/udev/udev-rules.c         | 12 ++++++++----
+ test/units/TEST-17-UDEV.11.sh |  2 +-
+ 2 files changed, 9 insertions(+), 5 deletions(-)
+
+diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c
+index ec4660968c..4d9fbd39a5 100644
+--- a/src/udev/udev-rules.c
++++ b/src/udev/udev-rules.c
+@@ -1631,10 +1631,8 @@ static void udev_check_rule_line(UdevRuleLine *line) {
+ 
+ int udev_rules_parse_file(UdevRules *rules, const char *filename, bool extra_checks, UdevRuleFile **ret) {
+         _cleanup_(udev_rule_file_freep) UdevRuleFile *rule_file = NULL;
+-        _cleanup_free_ char *continuation = NULL, *name = NULL;
++        _cleanup_free_ char *name = NULL;
+         _cleanup_fclose_ FILE *f = NULL;
+-        bool ignore_line = false;
+-        unsigned line_nr = 0;
+         struct stat st;
+         int r;
+ 
+@@ -1685,6 +1683,9 @@ int udev_rules_parse_file(UdevRules *rules, const char *filename, bool extra_che
+ 
+         LIST_APPEND(rule_files, rules->rule_files, rule_file);
+ 
++        _cleanup_free_ char *continuation = NULL;
++        unsigned line_nr = 0, current_line_nr = 0;
++        bool ignore_line = false;
+         for (;;) {
+                 _cleanup_free_ char *buf = NULL;
+                 size_t len;
+@@ -1696,7 +1697,10 @@ int udev_rules_parse_file(UdevRules *rules, const char *filename, bool extra_che
+                 if (r == 0)
+                         break;
+ 
+-                line_nr++;
++                current_line_nr++;
++                if (!continuation)
++                        line_nr = current_line_nr;
++
+                 line = skip_leading_chars(buf, NULL);
+ 
+                 /* Lines beginning with '#' are ignored regardless of line continuation. */
+diff --git a/test/units/TEST-17-UDEV.11.sh b/test/units/TEST-17-UDEV.11.sh
+index 8413d3c189..c0d87b7151 100755
+--- a/test/units/TEST-17-UDEV.11.sh
++++ b/test/units/TEST-17-UDEV.11.sh
+@@ -174,7 +174,7 @@ assert_0 "${rules}"
+ printf 'RUN+="/bin/true"%8176s\\\n #\n' ' ' ' ' >"${rules}"
+ echo >>"${rules}"
+ cat >"${exp}" <<EOF
+-${rules}:5 Line is too long, ignored.
++${rules}:1 Line is too long, ignored.
+ ${rules}: udev rules check failed.
+ EOF
+ assert_1 "${rules}"
diff --git a/SOURCES/0344-chase-introduce-flags-that-verify-that-chased-inode-.patch b/SOURCES/0344-chase-introduce-flags-that-verify-that-chased-inode-.patch
new file mode 100644
index 0000000000000000000000000000000000000000..70973dc200f6bfc9759be799eb2b21b900a89442
--- /dev/null
+++ b/SOURCES/0344-chase-introduce-flags-that-verify-that-chased-inode-.patch
@@ -0,0 +1,96 @@
+From a5486de446d4312b9bebdcb3ab8d6325187930f6 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Mon, 13 Jan 2025 13:12:23 +0100
+Subject: [PATCH] chase: introduce flags that verify that chased inode is
+ regular file or dir
+
+This also implies the new CHASE_MUST_BE_DIRECTORY flag in case the
+specified path ends in a slash. This makes the rules stricter, it means
+we'll be closer to how this is handled in kernel: if a path ends in a
+slash it can never refer to a non-directory.
+
+(cherry picked from commit 90b9f7a07e6f57825f416f6ce2db0a9f2086754b)
+
+Resolves: RHEL-75774
+---
+ src/basic/chase.c             | 20 +++++++++++++++++---
+ src/basic/chase.h             |  2 ++
+ src/shared/machine-id-setup.c |  2 +-
+ 3 files changed, 20 insertions(+), 4 deletions(-)
+
+diff --git a/src/basic/chase.c b/src/basic/chase.c
+index 8eac356665..e5a6fb1587 100644
+--- a/src/basic/chase.c
++++ b/src/basic/chase.c
+@@ -89,6 +89,7 @@ int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int
+         int r;
+ 
+         assert(!FLAGS_SET(flags, CHASE_PREFIX_ROOT));
++        assert(!FLAGS_SET(flags, CHASE_MUST_BE_DIRECTORY|CHASE_MUST_BE_REGULAR));
+         assert(!FLAGS_SET(flags, CHASE_STEP|CHASE_EXTRACT_FILENAME));
+         assert(!FLAGS_SET(flags, CHASE_TRAIL_SLASH|CHASE_EXTRACT_FILENAME));
+         assert(!FLAGS_SET(flags, CHASE_MKDIR_0755) || (flags & (CHASE_NONEXISTENT | CHASE_PARENT)) != 0);
+@@ -244,8 +245,15 @@ int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int
+         if (root_fd < 0)
+                 return -errno;
+ 
+-        if (FLAGS_SET(flags, CHASE_TRAIL_SLASH))
+-                append_trail_slash = ENDSWITH_SET(buffer, "/", "/.");
++        if (ENDSWITH_SET(buffer, "/", "/.")) {
++                flags |= CHASE_MUST_BE_DIRECTORY;
++                if (FLAGS_SET(flags, CHASE_TRAIL_SLASH))
++                        append_trail_slash = true;
++        } else if (dot_or_dot_dot(buffer) || endswith(buffer, "/.."))
++                flags |= CHASE_MUST_BE_DIRECTORY;
++
++        if (FLAGS_SET(flags, CHASE_PARENT))
++                flags |= CHASE_MUST_BE_DIRECTORY;
+ 
+         for (todo = buffer;;) {
+                 _cleanup_free_ char *first = NULL;
+@@ -477,12 +485,18 @@ int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int
+                 close_and_replace(fd, child);
+         }
+ 
+-        if (FLAGS_SET(flags, CHASE_PARENT)) {
++        if (FLAGS_SET(flags, CHASE_MUST_BE_DIRECTORY)) {
+                 r = stat_verify_directory(&st);
+                 if (r < 0)
+                         return r;
+         }
+ 
++        if (FLAGS_SET(flags, CHASE_MUST_BE_REGULAR)) {
++                r = stat_verify_regular(&st);
++                if (r < 0)
++                        return r;
++        }
++
+         if (ret_path) {
+                 if (FLAGS_SET(flags, CHASE_EXTRACT_FILENAME) && done) {
+                         _cleanup_free_ char *f = NULL;
+diff --git a/src/basic/chase.h b/src/basic/chase.h
+index cfc714b9f7..2d708b4bae 100644
+--- a/src/basic/chase.h
++++ b/src/basic/chase.h
+@@ -33,6 +33,8 @@ typedef enum ChaseFlags {
+                                              * when internally call chase(), hence CHASE_MKDIR_0755 can be
+                                              * safely set without CHASE_NONEXISTENT and CHASE_PARENT. */
+         CHASE_EXTRACT_FILENAME   = 1 << 12, /* Only return the last component of the resolved path */
++        CHASE_MUST_BE_DIRECTORY  = 1 << 13, /* Fail if returned inode fd is not a dir */
++        CHASE_MUST_BE_REGULAR    = 1 << 14, /* Fail if returned inode fd is not a regular file */
+ } ChaseFlags;
+ 
+ bool unsafe_transition(const struct stat *a, const struct stat *b);
+diff --git a/src/shared/machine-id-setup.c b/src/shared/machine-id-setup.c
+index f5e1b9ee72..4e355d8144 100644
+--- a/src/shared/machine-id-setup.c
++++ b/src/shared/machine-id-setup.c
+@@ -74,7 +74,7 @@ static int acquire_machine_id(const char *root, bool machine_id_from_firmware, s
+         }
+ 
+         /* Then, try reading the D-Bus machine ID, unless it is a symlink */
+-        fd = chase_and_open("/var/lib/dbus/machine-id", root, CHASE_PREFIX_ROOT | CHASE_NOFOLLOW, O_RDONLY|O_CLOEXEC|O_NOCTTY, NULL);
++        fd = chase_and_open("/var/lib/dbus/machine-id", root, CHASE_PREFIX_ROOT|CHASE_NOFOLLOW|CHASE_MUST_BE_REGULAR, O_RDONLY|O_CLOEXEC|O_NOCTTY, NULL);
+         if (fd >= 0 && id128_read_fd(fd, ID128_FORMAT_PLAIN | ID128_REFUSE_NULL, ret) >= 0) {
+                 log_info("Initializing machine ID from D-Bus machine ID.");
+                 return 0;
diff --git a/SOURCES/0345-udevadm-verify-chase-specified-paths.patch b/SOURCES/0345-udevadm-verify-chase-specified-paths.patch
new file mode 100644
index 0000000000000000000000000000000000000000..42303f44f02180c5a07477c30adf3b836af3193c
--- /dev/null
+++ b/SOURCES/0345-udevadm-verify-chase-specified-paths.patch
@@ -0,0 +1,541 @@
+From 109617461d161e7a0e1a167a4cef92830628f671 Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Thu, 9 Jan 2025 10:27:11 +0900
+Subject: [PATCH] udevadm-verify: chase specified paths
+
+Also, when a filename is specified, also search udev rules file in
+udev/rules.d directories.
+
+This also refuses non-existing files, and file neither nor a regular
+nor a directory, e.g. /dev/null.
+
+(cherry picked from commit 7cb4508c5af465ab1be1b103e6c2b613eb58e63c)
+
+Resolves: RHEL-75774
+---
+ man/udevadm.xml               |  28 +++++----
+ src/udev/udevadm-util.c       | 109 ++++++++++++++++++++++++++++++++++
+ src/udev/udevadm-util.h       |   1 +
+ src/udev/udevadm-verify.c     |  85 ++++++--------------------
+ test/units/TEST-17-UDEV.11.sh |  79 ++++++++++++------------
+ 5 files changed, 182 insertions(+), 120 deletions(-)
+
+diff --git a/man/udevadm.xml b/man/udevadm.xml
+index 79907b30c3..eed84d27cc 100644
+--- a/man/udevadm.xml
++++ b/man/udevadm.xml
+@@ -935,9 +935,15 @@
+ 
+       <para>Verify syntactic, semantic, and stylistic correctness of udev rules files.</para>
+ 
+-      <para>Positional arguments could be used to specify one or more files to check.
+-      If no files are specified, the udev rules are read from the files located in
+-      the same udev/rules.d directories that are processed by the udev daemon.</para>
++      <para>Positional arguments can be used to specify one or more files to check. Each argument must be an
++      absolute path to a udev rules file or a directory that contains rules files, or a file name of udev
++      rules file (e.g. <filename>99-systemd.rules</filename>). If a file name is specified, the file will be
++      searched in the <filename>udev/rules.d</filename> directories that are processed by
++      <command>systemd-udevd</command>, and searched in the current working directory if not found. If no
++      files are specified, the udev rules are read from the files located in the same
++      <filename>udev/rules.d</filename> directories that are processed by <command>systemd-udevd</command>.
++      See <citerefentry><refentrytitle>udev</refentrytitle><manvolnum>7</manvolnum></citerefentry> for more
++      details about the search paths.</para>
+ 
+       <para>The exit status is <constant>0</constant> if all specified udev
+       rules files are syntactically, semantically, and stylistically correct,
+@@ -961,8 +967,11 @@
+         <varlistentry>
+           <term><option>--root=<replaceable>PATH</replaceable></option></term>
+           <listitem>
+-            <para>When looking for udev rules files located in udev/rules.d directories,
+-            operate on files underneath the specified root path <replaceable>PATH</replaceable>.</para>
++            <para>When looking for udev rules files located in the <filename>udev/rules.d</filename>
++            directories, operate on files underneath the specified root path <replaceable>PATH</replaceable>.
++            When a file name is specified, and it is not found in the <filename>udev/rules.d</filename>
++            directories, the file will be searched in the specified root path
++            <replaceable>PATH</replaceable>, rather than the current working directory.</para>
+ 
+             <xi:include href="version-info.xml" xpointer="v254"/>
+           </listitem>
+@@ -1192,12 +1201,9 @@
+   <refsect1>
+     <title>See Also</title>
+     <para><simplelist type="inline">
+-      <member><citerefentry>
+-        <refentrytitle>udev</refentrytitle><manvolnum>7</manvolnum>
+-      </citerefentry></member>
+-      <member><citerefentry>
+-        <refentrytitle>systemd-udevd.service</refentrytitle><manvolnum>8</manvolnum>
+-      </citerefentry></member>
++      <member><citerefentry><refentrytitle>udev</refentrytitle><manvolnum>7</manvolnum></citerefentry></member>
++      <member><citerefentry><refentrytitle>systemd-udevd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry></member>
++      <member><citerefentry><refentrytitle>udev.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry></member>
+     </simplelist></para>
+   </refsect1>
+ </refentry>
+diff --git a/src/udev/udevadm-util.c b/src/udev/udevadm-util.c
+index 2447edad19..4aa5e6b6d7 100644
+--- a/src/udev/udevadm-util.c
++++ b/src/udev/udevadm-util.c
+@@ -5,6 +5,9 @@
+ #include "alloc-util.h"
+ #include "bus-error.h"
+ #include "bus-util.h"
++#include "chase.h"
++#include "conf-files.h"
++#include "constants.h"
+ #include "device-private.h"
+ #include "path-util.h"
+ #include "udevadm-util.h"
+@@ -122,3 +125,109 @@ int parse_device_action(const char *str, sd_device_action_t *action) {
+         *action = a;
+         return 1;
+ }
++
++static int search_rules_file_in_conf_dirs(const char *s, const char *root, char ***files) {
++        _cleanup_free_ char *filename = NULL;
++        int r;
++
++        assert(s);
++
++        if (!endswith(s, ".rules"))
++                filename = strjoin(s, ".rules");
++        else
++                filename = strdup(s);
++        if (!filename)
++                return log_oom();
++
++        if (!filename_is_valid(filename))
++                return 0;
++
++        STRV_FOREACH(p, CONF_PATHS_STRV("udev/rules.d")) {
++                _cleanup_free_ char *path = NULL, *resolved = NULL;
++
++                path = path_join(*p, filename);
++                if (!path)
++                        return log_oom();
++
++                r = chase(path, root, CHASE_PREFIX_ROOT | CHASE_MUST_BE_REGULAR, &resolved, /* ret_fd = */ NULL);
++                if (r == -ENOENT)
++                        continue;
++                if (r < 0)
++                        return log_error_errno(r, "Failed to chase \"%s\": %m", path);
++
++                r = strv_consume(files, TAKE_PTR(resolved));
++                if (r < 0)
++                        return log_oom();
++
++                return 1; /* found */
++        }
++
++        return 0;
++}
++
++static int search_rules_file(const char *s, const char *root, char ***files) {
++        int r;
++
++        assert(s);
++        assert(files);
++
++        /* If the input is a file name (e.g. 99-systemd.rules), then try to find it in udev/rules.d directories. */
++        r = search_rules_file_in_conf_dirs(s, root, files);
++        if (r != 0)
++                return r;
++
++        /* If not found, or if it is a path, then chase it. */
++        struct stat st;
++        _cleanup_free_ char *resolved = NULL;
++        r = chase_and_stat(s, root, CHASE_PREFIX_ROOT, &resolved, &st);
++        if (r < 0)
++                return log_error_errno(r, "Failed to chase \"%s\": %m", s);
++
++        r = stat_verify_regular(&st);
++        if (r == -EISDIR) {
++                _cleanup_strv_free_ char **files_in_dir = NULL;
++
++                r = conf_files_list_strv(&files_in_dir, ".rules", root, 0, (const char* const*) STRV_MAKE_CONST(s));
++                if (r < 0)
++                        return log_error_errno(r, "Failed to enumerate rules files in '%s': %m", resolved);
++
++                r = strv_extend_strv_consume(files, TAKE_PTR(files_in_dir), /* filter_duplicates = */ false);
++                if (r < 0)
++                        return log_oom();
++
++                return 0;
++        }
++        if (r < 0)
++                return log_error_errno(r, "'%s' is neither a regular file nor a directory: %m", resolved);
++
++        r = strv_consume(files, TAKE_PTR(resolved));
++        if (r < 0)
++                return log_oom();
++
++        return 0;
++}
++
++int search_rules_files(char * const *a, const char *root, char ***ret) {
++        _cleanup_strv_free_ char **files = NULL;
++        int r;
++
++        assert(ret);
++
++        if (strv_isempty(a)) {
++                r = conf_files_list_strv(&files, ".rules", root, 0, (const char* const*) CONF_PATHS_STRV("udev/rules.d"));
++                if (r < 0)
++                        return log_error_errno(r, "Failed to enumerate rules files: %m");
++
++                if (root && strv_isempty(files))
++                        return log_error_errno(SYNTHETIC_ERRNO(ENOENT), "No rules files found in %s.", root);
++
++        } else
++                STRV_FOREACH(s, a) {
++                        r = search_rules_file(*s, root, &files);
++                        if (r < 0)
++                                return r;
++                }
++
++        *ret = TAKE_PTR(files);
++        return 0;
++}
+diff --git a/src/udev/udevadm-util.h b/src/udev/udevadm-util.h
+index 7fb4556413..9a396a1faa 100644
+--- a/src/udev/udevadm-util.h
++++ b/src/udev/udevadm-util.h
+@@ -6,3 +6,4 @@
+ int find_device(const char *id, const char *prefix, sd_device **ret);
+ int find_device_with_action(const char *id, sd_device_action_t action, sd_device **ret);
+ int parse_device_action(const char *str, sd_device_action_t *action);
++int search_rules_files(char * const *a, const char *root, char ***ret);
+diff --git a/src/udev/udevadm-verify.c b/src/udev/udevadm-verify.c
+index 32202508f3..fb8cdee4f2 100644
+--- a/src/udev/udevadm-verify.c
++++ b/src/udev/udevadm-verify.c
+@@ -7,16 +7,15 @@
+ #include <stdlib.h>
+ #include <unistd.h>
+ 
+-#include "conf-files.h"
+-#include "constants.h"
++#include "errno-util.h"
+ #include "log.h"
+ #include "parse-argument.h"
+ #include "pretty-print.h"
+-#include "stat-util.h"
+ #include "static-destruct.h"
+ #include "strv.h"
+ #include "udev-rules.h"
+ #include "udevadm.h"
++#include "udevadm-util.h"
+ 
+ static ResolveNameTiming arg_resolve_name_timing = RESOLVE_NAME_EARLY;
+ static char *arg_root = NULL;
+@@ -109,10 +108,6 @@ static int parse_argv(int argc, char *argv[]) {
+                         assert_not_reached();
+                 }
+ 
+-        if (arg_root && optind < argc)
+-                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+-                                       "Combination of --root= and FILEs is not supported.");
+-
+         return 1;
+ }
+ 
+@@ -139,57 +134,20 @@ static int verify_rules_file(UdevRules *rules, const char *fname) {
+         return 0;
+ }
+ 
+-static int verify_rules_filelist(UdevRules *rules, char **files, size_t *fail_count, size_t *success_count, bool walk_dirs);
+-
+-static int verify_rules_dir(UdevRules *rules, const char *dir, size_t *fail_count, size_t *success_count) {
+-        int r;
+-        _cleanup_strv_free_ char **files = NULL;
+-
+-        assert(rules);
+-        assert(dir);
+-        assert(fail_count);
+-        assert(success_count);
+-
+-        r = conf_files_list(&files, ".rules", NULL, 0, dir);
+-        if (r < 0)
+-                return log_error_errno(r, "Failed to enumerate rules files: %m");
+-
+-        return verify_rules_filelist(rules, files, fail_count, success_count, /* walk_dirs */ false);
+-}
+-
+-static int verify_rules_filelist(UdevRules *rules, char **files, size_t *fail_count, size_t *success_count, bool walk_dirs) {
+-        int r, rv = 0;
+-
+-        assert(rules);
+-        assert(files);
+-        assert(fail_count);
+-        assert(success_count);
+-
+-        STRV_FOREACH(fp, files) {
+-                if (walk_dirs && is_dir(*fp, /* follow = */ true) > 0)
+-                        r = verify_rules_dir(rules, *fp, fail_count, success_count);
+-                else {
+-                        r = verify_rules_file(rules, *fp);
+-                        if (r < 0)
+-                                ++(*fail_count);
+-                        else
+-                                ++(*success_count);
+-                }
+-                if (r < 0 && rv >= 0)
+-                        rv = r;
+-        }
+-
+-        return rv;
+-}
+-
+ static int verify_rules(UdevRules *rules, char **files) {
+         size_t fail_count = 0, success_count = 0;
+-        int r;
++        int r, ret = 0;
+ 
+         assert(rules);
+-        assert(files);
+ 
+-        r = verify_rules_filelist(rules, files, &fail_count, &success_count, /* walk_dirs */ true);
++        STRV_FOREACH(fp, files) {
++                r = verify_rules_file(rules, *fp);
++                if (r < 0)
++                        ++fail_count;
++                else
++                        ++success_count;
++                RET_GATHER(ret, r);
++        }
+ 
+         if (arg_summary)
+                 printf("\n%s%zu udev rules files have been checked.%s\n"
+@@ -203,7 +161,7 @@ static int verify_rules(UdevRules *rules, char **files) {
+                        fail_count,
+                        fail_count > 0 ? ansi_normal() : "");
+ 
+-        return r;
++        return ret;
+ }
+ 
+ int verify_main(int argc, char *argv[], void *userdata) {
+@@ -218,19 +176,10 @@ int verify_main(int argc, char *argv[], void *userdata) {
+         if (!rules)
+                 return -ENOMEM;
+ 
+-        if (optind == argc) {
+-                const char* const* rules_dirs = STRV_MAKE_CONST(CONF_PATHS("udev/rules.d"));
+-                _cleanup_strv_free_ char **files = NULL;
+-
+-                r = conf_files_list_strv(&files, ".rules", arg_root, 0, rules_dirs);
+-                if (r < 0)
+-                        return log_error_errno(r, "Failed to enumerate rules files: %m");
+-                if (arg_root && strv_isempty(files))
+-                        return log_error_errno(SYNTHETIC_ERRNO(ENOENT),
+-                                               "No rules files found in %s.", arg_root);
+-
+-                return verify_rules(rules, files);
+-        }
++        _cleanup_strv_free_ char **files = NULL;
++        r = search_rules_files(strv_skip(argv, optind), arg_root, &files);
++        if (r < 0)
++                return r;
+ 
+-        return verify_rules(rules, strv_skip(argv, optind));
++        return verify_rules(rules, files);
+ }
+diff --git a/test/units/TEST-17-UDEV.11.sh b/test/units/TEST-17-UDEV.11.sh
+index c0d87b7151..ac99a80b0f 100755
+--- a/test/units/TEST-17-UDEV.11.sh
++++ b/test/units/TEST-17-UDEV.11.sh
+@@ -8,6 +8,8 @@ set -o pipefail
+ # shellcheck source=test/units/util.sh
+ . "$(dirname "$0")"/util.sh
+ 
++PATH=/var/build:$PATH
++
+ # shellcheck disable=SC2317
+ cleanup() {
+     cd /
+@@ -101,7 +103,6 @@ assert_0 -h
+ assert_0 --help
+ assert_0 -V
+ assert_0 --version
+-assert_0 /dev/null
+ 
+ # unrecognized option '--unknown'
+ assert_1 --unknown
+@@ -116,13 +117,9 @@ assert_1 --resolve-names=now
+ # Failed to parse rules file ./nosuchfile: No such file or directory
+ assert_1 ./nosuchfile
+ # Failed to parse rules file ./nosuchfile: No such file or directory
+-cat >"${exo}" <<EOF
+-
+-3 udev rules files have been checked.
+-  Success: 2
+-  Fail:    1
+-EOF
+-assert_1 /dev/null ./nosuchfile /dev/null
++assert_1 ./nosuchfile /dev/null
++# '/dev/null' is neither a regular file nor a directory: File descriptor in bad state
++assert_1 /dev/null
+ 
+ rules_dir='etc/udev/rules.d'
+ mkdir -p "${rules_dir}"
+@@ -148,8 +145,6 @@ assert_0 --root="${workdir}" --no-summary
+ cp "${workdir}/default_output_1_success" "${exo}"
+ assert_0 "${rules_dir}"
+ 
+-# Combination of --root= and FILEs is not supported.
+-assert_1 --root="${workdir}" /dev/null
+ # No rules files found in nosuchdir
+ assert_1 --root=nosuchdir
+ 
+@@ -161,7 +156,7 @@ assert_0 "${rules}"
+ 
+ # Failed to parse rules file ${rules}: No buffer space available
+ printf '%16384s\n' ' ' >"${rules}"
+-echo "Failed to parse rules file ${rules}: No buffer space available" >"${exp}"
++echo "Failed to parse rules file $(pwd)/${rules}: No buffer space available" >"${exp}"
+ assert_1 "${rules}"
+ 
+ {
+@@ -174,17 +169,17 @@ assert_0 "${rules}"
+ printf 'RUN+="/bin/true"%8176s\\\n #\n' ' ' ' ' >"${rules}"
+ echo >>"${rules}"
+ cat >"${exp}" <<EOF
+-${rules}:1 Line is too long, ignored.
+-${rules}: udev rules check failed.
++$(pwd)/${rules}:1 Line is too long, ignored.
++$(pwd)/${rules}: udev rules check failed.
+ EOF
+ assert_1 "${rules}"
+ 
+ printf '\\\n' >"${rules}"
+ cat >"${exp}" <<EOF
+-${rules}:1 Unexpected EOF after line continuation, line ignored.
+-${rules}: udev rules check failed.
++$(pwd)/${rules}:1 Unexpected EOF after line continuation, line ignored.
++$(pwd)/${rules}: udev rules check failed.
+ EOF
+-assert_1 "${rules}"
++assert_1 --root="${workdir}" "${rules}"
+ 
+ test_syntax_error() {
+     local rule msg
+@@ -194,8 +189,8 @@ test_syntax_error() {
+ 
+     printf '%s\n' "${rule}" >"${rules}"
+     cat >"${exp}" <<EOF
+-${rules}:1 ${msg}
+-${rules}: udev rules check failed.
++$(pwd)/${rules}:1 ${msg}
++$(pwd)/${rules}: udev rules check failed.
+ EOF
+     assert_1 "${rules}"
+ }
+@@ -208,8 +203,8 @@ test_style_error() {
+ 
+     printf '%s\n' "${rule}" >"${rules}"
+     cat >"${exp}" <<EOF
+-${rules}:1 ${msg}
+-${rules}: udev rules have style issues.
++$(pwd)/${rules}:1 ${msg}
++$(pwd)/${rules}: udev rules have style issues.
+ EOF
+     assert_0_impl --no-style "${rules}"
+     assert_1_impl "${rules}"
+@@ -365,9 +360,9 @@ assert_0 "${rules}"
+ 
+ echo 'GOTO="a"' >"${rules}"
+ cat >"${exp}" <<EOF
+-${rules}:1 GOTO="a" has no matching label, ignoring.
+-${rules}:1 The line has no effect any more, dropping.
+-${rules}: udev rules check failed.
++$(pwd)/${rules}:1 GOTO="a" has no matching label, ignoring.
++$(pwd)/${rules}:1 The line has no effect any more, dropping.
++$(pwd)/${rules}: udev rules check failed.
+ EOF
+ assert_1 "${rules}"
+ 
+@@ -383,8 +378,8 @@ LABEL="b"
+ LABEL="b"
+ EOF
+ cat >"${exp}" <<EOF
+-${rules}:3 style: LABEL="b" is unused.
+-${rules}: udev rules have style issues.
++$(pwd)/${rules}:3 style: LABEL="b" is unused.
++$(pwd)/${rules}: udev rules have style issues.
+ EOF
+ assert_0_impl --no-style "${rules}"
+ assert_1_impl "${rules}"
+@@ -394,11 +389,11 @@ GOTO="a"
+ LABEL="a", LABEL="b"
+ EOF
+ cat >"${exp}" <<EOF
+-${rules}:2 Contains multiple LABEL keys, ignoring LABEL="a".
+-${rules}:1 GOTO="a" has no matching label, ignoring.
+-${rules}:1 The line has no effect any more, dropping.
+-${rules}:2 style: LABEL="b" is unused.
+-${rules}: udev rules check failed.
++$(pwd)/${rules}:2 Contains multiple LABEL keys, ignoring LABEL="a".
++$(pwd)/${rules}:1 GOTO="a" has no matching label, ignoring.
++$(pwd)/${rules}:1 The line has no effect any more, dropping.
++$(pwd)/${rules}:2 style: LABEL="b" is unused.
++$(pwd)/${rules}: udev rules check failed.
+ EOF
+ assert_1 "${rules}"
+ 
+@@ -406,9 +401,9 @@ cat >"${rules}" <<'EOF'
+ KERNEL!="", KERNEL=="?*", KERNEL=="", NAME="a"
+ EOF
+ cat >"${exp}" <<EOF
+-${rules}:1 duplicate expressions.
+-${rules}:1 conflicting match expressions, the line has no effect.
+-${rules}: udev rules check failed.
++$(pwd)/${rules}:1 duplicate expressions.
++$(pwd)/${rules}:1 conflicting match expressions, the line has no effect.
++$(pwd)/${rules}: udev rules check failed.
+ EOF
+ assert_1 "${rules}"
+ 
+@@ -416,9 +411,9 @@ cat >"${rules}" <<'EOF'
+ ACTION=="a"NAME="b"
+ EOF
+ cat >"${exp}" <<EOF
+-${rules}:1 style: a comma between tokens is expected.
+-${rules}:1 style: whitespace between tokens is expected.
+-${rules}: udev rules have style issues.
++$(pwd)/${rules}:1 style: a comma between tokens is expected.
++$(pwd)/${rules}:1 style: whitespace between tokens is expected.
++$(pwd)/${rules}: udev rules have style issues.
+ EOF
+ assert_0_impl --no-style "${rules}"
+ assert_1_impl "${rules}"
+@@ -428,22 +423,24 @@ cat >"${rules}" <<'EOF'
+ ACTION=="a" ,NAME="b"
+ EOF
+ cat >"${exp}" <<EOF
+-${rules}:1 style: stray whitespace before comma.
+-${rules}:1 style: whitespace after comma is expected.
+-${rules}: udev rules have style issues.
++$(pwd)/${rules}:1 style: stray whitespace before comma.
++$(pwd)/${rules}:1 style: whitespace after comma is expected.
++$(pwd)/${rules}: udev rules have style issues.
+ EOF
+ assert_0_impl --no-style "${rules}"
+ assert_1_impl "${rules}"
+ next_test_number
+ 
+ # udevadm verify --root
+-sed "s|sample-[0-9]*.rules|${workdir}/${rules_dir}/&|" sample-*.exp >"${workdir}/${exp}"
++#sed "s|sample-[0-9]*.rules|${workdir}/${rules_dir}/&|" sample-*.exp >"${workdir}/${exp}"
++cat sample-*.exp >"${workdir}/${exp}"
+ cd -
+ assert_1 --root="${workdir}"
+ cd -
+ 
+ # udevadm verify path/
+-sed "s|sample-[0-9]*.rules|${workdir}/${rules_dir}/&|" sample-*.exp >"${workdir}/${exp}"
++#sed "s|sample-[0-9]*.rules|${workdir}/${rules_dir}/&|" sample-*.exp >"${workdir}/${exp}"
++cat sample-*.exp >"${workdir}/${exp}"
+ cd -
+ assert_1 "${rules_dir}"
+ cd -
diff --git a/SOURCES/0346-bash-completion-udevadm-verify-suggest-found-udev-ru.patch b/SOURCES/0346-bash-completion-udevadm-verify-suggest-found-udev-ru.patch
new file mode 100644
index 0000000000000000000000000000000000000000..66065b5c3fc39d27036df7629fe013d1d58379d8
--- /dev/null
+++ b/SOURCES/0346-bash-completion-udevadm-verify-suggest-found-udev-ru.patch
@@ -0,0 +1,103 @@
+From 6aa9e8d394dc04f3432a74e837cd21a3e860a43c Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Thu, 9 Jan 2025 19:25:49 +0900
+Subject: [PATCH] bash-completion/udevadm-verify: suggest found udev rules
+ files
+
+This also fixes the issue that no suggestion is provided after a standalone
+option is specified.
+
+(cherry picked from commit bbe1ba5e87a74fa0b56d88a7266040e534c527b0)
+
+Resolves: RHEL-75774
+---
+ shell-completion/bash/udevadm | 50 ++++++++++++++++++++++++++++-------
+ 1 file changed, 40 insertions(+), 10 deletions(-)
+
+diff --git a/shell-completion/bash/udevadm b/shell-completion/bash/udevadm
+index 496eac5fd7..54d024c1b8 100644
+--- a/shell-completion/bash/udevadm
++++ b/shell-completion/bash/udevadm
+@@ -46,6 +46,35 @@ __get_all_devices() {
+     __get_all_device_units
+ }
+ 
++__get_root() {
++    local i
++
++    for ((i=0; i < COMP_CWORD; i++)); do
++        if [[ "${COMP_WORDS[i]}" = --root=* ]]; then
++             echo "${COMP_WORDS[i]#--root=}"
++             break
++        fi
++        if (( i > 0 )) && [[ "${COMP_WORDS[i-1]}" == "--root" ]]; then
++             echo "${COMP_WORDS[i]}"
++             break
++        fi
++    done
++}
++
++__get_udev_rules_files() {
++    local root=$( __get_root )
++
++    ls "$root"/usr/lib/udev/rules.d/*.rules \
++       "$root"/usr/local/lib/udev/rules.d/*.rules \
++       "$root"/run/udev/rules.d/*.rules \
++       "$root"/etc/udev/rules.d/*.rules 2>/dev/null
++}
++
++__get_udev_rules_names() {
++    local -a rules=( $( __get_udev_rules_files ) )
++    printf '%s\n' "${rules[@]##*/}"
++}
++
+ _udevadm() {
+     local i verb comps builtin
+     local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]}
+@@ -72,7 +101,8 @@ _udevadm() {
+         [TEST_STANDALONE]='-v --verbose'
+         [TEST_ARG]='-a --action -N --resolve-names -D --extra-rules-dir'
+         [TEST_BUILTIN]='-a --action'
+-        [VERIFY]='-N --resolve-names --root --no-summary --no-style'
++        [VERIFY_STANDALONE]='--no-summary --no-style'
++        [VERIFY_ARG]='-N --resolve-names --root'
+         [WAIT]='-t --timeout --initialized=no --removed --settle'
+         [LOCK]='-t --timeout -d --device -b --backing -p --print'
+     )
+@@ -266,27 +296,27 @@ _udevadm() {
+             ;;
+ 
+         'verify')
+-            if __contains_word "$prev" ${OPTS[VERIFY]}; then
++            if __contains_word "$prev" ${OPTS[VERIFY_ARG]}; then
+                 case $prev in
+                     -N|--resolve-names)
+                         comps='early never'
+                         ;;
+                     --root)
+-                        comps=$(compgen -A directory -- "$cur" )
++                        comps=''
+                         compopt -o dirnames
+                         ;;
+                     *)
+                         comps=''
+                         ;;
+                 esac
+-                COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
+-                return 0
+-            fi
+-
+-            if [[ $cur = -* ]]; then
+-                comps="${OPTS[COMMON]} ${OPTS[VERIFY]}"
++            elif [[ $cur = -* ]]; then
++                comps="${OPTS[COMMON]} ${OPTS[VERIFY_ARG]} ${OPTS[VERIFY_STANDALONE]}"
++            elif [[ $cur = */* ]]; then
++                comps=$( __get_udev_rules_files )
++                compopt -o dirnames
+             else
+-                comps=$( compgen -A file -- "$cur" )
++                comps=$( __get_udev_rules_names )
++                compopt -o default
+             fi
+             ;;
+ 
diff --git a/SOURCES/0347-udevadm-introduce-cat-command.patch b/SOURCES/0347-udevadm-introduce-cat-command.patch
new file mode 100644
index 0000000000000000000000000000000000000000..0a42516e629f0c338d680585decb3b9388950483
--- /dev/null
+++ b/SOURCES/0347-udevadm-introduce-cat-command.patch
@@ -0,0 +1,359 @@
+From 29959da4228413ad35faf9656c8304ebfd0c482d Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Tue, 7 Jan 2025 16:58:37 +0900
+Subject: [PATCH] udevadm: introduce cat command
+
+This introduces 'udevadm cat' command, that shows udev rules files or
+udev.conf, which may be useful for debugging.
+
+Closes #35818.
+
+(cherry picked from commit 7f2175eabbea882d02e9df0e9fcb8e2f03a121da)
+
+Resolves: RHEL-75774
+---
+ man/udevadm.xml               |  64 ++++++++++++++++++++
+ shell-completion/bash/udevadm |  28 ++++++++-
+ shell-completion/zsh/_udevadm |  11 ++++
+ src/udev/meson.build          |   1 +
+ src/udev/udevadm-cat.c        | 110 ++++++++++++++++++++++++++++++++++
+ src/udev/udevadm.c            |   2 +
+ src/udev/udevadm.h            |   1 +
+ test/units/TEST-17-UDEV.10.sh |   9 +++
+ 8 files changed, 225 insertions(+), 1 deletion(-)
+ create mode 100644 src/udev/udevadm-cat.c
+
+diff --git a/man/udevadm.xml b/man/udevadm.xml
+index eed84d27cc..9cbbdc254d 100644
+--- a/man/udevadm.xml
++++ b/man/udevadm.xml
+@@ -53,6 +53,11 @@
+       <arg choice="opt" rep="repeat">options</arg>
+       <arg choice="opt" rep="repeat"><replaceable>file</replaceable></arg>
+     </cmdsynopsis>
++    <cmdsynopsis>
++      <command>udevadm cat</command>
++      <arg choice="opt" rep="repeat">options</arg>
++      <arg choice="opt" rep="repeat"><replaceable>file</replaceable></arg>
++    </cmdsynopsis>
+     <cmdsynopsis>
+       <command>udevadm wait <optional>options</optional> <replaceable>device|syspath</replaceable></command>
+     </cmdsynopsis>
+@@ -1000,6 +1005,65 @@
+       </variablelist>
+     </refsect2>
+ 
++    <refsect2>
++      <title>udevadm cat
++      <optional><replaceable>options</replaceable></optional>
++      <optional><replaceable>file</replaceable></optional>
++      …
++      </title>
++
++      <para>Show udev rules files or udev.conf.</para>
++
++      <para>Positional arguments can be used to specify one or more files to show. Each argument must be an
++      absolute path to a udev rules file or a directory that contains rules files, or a file name of udev
++      rules file (e.g. <filename>99-systemd.rules</filename>). If a file name is specified, the file will be
++      searched in the <filename>udev/rules.d</filename> directories that are processed by
++      <command>systemd-udevd</command>, and searched in the current working directory if not found. If no
++      files are specified, the udev rules are read from the files located in the same
++      <filename>udev/rules.d</filename> directories that are processed by <command>systemd-udevd</command>.
++      See <citerefentry><refentrytitle>udev</refentrytitle><manvolnum>7</manvolnum></citerefentry> for more
++      details about the search paths.</para>
++
++      <variablelist>
++        <varlistentry>
++          <term><option>--root=<replaceable>PATH</replaceable></option></term>
++          <listitem>
++            <para>When looking for udev rules files located in the <filename>udev/rules.d</filename>
++            directories, operate on files underneath the specified root path <replaceable>PATH</replaceable>.
++            When a file name is specified, and it is not found in the <filename>udev/rules.d</filename>
++            directories, the file will be searched in the specified root path
++            <replaceable>PATH</replaceable>, rather than the current working directory.</para>
++
++            <xi:include href="version-info.xml" xpointer="v258"/>
++          </listitem>
++        </varlistentry>
++
++        <varlistentry>
++          <term><option>--tldr</option></term>
++          <listitem>
++            <para>Only print the "interesting" parts of the configuration files, skipping comments and empty
++            lines and section headers followed only by comments and empty lines.</para>
++
++            <xi:include href="version-info.xml" xpointer="v258"/>
++          </listitem>
++        </varlistentry>
++
++        <varlistentry>
++          <term><option>--config</option></term>
++          <listitem>
++            <para>Shows
++            <citerefentry><refentrytitle>udev.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
++            files, rather than udev rules files. When specified, no udev rules file cannot be specified.
++            </para>
++
++            <xi:include href="version-info.xml" xpointer="v258"/>
++          </listitem>
++        </varlistentry>
++
++        <xi:include href="standard-options.xml" xpointer="help" />
++      </variablelist>
++    </refsect2>
++
+     <refsect2>
+       <title>udevadm wait
+       <optional><replaceable>options</replaceable></optional>
+diff --git a/shell-completion/bash/udevadm b/shell-completion/bash/udevadm
+index 54d024c1b8..010d4cff8a 100644
+--- a/shell-completion/bash/udevadm
++++ b/shell-completion/bash/udevadm
+@@ -103,11 +103,13 @@ _udevadm() {
+         [TEST_BUILTIN]='-a --action'
+         [VERIFY_STANDALONE]='--no-summary --no-style'
+         [VERIFY_ARG]='-N --resolve-names --root'
++        [CAT_STANDALONE]='--tldr --config'
++        [CAT_ARG]='--root'
+         [WAIT]='-t --timeout --initialized=no --removed --settle'
+         [LOCK]='-t --timeout -d --device -b --backing -p --print'
+     )
+ 
+-    local verbs=(info trigger settle control monitor test-builtin test verify wait lock)
++    local verbs=(info trigger settle control monitor test-builtin test verify cat wait lock)
+     local builtins=(blkid btrfs hwdb input_id keyboard kmod net_driver net_id net_setup_link path_id uaccess usb_id)
+ 
+     for ((i=0; i < COMP_CWORD; i++)); do
+@@ -320,6 +322,30 @@ _udevadm() {
+             fi
+             ;;
+ 
++        'cat')
++            if __contains_word "$prev" ${OPTS[CAT_ARG]}; then
++                case $prev in
++                    --root)
++                        comps=''
++                        compopt -o dirnames
++                        ;;
++                    *)
++                        comps=''
++                        ;;
++                esac
++            elif [[ $cur = -* ]]; then
++                comps="${OPTS[COMMON]} ${OPTS[CAT_ARG]} ${OPTS[CAT_STANDALONE]}"
++            elif __contains_word "--config" ${COMP_WORDS[*]}; then
++                comps="${OPTS[COMMON]} ${OPTS[CAT_ARG]} ${OPTS[CAT_STANDALONE]}"
++            elif [[ $cur = */* ]]; then
++                comps=$( __get_udev_rules_files )
++                compopt -o dirnames
++            else
++                comps=$( __get_udev_rules_names )
++                compopt -o default
++            fi
++            ;;
++
+         'wait')
+             if __contains_word "$prev" ${OPTS[WAIT]}; then
+                 case $prev in
+diff --git a/shell-completion/zsh/_udevadm b/shell-completion/zsh/_udevadm
+index 63db11cea9..c9b43e231d 100644
+--- a/shell-completion/zsh/_udevadm
++++ b/shell-completion/zsh/_udevadm
+@@ -124,6 +124,17 @@ _udevadm_verify(){
+         '*::files:_files'
+ }
+ 
++(( $+functions[_udevadm_cat] )) ||
++_udevadm_cat(){
++    _arguments \
++        '(- *)'{-h,--help}'[Show help]' \
++        '(- *)'{-V,--version}'[Show package version]' \
++        '--root=[Operate on catalog hierarchy under specified directory]:directories:_directories' \
++        --tldr'[Skip comments and empty lines.]' \
++        --config'[Show udev.conf.]' \
++        '*::files:_files'
++}
++
+ (( $+functions[_udevadm_wait] )) ||
+ _udevadm_wait(){
+     _arguments \
+diff --git a/src/udev/meson.build b/src/udev/meson.build
+index 171bbd2b70..62cd8014d2 100644
+--- a/src/udev/meson.build
++++ b/src/udev/meson.build
+@@ -1,6 +1,7 @@
+ # SPDX-License-Identifier: LGPL-2.1-or-later
+ 
+ udevadm_sources = files(
++        'udevadm-cat.c',
+         'udevadm-control.c',
+         'udevadm-hwdb.c',
+         'udevadm-info.c',
+diff --git a/src/udev/udevadm-cat.c b/src/udev/udevadm-cat.c
+new file mode 100644
+index 0000000000..2d7e86994d
+--- /dev/null
++++ b/src/udev/udevadm-cat.c
+@@ -0,0 +1,110 @@
++/* SPDX-License-Identifier: GPL-2.0-or-later */
++
++#include <getopt.h>
++
++#include "log.h"
++#include "parse-argument.h"
++#include "pretty-print.h"
++#include "static-destruct.h"
++#include "strv.h"
++#include "udevadm.h"
++#include "udevadm-util.h"
++
++static char *arg_root = NULL;
++static CatFlags arg_cat_flags = 0;
++static bool arg_config = false;
++
++STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
++
++static int help(void) {
++        _cleanup_free_ char *link = NULL;
++        int r;
++
++        r = terminal_urlify_man("udevadm", "8", &link);
++        if (r < 0)
++                return log_oom();
++
++        printf("%s cat [OPTIONS] [FILE...]\n"
++               "\n%sShow udev rules files.%s\n\n"
++               "  -h --help            Show this help\n"
++               "  -V --version         Show package version\n"
++               "     --root=PATH       Operate on an alternate filesystem root\n"
++               "     --tldr            Skip comments and empty lines\n"
++               "     --config          Show udev.conf rather than udev rules files\n"
++               "\nSee the %s for details.\n",
++               program_invocation_short_name,
++               ansi_highlight(),
++               ansi_normal(),
++               link);
++
++        return 0;
++}
++
++static int parse_argv(int argc, char *argv[]) {
++        enum {
++                ARG_ROOT = 0x100,
++                ARG_TLDR,
++                ARG_CONFIG,
++        };
++        static const struct option options[] = {
++                { "help",          no_argument,       NULL, 'h'             },
++                { "version",       no_argument,       NULL, 'V'             },
++                { "root",          required_argument, NULL, ARG_ROOT        },
++                { "tldr",          no_argument,       NULL, ARG_TLDR        },
++                { "config",        no_argument,       NULL, ARG_CONFIG      },
++                {}
++        };
++
++        int r, c;
++
++        assert(argc >= 0);
++        assert(argv);
++
++        while ((c = getopt_long(argc, argv, "hVN:", options, NULL)) >= 0)
++                switch (c) {
++                case 'h':
++                        return help();
++                case 'V':
++                        return print_version();
++                case ARG_ROOT:
++                        r = parse_path_argument(optarg, /* suppress_root= */ true, &arg_root);
++                        if (r < 0)
++                                return r;
++                        break;
++                case ARG_TLDR:
++                        arg_cat_flags = CAT_TLDR;
++                        break;
++                case ARG_CONFIG:
++                        arg_config = true;
++                        break;
++                case '?':
++                        return -EINVAL;
++                default:
++                        assert_not_reached();
++                }
++
++        if (arg_config && optind < argc)
++                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
++                                       "Combination of --config and FILEs is not supported.");
++
++        return 1;
++}
++
++int cat_main(int argc, char *argv[], void *userdata) {
++        int r;
++
++        r = parse_argv(argc, argv);
++        if (r <= 0)
++                return r;
++
++        if (arg_config)
++                return conf_files_cat(arg_root, "udev/udev.conf", arg_cat_flags);
++
++        _cleanup_strv_free_ char **files = NULL;
++        r = search_rules_files(strv_skip(argv, optind), arg_root, &files);
++        if (r < 0)
++                return r;
++
++        /* udev rules file does not support dropin configs. So, we can safely pass multiple files as dropins. */
++        return cat_files(/* file = */ NULL, /* dropins = */ files, arg_cat_flags);
++}
+diff --git a/src/udev/udevadm.c b/src/udev/udevadm.c
+index 30b6ddb728..ebf1e5190c 100644
+--- a/src/udev/udevadm.c
++++ b/src/udev/udevadm.c
+@@ -26,6 +26,7 @@ static int help(void) {
+                 { "test",         "Test an event run"                 },
+                 { "test-builtin", "Test a built-in command"           },
+                 { "verify",       "Verify udev rules files"           },
++                { "cat",          "Show udev rules files"             },
+                 { "wait",         "Wait for device or device symlink" },
+                 { "lock",         "Lock a block device"               },
+         };
+@@ -97,6 +98,7 @@ static int help_main(int argc, char *argv[], void *userdata) {
+ 
+ static int udevadm_main(int argc, char *argv[]) {
+         static const Verb verbs[] = {
++                { "cat",          VERB_ANY, VERB_ANY, 0, cat_main     },
+                 { "info",         VERB_ANY, VERB_ANY, 0, info_main    },
+                 { "trigger",      VERB_ANY, VERB_ANY, 0, trigger_main },
+                 { "settle",       VERB_ANY, VERB_ANY, 0, settle_main  },
+diff --git a/src/udev/udevadm.h b/src/udev/udevadm.h
+index 7920a70d5b..e39dbf655d 100644
+--- a/src/udev/udevadm.h
++++ b/src/udev/udevadm.h
+@@ -5,6 +5,7 @@
+ 
+ #include "macro.h"
+ 
++int cat_main(int argc, char *argv[], void *userdata);
+ int info_main(int argc, char *argv[], void *userdata);
+ int trigger_main(int argc, char *argv[], void *userdata);
+ int settle_main(int argc, char *argv[], void *userdata);
+diff --git a/test/units/TEST-17-UDEV.10.sh b/test/units/TEST-17-UDEV.10.sh
+index be342b3468..68d310a8e5 100755
+--- a/test/units/TEST-17-UDEV.10.sh
++++ b/test/units/TEST-17-UDEV.10.sh
+@@ -33,6 +33,15 @@ udevadm settle --timeout 30
+ 
+ udevadm -h
+ 
++udevadm cat
++udevadm cat 99-systemd
++udevadm cat 99-systemd.rules
++udevadm cat /usr/lib/udev/rules.d/99-systemd.rules
++udevadm cat /usr/lib/udev/rules.d
++(! udevadm cat /dev/null)
++udevadm cat --config
++udevadm cat -h
++
+ INVOCATION_ID=$(systemctl show --property InvocationID --value systemd-udevd.service)
+ udevadm control -e
+ # Wait for systemd-udevd.service being restarted.
diff --git a/SPECS/systemd.spec b/SPECS/systemd.spec
index fcc7c654f52dd33a9340cb79ec658362e052f15b..099853826fc11c6a31c88bc7a6820fbebda39078 100644
--- a/SPECS/systemd.spec
+++ b/SPECS/systemd.spec
@@ -48,7 +48,7 @@ Url:            https://systemd.io
 # Allow users to specify the version and release when building the rpm by 
 # setting the %%version_override and %%release_override macros.
 Version:        %{?version_override}%{!?version_override:257}
-Release:        7%{?dist}
+Release:        9%{?dist}
 
 %global stable %(c="%version"; [ "$c" = "${c#*.*}" ]; echo $?)
 
@@ -336,67 +336,126 @@ Patch0224:  0224-meson-fix-suite-of-alignment-check-tests.patch
 Patch0225:  0225-hwdb-Make-remote-controllable-lights-work-out-of-the.patch
 Patch0226:  0226-hwdb-update-to-main-2025-02-07.patch
 Patch0227:  0227-udevadm-test-fix-gid-check.patch
-Patch0228:  0228-ci-update-workflows-to-run-on-source-git-setup.patch
-Patch0229:  0229-ci-setup-source-git-automation.patch
-Patch0230:  0230-ci-reconfigure-Packit-for-RHEL-10.patch
-Patch0231:  0231-journal-again-create-user-journals-for-users-with-hi.patch
-Patch0232:  0232-tmpfiles-make-purge-hard-to-mis-use.patch
-Patch0233:  0233-fedora-use-system-auth-in-pam-systemd-user.patch
-Patch0234:  0234-net-naming-scheme-start-rhel10-naming-and-include-rh.patch
-Patch0235:  0235-rules-copy-40-redhat.rules-from-RHEL-9.patch
-Patch0236:  0236-logind-set-RemoveIPC-to-false-by-default.patch
-Patch0237:  0237-tmpfiles-don-t-create-resolv.conf-stub-resolv.conf-s.patch
-Patch0238:  0238-rc-local-order-after-network-online.target.patch
-Patch0239:  0239-random-util-increase-random-seed-size-to-1024.patch
-Patch0240:  0240-journal-don-t-enable-systemd-journald-audit.socket-b.patch
-Patch0241:  0241-journald.conf-don-t-touch-current-audit-settings.patch
-Patch0242:  0242-rules-add-elevator-kernel-command-line-parameter.patch
-Patch0243:  0243-pid1-bump-DefaultTasksMax-to-80-of-the-kernel-pid.ma.patch
-Patch0244:  0244-udev-net-setup-link-change-the-default-MACAddressPol.patch
-Patch0245:  0245-core-decrease-log-level-of-messages-about-use-of-Kil.patch
-Patch0246:  0246-taint-remove-unmerged-bin.patch
-Patch0247:  0247-presets-remove-resolved.patch
-Patch0248:  0248-ci-run-mkosi-test-only-for-Fedora-and-CentOS-Stream.patch
-Patch0249:  0249-taint-remove-unused-variable-usr_sbin.patch
-Patch0250:  0250-packit-drop-the-libarchive-workaround.patch
-Patch0251:  0251-coredump-by-default-process-and-store-core-files-up-.patch
-Patch0252:  0252-Avoid-tmp-being-mounted-as-tmpfs-without-the-user-s-.patch
-Patch0253:  0253-unit-don-t-add-Requires-for-tmp.mount.patch
-Patch0254:  0254-units-add-Install-section-to-tmp.mount.patch
-Patch0255:  0255-units-don-t-enable-tmp.mount-statically-in-local-fs..patch
-Patch0256:  0256-netif-naming-scheme-add-rhel-9.5-scheme.patch
-Patch0257:  0257-netif-naming-scheme-rename-rhel-10.0-to-rhel-10.0.be.patch
-Patch0258:  0258-net-naming-scheme-disable-NAMING_FIRMWARE_NODE_SUN.patch
-Patch0259:  0259-netif-naming-scheme-introduce-rhel-10.0-scheme.patch
-Patch0260:  0260-udev-net_id-introduce-naming-scheme-for-RHEL-9.6.patch
-Patch0261:  0261-ci-use-ubuntu-22-04-for-deploy-of-man-pages.patch
-Patch0262:  0262-ci-fix-Packit.patch
-Patch0263:  0263-ci-drop-testing-farm-test.patch
-Patch0264:  0264-dbus-stash-the-subscriber-list-when-we-disconenct-fr.patch
-Patch0265:  0265-manager-s-deserialized_subscribed-subscribed_as_strv.patch
-Patch0266:  0266-shared-bus-util-move-bus_message_read_id128-to-bus-m.patch
-Patch0267:  0267-shared-bus-util-move-bus_message_hash_ops-to-bus-mes.patch
-Patch0268:  0268-shared-bus-util-move-string-set-append-get-funcs-to-.patch
-Patch0269:  0269-shared-serialize-make-input-params-const.patch
-Patch0270:  0270-shared-serialize-introduce-serialize_id128.patch
-Patch0271:  0271-bus-util-do-not-reset-the-count-returned-by-sd_bus_t.patch
-Patch0272:  0272-core-manager-use-FOREACH_ARRAY-at-one-more-place.patch
-Patch0273:  0273-core-manager-drop-duplicate-bus-track-deserializatio.patch
-Patch0274:  0274-bus-util-introduce-bus_get_instance_id.patch
-Patch0275:  0275-core-serialize-API-bus-id-and-validate-before-deseri.patch
-Patch0276:  0276-core-manager-restore-bus-track-deserialization-clean.patch
-Patch0277:  0277-shared-bus-util-add-missing-set.h-include.patch
-Patch0278:  0278-udevadm-test-add-missing-oom-check.patch
-Patch0279:  0279-udev-rules-replace-type-func-type-func.patch
-Patch0280:  0280-udev-rules-do-not-change-maximum-log-level-when-runn.patch
-Patch0281:  0281-udevadm-test-introduce-v-verbose-option-to-show-verb.patch
-Patch0282:  0282-udev-rules-show-original-token-string-in-log_event_e.patch
-Patch0283:  0283-udev-rules-logs-result-of-format-substitution.patch
-Patch0284:  0284-udev-rules-add-more-trace-logs-for-string-match.patch
-Patch0285:  0285-udev-rules-introduce-udev_replace_chars_and_log.patch
-Patch0286:  0286-udev-rules-ignore-whole-command-result-if-it-is-too-.patch
-Patch0287:  0287-udev-rules-update-log-messages.patch
-Patch0288:  0288-udev-rules-add-trace-logs-for-GOTO-and-parent-condit.patch
+Patch0228:  0228-update-utmp-do-not-give-up-if-the-first-attempt-at-c.patch
+Patch0229:  0229-bootctl-fix-potential-uninitialized-memory-access.patch
+Patch0230:  0230-bootctl-also-shown-whether-stub-loader-partition-dat.patch
+Patch0231:  0231-bootctl-suppress-output-of-empty-partition-info-if-w.patch
+Patch0232:  0232-bootctl-minor-reordering-of-fields-in-output.patch
+Patch0233:  0233-missing_sched-add-CLONE_PIDFD.patch
+Patch0234:  0234-stub-Mention-that-VirtualSize-should-be-SizeOfRawDat.patch
+Patch0235:  0235-import-pubring.gpg-add-openSUSE-build-key.patch
+Patch0236:  0236-import-update-to-current-fedora-keyring.patch
+Patch0237:  0237-ukify-do-not-fail-if-pefile-complains-about-hardcode.patch
+Patch0238:  0238-tmpfiles-fix-copypasta-in-create_symlink-FIFO-symlin.patch
+Patch0239:  0239-udev-worker-add-debugging-log-about-success-of-flock.patch
+Patch0240:  0240-udev-watch-mention-that-the-failure-is-ignored.patch
+Patch0241:  0241-udev-watch-do-not-try-to-remove-invalid-watch-handle.patch
+Patch0242:  0242-login-Continue-watching-leader-pidfd-after-stop.patch
+Patch0243:  0243-login-Queue-session-for-garbage-collection-on-leader.patch
+Patch0244:  0244-ukify-print-debug-progress-messages-to-stderr.patch
+Patch0245:  0245-ukify-Calculate-section-size-more-correctly.patch
+Patch0246:  0246-mkosi-Update-to-latest.patch
+Patch0247:  0247-core-condition-fix-segfault-when-key-not-found-in-os.patch
+Patch0248:  0248-meson-bump-version-to-257.3.patch
+Patch0249:  0249-ci-update-workflows-to-run-on-source-git-setup.patch
+Patch0250:  0250-ci-setup-source-git-automation.patch
+Patch0251:  0251-ci-reconfigure-Packit-for-RHEL-10.patch
+Patch0252:  0252-journal-again-create-user-journals-for-users-with-hi.patch
+Patch0253:  0253-tmpfiles-make-purge-hard-to-mis-use.patch
+Patch0254:  0254-fedora-use-system-auth-in-pam-systemd-user.patch
+Patch0255:  0255-net-naming-scheme-start-rhel10-naming-and-include-rh.patch
+Patch0256:  0256-rules-copy-40-redhat.rules-from-RHEL-9.patch
+Patch0257:  0257-logind-set-RemoveIPC-to-false-by-default.patch
+Patch0258:  0258-tmpfiles-don-t-create-resolv.conf-stub-resolv.conf-s.patch
+Patch0259:  0259-rc-local-order-after-network-online.target.patch
+Patch0260:  0260-random-util-increase-random-seed-size-to-1024.patch
+Patch0261:  0261-journal-don-t-enable-systemd-journald-audit.socket-b.patch
+Patch0262:  0262-journald.conf-don-t-touch-current-audit-settings.patch
+Patch0263:  0263-rules-add-elevator-kernel-command-line-parameter.patch
+Patch0264:  0264-pid1-bump-DefaultTasksMax-to-80-of-the-kernel-pid.ma.patch
+Patch0265:  0265-udev-net-setup-link-change-the-default-MACAddressPol.patch
+Patch0266:  0266-core-decrease-log-level-of-messages-about-use-of-Kil.patch
+Patch0267:  0267-taint-remove-unmerged-bin.patch
+Patch0268:  0268-presets-remove-resolved.patch
+Patch0269:  0269-ci-run-mkosi-test-only-for-Fedora-and-CentOS-Stream.patch
+Patch0270:  0270-taint-remove-unused-variable-usr_sbin.patch
+Patch0271:  0271-packit-drop-the-libarchive-workaround.patch
+Patch0272:  0272-coredump-by-default-process-and-store-core-files-up-.patch
+Patch0273:  0273-Avoid-tmp-being-mounted-as-tmpfs-without-the-user-s-.patch
+Patch0274:  0274-unit-don-t-add-Requires-for-tmp.mount.patch
+Patch0275:  0275-units-add-Install-section-to-tmp.mount.patch
+Patch0276:  0276-units-don-t-enable-tmp.mount-statically-in-local-fs..patch
+Patch0277:  0277-netif-naming-scheme-add-rhel-9.5-scheme.patch
+Patch0278:  0278-netif-naming-scheme-rename-rhel-10.0-to-rhel-10.0.be.patch
+Patch0279:  0279-net-naming-scheme-disable-NAMING_FIRMWARE_NODE_SUN.patch
+Patch0280:  0280-netif-naming-scheme-introduce-rhel-10.0-scheme.patch
+Patch0281:  0281-udev-net_id-introduce-naming-scheme-for-RHEL-9.6.patch
+Patch0282:  0282-ci-use-ubuntu-22-04-for-deploy-of-man-pages.patch
+Patch0283:  0283-ci-fix-Packit.patch
+Patch0284:  0284-ci-drop-testing-farm-test.patch
+Patch0285:  0285-dbus-stash-the-subscriber-list-when-we-disconenct-fr.patch
+Patch0286:  0286-manager-s-deserialized_subscribed-subscribed_as_strv.patch
+Patch0287:  0287-shared-bus-util-move-bus_message_read_id128-to-bus-m.patch
+Patch0288:  0288-shared-bus-util-move-bus_message_hash_ops-to-bus-mes.patch
+Patch0289:  0289-shared-bus-util-move-string-set-append-get-funcs-to-.patch
+Patch0290:  0290-shared-serialize-make-input-params-const.patch
+Patch0291:  0291-shared-serialize-introduce-serialize_id128.patch
+Patch0292:  0292-bus-util-do-not-reset-the-count-returned-by-sd_bus_t.patch
+Patch0293:  0293-core-manager-use-FOREACH_ARRAY-at-one-more-place.patch
+Patch0294:  0294-core-manager-drop-duplicate-bus-track-deserializatio.patch
+Patch0295:  0295-bus-util-introduce-bus_get_instance_id.patch
+Patch0296:  0296-core-serialize-API-bus-id-and-validate-before-deseri.patch
+Patch0297:  0297-core-manager-restore-bus-track-deserialization-clean.patch
+Patch0298:  0298-shared-bus-util-add-missing-set.h-include.patch
+Patch0299:  0299-udevadm-test-add-missing-oom-check.patch
+Patch0300:  0300-udev-rules-replace-type-func-type-func.patch
+Patch0301:  0301-udev-rules-do-not-change-maximum-log-level-when-runn.patch
+Patch0302:  0302-udevadm-test-introduce-v-verbose-option-to-show-verb.patch
+Patch0303:  0303-udev-rules-show-original-token-string-in-log_event_e.patch
+Patch0304:  0304-udev-rules-logs-result-of-format-substitution.patch
+Patch0305:  0305-udev-rules-add-more-trace-logs-for-string-match.patch
+Patch0306:  0306-udev-rules-introduce-udev_replace_chars_and_log.patch
+Patch0307:  0307-udev-rules-ignore-whole-command-result-if-it-is-too-.patch
+Patch0308:  0308-udev-rules-update-log-messages.patch
+Patch0309:  0309-udev-rules-add-trace-logs-for-GOTO-and-parent-condit.patch
+Patch0310:  0310-udev-move-enums-to-udev-def.h.patch
+Patch0311:  0311-udev-move-listen_fds-to-udev-manager.c.patch
+Patch0312:  0312-udev-several-coding-style-fixes.patch
+Patch0313:  0313-udev-builtin-make-udev_builtin_add_property-and-frie.patch
+Patch0314:  0314-udev-introduce-reference-counter-for-UdevEvent.patch
+Patch0315:  0315-udev-net-make-Link-object-take-reference-to-UdevEven.patch
+Patch0316:  0316-udev-move-parsers-for-config-file-kerenel-command-li.patch
+Patch0317:  0317-udev-config-introduce-UdevConfig.patch
+Patch0318:  0318-udev-reload-.rules-files-and-builtins-only-when-nece.patch
+Patch0319:  0319-udev-also-reload-udev.conf-when-explicitly-requested.patch
+Patch0320:  0320-TEST-17-use-udevadm-control-reload-or-systemctl-relo.patch
+Patch0321:  0321-udevd-add-missing-header-for-glibc-2.34.patch
+Patch0322:  0322-meson-sort-source-files.patch
+Patch0323:  0323-sd-json-introduce-json_dispatch_log_level.patch
+Patch0324:  0324-varlink-invert-uid-check-to-reduce-call-of-getuid.patch
+Patch0325:  0325-string-util-modernize-split_pair.patch
+Patch0326:  0326-udev-split-manager_init-and-manager_main-into-small-.patch
+Patch0327:  0327-udev-config-split-on_ctrl_msg-into-small-pieces.patch
+Patch0328:  0328-udev-introduce-udev_property_name_is_valid-and-frien.patch
+Patch0329:  0329-udev-ctrl-refuse-ENV-control-message-with-invalid-en.patch
+Patch0330:  0330-varlink-add-comments-for-io.systemd.service-interfac.patch
+Patch0331:  0331-sd-varlink-introduce-sd_varlink_get_current_method.patch
+Patch0332:  0332-TEST-17-UDEV-wait-for-udevd-being-restarted-after-ex.patch
+Patch0333:  0333-udev-make-worker-event-source-take-file-descriptor.patch
+Patch0334:  0334-udev-dump-split-out-dump_event-from-udevadm-test.c.patch
+Patch0335:  0335-udev-rules-introduce-OPTIONS-dump-token.patch
+Patch0336:  0336-udev-control-move-setting-of-log-level-to-manager_ad.patch
+Patch0337:  0337-udev-config-allow-to-enable-trace-logging-through-ke.patch
+Patch0338:  0338-udev-dump-voidify-one-function-call.patch
+Patch0339:  0339-udev-dump-also-show-written-sysfs-attributes-and-sys.patch
+Patch0340:  0340-udevadm-test-allow-to-specify-extra-directories-to-l.patch
+Patch0341:  0341-shell-completion-udevadm-add-net_driver.patch
+Patch0342:  0342-udev-sort-builtins.patch
+Patch0343:  0343-udev-rules-log-the-first-line-number-when-continued.patch
+Patch0344:  0344-chase-introduce-flags-that-verify-that-chased-inode-.patch
+Patch0345:  0345-udevadm-verify-chase-specified-paths.patch
+Patch0346:  0346-bash-completion-udevadm-verify-suggest-found-udev-ru.patch
+Patch0347:  0347-udevadm-introduce-cat-command.patch
 
 # Downstream-only patches (9000–9999)
 
@@ -408,6 +467,7 @@ BuildRequires:  gcc
 BuildRequires:  gcc-c++
 BuildRequires:  clang
 BuildRequires:  coreutils
+BuildRequires:  git-core
 BuildRequires:  libcap-devel
 BuildRequires:  libmount-devel
 BuildRequires:  libfdisk-devel
@@ -831,7 +891,7 @@ information (PSI) to monitor and take action on processes before an OOM
 occurs in kernel space.
 
 %prep
-%autosetup -n %{?commit:%{name}-%{commit}}%{!?commit:%{name}-%{version_no_tilde}} -p1
+%autosetup -S git
 
 %build
 %global ntpvendor %(source /etc/os-release; echo ${ID})
@@ -1327,6 +1387,13 @@ rm -f .file-list-*
 rm -f %{name}.lang
 
 %changelog
+* Fri Feb 14 2025 systemd maintenance team <systemd-maint@redhat.com> - 257-9
+- Add BuildRequires for git-core (RHEL-71409)
+
+* Fri Feb 14 2025 systemd maintenance team <systemd-maint@redhat.com> - 257-8
+- Rebase to new upstream stable release v257.3 (RHEL-71409)
+- udev: introduce several features to make debugging rules easier (RHEL-75774)
+
 * Mon Feb 10 2025 systemd maintenance team <systemd-maint@redhat.com> - 257-7
 - Rebase to new upstream stable version v257.2+ (RHEL-71409)