From d6511e057b0b9e54c69d5a2d1b5d0eac8c2fd22b Mon Sep 17 00:00:00 2001 From: Jan Macku Date: Wed, 15 Jan 2025 16:13:59 +0100 Subject: [PATCH 1/2] spec: fix bogus date Related: RHEL-71409 --- systemd.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/systemd.spec b/systemd.spec index e389beb..1ed02b7 100644 --- a/systemd.spec +++ b/systemd.spec @@ -1182,7 +1182,7 @@ rm -f .file-list-* rm -f %{name}.lang %changelog -* Wed Jan 08 2024 Jan Macku - 257-3 +* Wed Jan 08 2025 Jan Macku - 257-3 - udev/net_id: introduce naming scheme for RHEL-9.6 (RHEL-44417) - Rebase to new upstream stable release v257.2 (RHEL-71409) From 490ac630af357dd88aaf3f42927bba37e3114861 Mon Sep 17 00:00:00 2001 From: Jan Macku Date: Thu, 30 Jan 2025 09:29:29 +0100 Subject: [PATCH 2/2] systemd-257-4 Resolves: RHEL-57603,RHEL-73780,RHEL-75774 --- ...t-bail-if-SHELL_-variables-are-unset.patch | 58 - ...ubuntu-22-04-for-deploy-of-man-pages.patch | 25 + 0145-tree-wide-Fix-python-formatting.patch | 78 + 0146-ci-fix-Packit.patch | 25 + 0147-ci-drop-testing-farm-test.patch | 29 + ...ubscriber-list-when-we-disconenct-fr.patch | 180 +++ ...alized_subscribed-subscribed_as_strv.patch | 94 ++ ...move-bus_message_read_id128-to-bus-m.patch | 197 +++ ...move-bus_message_hash_ops-to-bus-mes.patch | 157 ++ ...move-string-set-append-get-funcs-to-.patch | 184 +++ ...ed-serialize-make-input-params-const.patch | 68 + ...-serialize-introduce-serialize_id128.patch | 70 + ...reset-the-count-returned-by-sd_bus_t.patch | 55 + ...-use-FOREACH_ARRAY-at-one-more-place.patch | 36 + ...p-duplicate-bus-track-deserializatio.patch | 32 + ...s-util-introduce-bus_get_instance_id.patch | 58 + ...PI-bus-id-and-validate-before-deseri.patch | 203 +++ ...tore-bus-track-deserialization-clean.patch | 32 + ...d-bus-util-add-missing-set.h-include.patch | 40 + 0162-udevadm-test-add-missing-oom-check.patch | 27 + ...ev-rules-replace-type-func-type-func.patch | 43 + ...t-change-maximum-log-level-when-runn.patch | 42 + ...roduce-v-verbose-option-to-show-verb.patch | 209 +++ ...original-token-string-in-log_event_e.patch | 1343 +++++++++++++++++ ...s-logs-result-of-format-substitution.patch | 524 +++++++ ...add-more-trace-logs-for-string-match.patch | 205 +++ ...introduce-udev_replace_chars_and_log.patch | 163 ++ ...e-whole-command-result-if-it-is-too-.patch | 38 + 0171-udev-rules-update-log-messages.patch | 900 +++++++++++ ...race-logs-for-GOTO-and-parent-condit.patch | 103 ++ systemd.spec | 62 +- 31 files changed, 5221 insertions(+), 59 deletions(-) delete mode 100644 0033-profile.d-don-t-bail-if-SHELL_-variables-are-unset.patch create mode 100644 0144-ci-use-ubuntu-22-04-for-deploy-of-man-pages.patch create mode 100644 0145-tree-wide-Fix-python-formatting.patch create mode 100644 0146-ci-fix-Packit.patch create mode 100644 0147-ci-drop-testing-farm-test.patch create mode 100644 0148-dbus-stash-the-subscriber-list-when-we-disconenct-fr.patch create mode 100644 0149-manager-s-deserialized_subscribed-subscribed_as_strv.patch create mode 100644 0150-shared-bus-util-move-bus_message_read_id128-to-bus-m.patch create mode 100644 0151-shared-bus-util-move-bus_message_hash_ops-to-bus-mes.patch create mode 100644 0152-shared-bus-util-move-string-set-append-get-funcs-to-.patch create mode 100644 0153-shared-serialize-make-input-params-const.patch create mode 100644 0154-shared-serialize-introduce-serialize_id128.patch create mode 100644 0155-bus-util-do-not-reset-the-count-returned-by-sd_bus_t.patch create mode 100644 0156-core-manager-use-FOREACH_ARRAY-at-one-more-place.patch create mode 100644 0157-core-manager-drop-duplicate-bus-track-deserializatio.patch create mode 100644 0158-bus-util-introduce-bus_get_instance_id.patch create mode 100644 0159-core-serialize-API-bus-id-and-validate-before-deseri.patch create mode 100644 0160-core-manager-restore-bus-track-deserialization-clean.patch create mode 100644 0161-shared-bus-util-add-missing-set.h-include.patch create mode 100644 0162-udevadm-test-add-missing-oom-check.patch create mode 100644 0163-udev-rules-replace-type-func-type-func.patch create mode 100644 0164-udev-rules-do-not-change-maximum-log-level-when-runn.patch create mode 100644 0165-udevadm-test-introduce-v-verbose-option-to-show-verb.patch create mode 100644 0166-udev-rules-show-original-token-string-in-log_event_e.patch create mode 100644 0167-udev-rules-logs-result-of-format-substitution.patch create mode 100644 0168-udev-rules-add-more-trace-logs-for-string-match.patch create mode 100644 0169-udev-rules-introduce-udev_replace_chars_and_log.patch create mode 100644 0170-udev-rules-ignore-whole-command-result-if-it-is-too-.patch create mode 100644 0171-udev-rules-update-log-messages.patch create mode 100644 0172-udev-rules-add-trace-logs-for-GOTO-and-parent-condit.patch diff --git a/0033-profile.d-don-t-bail-if-SHELL_-variables-are-unset.patch b/0033-profile.d-don-t-bail-if-SHELL_-variables-are-unset.patch deleted file mode 100644 index 84a4d66..0000000 --- a/0033-profile.d-don-t-bail-if-SHELL_-variables-are-unset.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 2a6fbf9da93ad2f76aa5578641e39801a13fd5dd Mon Sep 17 00:00:00 2001 -From: Tobias Klauser -Date: Wed, 11 Dec 2024 15:10:39 +0100 -Subject: [PATCH] profile.d: don't bail if $SHELL_* variables are unset - -If - for whatever reason - a script uses set -u (nounset) and includes -/etc/profile.d/70-systemd-shell-extra.sh (e.g. transitively via -/etc/profile) the script would fail with: - - /etc/profile.d/70-systemd-shell-extra.sh: line 15: SHELL_PROMPT_PREFIX: unbound variable - -For example: - - $ cat > foo.sh < +Date: Tue, 14 Jan 2025 13:26:05 +0100 +Subject: [PATCH] ci: use ubuntu 22:04 for deploy of man pages + +rhel-only: ci + +Related: RHEL-57603 +--- + .github/workflows/deploy-man-pages.yml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/.github/workflows/deploy-man-pages.yml b/.github/workflows/deploy-man-pages.yml +index 9739228a87..82fab81072 100644 +--- a/.github/workflows/deploy-man-pages.yml ++++ b/.github/workflows/deploy-man-pages.yml +@@ -26,7 +26,7 @@ jobs: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} +- runs-on: ubuntu-latest ++ runs-on: ubuntu-22.04 + + permissions: + pages: write diff --git a/0145-tree-wide-Fix-python-formatting.patch b/0145-tree-wide-Fix-python-formatting.patch new file mode 100644 index 0000000..c624880 --- /dev/null +++ b/0145-tree-wide-Fix-python-formatting.patch @@ -0,0 +1,78 @@ +From 879603eda7440bf84a4094863283d556c8562907 Mon Sep 17 00:00:00 2001 +From: Daan De Meyer +Date: Thu, 9 Jan 2025 16:24:22 +0100 +Subject: [PATCH] tree-wide: Fix python formatting + +The new release of ruff formats a few more things which causes linter +failures in CI so let's fix those formatting nits. + +(cherry picked from commit 96403d5121d93dd47dbe9dab5b90ff973e664ac3) + +Related: RHEL-57603 +--- + src/ukify/ukify.py | 6 +++--- + test/integration-test-wrapper.py | 6 +++--- + 2 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/src/ukify/ukify.py b/src/ukify/ukify.py +index 3f36aa7af6..be4e30eb8e 100755 +--- a/src/ukify/ukify.py ++++ b/src/ukify/ukify.py +@@ -763,7 +763,7 @@ def call_systemd_measure(uki: UKI, opts: UkifyConfig, profile_start: int = 0) -> + cmd = [ + measure_tool, + 'calculate', +- *(f"--{s.name.removeprefix('.')}={s.content}" for s in to_measure.values()), ++ *(f'--{s.name.removeprefix(".")}={s.content}' for s in to_measure.values()), + *(f'--bank={bank}' for bank in banks), + # For measurement, the keys are not relevant, so we can lump all the phase paths + # into one call to systemd-measure calculate. +@@ -786,7 +786,7 @@ def call_systemd_measure(uki: UKI, opts: UkifyConfig, profile_start: int = 0) -> + cmd = [ + measure_tool, + 'sign', +- *(f"--{s.name.removeprefix('.')}={s.content}" for s in to_measure.values()), ++ *(f'--{s.name.removeprefix(".")}={s.content}' for s in to_measure.values()), + *(f'--bank={bank}' for bank in banks), + ] + +@@ -1284,7 +1284,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}') + + + @contextlib.contextmanager +diff --git a/test/integration-test-wrapper.py b/test/integration-test-wrapper.py +index ef6df8840f..eacfeffe9c 100755 +--- a/test/integration-test-wrapper.py ++++ b/test/integration-test-wrapper.py +@@ -429,7 +429,7 @@ def main() -> None: + dropin += textwrap.dedent( + f""" + [Service] +- Environment=TEST_MATCH_SUBTEST={os.environ["TEST_MATCH_SUBTEST"]} ++ Environment=TEST_MATCH_SUBTEST={os.environ['TEST_MATCH_SUBTEST']} + """ + ) + +@@ -437,7 +437,7 @@ def main() -> None: + dropin += textwrap.dedent( + f""" + [Service] +- Environment=TEST_MATCH_TESTCASE={os.environ["TEST_MATCH_TESTCASE"]} ++ Environment=TEST_MATCH_TESTCASE={os.environ['TEST_MATCH_TESTCASE']} + """ + ) + +@@ -559,7 +559,7 @@ def main() -> None: + + ops += [f'journalctl --file {journal_file} --no-hostname -o short-monotonic -u {args.unit} -p info'] + +- print("Test failed, relevant logs can be viewed with: \n\n" f"{(' && '.join(ops))}\n", file=sys.stderr) ++ print(f'Test failed, relevant logs can be viewed with: \n\n{(" && ".join(ops))}\n', file=sys.stderr) + + # 0 also means we failed so translate that to a non-zero exit code to mark the test as failed. + exit(result.returncode or 1) diff --git a/0146-ci-fix-Packit.patch b/0146-ci-fix-Packit.patch new file mode 100644 index 0000000..8fa20ad --- /dev/null +++ b/0146-ci-fix-Packit.patch @@ -0,0 +1,25 @@ +From 5588bd5336067976b13857b443b883b27fe8606e Mon Sep 17 00:00:00 2001 +From: Jan Macku +Date: Wed, 15 Jan 2025 15:35:00 +0100 +Subject: [PATCH] ci: fix Packit + +rhel-only: ci + +Related: RHEL-57603 +--- + .packit.yml | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/.packit.yml b/.packit.yml +index d16e630817..9d6e6c1e4e 100644 +--- a/.packit.yml ++++ b/.packit.yml +@@ -7,6 +7,8 @@ files_to_sync: + - .packit.yml + - src: .packit_rpm/systemd.spec + dest: systemd.spec ++upstream_package_name: systemd ++downstream_package_name: systemd + # `git describe` returns in systemd's case 'v245-xxx' which breaks RPM version + # detection (that expects 245-xxxx'). Let's tweak the version string accordingly + upstream_tag_template: "v{version}" diff --git a/0147-ci-drop-testing-farm-test.patch b/0147-ci-drop-testing-farm-test.patch new file mode 100644 index 0000000..8820e69 --- /dev/null +++ b/0147-ci-drop-testing-farm-test.patch @@ -0,0 +1,29 @@ +From 956076a7fd7f02f10b28ef6de5c365f77fed4516 Mon Sep 17 00:00:00 2001 +From: Jan Macku +Date: Thu, 16 Jan 2025 14:42:48 +0100 +Subject: [PATCH] ci: drop testing farm test + +Test doesn't work on source-git repos, so let's drop it. + +rhel-only: ci + +Related: RHEL-57603 +--- + .packit.yml | 7 ------- + 1 file changed, 7 deletions(-) + +diff --git a/.packit.yml b/.packit.yml +index 9d6e6c1e4e..a5d9aca0e1 100644 +--- a/.packit.yml ++++ b/.packit.yml +@@ -48,10 +48,3 @@ jobs: + - centos-stream-10-ppc64le + - centos-stream-10-s390x + - centos-stream-10-x86_64 +- +-- job: tests +- trigger: pull_request +- fmf_path: test/fmf +- tmt_plan: ci +- targets: +- - centos-stream-10-x86_64 diff --git a/0148-dbus-stash-the-subscriber-list-when-we-disconenct-fr.patch b/0148-dbus-stash-the-subscriber-list-when-we-disconenct-fr.patch new file mode 100644 index 0000000..2874672 --- /dev/null +++ b/0148-dbus-stash-the-subscriber-list-when-we-disconenct-fr.patch @@ -0,0 +1,180 @@ +From 24c7b86ce25b4bc1b55cbf0dffe4fa78925476b5 Mon Sep 17 00:00:00 2001 +From: Ronan Pigott +Date: Thu, 28 Nov 2024 12:53:32 -0700 +Subject: [PATCH] dbus: stash the subscriber list when we disconenct from the + bus + +If we unexpectly disconnect from the bus, systemd would end up dropping +the list of subscribers, which breaks the ability of clients like logind +to monitor the state of units. + +Stash the list of subscribers into the deserialized state in the event +of a disconnect so that when we recover we can renew the broken +subscriptions. + +(cherry picked from commit 8402ca04d1a063c3d8a9e3d5c16df8bb8778ae98) + +Resolves: RHEL-73780 +--- + src/core/dbus.c | 21 +++++++++++++++------ + src/core/dbus.h | 2 +- + src/core/manager.c | 8 ++++---- + src/shared/bus-util.c | 22 ++++++++++++++++++++++ + src/shared/bus-util.h | 1 + + 5 files changed, 43 insertions(+), 11 deletions(-) + +diff --git a/src/core/dbus.c b/src/core/dbus.c +index 3f0f40e702..9abc35888d 100644 +--- a/src/core/dbus.c ++++ b/src/core/dbus.c +@@ -860,6 +860,8 @@ int bus_init_api(Manager *m) { + if (r < 0) + return log_error_errno(r, "Failed to set up API bus: %m"); + ++ (void) bus_track_coldplug(bus, &m->subscribed, /* recursive= */ false, m->deserialized_subscribed); ++ m->deserialized_subscribed = strv_free(m->deserialized_subscribed); + m->api_bus = TAKE_PTR(bus); + + return 0; +@@ -1004,8 +1006,17 @@ static void destroy_bus(Manager *m, sd_bus **bus) { + } + + /* Get rid of tracked clients on this bus */ +- if (m->subscribed && sd_bus_track_get_bus(m->subscribed) == *bus) ++ if (m->subscribed && sd_bus_track_get_bus(m->subscribed) == *bus) { ++ _cleanup_strv_free_ char **subscribed = NULL; ++ int r; ++ ++ r = bus_track_to_strv(m->subscribed, &subscribed); ++ if (r < 0) ++ log_warning_errno(r, "Failed to serialize api subscribers, ignoring: %m"); ++ strv_free_and_replace(m->deserialized_subscribed, subscribed); ++ + m->subscribed = sd_bus_track_unref(m->subscribed); ++ } + + HASHMAP_FOREACH(j, m->jobs) + if (j->bus_track && sd_bus_track_get_bus(j->bus_track) == *bus) +@@ -1064,7 +1075,6 @@ void bus_done(Manager *m) { + + assert(!m->subscribed); + +- m->deserialized_subscribed = strv_free(m->deserialized_subscribed); + m->polkit_registry = hashmap_free(m->polkit_registry); + } + +@@ -1153,20 +1163,19 @@ void bus_track_serialize(sd_bus_track *t, FILE *f, const char *prefix) { + } + } + +-int bus_track_coldplug(Manager *m, sd_bus_track **t, bool recursive, char **l) { ++int bus_track_coldplug(sd_bus *bus, sd_bus_track **t, bool recursive, char **l) { + int r; + +- assert(m); + assert(t); + + if (strv_isempty(l)) + return 0; + +- if (!m->api_bus) ++ if (!bus) + return 0; + + if (!*t) { +- r = sd_bus_track_new(m->api_bus, t, NULL, NULL); ++ r = sd_bus_track_new(bus, t, NULL, NULL); + if (r < 0) + return r; + } +diff --git a/src/core/dbus.h b/src/core/dbus.h +index d00c14d3b7..eb1baf6049 100644 +--- a/src/core/dbus.h ++++ b/src/core/dbus.h +@@ -19,7 +19,7 @@ void bus_done(Manager *m); + int bus_fdset_add_all(Manager *m, FDSet *fds); + + void bus_track_serialize(sd_bus_track *t, FILE *f, const char *prefix); +-int bus_track_coldplug(Manager *m, sd_bus_track **t, bool recursive, char **l); ++int bus_track_coldplug(sd_bus *bus, sd_bus_track **t, bool recursive, char **l); + + int bus_foreach_bus(Manager *m, sd_bus_track *subscribed2, int (*send_message)(sd_bus *bus, void *userdata), void *userdata); + +diff --git a/src/core/manager.c b/src/core/manager.c +index 485fdd1a66..068ea2ab03 100644 +--- a/src/core/manager.c ++++ b/src/core/manager.c +@@ -1803,6 +1803,9 @@ Manager* manager_free(Manager *m) { + free(m->switch_root); + free(m->switch_root_init); + ++ sd_bus_track_unref(m->subscribed); ++ strv_free(m->deserialized_subscribed); ++ + unit_defaults_done(&m->defaults); + + FOREACH_ARRAY(map, m->units_needing_mounts_for, _UNIT_MOUNT_DEPENDENCY_TYPE_MAX) { +@@ -2139,7 +2142,7 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds, const char *roo + manager_setup_bus(m); + + /* Now that we are connected to all possible buses, let's deserialize who is tracking us. */ +- r = bus_track_coldplug(m, &m->subscribed, false, m->deserialized_subscribed); ++ r = bus_track_coldplug(m->api_bus, &m->subscribed, false, m->deserialized_subscribed); + if (r < 0) + log_warning_errno(r, "Failed to deserialized tracked clients, ignoring: %m"); + m->deserialized_subscribed = strv_free(m->deserialized_subscribed); +@@ -3813,9 +3816,6 @@ int manager_reload(Manager *m) { + /* Clean up runtime objects no longer referenced */ + manager_vacuum(m); + +- /* Clean up deserialized tracked clients */ +- m->deserialized_subscribed = strv_free(m->deserialized_subscribed); +- + /* Consider the reload process complete now. */ + assert(m->n_reloading > 0); + m->n_reloading--; +diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c +index ff80e580fc..2cdde97b78 100644 +--- a/src/shared/bus-util.c ++++ b/src/shared/bus-util.c +@@ -698,6 +698,28 @@ int bus_track_add_name_many(sd_bus_track *t, char **l) { + return r; + } + ++int bus_track_to_strv(sd_bus_track *t, char ***ret) { ++ _cleanup_strv_free_ char **subscribed = NULL; ++ int r = 0; ++ ++ assert(ret); ++ ++ for (const char *n = sd_bus_track_first(t); n; n = sd_bus_track_next(t)) { ++ r = sd_bus_track_count_name(t, n); ++ if (r < 0) ++ return r; ++ ++ for (int j = 0; j < r; j++) { ++ r = strv_extend(&subscribed, n); ++ if (r < 0) ++ return r; ++ } ++ } ++ ++ *ret = TAKE_PTR(subscribed); ++ return r; ++} ++ + int bus_open_system_watch_bind_with_description(sd_bus **ret, const char *description) { + _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL; + const char *e; +diff --git a/src/shared/bus-util.h b/src/shared/bus-util.h +index fbccb24314..83522ad1c1 100644 +--- a/src/shared/bus-util.h ++++ b/src/shared/bus-util.h +@@ -63,6 +63,7 @@ int bus_path_encode_unique(sd_bus *b, const char *prefix, const char *sender_id, + int bus_path_decode_unique(const char *path, const char *prefix, char **ret_sender, char **ret_external); + + int bus_track_add_name_many(sd_bus_track *t, char **l); ++int bus_track_to_strv(sd_bus_track *t, char ***ret); + + int bus_open_system_watch_bind_with_description(sd_bus **ret, const char *description); + static inline int bus_open_system_watch_bind(sd_bus **ret) { diff --git a/0149-manager-s-deserialized_subscribed-subscribed_as_strv.patch b/0149-manager-s-deserialized_subscribed-subscribed_as_strv.patch new file mode 100644 index 0000000..ed050cd --- /dev/null +++ b/0149-manager-s-deserialized_subscribed-subscribed_as_strv.patch @@ -0,0 +1,94 @@ +From dedad9da3b54cbbe61086cac8cfe699feafeabd6 Mon Sep 17 00:00:00 2001 +From: Ronan Pigott +Date: Wed, 11 Dec 2024 12:47:10 -0700 +Subject: [PATCH] manager: s/deserialized_subscribed/subscribed_as_strv + +Now that this field may get populated at runtime, the deserialized name +is misleading. Change the name to reflect its updated purpose. + +(cherry picked from commit e1315a621ae26473fcc9cd0d6013836f5f498d40) + +Resolves: RHEL-73780 +--- + src/core/dbus.c | 6 +++--- + src/core/manager-serialize.c | 2 +- + src/core/manager.c | 6 +++--- + src/core/manager.h | 2 +- + 4 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/src/core/dbus.c b/src/core/dbus.c +index 9abc35888d..58cd1ee175 100644 +--- a/src/core/dbus.c ++++ b/src/core/dbus.c +@@ -860,8 +860,8 @@ int bus_init_api(Manager *m) { + if (r < 0) + return log_error_errno(r, "Failed to set up API bus: %m"); + +- (void) bus_track_coldplug(bus, &m->subscribed, /* recursive= */ false, m->deserialized_subscribed); +- m->deserialized_subscribed = strv_free(m->deserialized_subscribed); ++ (void) bus_track_coldplug(bus, &m->subscribed, /* recursive= */ false, m->subscribed_as_strv); ++ m->subscribed_as_strv = strv_free(m->subscribed_as_strv); + m->api_bus = TAKE_PTR(bus); + + return 0; +@@ -1013,7 +1013,7 @@ static void destroy_bus(Manager *m, sd_bus **bus) { + r = bus_track_to_strv(m->subscribed, &subscribed); + if (r < 0) + log_warning_errno(r, "Failed to serialize api subscribers, ignoring: %m"); +- strv_free_and_replace(m->deserialized_subscribed, subscribed); ++ strv_free_and_replace(m->subscribed_as_strv, subscribed); + + m->subscribed = sd_bus_track_unref(m->subscribed); + } +diff --git a/src/core/manager-serialize.c b/src/core/manager-serialize.c +index 3f624619df..bc29ac91c6 100644 +--- a/src/core/manager-serialize.c ++++ b/src/core/manager-serialize.c +@@ -493,7 +493,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { + (void) exec_shared_runtime_deserialize_one(m, val, fds); + else if ((val = startswith(l, "subscribed="))) { + +- r = strv_extend(&m->deserialized_subscribed, val); ++ r = strv_extend(&m->subscribed_as_strv, val); + if (r < 0) + return r; + } else if ((val = startswith(l, "varlink-server-socket-address="))) { +diff --git a/src/core/manager.c b/src/core/manager.c +index 068ea2ab03..4a7132274f 100644 +--- a/src/core/manager.c ++++ b/src/core/manager.c +@@ -1804,7 +1804,7 @@ Manager* manager_free(Manager *m) { + free(m->switch_root_init); + + sd_bus_track_unref(m->subscribed); +- strv_free(m->deserialized_subscribed); ++ strv_free(m->subscribed_as_strv); + + unit_defaults_done(&m->defaults); + +@@ -2142,10 +2142,10 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds, const char *roo + manager_setup_bus(m); + + /* Now that we are connected to all possible buses, let's deserialize who is tracking us. */ +- r = bus_track_coldplug(m->api_bus, &m->subscribed, false, m->deserialized_subscribed); ++ r = bus_track_coldplug(m->api_bus, &m->subscribed, false, m->subscribed_as_strv); + if (r < 0) + log_warning_errno(r, "Failed to deserialized tracked clients, ignoring: %m"); +- m->deserialized_subscribed = strv_free(m->deserialized_subscribed); ++ m->subscribed_as_strv = strv_free(m->subscribed_as_strv); + + r = manager_varlink_init(m); + if (r < 0) +diff --git a/src/core/manager.h b/src/core/manager.h +index e4cada80ff..7016eab2d3 100644 +--- a/src/core/manager.h ++++ b/src/core/manager.h +@@ -340,7 +340,7 @@ struct Manager { + considered subscribes, since they last for very short only, + and it is much simpler that way. */ + sd_bus_track *subscribed; +- char **deserialized_subscribed; ++ char **subscribed_as_strv; + + /* This is used during reloading: before the reload we queue + * the reply message here, and afterwards we send it */ diff --git a/0150-shared-bus-util-move-bus_message_read_id128-to-bus-m.patch b/0150-shared-bus-util-move-bus_message_read_id128-to-bus-m.patch new file mode 100644 index 0000000..de11747 --- /dev/null +++ b/0150-shared-bus-util-move-bus_message_read_id128-to-bus-m.patch @@ -0,0 +1,197 @@ +From 744459cb070eff2c30853bfd799f48878cea987a Mon Sep 17 00:00:00 2001 +From: Mike Yuan +Date: Sat, 11 Jan 2025 16:52:05 +0100 +Subject: [PATCH] shared/bus-util: move bus_message_read_id128() to + bus-message-util + +(cherry picked from commit ab33edb05b7d4c90fb80f46aa6b951c505048798) + +Resolves: RHEL-73780 +--- + src/core/dbus-manager.c | 1 + + src/hostname/hostnamectl.c | 1 + + src/machine/machinectl.c | 1 + + src/machine/machined-dbus.c | 1 + + src/run/run.c | 1 + + src/shared/bus-map-properties.c | 1 + + src/shared/bus-message-util.c | 29 +++++++++++++++++++++++++++++ + src/shared/bus-message-util.h | 2 ++ + src/shared/bus-util.c | 28 ---------------------------- + src/shared/bus-util.h | 2 -- + 10 files changed, 37 insertions(+), 30 deletions(-) + +diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c +index c4a7e2a20b..8e39d67a00 100644 +--- a/src/core/dbus-manager.c ++++ b/src/core/dbus-manager.c +@@ -11,6 +11,7 @@ + #include "bus-common-errors.h" + #include "bus-get-properties.h" + #include "bus-log-control-api.h" ++#include "bus-message-util.h" + #include "bus-util.h" + #include "chase.h" + #include "confidential-virt.h" +diff --git a/src/hostname/hostnamectl.c b/src/hostname/hostnamectl.c +index cd4f86af80..2d1334f654 100644 +--- a/src/hostname/hostnamectl.c ++++ b/src/hostname/hostnamectl.c +@@ -18,6 +18,7 @@ + #include "bus-error.h" + #include "bus-locator.h" + #include "bus-map-properties.h" ++#include "bus-message-util.h" + #include "format-table.h" + #include "hostname-setup.h" + #include "hostname-util.h" +diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c +index 7843b9aa63..8854d9a550 100644 +--- a/src/machine/machinectl.c ++++ b/src/machine/machinectl.c +@@ -21,6 +21,7 @@ + #include "bus-error.h" + #include "bus-locator.h" + #include "bus-map-properties.h" ++#include "bus-message-util.h" + #include "bus-print-properties.h" + #include "bus-unit-procs.h" + #include "bus-unit-util.h" +diff --git a/src/machine/machined-dbus.c b/src/machine/machined-dbus.c +index f4915f67da..05e44b5030 100644 +--- a/src/machine/machined-dbus.c ++++ b/src/machine/machined-dbus.c +@@ -10,6 +10,7 @@ + #include "bus-common-errors.h" + #include "bus-get-properties.h" + #include "bus-locator.h" ++#include "bus-message-util.h" + #include "bus-polkit.h" + #include "cgroup-util.h" + #include "discover-image.h" +diff --git a/src/run/run.c b/src/run/run.c +index 1b13e74b83..c4e79adc7a 100644 +--- a/src/run/run.c ++++ b/src/run/run.c +@@ -15,6 +15,7 @@ + #include "bus-error.h" + #include "bus-locator.h" + #include "bus-map-properties.h" ++#include "bus-message-util.h" + #include "bus-unit-util.h" + #include "bus-wait-for-jobs.h" + #include "calendarspec.h" +diff --git a/src/shared/bus-map-properties.c b/src/shared/bus-map-properties.c +index a6cd752894..18d83c336f 100644 +--- a/src/shared/bus-map-properties.c ++++ b/src/shared/bus-map-properties.c +@@ -5,6 +5,7 @@ + #include "bus-util.h" + #include "strv.h" + #include "bus-message.h" ++#include "bus-message-util.h" + + int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) { + sd_id128_t *p = userdata; +diff --git a/src/shared/bus-message-util.c b/src/shared/bus-message-util.c +index d8c483ef62..e93be9b3c5 100644 +--- a/src/shared/bus-message-util.c ++++ b/src/shared/bus-message-util.c +@@ -7,6 +7,35 @@ + #include "copy.h" + #include "resolve-util.h" + ++int bus_message_read_id128(sd_bus_message *m, sd_id128_t *ret) { ++ const void *a; ++ size_t sz; ++ int r; ++ ++ assert(m); ++ ++ r = sd_bus_message_read_array(m, 'y', &a, &sz); ++ if (r < 0) ++ return r; ++ ++ switch (sz) { ++ ++ case 0: ++ if (ret) ++ *ret = SD_ID128_NULL; ++ return 0; ++ ++ case sizeof(sd_id128_t): ++ if (ret) ++ memcpy(ret, a, sz); ++ return !memeqzero(a, sz); /* This mimics sd_id128_is_null(), but ret may be NULL, ++ * and a may be misaligned, so use memeqzero() here. */ ++ ++ default: ++ return -EINVAL; ++ } ++} ++ + int bus_message_read_ifindex(sd_bus_message *message, sd_bus_error *error, int *ret) { + int ifindex, r; + +diff --git a/src/shared/bus-message-util.h b/src/shared/bus-message-util.h +index 50025766c2..698960561c 100644 +--- a/src/shared/bus-message-util.h ++++ b/src/shared/bus-message-util.h +@@ -6,6 +6,8 @@ + #include "in-addr-util.h" + #include "socket-netlink.h" + ++int bus_message_read_id128(sd_bus_message *m, sd_id128_t *ret); ++ + int bus_message_read_ifindex(sd_bus_message *message, sd_bus_error *error, int *ret); + int bus_message_read_family(sd_bus_message *message, sd_bus_error *error, int *ret); + int bus_message_read_in_addr_auto(sd_bus_message *message, sd_bus_error *error, int *ret_family, union in_addr_union *ret_addr); +diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c +index 2cdde97b78..d3d3f1733e 100644 +--- a/src/shared/bus-util.c ++++ b/src/shared/bus-util.c +@@ -953,34 +953,6 @@ int bus_query_sender_pidref( + return bus_creds_get_pidref(creds, ret); + } + +-int bus_message_read_id128(sd_bus_message *m, sd_id128_t *ret) { +- const void *a; +- size_t sz; +- int r; +- +- assert(m); +- +- r = sd_bus_message_read_array(m, 'y', &a, &sz); +- if (r < 0) +- return r; +- +- switch (sz) { +- case 0: +- if (ret) +- *ret = SD_ID128_NULL; +- return 0; +- +- case sizeof(sd_id128_t): +- if (ret) +- memcpy(ret, a, sz); +- return !memeqzero(a, sz); /* This mimics sd_id128_is_null(), but ret may be NULL, +- * and a may be misaligned, so use memeqzero() here. */ +- +- default: +- return -EINVAL; +- } +-} +- + static const char* const bus_transport_table[] = { + [BUS_TRANSPORT_LOCAL] = "local", + [BUS_TRANSPORT_REMOTE] = "remote", +diff --git a/src/shared/bus-util.h b/src/shared/bus-util.h +index 83522ad1c1..c2b9b126c8 100644 +--- a/src/shared/bus-util.h ++++ b/src/shared/bus-util.h +@@ -84,6 +84,4 @@ int bus_property_get_string_set(sd_bus *bus, const char *path, const char *inter + int bus_creds_get_pidref(sd_bus_creds *c, PidRef *ret); + int bus_query_sender_pidref(sd_bus_message *m, PidRef *ret); + +-int bus_message_read_id128(sd_bus_message *m, sd_id128_t *ret); +- + const char* bus_transport_to_string(BusTransport transport) _const_; diff --git a/0151-shared-bus-util-move-bus_message_hash_ops-to-bus-mes.patch b/0151-shared-bus-util-move-bus_message_hash_ops-to-bus-mes.patch new file mode 100644 index 0000000..a98f605 --- /dev/null +++ b/0151-shared-bus-util-move-bus_message_hash_ops-to-bus-mes.patch @@ -0,0 +1,157 @@ +From 3a71e1dba1e5d56a3f0784df2ac53f5ad73a9451 Mon Sep 17 00:00:00 2001 +From: Mike Yuan +Date: Sat, 11 Jan 2025 17:10:43 +0100 +Subject: [PATCH] shared/bus-util: move bus_message_hash_ops to + bus-message-util + +(cherry picked from commit e3d37628aabff92e4b756e63ef0a6cd4569ce743) + +Resolves: RHEL-73780 +--- + src/home/homed-manager-bus.c | 9 +++++---- + src/login/logind-brightness.c | 4 ++-- + src/shared/bus-message-util.c | 4 ++++ + src/shared/bus-message-util.h | 2 ++ + src/shared/bus-util.c | 10 ---------- + src/shared/bus-util.h | 2 -- + src/systemctl/systemctl-list-units.c | 1 + + src/timedate/timedated.c | 1 + + 8 files changed, 15 insertions(+), 18 deletions(-) + +diff --git a/src/home/homed-manager-bus.c b/src/home/homed-manager-bus.c +index 69c7680b9e..08c917aee2 100644 +--- a/src/home/homed-manager-bus.c ++++ b/src/home/homed-manager-bus.c +@@ -4,6 +4,7 @@ + + #include "alloc-util.h" + #include "bus-common-errors.h" ++#include "bus-message-util.h" + #include "bus-polkit.h" + #include "format-util.h" + #include "home-util.h" +@@ -704,17 +705,17 @@ static int method_rebalance(sd_bus_message *message, void *userdata, sd_bus_erro + int r; + + r = manager_schedule_rebalance(m, /* immediately= */ true); +- if (r == 0) +- return sd_bus_reply_method_errorf(message, BUS_ERROR_REBALANCE_NOT_NEEDED, "No home directories need rebalancing."); + if (r < 0) + return r; ++ if (r == 0) ++ return sd_bus_reply_method_errorf(message, BUS_ERROR_REBALANCE_NOT_NEEDED, "No home directories need rebalancing."); + + /* Keep a reference to this message, so that we can reply to it once we are done */ +- r = set_ensure_put(&m->rebalance_queued_method_calls, &bus_message_hash_ops, message); ++ r = set_ensure_consume(&m->rebalance_queued_method_calls, &bus_message_hash_ops, sd_bus_message_ref(message)); + if (r < 0) + return log_error_errno(r, "Failed to track rebalance bus message: %m"); ++ assert(r > 0); + +- sd_bus_message_ref(message); + return 1; + } + +diff --git a/src/login/logind-brightness.c b/src/login/logind-brightness.c +index 40bcb39ce0..b3e7718394 100644 +--- a/src/login/logind-brightness.c ++++ b/src/login/logind-brightness.c +@@ -1,5 +1,6 @@ + /* SPDX-License-Identifier: LGPL-2.1-or-later */ + ++#include "bus-message-util.h" + #include "bus-util.h" + #include "device-util.h" + #include "hash-funcs.h" +@@ -173,10 +174,9 @@ static int set_add_message(Set **set, sd_bus_message *message) { + if (r <= 0) + return r; + +- r = set_ensure_put(set, &bus_message_hash_ops, message); ++ r = set_ensure_consume(set, &bus_message_hash_ops, sd_bus_message_ref(message)); + if (r <= 0) + return r; +- sd_bus_message_ref(message); + + return 1; + } +diff --git a/src/shared/bus-message-util.c b/src/shared/bus-message-util.c +index e93be9b3c5..a6523ff00e 100644 +--- a/src/shared/bus-message-util.c ++++ b/src/shared/bus-message-util.c +@@ -246,3 +246,7 @@ int bus_message_dump_fd(sd_bus_message *message) { + + return 0; + } ++ ++DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(bus_message_hash_ops, ++ void, trivial_hash_func, trivial_compare_func, ++ sd_bus_message, sd_bus_message_unref); +diff --git a/src/shared/bus-message-util.h b/src/shared/bus-message-util.h +index 698960561c..baec1cb92b 100644 +--- a/src/shared/bus-message-util.h ++++ b/src/shared/bus-message-util.h +@@ -21,3 +21,5 @@ int bus_message_read_dns_servers( + + int bus_message_dump_string(sd_bus_message *message); + int bus_message_dump_fd(sd_bus_message *message); ++ ++extern const struct hash_ops bus_message_hash_ops; +diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c +index d3d3f1733e..362dd78537 100644 +--- a/src/shared/bus-util.c ++++ b/src/shared/bus-util.c +@@ -862,16 +862,6 @@ int bus_register_malloc_status(sd_bus *bus, const char *destination) { + return 0; + } + +-static void bus_message_unref_wrapper(void *m) { +- sd_bus_message_unref(m); +-} +- +-const struct hash_ops bus_message_hash_ops = { +- .hash = trivial_hash_func, +- .compare = trivial_compare_func, +- .free_value = bus_message_unref_wrapper, +-}; +- + int bus_message_append_string_set(sd_bus_message *m, Set *set) { + const char *s; + int r; +diff --git a/src/shared/bus-util.h b/src/shared/bus-util.h +index c2b9b126c8..a2193ebf97 100644 +--- a/src/shared/bus-util.h ++++ b/src/shared/bus-util.h +@@ -75,8 +75,6 @@ int bus_reply_pair_array(sd_bus_message *m, char **l); + /* Listen to GetMallocInfo() calls to 'destination' and return malloc_info() via FD */ + int bus_register_malloc_status(sd_bus *bus, const char *destination); + +-extern const struct hash_ops bus_message_hash_ops; +- + int bus_message_append_string_set(sd_bus_message *m, Set *s); + + int bus_property_get_string_set(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error); +diff --git a/src/systemctl/systemctl-list-units.c b/src/systemctl/systemctl-list-units.c +index a2f3074358..b7cb103513 100644 +--- a/src/systemctl/systemctl-list-units.c ++++ b/src/systemctl/systemctl-list-units.c +@@ -5,6 +5,7 @@ + #include "ansi-color.h" + #include "bus-error.h" + #include "bus-locator.h" ++#include "bus-message-util.h" + #include "format-table.h" + #include "locale-util.h" + #include "path-util.h" +diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c +index c79bb864df..b196034a25 100644 +--- a/src/timedate/timedated.c ++++ b/src/timedate/timedated.c +@@ -17,6 +17,7 @@ + #include "bus-locator.h" + #include "bus-log-control-api.h" + #include "bus-map-properties.h" ++#include "bus-message-util.h" + #include "bus-polkit.h" + #include "bus-unit-util.h" + #include "clock-util.h" diff --git a/0152-shared-bus-util-move-string-set-append-get-funcs-to-.patch b/0152-shared-bus-util-move-string-set-append-get-funcs-to-.patch new file mode 100644 index 0000000..7f3997e --- /dev/null +++ b/0152-shared-bus-util-move-string-set-append-get-funcs-to-.patch @@ -0,0 +1,184 @@ +From b1e0b30efe89592eff532a35b14345bc48b2afce Mon Sep 17 00:00:00 2001 +From: Mike Yuan +Date: Sat, 11 Jan 2025 18:04:37 +0100 +Subject: [PATCH] shared/bus-util: move string set append/get funcs to + bus-message-util and bus-get-properties, respectively + +(cherry picked from commit 91080bc9733b5b2478bfc0ed58f6a7ae5da7e639) + +Resolves: RHEL-73780 +--- + src/core/dbus-cgroup.c | 1 + + src/shared/bus-get-properties.c | 19 +++++++++++++++++ + src/shared/bus-get-properties.h | 2 ++ + src/shared/bus-message-util.c | 19 +++++++++++++++++ + src/shared/bus-message-util.h | 2 ++ + src/shared/bus-util.c | 37 --------------------------------- + src/shared/bus-util.h | 4 ---- + 7 files changed, 43 insertions(+), 41 deletions(-) + +diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c +index fd48f3b07c..c99f1e29ac 100644 +--- a/src/core/dbus-cgroup.c ++++ b/src/core/dbus-cgroup.c +@@ -7,6 +7,7 @@ + #include "bpf-firewall.h" + #include "bpf-foreign.h" + #include "bus-get-properties.h" ++#include "bus-message-util.h" + #include "bus-util.h" + #include "cgroup-util.h" + #include "cgroup.h" +diff --git a/src/shared/bus-get-properties.c b/src/shared/bus-get-properties.c +index 53e5d6b99f..bf267a23a5 100644 +--- a/src/shared/bus-get-properties.c ++++ b/src/shared/bus-get-properties.c +@@ -1,6 +1,7 @@ + /* SPDX-License-Identifier: LGPL-2.1-or-later */ + + #include "bus-get-properties.h" ++#include "bus-message-util.h" + #include "rlimit-util.h" + #include "stdio-util.h" + #include "string-util.h" +@@ -164,3 +165,21 @@ int bus_property_get_rlimit( + + return sd_bus_message_append(reply, "t", u); + } ++ ++int bus_property_get_string_set( ++ sd_bus *bus, ++ const char *path, ++ const char *interface, ++ const char *property, ++ sd_bus_message *reply, ++ void *userdata, ++ sd_bus_error *error) { ++ ++ Set **s = ASSERT_PTR(userdata); ++ ++ assert(bus); ++ assert(property); ++ assert(reply); ++ ++ return bus_message_append_string_set(reply, *s); ++} +diff --git a/src/shared/bus-get-properties.h b/src/shared/bus-get-properties.h +index 4c35126502..9ddf5454de 100644 +--- a/src/shared/bus-get-properties.h ++++ b/src/shared/bus-get-properties.h +@@ -52,6 +52,8 @@ assert_cc(sizeof(mode_t) == sizeof(uint32_t)); + + int bus_property_get_rlimit(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error); + ++int bus_property_get_string_set(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error); ++ + #define BUS_DEFINE_PROPERTY_GET_GLOBAL(function, bus_type, val) \ + int function(sd_bus *bus, \ + const char *path, \ +diff --git a/src/shared/bus-message-util.c b/src/shared/bus-message-util.c +index a6523ff00e..8da112cacc 100644 +--- a/src/shared/bus-message-util.c ++++ b/src/shared/bus-message-util.c +@@ -216,6 +216,25 @@ clear: + return r; + } + ++int bus_message_append_string_set(sd_bus_message *m, const Set *set) { ++ int r; ++ ++ assert(m); ++ ++ r = sd_bus_message_open_container(m, 'a', "s"); ++ if (r < 0) ++ return r; ++ ++ const char *s; ++ SET_FOREACH(s, set) { ++ r = sd_bus_message_append(m, "s", s); ++ if (r < 0) ++ return r; ++ } ++ ++ return sd_bus_message_close_container(m); ++} ++ + int bus_message_dump_string(sd_bus_message *message) { + const char *s; + int r; +diff --git a/src/shared/bus-message-util.h b/src/shared/bus-message-util.h +index baec1cb92b..d4a05f5b9c 100644 +--- a/src/shared/bus-message-util.h ++++ b/src/shared/bus-message-util.h +@@ -19,6 +19,8 @@ int bus_message_read_dns_servers( + struct in_addr_full ***ret_dns, + size_t *ret_n_dns); + ++int bus_message_append_string_set(sd_bus_message *m, const Set *s); ++ + int bus_message_dump_string(sd_bus_message *message); + int bus_message_dump_fd(sd_bus_message *message); + +diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c +index 362dd78537..bdce97790d 100644 +--- a/src/shared/bus-util.c ++++ b/src/shared/bus-util.c +@@ -862,43 +862,6 @@ int bus_register_malloc_status(sd_bus *bus, const char *destination) { + return 0; + } + +-int bus_message_append_string_set(sd_bus_message *m, Set *set) { +- const char *s; +- int r; +- +- assert(m); +- +- r = sd_bus_message_open_container(m, 'a', "s"); +- if (r < 0) +- return r; +- +- SET_FOREACH(s, set) { +- r = sd_bus_message_append(m, "s", s); +- if (r < 0) +- return r; +- } +- +- return sd_bus_message_close_container(m); +-} +- +-int bus_property_get_string_set( +- sd_bus *bus, +- const char *path, +- const char *interface, +- const char *property, +- sd_bus_message *reply, +- void *userdata, +- sd_bus_error *error) { +- +- Set **s = ASSERT_PTR(userdata); +- +- assert(bus); +- assert(property); +- assert(reply); +- +- return bus_message_append_string_set(reply, *s); +-} +- + int bus_creds_get_pidref( + sd_bus_creds *c, + PidRef *ret) { +diff --git a/src/shared/bus-util.h b/src/shared/bus-util.h +index a2193ebf97..e49ba66a10 100644 +--- a/src/shared/bus-util.h ++++ b/src/shared/bus-util.h +@@ -75,10 +75,6 @@ int bus_reply_pair_array(sd_bus_message *m, char **l); + /* Listen to GetMallocInfo() calls to 'destination' and return malloc_info() via FD */ + int bus_register_malloc_status(sd_bus *bus, const char *destination); + +-int bus_message_append_string_set(sd_bus_message *m, Set *s); +- +-int bus_property_get_string_set(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error); +- + int bus_creds_get_pidref(sd_bus_creds *c, PidRef *ret); + int bus_query_sender_pidref(sd_bus_message *m, PidRef *ret); + diff --git a/0153-shared-serialize-make-input-params-const.patch b/0153-shared-serialize-make-input-params-const.patch new file mode 100644 index 0000000..0e4852c --- /dev/null +++ b/0153-shared-serialize-make-input-params-const.patch @@ -0,0 +1,68 @@ +From 47224a5d1eae82421419fb9bcf2916ee1de041dd Mon Sep 17 00:00:00 2001 +From: Mike Yuan +Date: Mon, 13 Jan 2025 16:35:13 +0100 +Subject: [PATCH] shared/serialize: make input params const + +(cherry picked from commit 3f03d39ca3b2f25f521342f2b0e49f60c51246e1) + +Resolves: RHEL-73780 +--- + src/shared/serialize.c | 9 ++++++--- + src/shared/serialize.h | 4 ++-- + 2 files changed, 8 insertions(+), 5 deletions(-) + +diff --git a/src/shared/serialize.c b/src/shared/serialize.c +index 735caf4978..58773e5ddd 100644 +--- a/src/shared/serialize.c ++++ b/src/shared/serialize.c +@@ -164,11 +164,14 @@ int serialize_dual_timestamp(FILE *f, const char *name, const dual_timestamp *t) + return serialize_item_format(f, name, USEC_FMT " " USEC_FMT, t->realtime, t->monotonic); + } + +-int serialize_strv(FILE *f, const char *key, char **l) { ++int serialize_strv(FILE *f, const char *key, char * const *l) { + int ret = 0, r; + + /* Returns the first error, or positive if anything was serialized, 0 otherwise. */ + ++ assert(f); ++ assert(key); ++ + STRV_FOREACH(i, l) { + r = serialize_item_escaped(f, key, *i); + if ((ret >= 0 && r < 0) || +@@ -267,8 +270,7 @@ int serialize_item_base64mem(FILE *f, const char *key, const void *p, size_t l) + return 1; + } + +-int serialize_string_set(FILE *f, const char *key, Set *s) { +- const char *e; ++int serialize_string_set(FILE *f, const char *key, const Set *s) { + int r; + + assert(f); +@@ -279,6 +281,7 @@ int serialize_string_set(FILE *f, const char *key, Set *s) { + + /* Serialize as individual items, as each element might contain separators and escapes */ + ++ const char *e; + SET_FOREACH(e, s) { + r = serialize_item(f, key, e); + if (r < 0) +diff --git a/src/shared/serialize.h b/src/shared/serialize.h +index 355eff9b8f..a1350533cf 100644 +--- a/src/shared/serialize.h ++++ b/src/shared/serialize.h +@@ -21,10 +21,10 @@ int serialize_fd(FILE *f, FDSet *fds, const char *key, int fd); + int serialize_fd_many(FILE *f, FDSet *fds, const char *key, const int fd_array[], size_t n_fd_array); + int serialize_usec(FILE *f, const char *key, usec_t usec); + int serialize_dual_timestamp(FILE *f, const char *key, const dual_timestamp *t); +-int serialize_strv(FILE *f, const char *key, char **l); ++int serialize_strv(FILE *f, const char *key, char * const *l); + int serialize_pidref(FILE *f, FDSet *fds, const char *key, PidRef *pidref); + int serialize_ratelimit(FILE *f, const char *key, const RateLimit *rl); +-int serialize_string_set(FILE *f, const char *key, Set *s); ++int serialize_string_set(FILE *f, const char *key, const Set *s); + int serialize_image_policy(FILE *f, const char *key, const ImagePolicy *p); + + static inline int serialize_bool(FILE *f, const char *key, bool b) { diff --git a/0154-shared-serialize-introduce-serialize_id128.patch b/0154-shared-serialize-introduce-serialize_id128.patch new file mode 100644 index 0000000..731858a --- /dev/null +++ b/0154-shared-serialize-introduce-serialize_id128.patch @@ -0,0 +1,70 @@ +From 6eda0675d5a30080c6dd68c863707e22192b9e42 Mon Sep 17 00:00:00 2001 +From: Mike Yuan +Date: Mon, 13 Jan 2025 16:35:58 +0100 +Subject: [PATCH] shared/serialize: introduce serialize_id128() + +(cherry picked from commit 38a2c2bf6a89def24007c0dac529c07da713abfb) + +Resolves: RHEL-73780 +--- + src/core/unit-serialize.c | 3 +-- + src/shared/serialize.c | 10 ++++++++++ + src/shared/serialize.h | 3 +++ + 3 files changed, 14 insertions(+), 2 deletions(-) + +diff --git a/src/core/unit-serialize.c b/src/core/unit-serialize.c +index 82102c0c32..2b5b472c47 100644 +--- a/src/core/unit-serialize.c ++++ b/src/core/unit-serialize.c +@@ -117,8 +117,7 @@ int unit_serialize_state(Unit *u, FILE *f, FDSet *fds, bool switching_root) { + if (gid_is_valid(u->ref_gid)) + (void) serialize_item_format(f, "ref-gid", GID_FMT, u->ref_gid); + +- if (!sd_id128_is_null(u->invocation_id)) +- (void) serialize_item_format(f, "invocation-id", SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(u->invocation_id)); ++ (void) serialize_id128(f, "invocation-id", u->invocation_id); + + (void) serialize_item(f, "freezer-state", freezer_state_to_string(u->freezer_state)); + +diff --git a/src/shared/serialize.c b/src/shared/serialize.c +index 58773e5ddd..44148bea2c 100644 +--- a/src/shared/serialize.c ++++ b/src/shared/serialize.c +@@ -182,6 +182,16 @@ int serialize_strv(FILE *f, const char *key, char * const *l) { + return ret; + } + ++int serialize_id128(FILE *f, const char *key, sd_id128_t id) { ++ assert(f); ++ assert(key); ++ ++ if (sd_id128_is_null(id)) ++ return 0; ++ ++ return serialize_item_format(f, key, SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(id)); ++} ++ + int serialize_pidref(FILE *f, FDSet *fds, const char *key, PidRef *pidref) { + int r; + +diff --git a/src/shared/serialize.h b/src/shared/serialize.h +index a1350533cf..f2be84807a 100644 +--- a/src/shared/serialize.h ++++ b/src/shared/serialize.h +@@ -3,6 +3,8 @@ + + #include + ++#include "sd-id128.h" ++ + #include "fdset.h" + #include "image-policy.h" + #include "macro.h" +@@ -22,6 +24,7 @@ int serialize_fd_many(FILE *f, FDSet *fds, const char *key, const int fd_array[] + int serialize_usec(FILE *f, const char *key, usec_t usec); + int serialize_dual_timestamp(FILE *f, const char *key, const dual_timestamp *t); + int serialize_strv(FILE *f, const char *key, char * const *l); ++int serialize_id128(FILE *f, const char *key, sd_id128_t id); + int serialize_pidref(FILE *f, FDSet *fds, const char *key, PidRef *pidref); + int serialize_ratelimit(FILE *f, const char *key, const RateLimit *rl); + int serialize_string_set(FILE *f, const char *key, const Set *s); diff --git a/0155-bus-util-do-not-reset-the-count-returned-by-sd_bus_t.patch b/0155-bus-util-do-not-reset-the-count-returned-by-sd_bus_t.patch new file mode 100644 index 0000000..44ebd68 --- /dev/null +++ b/0155-bus-util-do-not-reset-the-count-returned-by-sd_bus_t.patch @@ -0,0 +1,55 @@ +From 370d94580947ffbc2e3e1bee30564b98896d9d02 Mon Sep 17 00:00:00 2001 +From: Mike Yuan +Date: Sat, 11 Jan 2025 16:26:55 +0100 +Subject: [PATCH] bus-util: do not reset the count returned by + sd_bus_track_count_name() + +Follow-up for 8402ca04d1a063c3d8a9e3d5c16df8bb8778ae98 + +While at it, turn the retval check for sd_bus_track_count_name() +into assertion, given we're working with already established tracks +(service_name_is_valid() should never yield false in this case). + +Addresses https://github.com/systemd/systemd/pull/35406#discussion_r1912066774 + +(cherry picked from commit 33eeea4128f31df7ab4bd8866b582062d70114ae) + +Resolves: RHEL-73780 +--- + src/shared/bus-util.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c +index bdce97790d..1fda013697 100644 +--- a/src/shared/bus-util.c ++++ b/src/shared/bus-util.c +@@ -700,16 +700,15 @@ int bus_track_add_name_many(sd_bus_track *t, char **l) { + + int bus_track_to_strv(sd_bus_track *t, char ***ret) { + _cleanup_strv_free_ char **subscribed = NULL; +- int r = 0; ++ int r; + + assert(ret); + + for (const char *n = sd_bus_track_first(t); n; n = sd_bus_track_next(t)) { +- r = sd_bus_track_count_name(t, n); +- if (r < 0) +- return r; ++ int c = sd_bus_track_count_name(t, n); ++ assert(c >= 0); + +- for (int j = 0; j < r; j++) { ++ for (int j = 0; j < c; j++) { + r = strv_extend(&subscribed, n); + if (r < 0) + return r; +@@ -717,7 +716,7 @@ int bus_track_to_strv(sd_bus_track *t, char ***ret) { + } + + *ret = TAKE_PTR(subscribed); +- return r; ++ return 0; + } + + int bus_open_system_watch_bind_with_description(sd_bus **ret, const char *description) { diff --git a/0156-core-manager-use-FOREACH_ARRAY-at-one-more-place.patch b/0156-core-manager-use-FOREACH_ARRAY-at-one-more-place.patch new file mode 100644 index 0000000..be7e0c0 --- /dev/null +++ b/0156-core-manager-use-FOREACH_ARRAY-at-one-more-place.patch @@ -0,0 +1,36 @@ +From 19b9d9140cbb9270119f807e8b7fe4047d5aae4a Mon Sep 17 00:00:00 2001 +From: Mike Yuan +Date: Mon, 13 Jan 2025 17:06:21 +0100 +Subject: [PATCH] core/manager: use FOREACH_ARRAY at one more place + +(cherry picked from commit a7516260b32dd26fb61b1dd702b9bc718cd420f9) + +Resolves: RHEL-73780 +--- + src/core/manager.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/src/core/manager.c b/src/core/manager.c +index 4a7132274f..96fc8941eb 100644 +--- a/src/core/manager.c ++++ b/src/core/manager.c +@@ -1816,15 +1816,16 @@ Manager* manager_free(Manager *m) { + hashmap_free(m->uid_refs); + hashmap_free(m->gid_refs); + +- for (ExecDirectoryType dt = 0; dt < _EXEC_DIRECTORY_TYPE_MAX; dt++) +- m->prefix[dt] = mfree(m->prefix[dt]); ++ FOREACH_ARRAY(i, m->prefix, _EXEC_DIRECTORY_TYPE_MAX) ++ free(*i); ++ + free(m->received_credentials_directory); + free(m->received_encrypted_credentials_directory); + + free(m->watchdog_pretimeout_governor); + free(m->watchdog_pretimeout_governor_overridden); + +- m->fw_ctx = fw_ctx_free(m->fw_ctx); ++ fw_ctx_free(m->fw_ctx); + + #if BPF_FRAMEWORK + bpf_restrict_fs_destroy(m->restrict_fs); diff --git a/0157-core-manager-drop-duplicate-bus-track-deserializatio.patch b/0157-core-manager-drop-duplicate-bus-track-deserializatio.patch new file mode 100644 index 0000000..d4f34e7 --- /dev/null +++ b/0157-core-manager-drop-duplicate-bus-track-deserializatio.patch @@ -0,0 +1,32 @@ +From 860690d1fb190600ec6c8db9052ec4c9fac0666f Mon Sep 17 00:00:00 2001 +From: Mike Yuan +Date: Sat, 11 Jan 2025 18:38:49 +0100 +Subject: [PATCH] core/manager: drop duplicate bus track deserialization + +bus_init_api() now does this internally +(after 8402ca04d1a063c3d8a9e3d5c16df8bb8778ae98). + +(cherry picked from commit af0e10354e567bfd0b9521376b2aad55f12a4e3d) + +Resolves: RHEL-73780 +--- + src/core/manager.c | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/src/core/manager.c b/src/core/manager.c +index 96fc8941eb..38fe53c319 100644 +--- a/src/core/manager.c ++++ b/src/core/manager.c +@@ -2142,12 +2142,6 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds, const char *roo + /* Connect to the bus if we are good for it */ + manager_setup_bus(m); + +- /* Now that we are connected to all possible buses, let's deserialize who is tracking us. */ +- r = bus_track_coldplug(m->api_bus, &m->subscribed, false, m->subscribed_as_strv); +- if (r < 0) +- log_warning_errno(r, "Failed to deserialized tracked clients, ignoring: %m"); +- m->subscribed_as_strv = strv_free(m->subscribed_as_strv); +- + r = manager_varlink_init(m); + if (r < 0) + log_warning_errno(r, "Failed to set up Varlink, ignoring: %m"); diff --git a/0158-bus-util-introduce-bus_get_instance_id.patch b/0158-bus-util-introduce-bus_get_instance_id.patch new file mode 100644 index 0000000..1a8bb9f --- /dev/null +++ b/0158-bus-util-introduce-bus_get_instance_id.patch @@ -0,0 +1,58 @@ +From b5b61bf95b6d7d7ab1b01eb7e5195eb99b06635d Mon Sep 17 00:00:00 2001 +From: Mike Yuan +Date: Mon, 13 Jan 2025 16:42:34 +0100 +Subject: [PATCH] bus-util: introduce bus_get_instance_id() + +(cherry picked from commit a9a8d2e12fe01b928135895f00c5bca465b7d13b) + +Resolves: RHEL-73780 +--- + src/shared/bus-util.c | 23 +++++++++++++++++++++++ + src/shared/bus-util.h | 2 ++ + 2 files changed, 25 insertions(+) + +diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c +index 1fda013697..8eb3fbbf54 100644 +--- a/src/shared/bus-util.c ++++ b/src/shared/bus-util.c +@@ -905,6 +905,29 @@ int bus_query_sender_pidref( + return bus_creds_get_pidref(creds, ret); + } + ++int bus_get_instance_id(sd_bus *bus, sd_id128_t *ret) { ++ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; ++ int r; ++ ++ assert(bus); ++ assert(ret); ++ ++ r = sd_bus_call_method(bus, ++ "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "GetId", ++ /* error = */ NULL, &reply, ++ NULL); ++ if (r < 0) ++ return r; ++ ++ const char *id; ++ ++ r = sd_bus_message_read_basic(reply, 's', &id); ++ if (r < 0) ++ return r; ++ ++ return sd_id128_from_string(id, ret); ++} ++ + static const char* const bus_transport_table[] = { + [BUS_TRANSPORT_LOCAL] = "local", + [BUS_TRANSPORT_REMOTE] = "remote", +diff --git a/src/shared/bus-util.h b/src/shared/bus-util.h +index e49ba66a10..fe85d815b8 100644 +--- a/src/shared/bus-util.h ++++ b/src/shared/bus-util.h +@@ -78,4 +78,6 @@ int bus_register_malloc_status(sd_bus *bus, const char *destination); + int bus_creds_get_pidref(sd_bus_creds *c, PidRef *ret); + int bus_query_sender_pidref(sd_bus_message *m, PidRef *ret); + ++int bus_get_instance_id(sd_bus *bus, sd_id128_t *ret); ++ + const char* bus_transport_to_string(BusTransport transport) _const_; diff --git a/0159-core-serialize-API-bus-id-and-validate-before-deseri.patch b/0159-core-serialize-API-bus-id-and-validate-before-deseri.patch new file mode 100644 index 0000000..9bd03a1 --- /dev/null +++ b/0159-core-serialize-API-bus-id-and-validate-before-deseri.patch @@ -0,0 +1,203 @@ +From 1c3965954b88c0ac3811d29a186382633f336db7 Mon Sep 17 00:00:00 2001 +From: Mike Yuan +Date: Mon, 13 Jan 2025 17:06:35 +0100 +Subject: [PATCH] core: serialize API bus id and validate before deserializing + bus tracks + +(cherry picked from commit 1446e3c3921067e3a6228a3e172b5dfd95437136) + +Resolves: RHEL-73780 +--- + src/core/dbus.c | 55 +++++++++++++++++++----------------- + src/core/dbus.h | 1 - + src/core/manager-serialize.c | 8 +++++- + src/core/manager.h | 11 +++++--- + src/shared/bus-util.c | 2 +- + src/shared/bus-util.h | 2 +- + 6 files changed, 45 insertions(+), 34 deletions(-) + +diff --git a/src/core/dbus.c b/src/core/dbus.c +index 58cd1ee175..a2a2611a03 100644 +--- a/src/core/dbus.c ++++ b/src/core/dbus.c +@@ -5,6 +5,7 @@ + #include + + #include "sd-bus.h" ++#include "sd-id128.h" + + #include "alloc-util.h" + #include "bus-common-errors.h" +@@ -774,6 +775,24 @@ static int bus_on_connection(sd_event_source *s, int fd, uint32_t revents, void + return 0; + } + ++static int bus_track_coldplug(sd_bus *bus, sd_bus_track **t, char * const *l) { ++ int r; ++ ++ assert(bus); ++ assert(t); ++ ++ if (strv_isempty(l)) ++ return 0; ++ ++ if (!*t) { ++ r = sd_bus_track_new(bus, t, NULL, NULL); ++ if (r < 0) ++ return r; ++ } ++ ++ return bus_track_add_name_many(*t, l); ++} ++ + static int bus_setup_api(Manager *m, sd_bus *bus) { + char *name; + Unit *u; +@@ -860,10 +879,15 @@ int bus_init_api(Manager *m) { + if (r < 0) + return log_error_errno(r, "Failed to set up API bus: %m"); + +- (void) bus_track_coldplug(bus, &m->subscribed, /* recursive= */ false, m->subscribed_as_strv); ++ r = bus_get_instance_id(bus, &m->bus_id); ++ if (r < 0) ++ log_warning_errno(r, "Failed to query API bus instance ID, not deserializing subscriptions: %m"); ++ else if (sd_id128_is_null(m->deserialized_bus_id) || sd_id128_equal(m->bus_id, m->deserialized_bus_id)) ++ (void) bus_track_coldplug(bus, &m->subscribed, m->subscribed_as_strv); + m->subscribed_as_strv = strv_free(m->subscribed_as_strv); +- m->api_bus = TAKE_PTR(bus); ++ m->deserialized_bus_id = SD_ID128_NULL; + ++ m->api_bus = TAKE_PTR(bus); + return 0; + } + +@@ -1015,6 +1039,9 @@ static void destroy_bus(Manager *m, sd_bus **bus) { + log_warning_errno(r, "Failed to serialize api subscribers, ignoring: %m"); + strv_free_and_replace(m->subscribed_as_strv, subscribed); + ++ m->deserialized_bus_id = m->bus_id; ++ m->bus_id = SD_ID128_NULL; ++ + m->subscribed = sd_bus_track_unref(m->subscribed); + } + +@@ -1163,30 +1190,6 @@ void bus_track_serialize(sd_bus_track *t, FILE *f, const char *prefix) { + } + } + +-int bus_track_coldplug(sd_bus *bus, sd_bus_track **t, bool recursive, char **l) { +- int r; +- +- assert(t); +- +- if (strv_isempty(l)) +- return 0; +- +- if (!bus) +- return 0; +- +- if (!*t) { +- r = sd_bus_track_new(bus, t, NULL, NULL); +- if (r < 0) +- return r; +- } +- +- r = sd_bus_track_set_recursive(*t, recursive); +- if (r < 0) +- return r; +- +- return bus_track_add_name_many(*t, l); +-} +- + uint64_t manager_bus_n_queued_write(Manager *m) { + uint64_t c = 0; + sd_bus *b; +diff --git a/src/core/dbus.h b/src/core/dbus.h +index eb1baf6049..0f81102fc1 100644 +--- a/src/core/dbus.h ++++ b/src/core/dbus.h +@@ -19,7 +19,6 @@ void bus_done(Manager *m); + int bus_fdset_add_all(Manager *m, FDSet *fds); + + void bus_track_serialize(sd_bus_track *t, FILE *f, const char *prefix); +-int bus_track_coldplug(sd_bus *bus, sd_bus_track **t, bool recursive, char **l); + + int bus_foreach_bus(Manager *m, sd_bus_track *subscribed2, int (*send_message)(sd_bus *bus, void *userdata), void *userdata); + +diff --git a/src/core/manager-serialize.c b/src/core/manager-serialize.c +index bc29ac91c6..b225799ed9 100644 +--- a/src/core/manager-serialize.c ++++ b/src/core/manager-serialize.c +@@ -158,6 +158,7 @@ int manager_serialize( + (void) serialize_ratelimit(f, "dump-ratelimit", &m->dump_ratelimit); + (void) serialize_ratelimit(f, "reload-reexec-ratelimit", &m->reload_reexec_ratelimit); + ++ (void) serialize_id128(f, "bus-id", m->bus_id); + bus_track_serialize(m->subscribed, f, "subscribed"); + + r = dynamic_user_serialize(m, f, fds); +@@ -491,7 +492,12 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { + manager_deserialize_gid_refs_one(m, val); + else if ((val = startswith(l, "exec-runtime="))) + (void) exec_shared_runtime_deserialize_one(m, val, fds); +- else if ((val = startswith(l, "subscribed="))) { ++ else if ((val = startswith(l, "bus-id="))) { ++ ++ r = sd_id128_from_string(val, &m->deserialized_bus_id); ++ if (r < 0) ++ return r; ++ } else if ((val = startswith(l, "subscribed="))) { + + r = strv_extend(&m->subscribed_as_strv, val); + if (r < 0) +diff --git a/src/core/manager.h b/src/core/manager.h +index 7016eab2d3..c5bd242968 100644 +--- a/src/core/manager.h ++++ b/src/core/manager.h +@@ -335,13 +335,16 @@ struct Manager { + int private_listen_fd; + sd_event_source *private_listen_event_source; + +- /* Contains all the clients that are subscribed to signals via +- the API bus. Note that private bus connections are always +- considered subscribes, since they last for very short only, +- and it is much simpler that way. */ ++ /* Contains all the clients that are subscribed to signals via the API bus. Note that private bus ++ * connections are always considered subscribes, since they last for very short only, and it is ++ * much simpler that way. */ + sd_bus_track *subscribed; + char **subscribed_as_strv; + ++ /* The bus id of API bus acquired through org.freedesktop.DBus.GetId, which before deserializing ++ * subscriptions we'd use to verify the bus is still the same instance as before. */ ++ sd_id128_t bus_id, deserialized_bus_id; ++ + /* This is used during reloading: before the reload we queue + * the reply message here, and afterwards we send it */ + sd_bus_message *pending_reload_message; +diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c +index 8eb3fbbf54..9255dbc9b6 100644 +--- a/src/shared/bus-util.c ++++ b/src/shared/bus-util.c +@@ -686,7 +686,7 @@ int bus_path_decode_unique(const char *path, const char *prefix, char **ret_send + return 1; + } + +-int bus_track_add_name_many(sd_bus_track *t, char **l) { ++int bus_track_add_name_many(sd_bus_track *t, char * const *l) { + int r = 0; + + assert(t); +diff --git a/src/shared/bus-util.h b/src/shared/bus-util.h +index fe85d815b8..024b54648d 100644 +--- a/src/shared/bus-util.h ++++ b/src/shared/bus-util.h +@@ -62,7 +62,7 @@ int bus_log_connect_error(int r, BusTransport transport, RuntimeScope scope); + int bus_path_encode_unique(sd_bus *b, const char *prefix, const char *sender_id, const char *external_id, char **ret_path); + int bus_path_decode_unique(const char *path, const char *prefix, char **ret_sender, char **ret_external); + +-int bus_track_add_name_many(sd_bus_track *t, char **l); ++int bus_track_add_name_many(sd_bus_track *t, char * const *l); + int bus_track_to_strv(sd_bus_track *t, char ***ret); + + int bus_open_system_watch_bind_with_description(sd_bus **ret, const char *description); diff --git a/0160-core-manager-restore-bus-track-deserialization-clean.patch b/0160-core-manager-restore-bus-track-deserialization-clean.patch new file mode 100644 index 0000000..25f9afa --- /dev/null +++ b/0160-core-manager-restore-bus-track-deserialization-clean.patch @@ -0,0 +1,32 @@ +From ce3d2da71072a3bb4d2ea49159cba8a671bcde90 Mon Sep 17 00:00:00 2001 +From: Mike Yuan +Date: Mon, 13 Jan 2025 17:30:51 +0100 +Subject: [PATCH] core/manager: restore bus track deserialization cleanup in + manager_reload() + +There's zero explanation why it got (spuriously) removed in +8402ca04d1a063c3d8a9e3d5c16df8bb8778ae98... + +(cherry picked from commit 34f4b817f67b002eae7e2c09b19bf4b66c4791b6) + +Resolves: RHEL-73780 +--- + src/core/manager.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/src/core/manager.c b/src/core/manager.c +index 38fe53c319..cd8cdd87a5 100644 +--- a/src/core/manager.c ++++ b/src/core/manager.c +@@ -3805,6 +3805,11 @@ int manager_reload(Manager *m) { + (void) manager_setup_handoff_timestamp_fd(m); + (void) manager_setup_pidref_transport_fd(m); + ++ /* Clean up deserialized bus track information. They're never consumed during reload (as opposed to ++ * reexec) since we do not disconnect from the bus. */ ++ m->subscribed_as_strv = strv_free(m->subscribed_as_strv); ++ m->deserialized_bus_id = SD_ID128_NULL; ++ + /* Third, fire things up! */ + manager_coldplug(m); + diff --git a/0161-shared-bus-util-add-missing-set.h-include.patch b/0161-shared-bus-util-add-missing-set.h-include.patch new file mode 100644 index 0000000..662894a --- /dev/null +++ b/0161-shared-bus-util-add-missing-set.h-include.patch @@ -0,0 +1,40 @@ +From 4ffeaa184cc33612e7229328a9272059f4d3ce34 Mon Sep 17 00:00:00 2001 +From: Jan Macku +Date: Wed, 15 Jan 2025 15:06:46 +0100 +Subject: [PATCH] shared/bus-util: add missing `set.h` include +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +``` +In file included from ../src/shared/bus-get-properties.c:4: +../src/shared/bus-message-util.h:22:60: error: unknown type name ‘Set’ + 22 | int bus_message_append_string_set(sd_bus_message *m, const Set *s); + | ^~~ +../src/shared/bus-get-properties.c: In function ‘bus_property_get_string_set’: +../src/shared/bus-get-properties.c:178:9: error: unknown type name ‘Set’ + 178 | Set **s = ASSERT_PTR(userdata); + | ^~~ +``` + +follow-up to https://github.com/systemd/systemd/commit/91080bc9733b5b2478bfc0ed58f6a7ae5da7e639 + +(cherry picked from commit ca97d48bd425685d4ec20397812c3b1b006f5070) + +Resolves: RHEL-73780 +--- + src/shared/bus-message-util.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/shared/bus-message-util.h b/src/shared/bus-message-util.h +index d4a05f5b9c..02c670695e 100644 +--- a/src/shared/bus-message-util.h ++++ b/src/shared/bus-message-util.h +@@ -4,6 +4,7 @@ + #include "sd-bus.h" + + #include "in-addr-util.h" ++#include "set.h" + #include "socket-netlink.h" + + int bus_message_read_id128(sd_bus_message *m, sd_id128_t *ret); diff --git a/0162-udevadm-test-add-missing-oom-check.patch b/0162-udevadm-test-add-missing-oom-check.patch new file mode 100644 index 0000000..3ca19bf --- /dev/null +++ b/0162-udevadm-test-add-missing-oom-check.patch @@ -0,0 +1,27 @@ +From 6368b96d9333723c70413511d87630df896ff48c Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Sat, 11 Jan 2025 05:27:44 +0900 +Subject: [PATCH] udevadm-test: add missing oom check + +(cherry picked from commit 22ca9406c45bb07a02d28da13f6e3909071c9176) + +Resolves: RHEL-75774 +--- + src/udev/udevadm-test.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/udev/udevadm-test.c b/src/udev/udevadm-test.c +index 748bcaf364..34bc80ff4b 100644 +--- a/src/udev/udevadm-test.c ++++ b/src/udev/udevadm-test.c +@@ -129,6 +129,10 @@ int test_main(int argc, char *argv[], void *userdata) { + device_seal(dev); + + event = udev_event_new(dev, NULL, EVENT_UDEVADM_TEST); ++ if (!event) { ++ log_oom(); ++ goto out; ++ } + + assert_se(sigfillset(&mask) >= 0); + assert_se(sigprocmask(SIG_SETMASK, &mask, &sigmask_orig) >= 0); diff --git a/0163-udev-rules-replace-type-func-type-func.patch b/0163-udev-rules-replace-type-func-type-func.patch new file mode 100644 index 0000000..c97ed27 --- /dev/null +++ b/0163-udev-rules-replace-type-func-type-func.patch @@ -0,0 +1,43 @@ +From 69af60a47f87b85bc4f4bd82f61baa791c631138 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Sat, 11 Jan 2025 03:57:34 +0900 +Subject: [PATCH] udev-rules: replace 'type *func()' -> 'type* func()' + +(cherry picked from commit a75aeca78c3ad88dc9840f45963f86097d20cf6f) + +Resolves: RHEL-75774 +--- + src/udev/udev-rules.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c +index 85ae1c2163..8d00702595 100644 +--- a/src/udev/udev-rules.c ++++ b/src/udev/udev-rules.c +@@ -345,7 +345,7 @@ static void log_event_truncated( + + /*** Other functions ***/ + +-static UdevRuleToken *udev_rule_token_free(UdevRuleToken *token) { ++static UdevRuleToken* udev_rule_token_free(UdevRuleToken *token) { + if (!token) + return NULL; + +@@ -364,7 +364,7 @@ static void udev_rule_line_clear_tokens(UdevRuleLine *rule_line) { + udev_rule_token_free(i); + } + +-static UdevRuleLine *udev_rule_line_free(UdevRuleLine *rule_line) { ++static UdevRuleLine* udev_rule_line_free(UdevRuleLine *rule_line) { + if (!rule_line) + return NULL; + +@@ -379,7 +379,7 @@ static UdevRuleLine *udev_rule_line_free(UdevRuleLine *rule_line) { + + DEFINE_TRIVIAL_CLEANUP_FUNC(UdevRuleLine*, udev_rule_line_free); + +-static UdevRuleFile *udev_rule_file_free(UdevRuleFile *rule_file) { ++static UdevRuleFile* udev_rule_file_free(UdevRuleFile *rule_file) { + if (!rule_file) + return NULL; + diff --git a/0164-udev-rules-do-not-change-maximum-log-level-when-runn.patch b/0164-udev-rules-do-not-change-maximum-log-level-when-runn.patch new file mode 100644 index 0000000..37f7068 --- /dev/null +++ b/0164-udev-rules-do-not-change-maximum-log-level-when-runn.patch @@ -0,0 +1,42 @@ +From be7684d1738dfd62415a5f1f05318a7a4caacd18 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Sat, 11 Jan 2025 06:07:55 +0900 +Subject: [PATCH] udev-rules: do not change maximum log level when running in + test mode + +When udev rules are being tested, log level specified by SYSTEMD_LOG_LEVEL= +environment variable should be honored, and should not be overridden by +the rules. + +(cherry picked from commit 0363a45898b304b6040cd20e132a3dd946faae50) + +Resolves: RHEL-75774 +--- + src/udev/udev-rules.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c +index 8d00702595..60e1976c5a 100644 +--- a/src/udev/udev-rules.c ++++ b/src/udev/udev-rules.c +@@ -2394,11 +2394,18 @@ static int udev_rule_apply_token_to_event( + if (level < 0) + level = event->default_log_level; + +- log_set_max_level(level); ++ if (event->event_mode == EVENT_UDEV_WORKER) ++ log_set_max_level(level); ++ else { ++ _cleanup_free_ char *level_str = NULL; ++ (void) log_level_to_string_alloc(level, &level_str); ++ log_event_debug(dev, token, "Running in test mode, skipping changing maximum log level to %s.", strna(level_str)); ++ } + + if (level == LOG_DEBUG && !event->log_level_was_debug) { + /* The log level becomes LOG_DEBUG at first time. Let's log basic information. */ +- log_device_uevent(dev, "The log level is changed to 'debug' while processing device"); ++ if (event->event_mode == EVENT_UDEV_WORKER) ++ log_device_uevent(dev, "The log level is changed to 'debug' while processing device"); + event->log_level_was_debug = true; + } + diff --git a/0165-udevadm-test-introduce-v-verbose-option-to-show-verb.patch b/0165-udevadm-test-introduce-v-verbose-option-to-show-verb.patch new file mode 100644 index 0000000..5c10157 --- /dev/null +++ b/0165-udevadm-test-introduce-v-verbose-option-to-show-verb.patch @@ -0,0 +1,209 @@ +From e1941a839bc22c7a84b78a68537b03e4e0b995b3 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Mon, 13 Jan 2025 05:09:15 +0900 +Subject: [PATCH] udevadm-test: introduce -v/--verbose option to show verbose + log messages + +Currently this does not show any extra log messages. In later commits, +more verbose log messages will be added. + +(cherry picked from commit 8846df63fa30d2fb8749ed1753ddc397b1ff411e) + +Resolves: RHEL-75774 +--- + man/udevadm.xml | 9 +++++++++ + shell-completion/bash/udevadm | 13 +++++-------- + shell-completion/zsh/_udevadm | 1 + + src/udev/udev-event.h | 1 + + src/udev/udevadm-test.c | 25 +++++++++++++++++++------ + test/units/TEST-17-UDEV.10.sh | 1 + + 6 files changed, 36 insertions(+), 14 deletions(-) + +diff --git a/man/udevadm.xml b/man/udevadm.xml +index eb77356d86..caa41bd204 100644 +--- a/man/udevadm.xml ++++ b/man/udevadm.xml +@@ -869,6 +869,15 @@ + + + ++ ++ ++ ++ ++ Shows verbose logs in processing udev rules. ++ ++ ++ ++ + + + +diff --git a/shell-completion/bash/udevadm b/shell-completion/bash/udevadm +index 3842d722e7..af3a0b9058 100644 +--- a/shell-completion/bash/udevadm ++++ b/shell-completion/bash/udevadm +@@ -69,7 +69,8 @@ _udevadm() { + [CONTROL_ARG]='-l --log-priority -p --property -m --children-max -t --timeout' + [MONITOR_STANDALONE]='-k --kernel -u --udev -p --property' + [MONITOR_ARG]='-s --subsystem-match -t --tag-match' +- [TEST]='-a --action -N --resolve-names' ++ [TEST_STANDALONE]='-v --verbose' ++ [TEST_ARG]='-a --action -N --resolve-names' + [TEST_BUILTIN]='-a --action' + [VERIFY]='-N --resolve-names --root --no-summary --no-style' + [WAIT]='-t --timeout --initialized=no --removed --settle' +@@ -216,7 +217,7 @@ _udevadm() { + ;; + + 'test') +- if __contains_word "$prev" ${OPTS[TEST]}; then ++ if __contains_word "$prev" ${OPTS[TEST_ARG]}; then + case $prev in + -a|--action) + comps=$( udevadm test --action help ) +@@ -225,12 +226,8 @@ _udevadm() { + comps='early late never' + ;; + esac +- COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) +- return 0 +- fi +- +- if [[ $cur = -* ]]; then +- comps="${OPTS[COMMON]} ${OPTS[TEST]}" ++ elif [[ $cur = -* ]]; then ++ comps="${OPTS[COMMON]} ${OPTS[TEST_ARG]} ${OPTS[TEST_STANDALONE]}" + else + comps=$( __get_all_devices ) + local IFS=$'\n' +diff --git a/shell-completion/zsh/_udevadm b/shell-completion/zsh/_udevadm +index 9ff87d8312..5c3d3c93ef 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.]' \ ++ '(-v --verbose)'{-v,--verbose}'[Show verbose logs.]' \ + '*::devpath:_files -P /sys/ -W /sys' + } + +diff --git a/src/udev/udev-event.h b/src/udev/udev-event.h +index 3dc89365bb..22388fe904 100644 +--- a/src/udev/udev-event.h ++++ b/src/udev/udev-event.h +@@ -53,6 +53,7 @@ typedef struct UdevEvent { + bool name_final; + bool devlink_final; + bool run_final; ++ bool trace; + bool log_level_was_debug; + int default_log_level; + EventMode event_mode; +diff --git a/src/udev/udevadm-test.c b/src/udev/udevadm-test.c +index 34bc80ff4b..199ee0c18d 100644 +--- a/src/udev/udevadm-test.c ++++ b/src/udev/udevadm-test.c +@@ -33,6 +33,7 @@ + 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 bool arg_verbose = false; + + static int help(void) { + +@@ -41,7 +42,8 @@ static int help(void) { + " -h --help Show this help\n" + " -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", ++ " -N --resolve-names=early|late|never When to resolve names\n" ++ " -v --verbose Show verbose logs\n", + program_invocation_short_name); + + return 0; +@@ -51,6 +53,7 @@ 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' }, + {} +@@ -58,7 +61,7 @@ static int parse_argv(int argc, char *argv[]) { + + int r, c; + +- while ((c = getopt_long(argc, argv, "a:N:Vh", options, NULL)) >= 0) ++ while ((c = getopt_long(argc, argv, "a:N:vVh", options, NULL)) >= 0) + switch (c) { + case 'a': + r = parse_device_action(optarg, &arg_action); +@@ -73,6 +76,9 @@ 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 'v': ++ arg_verbose = true; ++ break; + case 'V': + return print_version(); + case 'h': +@@ -104,20 +110,23 @@ int test_main(int argc, char *argv[], void *userdata) { + if (r <= 0) + return r; + +- printf("This program is for debugging only, it does not run any program\n" +- "specified by a RUN key. It may show incorrect results, because\n" +- "some values may be different, or not available at a simulation run.\n" +- "\n"); ++ puts("This program is for debugging only, it does not run any program\n" ++ "specified by a RUN key. It may show incorrect results, because\n" ++ "some values may be different, or not available at a simulation run."); + + assert_se(sigprocmask(SIG_SETMASK, NULL, &sigmask_orig) >= 0); + ++ puts("\nLoading builtins..."); + udev_builtin_init(); ++ puts("Loading builtins done."); + ++ puts("\nLoading udev rules files..."); + r = udev_rules_load(&rules, arg_resolve_name_timing); + if (r < 0) { + log_error_errno(r, "Failed to read udev rules: %m"); + goto out; + } ++ puts("Loading udev rules files done."); + + r = find_device_with_action(arg_syspath, arg_action, &dev); + if (r < 0) { +@@ -133,12 +142,16 @@ int test_main(int argc, char *argv[], void *userdata) { + log_oom(); + goto out; + } ++ event->trace = arg_verbose; + + assert_se(sigfillset(&mask) >= 0); + assert_se(sigprocmask(SIG_SETMASK, &mask, &sigmask_orig) >= 0); + ++ printf("\nProcessing udev rules%s...\n", arg_verbose ? "" : " (verbose logs can be shown by -v/--verbose)"); + udev_event_execute_rules(event, rules); ++ 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); +diff --git a/test/units/TEST-17-UDEV.10.sh b/test/units/TEST-17-UDEV.10.sh +index 7ca05f5287..6820e76679 100755 +--- a/test/units/TEST-17-UDEV.10.sh ++++ b/test/units/TEST-17-UDEV.10.sh +@@ -130,6 +130,7 @@ udevadm test -N early /sys/class/net/$netdev + udevadm test -N late /sys/class/net/$netdev + udevadm test --resolve-names never /sys/class/net/$netdev + (! udevadm test -N hello /sys/class/net/$netdev) ++udevadm test -v /sys/class/net/$netdev + udevadm test -h + + # udevadm test-builtin path_id "$loopdev" diff --git a/0166-udev-rules-show-original-token-string-in-log_event_e.patch b/0166-udev-rules-show-original-token-string-in-log_event_e.patch new file mode 100644 index 0000000..ba32f18 --- /dev/null +++ b/0166-udev-rules-show-original-token-string-in-log_event_e.patch @@ -0,0 +1,1343 @@ +From 8ec8cd19867cacbf653c05caed80cf97569cbda4 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Mon, 13 Jan 2025 05:12:40 +0900 +Subject: [PATCH] udev-rules: show original token string in log_event_error() + and friends + +This also makes +- make many loggers refactored, +- log_event_error() and friends UdevEvent object, +- introduces log_event_trace(). + +No functional change, just refactoring and preparation for later +commits. + +(cherry picked from commit 6809bae6434707dbdbea7a7500612ebd8958f3cd) + +Resolves: RHEL-75774 +--- + src/udev/udev-rules.c | 458 +++++++++++++++++++++++------------------- + 1 file changed, 250 insertions(+), 208 deletions(-) + +diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c +index 60e1976c5a..c33d17aa47 100644 +--- a/src/udev/udev-rules.c ++++ b/src/udev/udev-rules.c +@@ -165,12 +165,15 @@ struct UdevRuleToken { + const char *value; + void *data; + ++ const char *token_str; /* original token string for logging */ ++ + UdevRuleLine *rule_line; + LIST_FIELDS(UdevRuleToken, tokens); + }; + + struct UdevRuleLine { + char *line; ++ char *line_for_logging; + unsigned line_number; + UdevRuleLineType type; + +@@ -203,82 +206,109 @@ struct UdevRules { + #define LINE_GET_RULES(line) \ + ASSERT_PTR(ASSERT_PTR(ASSERT_PTR(line)->rule_file)->rules) + ++static bool token_is_for_parents(UdevRuleToken *token) { ++ return token->type >= TK_M_PARENTS_KERNEL && token->type <= TK_M_PARENTS_TAG; ++} ++ + /*** Logging helpers ***/ + +-#define log_udev_rule_internal(device, file, line_nr, level, error, fmt, ...) \ ++#define _log_udev_rule_file_full(device, device_u, file, file_u, line_nr, level, level_u, error, fmt, ...) \ + ({ \ +- int _lv = (level); \ +- sd_device *_dev = (device); \ +- UdevRuleFile *_f = (file); \ +- const char *_n = _f ? _f->filename : NULL; \ ++ int level_u = (level); \ ++ sd_device *device_u = (device); \ ++ UdevRuleFile *file_u = (file); \ + \ +- if (!_dev && _f) \ +- _f->issues |= (1U << _lv); \ ++ if (!device_u && file_u) \ ++ file_u->issues |= (1U << level_u); \ + \ + log_device_full_errno_zerook( \ +- _dev, _lv, error, "%s:%u " fmt, \ +- strna(_n), line_nr, \ +- ##__VA_ARGS__); \ ++ device_u, level_u, error, "%s:%u " fmt, \ ++ strna(file_u ? file_u->filename : NULL), \ ++ line_nr, ##__VA_ARGS__); \ + }) + +-/* Mainly used when applying tokens to the event device. */ +-#define log_event_full_errno_zerook(device, token, ...) \ ++#define log_udev_rule_file_full(device, file, line_nr, level, error, fmt, ...) \ ++ _log_udev_rule_file_full(device, UNIQ_T(d, UNIQ), file, UNIQ_T(f, UNIQ), line_nr, level, UNIQ_T(l, UNIQ), error, fmt, ##__VA_ARGS__) ++ ++#define _log_udev_rule_line_full(device, line, line_u, ...) \ + ({ \ +- UdevRuleToken *_t = (token); \ +- UdevRuleLine *_l = _t ? _t->rule_line : NULL; \ ++ UdevRuleLine *line_u = ASSERT_PTR(line); \ + \ +- log_udev_rule_internal( \ ++ log_udev_rule_file_full( \ + device, \ +- _l ? _l->rule_file : NULL, \ +- _l ? _l->line_number : 0, \ ++ line_u->rule_file, line_u->line_number, \ + __VA_ARGS__); \ + }) + +-#define log_event_full_errno(device, token, level, error, ...) \ ++#define log_udev_rule_line_full(device, line, ...) \ ++ _log_udev_rule_line_full(device, line, UNIQ_T(l, UNIQ), __VA_ARGS__) ++ ++/* Mainly used when applying tokens to the event device. */ ++#define _log_event_full_errno_zerook(event, event_u, token, token_u, level, error, fmt, ...) \ ++ ({ \ ++ UdevEvent *event_u = ASSERT_PTR(event); \ ++ UdevRuleToken *token_u = ASSERT_PTR(token); \ ++ \ ++ log_udev_rule_line_full( \ ++ token_is_for_parents(token_u) ? event_u->dev_parent : event_u->dev, \ ++ token_u->rule_line, \ ++ level, error, "%s: " fmt, \ ++ token_u->token_str, ##__VA_ARGS__); \ ++ }) ++ ++#define log_event_full_errno_zerook(event, token, ...) \ ++ _log_event_full_errno_zerook(event, UNIQ_T(e, UNIQ), token, UNIQ_T(t, UNIQ), __VA_ARGS__) ++ ++#define _log_event_full_errno(event, token, level, error, error_u, ...) \ + ({ \ +- int _error = (error); \ +- ASSERT_NON_ZERO(_error); \ ++ int error_u = (error); \ ++ ASSERT_NON_ZERO(error_u); \ + log_event_full_errno_zerook( \ +- device, token, level, _error, ##__VA_ARGS__); \ ++ event, token, level, error_u, \ ++ __VA_ARGS__); \ + }) + +-#define log_event_full(device, token, level, ...) (void) log_event_full_errno_zerook(device, token, level, 0, __VA_ARGS__) ++#define log_event_full_errno(event, token, level, error, ...) \ ++ _log_event_full_errno(event, token, level, error, UNIQ_T(e, UNIQ), __VA_ARGS__) + +-#define log_event_debug(device, token, ...) log_event_full(device, token, LOG_DEBUG, __VA_ARGS__) +-#define log_event_info(device, token, ...) log_event_full(device, token, LOG_INFO, __VA_ARGS__) +-#define log_event_notice(device, token, ...) log_event_full(device, token, LOG_NOTICE, __VA_ARGS__) +-#define log_event_warning(device, token, ...) log_event_full(device, token, LOG_WARNING, __VA_ARGS__) +-#define log_event_error(device, token, ...) log_event_full(device, token, LOG_ERR, __VA_ARGS__) ++#define log_event_full(event, token, level, ...) (void) log_event_full_errno_zerook(event, token, level, 0, __VA_ARGS__) + +-#define log_event_debug_errno(device, token, error, ...) log_event_full_errno(device, token, LOG_DEBUG, error, __VA_ARGS__) +-#define log_event_info_errno(device, token, error, ...) log_event_full_errno(device, token, LOG_INFO, error, __VA_ARGS__) +-#define log_event_notice_errno(device, token, error, ...) log_event_full_errno(device, token, LOG_NOTICE, error, __VA_ARGS__) +-#define log_event_warning_errno(device, token, error, ...) log_event_full_errno(device, token, LOG_WARNING, error, __VA_ARGS__) +-#define log_event_error_errno(device, token, error, ...) log_event_full_errno(device, token, LOG_ERR, error, __VA_ARGS__) ++#define log_event_debug(event, token, ...) log_event_full(event, token, LOG_DEBUG, __VA_ARGS__) ++#define log_event_info(event, token, ...) log_event_full(event, token, LOG_INFO, __VA_ARGS__) ++#define log_event_notice(event, token, ...) log_event_full(event, token, LOG_NOTICE, __VA_ARGS__) ++#define log_event_warning(event, token, ...) log_event_full(event, token, LOG_WARNING, __VA_ARGS__) ++#define log_event_error(event, token, ...) log_event_full(event, token, LOG_ERR, __VA_ARGS__) ++ ++#define log_event_debug_errno(event, token, error, ...) log_event_full_errno(event, token, LOG_DEBUG, error, __VA_ARGS__) ++#define log_event_info_errno(event, token, error, ...) log_event_full_errno(event, token, LOG_INFO, error, __VA_ARGS__) ++#define log_event_notice_errno(event, token, error, ...) log_event_full_errno(event, token, LOG_NOTICE, error, __VA_ARGS__) ++#define log_event_warning_errno(event, token, error, ...) log_event_full_errno(event, token, LOG_WARNING, error, __VA_ARGS__) ++#define log_event_error_errno(event, token, error, ...) log_event_full_errno(event, token, LOG_ERR, error, __VA_ARGS__) ++ ++#define _log_event_trace(event, event_u, ...) \ ++ ({ \ ++ UdevEvent *event_u = ASSERT_PTR(event); \ ++ \ ++ event_u->trace ? \ ++ log_event_debug(event_u, __VA_ARGS__) : \ ++ (void) 0; \ ++ }) ++ ++#define log_event_trace(event, ...) \ ++ _log_event_trace(event, UNIQ_T(e, UNIQ), __VA_ARGS__) + + /* Mainly used when parsing .rules files. */ +-#define log_file_full_errno_zerook(...) \ +- log_udev_rule_internal(NULL, __VA_ARGS__) ++#define log_file_full_errno_zerook(...) \ ++ log_udev_rule_file_full(NULL, __VA_ARGS__) + + #define log_file_error(file, line_nr, ...) \ + log_file_full_errno_zerook(file, line_nr, LOG_ERR, 0, __VA_ARGS__) + +-#define log_line_full_errno_zerook(line, ...) \ +- ({ \ +- UdevRuleLine *_l = (line); \ +- log_file_full_errno_zerook( \ +- _l ? _l->rule_file : NULL, \ +- _l ? _l->line_number : 0, \ +- __VA_ARGS__); \ +- }) ++#define log_line_full_errno_zerook(...) \ ++ log_udev_rule_line_full(NULL, __VA_ARGS__) + + #define log_line_full_errno(line, level, error, ...) \ +- ({ \ +- int _error = (error); \ +- ASSERT_NON_ZERO(_error); \ +- log_line_full_errno_zerook( \ +- line, level, _error, ##__VA_ARGS__); \ +- }) ++ log_udev_rule_line_full(NULL, line, level, error, __VA_ARGS__) + + #define log_line_full(line, level, ...) (void) log_line_full_errno_zerook(line, level, 0, __VA_ARGS__) + +@@ -316,15 +346,13 @@ static void log_unknown_owner(sd_device *dev, UdevRuleLine *line, int error, con + ASSERT_NON_ZERO(error); + + if (IN_SET(abs(error), ENOENT, ESRCH)) +- log_udev_rule_internal(dev, line->rule_file, line->line_number, LOG_ERR, error, +- "Unknown %s '%s', ignoring.", entity, name); ++ log_udev_rule_line_full(dev, line, LOG_ERR, error, "Unknown %s '%s', ignoring.", entity, name); + else +- log_udev_rule_internal(dev, line->rule_file, line->line_number, LOG_ERR, error, +- "Failed to resolve %s '%s', ignoring: %m", entity, name); ++ log_udev_rule_line_full(dev, line, LOG_ERR, error, "Failed to resolve %s '%s', ignoring: %m", entity, name); + } + + static void log_event_truncated( +- sd_device *dev, ++ UdevEvent *event, + UdevRuleToken *token, + const char *what, + const char *format, +@@ -332,12 +360,12 @@ static void log_event_truncated( + bool is_match) { + + if (is_match) +- log_event_debug(dev, token, ++ log_event_debug(event, token, + "The %s is truncated while substituting into '%s', " + "assuming the %s key does not match.", + what, format, key); + else +- log_event_warning(dev, token, ++ log_event_warning(event, token, + "The %s is truncated while substituting into '%s', " + "refusing to apply the %s key.", + what, format, key); +@@ -374,6 +402,7 @@ static UdevRuleLine* udev_rule_line_free(UdevRuleLine *rule_line) { + LIST_REMOVE(rule_lines, rule_line->rule_file->rule_lines, rule_line); + + free(rule_line->line); ++ free(rule_line->line_for_logging); + return mfree(rule_line); + } + +@@ -494,7 +523,15 @@ static bool type_has_nulstr_value(UdevRuleTokenType type) { + return type < TK_M_TEST || type == TK_M_RESULT; + } + +-static int rule_line_add_token(UdevRuleLine *rule_line, UdevRuleTokenType type, UdevRuleOperatorType op, char *value, void *data, bool is_case_insensitive) { ++static int rule_line_add_token( ++ UdevRuleLine *rule_line, ++ UdevRuleTokenType type, ++ UdevRuleOperatorType op, ++ char *value, ++ void *data, ++ bool is_case_insensitive, ++ const char *token_str) { ++ + _cleanup_(udev_rule_token_freep) UdevRuleToken *token = NULL; + UdevRuleMatchType match_type = _MATCH_TYPE_INVALID; + UdevRuleSubstituteType subst_type = _SUBST_TYPE_INVALID; +@@ -582,6 +619,7 @@ static int rule_line_add_token(UdevRuleLine *rule_line, UdevRuleTokenType type, + .data = data, + .match_type = match_type, + .attr_subst_type = subst_type, ++ .token_str = token_str, + .rule_line = rule_line, + }; + +@@ -629,7 +667,15 @@ static int check_attr_format_and_warn(UdevRuleLine *line, const char *key, const + return 0; + } + +-static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, UdevRuleOperatorType op, char *value, bool is_case_insensitive) { ++static int parse_token( ++ UdevRuleLine *rule_line, ++ const char *key, ++ char *attr, ++ UdevRuleOperatorType op, ++ char *value, ++ bool is_case_insensitive, ++ const char *token_str) { ++ + ResolveNameTiming resolve_name_timing = LINE_GET_RULES(rule_line)->resolve_name_timing; + bool is_match = IN_SET(op, OP_MATCH, OP_NOMATCH); + int r; +@@ -647,29 +693,29 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude + if (!is_match) + return log_line_invalid_op(rule_line, key); + +- r = rule_line_add_token(rule_line, TK_M_ACTION, op, value, NULL, is_case_insensitive); ++ r = rule_line_add_token(rule_line, TK_M_ACTION, op, value, NULL, is_case_insensitive, token_str); + } else if (streq(key, "DEVPATH")) { + if (attr) + return log_line_invalid_attr(rule_line, key); + if (!is_match) + return log_line_invalid_op(rule_line, key); + +- r = rule_line_add_token(rule_line, TK_M_DEVPATH, op, value, NULL, is_case_insensitive); ++ r = rule_line_add_token(rule_line, TK_M_DEVPATH, op, value, NULL, is_case_insensitive, token_str); + } else if (streq(key, "KERNEL")) { + if (attr) + return log_line_invalid_attr(rule_line, key); + if (!is_match) + return log_line_invalid_op(rule_line, key); + +- r = rule_line_add_token(rule_line, TK_M_KERNEL, op, value, NULL, is_case_insensitive); ++ r = rule_line_add_token(rule_line, TK_M_KERNEL, op, value, NULL, is_case_insensitive, token_str); + } else if (streq(key, "SYMLINK")) { + if (attr) + return log_line_invalid_attr(rule_line, key); + if (!is_match) { + check_value_format_and_warn(rule_line, key, value, false); +- r = rule_line_add_token(rule_line, TK_A_DEVLINK, op, value, NULL, /* is_case_insensitive = */ false); ++ r = rule_line_add_token(rule_line, TK_A_DEVLINK, op, value, NULL, /* is_case_insensitive = */ false, token_str); + } else +- r = rule_line_add_token(rule_line, TK_M_DEVLINK, op, value, NULL, is_case_insensitive); ++ r = rule_line_add_token(rule_line, TK_M_DEVLINK, op, value, NULL, is_case_insensitive, token_str); + } else if (streq(key, "NAME")) { + if (attr) + return log_line_invalid_attr(rule_line, key); +@@ -689,9 +735,9 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude + "Ignoring NAME=\"\", as udev will not delete any network interfaces."); + check_value_format_and_warn(rule_line, key, value, false); + +- r = rule_line_add_token(rule_line, TK_A_NAME, op, value, NULL, /* is_case_insensitive = */ false); ++ r = rule_line_add_token(rule_line, TK_A_NAME, op, value, NULL, /* is_case_insensitive = */ false, token_str); + } else +- r = rule_line_add_token(rule_line, TK_M_NAME, op, value, NULL, is_case_insensitive); ++ r = rule_line_add_token(rule_line, TK_M_NAME, op, value, NULL, is_case_insensitive, token_str); + } else if (streq(key, "ENV")) { + if (isempty(attr)) + return log_line_invalid_attr(rule_line, key); +@@ -709,15 +755,15 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude + + check_value_format_and_warn(rule_line, key, value, false); + +- r = rule_line_add_token(rule_line, TK_A_ENV, op, value, attr, /* is_case_insensitive = */ false); ++ r = rule_line_add_token(rule_line, TK_A_ENV, op, value, attr, /* is_case_insensitive = */ false, token_str); + } else +- r = rule_line_add_token(rule_line, TK_M_ENV, op, value, attr, is_case_insensitive); ++ r = rule_line_add_token(rule_line, TK_M_ENV, op, value, attr, is_case_insensitive, token_str); + } else if (streq(key, "CONST")) { + if (isempty(attr) || !STR_IN_SET(attr, "arch", "virt")) + return log_line_invalid_attr(rule_line, key); + if (!is_match) + return log_line_invalid_op(rule_line, key); +- r = rule_line_add_token(rule_line, TK_M_CONST, op, value, attr, is_case_insensitive); ++ r = rule_line_add_token(rule_line, TK_M_CONST, op, value, attr, is_case_insensitive, token_str); + } else if (streq(key, "TAG")) { + if (attr) + return log_line_invalid_attr(rule_line, key); +@@ -729,9 +775,9 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude + if (!is_match) { + check_value_format_and_warn(rule_line, key, value, true); + +- r = rule_line_add_token(rule_line, TK_A_TAG, op, value, NULL, /* is_case_insensitive = */ false); ++ r = rule_line_add_token(rule_line, TK_A_TAG, op, value, NULL, /* is_case_insensitive = */ false, token_str); + } else +- r = rule_line_add_token(rule_line, TK_M_TAG, op, value, NULL, is_case_insensitive); ++ r = rule_line_add_token(rule_line, TK_M_TAG, op, value, NULL, is_case_insensitive, token_str); + } else if (streq(key, "SUBSYSTEM")) { + if (attr) + return log_line_invalid_attr(rule_line, key); +@@ -741,14 +787,14 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude + if (STR_IN_SET(value, "bus", "class")) + log_line_warning(rule_line, "\"%s\" must be specified as \"subsystem\".", value); + +- r = rule_line_add_token(rule_line, TK_M_SUBSYSTEM, op, value, NULL, is_case_insensitive); ++ r = rule_line_add_token(rule_line, TK_M_SUBSYSTEM, op, value, NULL, is_case_insensitive, token_str); + } else if (streq(key, "DRIVER")) { + if (attr) + return log_line_invalid_attr(rule_line, key); + if (!is_match) + return log_line_invalid_op(rule_line, key); + +- r = rule_line_add_token(rule_line, TK_M_DRIVER, op, value, NULL, is_case_insensitive); ++ r = rule_line_add_token(rule_line, TK_M_DRIVER, op, value, NULL, is_case_insensitive, token_str); + } else if (streq(key, "ATTR")) { + r = check_attr_format_and_warn(rule_line, key, attr); + if (r < 0) +@@ -762,9 +808,9 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude + + if (!is_match) { + check_value_format_and_warn(rule_line, key, value, false); +- r = rule_line_add_token(rule_line, TK_A_ATTR, op, value, attr, /* is_case_insensitive = */ false); ++ r = rule_line_add_token(rule_line, TK_A_ATTR, op, value, attr, /* is_case_insensitive = */ false, token_str); + } else +- r = rule_line_add_token(rule_line, TK_M_ATTR, op, value, attr, is_case_insensitive); ++ r = rule_line_add_token(rule_line, TK_M_ATTR, op, value, attr, is_case_insensitive, token_str); + } else if (streq(key, "SYSCTL")) { + r = check_attr_format_and_warn(rule_line, key, attr); + if (r < 0) +@@ -778,30 +824,30 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude + + if (!is_match) { + check_value_format_and_warn(rule_line, key, value, false); +- r = rule_line_add_token(rule_line, TK_A_SYSCTL, op, value, attr, /* is_case_insensitive = */ false); ++ r = rule_line_add_token(rule_line, TK_A_SYSCTL, op, value, attr, /* is_case_insensitive = */ false, token_str); + } else +- r = rule_line_add_token(rule_line, TK_M_SYSCTL, op, value, attr, is_case_insensitive); ++ r = rule_line_add_token(rule_line, TK_M_SYSCTL, op, value, attr, is_case_insensitive, token_str); + } else if (streq(key, "KERNELS")) { + if (attr) + return log_line_invalid_attr(rule_line, key); + if (!is_match) + return log_line_invalid_op(rule_line, key); + +- r = rule_line_add_token(rule_line, TK_M_PARENTS_KERNEL, op, value, NULL, is_case_insensitive); ++ r = rule_line_add_token(rule_line, TK_M_PARENTS_KERNEL, op, value, NULL, is_case_insensitive, token_str); + } else if (streq(key, "SUBSYSTEMS")) { + if (attr) + return log_line_invalid_attr(rule_line, key); + if (!is_match) + return log_line_invalid_op(rule_line, key); + +- r = rule_line_add_token(rule_line, TK_M_PARENTS_SUBSYSTEM, op, value, NULL, is_case_insensitive); ++ r = rule_line_add_token(rule_line, TK_M_PARENTS_SUBSYSTEM, op, value, NULL, is_case_insensitive, token_str); + } else if (streq(key, "DRIVERS")) { + if (attr) + return log_line_invalid_attr(rule_line, key); + if (!is_match) + return log_line_invalid_op(rule_line, key); + +- r = rule_line_add_token(rule_line, TK_M_PARENTS_DRIVER, op, value, NULL, is_case_insensitive); ++ r = rule_line_add_token(rule_line, TK_M_PARENTS_DRIVER, op, value, NULL, is_case_insensitive, token_str); + } else if (streq(key, "ATTRS")) { + r = check_attr_format_and_warn(rule_line, key, attr); + if (r < 0) +@@ -814,14 +860,14 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude + if (strstr(attr, "../")) + log_line_warning(rule_line, "Direct reference to parent sysfs directory, may break in future kernels."); + +- r = rule_line_add_token(rule_line, TK_M_PARENTS_ATTR, op, value, attr, is_case_insensitive); ++ r = rule_line_add_token(rule_line, TK_M_PARENTS_ATTR, op, value, attr, is_case_insensitive, token_str); + } else if (streq(key, "TAGS")) { + if (attr) + return log_line_invalid_attr(rule_line, key); + if (!is_match) + return log_line_invalid_op(rule_line, key); + +- r = rule_line_add_token(rule_line, TK_M_PARENTS_TAG, op, value, NULL, is_case_insensitive); ++ r = rule_line_add_token(rule_line, TK_M_PARENTS_TAG, op, value, NULL, is_case_insensitive, token_str); + } else if (streq(key, "TEST")) { + mode_t mode = MODE_INVALID; + +@@ -836,7 +882,7 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude + if (is_case_insensitive) + return log_line_invalid_prefix(rule_line, key); + +- r = rule_line_add_token(rule_line, TK_M_TEST, op, value, MODE_TO_PTR(mode), is_case_insensitive); ++ r = rule_line_add_token(rule_line, TK_M_TEST, op, value, MODE_TO_PTR(mode), is_case_insensitive, token_str); + } else if (streq(key, "PROGRAM")) { + if (attr) + return log_line_invalid_attr(rule_line, key); +@@ -848,7 +894,7 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude + if (is_case_insensitive) + return log_line_invalid_prefix(rule_line, key); + +- r = rule_line_add_token(rule_line, TK_M_PROGRAM, op, value, NULL, /* is_case_insensitive */ false); ++ r = rule_line_add_token(rule_line, TK_M_PROGRAM, op, value, NULL, /* is_case_insensitive */ false, token_str); + } else if (streq(key, "IMPORT")) { + if (isempty(attr)) + return log_line_invalid_attr(rule_line, key); +@@ -861,16 +907,16 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude + return log_line_invalid_prefix(rule_line, key); + + if (streq(attr, "file")) +- r = rule_line_add_token(rule_line, TK_M_IMPORT_FILE, op, value, NULL, /* is_case_insensitive = */ false); ++ r = rule_line_add_token(rule_line, TK_M_IMPORT_FILE, op, value, NULL, /* is_case_insensitive = */ false, token_str); + else if (streq(attr, "program")) { + UdevBuiltinCommand cmd; + + cmd = udev_builtin_lookup(value); + if (cmd >= 0) { + log_line_debug(rule_line, "Found builtin command '%s' for %s, replacing attribute.", value, key); +- r = rule_line_add_token(rule_line, TK_M_IMPORT_BUILTIN, op, value, UDEV_BUILTIN_CMD_TO_PTR(cmd), /* is_case_insensitive = */ false); ++ r = rule_line_add_token(rule_line, TK_M_IMPORT_BUILTIN, op, value, UDEV_BUILTIN_CMD_TO_PTR(cmd), /* is_case_insensitive = */ false, token_str); + } else +- r = rule_line_add_token(rule_line, TK_M_IMPORT_PROGRAM, op, value, NULL, /* is_case_insensitive = */ false); ++ r = rule_line_add_token(rule_line, TK_M_IMPORT_PROGRAM, op, value, NULL, /* is_case_insensitive = */ false, token_str); + } else if (streq(attr, "builtin")) { + UdevBuiltinCommand cmd; + +@@ -878,13 +924,13 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude + if (cmd < 0) + return log_line_error_errno(rule_line, SYNTHETIC_ERRNO(EINVAL), + "Unknown builtin command: %s", value); +- r = rule_line_add_token(rule_line, TK_M_IMPORT_BUILTIN, op, value, UDEV_BUILTIN_CMD_TO_PTR(cmd), /* is_case_insensitive = */ false); ++ r = rule_line_add_token(rule_line, TK_M_IMPORT_BUILTIN, op, value, UDEV_BUILTIN_CMD_TO_PTR(cmd), /* is_case_insensitive = */ false, token_str); + } else if (streq(attr, "db")) +- r = rule_line_add_token(rule_line, TK_M_IMPORT_DB, op, value, NULL, /* is_case_insensitive = */ false); ++ r = rule_line_add_token(rule_line, TK_M_IMPORT_DB, op, value, NULL, /* is_case_insensitive = */ false, token_str); + else if (streq(attr, "cmdline")) +- r = rule_line_add_token(rule_line, TK_M_IMPORT_CMDLINE, op, value, NULL, /* is_case_insensitive = */ false); ++ r = rule_line_add_token(rule_line, TK_M_IMPORT_CMDLINE, op, value, NULL, /* is_case_insensitive = */ false, token_str); + else if (streq(attr, "parent")) +- r = rule_line_add_token(rule_line, TK_M_IMPORT_PARENT, op, value, NULL, /* is_case_insensitive = */ false); ++ r = rule_line_add_token(rule_line, TK_M_IMPORT_PARENT, op, value, NULL, /* is_case_insensitive = */ false, token_str); + else + return log_line_invalid_attr(rule_line, key); + } else if (streq(key, "RESULT")) { +@@ -893,7 +939,7 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude + if (!is_match) + return log_line_invalid_op(rule_line, key); + +- r = rule_line_add_token(rule_line, TK_M_RESULT, op, value, NULL, is_case_insensitive); ++ r = rule_line_add_token(rule_line, TK_M_RESULT, op, value, NULL, is_case_insensitive, token_str); + } else if (streq(key, "OPTIONS")) { + char *tmp; + +@@ -905,24 +951,24 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude + op = OP_ASSIGN; + + 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); ++ 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); ++ r = rule_line_add_token(rule_line, TK_A_OPTIONS_STRING_ESCAPE_REPLACE, op, NULL, NULL, /* is_case_insensitive = */ false, token_str); + else if (streq(value, "db_persist")) +- r = rule_line_add_token(rule_line, TK_A_OPTIONS_DB_PERSIST, op, NULL, NULL, /* is_case_insensitive = */ false); ++ r = rule_line_add_token(rule_line, TK_A_OPTIONS_DB_PERSIST, op, NULL, NULL, /* is_case_insensitive = */ false, token_str); + else if (streq(value, "watch")) +- r = rule_line_add_token(rule_line, TK_A_OPTIONS_INOTIFY_WATCH, op, NULL, INT_TO_PTR(1), /* is_case_insensitive = */ false); ++ r = rule_line_add_token(rule_line, TK_A_OPTIONS_INOTIFY_WATCH, op, NULL, INT_TO_PTR(1), /* is_case_insensitive = */ false, token_str); + else if (streq(value, "nowatch")) +- r = rule_line_add_token(rule_line, TK_A_OPTIONS_INOTIFY_WATCH, op, NULL, INT_TO_PTR(0), /* is_case_insensitive = */ false); ++ r = rule_line_add_token(rule_line, TK_A_OPTIONS_INOTIFY_WATCH, op, NULL, INT_TO_PTR(0), /* is_case_insensitive = */ false, token_str); + else if ((tmp = startswith(value, "static_node="))) +- r = rule_line_add_token(rule_line, TK_A_OPTIONS_STATIC_NODE, op, tmp, NULL, /* is_case_insensitive = */ false); ++ r = rule_line_add_token(rule_line, TK_A_OPTIONS_STATIC_NODE, op, tmp, NULL, /* is_case_insensitive = */ false, token_str); + else if ((tmp = startswith(value, "link_priority="))) { + int prio; + + r = safe_atoi(tmp, &prio); + if (r < 0) + return log_line_error_errno(rule_line, r, "Failed to parse link priority '%s': %m", tmp); +- r = rule_line_add_token(rule_line, TK_A_OPTIONS_DEVLINK_PRIORITY, op, NULL, INT_TO_PTR(prio), /* is_case_insensitive = */ false); ++ r = rule_line_add_token(rule_line, TK_A_OPTIONS_DEVLINK_PRIORITY, op, NULL, INT_TO_PTR(prio), /* is_case_insensitive = */ false, token_str); + } else if ((tmp = startswith(value, "log_level="))) { + int level; + +@@ -933,7 +979,7 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude + if (level < 0) + return log_line_error_errno(rule_line, level, "Failed to parse log level '%s': %m", tmp); + } +- r = rule_line_add_token(rule_line, TK_A_OPTIONS_LOG_LEVEL, op, NULL, INT_TO_PTR(level), /* is_case_insensitive = */ false); ++ r = rule_line_add_token(rule_line, TK_A_OPTIONS_LOG_LEVEL, op, NULL, INT_TO_PTR(level), /* is_case_insensitive = */ false, token_str); + } else { + log_line_warning(rule_line, "Invalid value for OPTIONS key, ignoring: '%s'", value); + return 0; +@@ -951,17 +997,17 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude + } + + if (parse_uid(value, &uid) >= 0) +- r = rule_line_add_token(rule_line, TK_A_OWNER_ID, op, NULL, UID_TO_PTR(uid), /* is_case_insensitive = */ false); ++ r = rule_line_add_token(rule_line, TK_A_OWNER_ID, op, NULL, UID_TO_PTR(uid), /* is_case_insensitive = */ false, token_str); + else if (resolve_name_timing == RESOLVE_NAME_EARLY && + rule_get_substitution_type(value) == SUBST_TYPE_PLAIN) { + r = rule_resolve_user(rule_line, value, &uid); + if (r < 0) + return log_line_error_errno(rule_line, r, "Failed to resolve user name '%s': %m", value); + +- r = rule_line_add_token(rule_line, TK_A_OWNER_ID, op, NULL, UID_TO_PTR(uid), /* is_case_insensitive = */ false); ++ r = rule_line_add_token(rule_line, TK_A_OWNER_ID, op, NULL, UID_TO_PTR(uid), /* is_case_insensitive = */ false, token_str); + } else if (resolve_name_timing != RESOLVE_NAME_NEVER) { + check_value_format_and_warn(rule_line, key, value, true); +- r = rule_line_add_token(rule_line, TK_A_OWNER, op, value, NULL, /* is_case_insensitive = */ false); ++ r = rule_line_add_token(rule_line, TK_A_OWNER, op, value, NULL, /* is_case_insensitive = */ false, token_str); + } else { + log_line_debug(rule_line, "User name resolution is disabled, ignoring %s=\"%s\".", key, value); + return 0; +@@ -979,17 +1025,17 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude + } + + if (parse_gid(value, &gid) >= 0) +- r = rule_line_add_token(rule_line, TK_A_GROUP_ID, op, NULL, GID_TO_PTR(gid), /* is_case_insensitive = */ false); ++ r = rule_line_add_token(rule_line, TK_A_GROUP_ID, op, NULL, GID_TO_PTR(gid), /* is_case_insensitive = */ false, token_str); + else if (resolve_name_timing == RESOLVE_NAME_EARLY && + rule_get_substitution_type(value) == SUBST_TYPE_PLAIN) { + r = rule_resolve_group(rule_line, value, &gid); + if (r < 0) + return log_line_error_errno(rule_line, r, "Failed to resolve group name '%s': %m", value); + +- r = rule_line_add_token(rule_line, TK_A_GROUP_ID, op, NULL, GID_TO_PTR(gid), /* is_case_insensitive = */ false); ++ r = rule_line_add_token(rule_line, TK_A_GROUP_ID, op, NULL, GID_TO_PTR(gid), /* is_case_insensitive = */ false, token_str); + } else if (resolve_name_timing != RESOLVE_NAME_NEVER) { + check_value_format_and_warn(rule_line, key, value, true); +- r = rule_line_add_token(rule_line, TK_A_GROUP, op, value, NULL, /* is_case_insensitive = */ false); ++ r = rule_line_add_token(rule_line, TK_A_GROUP, op, value, NULL, /* is_case_insensitive = */ false, token_str); + } else { + log_line_debug(rule_line, "Resolving group name is disabled, ignoring GROUP=\"%s\".", value); + return 0; +@@ -1007,10 +1053,10 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude + } + + if (parse_mode(value, &mode) >= 0) +- r = rule_line_add_token(rule_line, TK_A_MODE_ID, op, NULL, MODE_TO_PTR(mode), /* is_case_insensitive = */ false); ++ r = rule_line_add_token(rule_line, TK_A_MODE_ID, op, NULL, MODE_TO_PTR(mode), /* is_case_insensitive = */ false, token_str); + else { + check_value_format_and_warn(rule_line, key, value, true); +- r = rule_line_add_token(rule_line, TK_A_MODE, op, value, NULL, /* is_case_insensitive = */ false); ++ r = rule_line_add_token(rule_line, TK_A_MODE, op, value, NULL, /* is_case_insensitive = */ false, token_str); + } + } else if (streq(key, "SECLABEL")) { + if (isempty(attr)) +@@ -1023,13 +1069,13 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude + op = OP_ASSIGN; + } + +- r = rule_line_add_token(rule_line, TK_A_SECLABEL, op, value, attr, /* is_case_insensitive = */ false); ++ r = rule_line_add_token(rule_line, TK_A_SECLABEL, op, value, attr, /* is_case_insensitive = */ false, token_str); + } else if (streq(key, "RUN")) { + if (is_match || op == OP_REMOVE) + return log_line_invalid_op(rule_line, key); + check_value_format_and_warn(rule_line, key, value, true); + if (!attr || streq(attr, "program")) +- r = rule_line_add_token(rule_line, TK_A_RUN_PROGRAM, op, value, NULL, /* is_case_insensitive = */ false); ++ r = rule_line_add_token(rule_line, TK_A_RUN_PROGRAM, op, value, NULL, /* is_case_insensitive = */ false, token_str); + else if (streq(attr, "builtin")) { + UdevBuiltinCommand cmd; + +@@ -1037,7 +1083,7 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude + if (cmd < 0) + return log_line_error_errno(rule_line, SYNTHETIC_ERRNO(EINVAL), + "Unknown builtin command '%s', ignoring.", value); +- r = rule_line_add_token(rule_line, TK_A_RUN_BUILTIN, op, value, UDEV_BUILTIN_CMD_TO_PTR(cmd), /* is_case_insensitive = */ false); ++ r = rule_line_add_token(rule_line, TK_A_RUN_BUILTIN, op, value, UDEV_BUILTIN_CMD_TO_PTR(cmd), /* is_case_insensitive = */ false, token_str); + } else + return log_line_invalid_attr(rule_line, key); + } else if (streq(key, "GOTO")) { +@@ -1297,32 +1343,30 @@ static void sort_tokens(UdevRuleLine *rule_line) { + } + } + +-static int rule_add_line(UdevRuleFile *rule_file, const char *line_str, unsigned line_nr, bool extra_checks) { ++static int rule_add_line(UdevRuleFile *rule_file, const char *line, unsigned line_nr, bool extra_checks) { + _cleanup_(udev_rule_line_freep) UdevRuleLine *rule_line = NULL; +- _cleanup_free_ char *line = NULL; + char *p; + int r; + + assert(rule_file); +- assert(line_str); ++ assert(line); + +- if (isempty(line_str)) ++ if (isempty(line)) + return 0; + +- line = strdup(line_str); +- if (!line) +- return log_oom(); +- + rule_line = new(UdevRuleLine, 1); + if (!rule_line) + return log_oom(); + + *rule_line = (UdevRuleLine) { +- .line = TAKE_PTR(line), ++ .line = strdup(line), ++ .line_for_logging = strdup(line), + .line_number = line_nr, +- .rule_file = rule_file, + }; ++ if (!rule_line->line || !rule_line->line_for_logging) ++ return log_oom(); + ++ rule_line->rule_file = rule_file; + LIST_APPEND(rule_lines, rule_file->rule_lines, rule_line); + + for (p = rule_line->line; !isempty(p); ) { +@@ -1339,7 +1383,9 @@ static int rule_add_line(UdevRuleFile *rule_file, const char *line_str, unsigned + if (r == 0) + break; + +- r = parse_token(rule_line, key, attr, op, value, is_case_insensitive); ++ char *token_str = rule_line->line_for_logging + (key - rule_line->line); ++ token_str[p - key] = '\0'; ++ r = parse_token(rule_line, key, attr, op, value, is_case_insensitive, token_str); + if (r < 0) + return r; + } +@@ -1801,7 +1847,7 @@ static bool token_match_attr(UdevRuleToken *token, sd_device *dev, UdevEvent *ev + case SUBST_TYPE_FORMAT: + (void) udev_event_apply_format(event, name, nbuf, sizeof(nbuf), false, &truncated); + if (truncated) { +- log_event_truncated(dev, token, "sysfs attribute name", name, ++ log_event_truncated(event, token, "sysfs attribute name", name, + token->type == TK_M_ATTR ? "ATTR" : "ATTRS", /* is_match = */ true); + return false; + } +@@ -1986,7 +2032,7 @@ static int udev_rule_apply_token_to_event( + + r = sd_device_get_action(dev, &a); + if (r < 0) +- return log_event_error_errno(dev, token, r, "Failed to get uevent action type: %m"); ++ return log_event_error_errno(event, token, r, "Failed to get uevent action type: %m"); + + return token_match_string(token, device_action_to_string(a)); + } +@@ -1995,7 +2041,7 @@ static int udev_rule_apply_token_to_event( + + r = sd_device_get_devpath(dev, &val); + if (r < 0) +- return log_event_error_errno(dev, token, r, "Failed to get devpath: %m"); ++ return log_event_error_errno(event, token, r, "Failed to get devpath: %m"); + + return token_match_string(token, val); + } +@@ -2005,7 +2051,7 @@ static int udev_rule_apply_token_to_event( + + r = sd_device_get_sysname(dev, &val); + if (r < 0) +- return log_event_error_errno(dev, token, r, "Failed to get sysname: %m"); ++ return log_event_error_errno(event, token, r, "Failed to get sysname: %m"); + + return token_match_string(token, val); + } +@@ -2050,7 +2096,7 @@ static int udev_rule_apply_token_to_event( + if (r == -ENOENT) + val = NULL; + else if (r < 0) +- return log_event_error_errno(dev, token, r, "Failed to get subsystem: %m"); ++ return log_event_error_errno(event, token, r, "Failed to get subsystem: %m"); + + return token_match_string(token, val); + } +@@ -2062,7 +2108,7 @@ static int udev_rule_apply_token_to_event( + if (r == -ENOENT) + val = NULL; + else if (r < 0) +- return log_event_error_errno(dev, token, r, "Failed to get driver: %m"); ++ return log_event_error_errno(event, token, r, "Failed to get driver: %m"); + + return token_match_string(token, val); + } +@@ -2076,13 +2122,13 @@ static int udev_rule_apply_token_to_event( + + (void) udev_event_apply_format(event, token->data, buf, sizeof(buf), false, &truncated); + if (truncated) { +- log_event_truncated(dev, token, "sysctl entry name", token->data, "SYSCTL", /* is_match = */ true); ++ log_event_truncated(event, token, "sysctl entry name", token->data, "SYSCTL", /* is_match = */ true); + return false; + } + + r = sysctl_read(sysctl_normalize(buf), &value); + if (r < 0 && r != -ENOENT) +- return log_event_error_errno(dev, token, r, "Failed to read sysctl '%s': %m", buf); ++ return log_event_error_errno(event, token, r, "Failed to read sysctl '%s': %m", buf); + + return token_match_string(token, strstrip(value)); + } +@@ -2094,7 +2140,7 @@ static int udev_rule_apply_token_to_event( + + (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated); + if (truncated) { +- log_event_truncated(dev, token, "file name", token->value, "TEST", /* is_match = */ true); ++ log_event_truncated(event, token, "file name", token->value, "TEST", /* is_match = */ true); + return false; + } + +@@ -2105,7 +2151,7 @@ static int udev_rule_apply_token_to_event( + + r = sd_device_get_syspath(dev, &val); + if (r < 0) +- return log_event_error_errno(dev, token, r, "Failed to get syspath: %m"); ++ return log_event_error_errno(event, token, r, "Failed to get syspath: %m"); + + strscpy_full(tmp, sizeof(tmp), buf, &truncated); + assert(!truncated); +@@ -2118,7 +2164,7 @@ static int udev_rule_apply_token_to_event( + if (r == -ENOENT) + return token->op == OP_NOMATCH; + if (r < 0) +- return log_event_error_errno(dev, token, r, "Failed to test for the existence of '%s': %m", buf); ++ return log_event_error_errno(event, token, r, "Failed to test for the existence of '%s': %m", buf); + + if (stat(buf, &statbuf) < 0) + return token->op == OP_NOMATCH; +@@ -2137,25 +2183,25 @@ static int udev_rule_apply_token_to_event( + event->program_result = mfree(event->program_result); + (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated); + if (truncated) { +- log_event_truncated(dev, token, "command", token->value, "PROGRAM", /* is_match = */ true); ++ log_event_truncated(event, token, "command", token->value, "PROGRAM", /* is_match = */ true); + return false; + } + +- log_event_debug(dev, token, "Running PROGRAM=\"%s\"", buf); ++ log_event_debug(event, token, "Running PROGRAM=\"%s\"", buf); + + r = udev_event_spawn(event, /* accept_failure = */ true, buf, result, sizeof(result), NULL); + if (r != 0) { + if (r < 0) +- log_event_warning_errno(dev, token, r, "Failed to execute \"%s\": %m", buf); ++ log_event_warning_errno(event, token, r, "Failed to execute \"%s\": %m", buf); + else /* returned value is positive when program fails */ +- log_event_debug(dev, token, "Command \"%s\" returned %d (error)", buf, r); ++ log_event_debug(event, token, "Command \"%s\" returned %d (error)", buf, r); + return token->op == OP_NOMATCH; + } + + delete_trailing_chars(result, "\n"); + count = udev_replace_chars(result, UDEV_ALLOWED_CHARS_INPUT); + if (count > 0) +- log_event_debug(dev, token, ++ log_event_debug(event, token, + "Replaced %zu character(s) in result of \"%s\"", + count, buf); + +@@ -2169,16 +2215,16 @@ static int udev_rule_apply_token_to_event( + + (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated); + if (truncated) { +- log_event_truncated(dev, token, "file name to be imported", token->value, "IMPORT", /* is_match = */ true); ++ log_event_truncated(event, token, "file name to be imported", token->value, "IMPORT", /* is_match = */ true); + return false; + } + +- log_event_debug(dev, token, "Importing properties from '%s'", buf); ++ log_event_debug(event, token, "Importing properties from '%s'", buf); + + f = fopen(buf, "re"); + if (!f) { + if (errno != ENOENT) +- return log_event_error_errno(dev, token, errno, "Failed to open '%s': %m", buf); ++ return log_event_error_errno(event, token, errno, "Failed to open '%s': %m", buf); + return token->op == OP_NOMATCH; + } + +@@ -2188,7 +2234,7 @@ static int udev_rule_apply_token_to_event( + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) { +- log_event_debug_errno(dev, token, r, "Failed to read '%s', ignoring: %m", buf); ++ log_event_debug_errno(event, token, r, "Failed to read '%s', ignoring: %m", buf); + return token->op == OP_NOMATCH; + } + if (r == 0) +@@ -2196,7 +2242,7 @@ static int udev_rule_apply_token_to_event( + + r = get_property_from_string(line, &key, &value); + if (r < 0) { +- log_event_debug_errno(dev, token, r, ++ log_event_debug_errno(event, token, r, + "Failed to parse key and value from '%s', ignoring: %m", + line); + continue; +@@ -2206,7 +2252,7 @@ static int udev_rule_apply_token_to_event( + + r = device_add_property(dev, key, value); + if (r < 0) +- return log_event_error_errno(dev, token, r, ++ return log_event_error_errno(event, token, r, + "Failed to add property %s=%s: %m", + key, value); + } +@@ -2220,18 +2266,18 @@ static int udev_rule_apply_token_to_event( + + (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated); + if (truncated) { +- log_event_truncated(dev, token, "command", token->value, "IMPORT", /* is_match = */ true); ++ log_event_truncated(event, token, "command", token->value, "IMPORT", /* is_match = */ true); + return false; + } + +- log_event_debug(dev, token, "Importing properties from results of '%s'", buf); ++ log_event_debug(event, token, "Importing properties from results of '%s'", buf); + + r = udev_event_spawn(event, /* accept_failure = */ true, buf, result, sizeof result, &truncated); + if (r != 0) { + if (r < 0) +- log_event_warning_errno(dev, token, r, "Failed to execute '%s', ignoring: %m", buf); ++ log_event_warning_errno(event, token, r, "Failed to execute '%s', ignoring: %m", buf); + else /* returned value is positive when program fails */ +- log_event_debug(dev, token, "Command \"%s\" returned %d (error), ignoring", buf, r); ++ log_event_debug(event, token, "Command \"%s\" returned %d (error), ignoring", buf, r); + return token->op == OP_NOMATCH; + } + +@@ -2251,7 +2297,7 @@ static int udev_rule_apply_token_to_event( + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { +- log_event_warning_errno(dev, token, r, ++ log_event_warning_errno(event, token, r, + "Failed to extract lines from result of command \"%s\", ignoring: %m", buf); + return false; + } +@@ -2261,7 +2307,7 @@ static int udev_rule_apply_token_to_event( + + r = get_property_from_string(*line, &key, &value); + if (r < 0) { +- log_event_debug_errno(dev, token, r, ++ log_event_debug_errno(event, token, r, + "Failed to parse key and value from '%s', ignoring: %m", + *line); + continue; +@@ -2271,7 +2317,7 @@ static int udev_rule_apply_token_to_event( + + r = device_add_property(dev, key, value); + if (r < 0) +- return log_event_error_errno(dev, token, r, ++ return log_event_error_errno(event, token, r, + "Failed to add property %s=%s: %m", + key, value); + } +@@ -2288,7 +2334,7 @@ static int udev_rule_apply_token_to_event( + if (udev_builtin_run_once(cmd)) { + /* check if we ran already */ + if (event->builtin_run & mask) { +- log_event_debug(dev, token, "Skipping builtin '%s' in IMPORT key", ++ log_event_debug(event, token, "Skipping builtin '%s' in IMPORT key", + udev_builtin_name(cmd)); + /* return the result from earlier run */ + return token->op == (event->builtin_ret & mask ? OP_NOMATCH : OP_MATCH); +@@ -2299,16 +2345,16 @@ static int udev_rule_apply_token_to_event( + + (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated); + if (truncated) { +- log_event_truncated(dev, token, "builtin command", token->value, "IMPORT", /* is_match = */ true); ++ log_event_truncated(event, token, "builtin command", token->value, "IMPORT", /* is_match = */ true); + return false; + } + +- log_event_debug(dev, token, "Importing properties from results of builtin command '%s'", buf); ++ log_event_debug(event, token, "Importing properties from results of builtin command '%s'", buf); + + r = udev_builtin_run(event, cmd, buf); + if (r < 0) { + /* remember failure */ +- log_event_debug_errno(dev, token, r, "Failed to run builtin '%s': %m", buf); ++ log_event_debug_errno(event, token, r, "Failed to run builtin '%s': %m", buf); + event->builtin_ret |= mask; + } + return token->op == (r >= 0 ? OP_MATCH : OP_NOMATCH); +@@ -2322,13 +2368,13 @@ static int udev_rule_apply_token_to_event( + if (r == -ENOENT) + return token->op == OP_NOMATCH; + if (r < 0) +- return log_event_error_errno(dev, token, r, ++ return log_event_error_errno(event, token, r, + "Failed to get property '%s' from database: %m", + token->value); + + r = device_add_property(dev, token->value, val); + if (r < 0) +- return log_event_error_errno(dev, token, r, "Failed to add property '%s=%s': %m", ++ return log_event_error_errno(event, token, r, "Failed to add property '%s=%s': %m", + token->value, val); + return token->op == OP_MATCH; + } +@@ -2337,7 +2383,7 @@ static int udev_rule_apply_token_to_event( + + r = proc_cmdline_get_key(token->value, PROC_CMDLINE_VALUE_OPTIONAL|PROC_CMDLINE_IGNORE_EFI_OPTIONS, &value); + if (r < 0) +- return log_event_error_errno(dev, token, r, ++ return log_event_error_errno(event, token, r, + "Failed to read '%s' option from /proc/cmdline: %m", + token->value); + if (r == 0) +@@ -2345,7 +2391,7 @@ static int udev_rule_apply_token_to_event( + + r = device_add_property(dev, token->value, value ?: "1"); + if (r < 0) +- return log_event_error_errno(dev, token, r, "Failed to add property '%s=%s': %m", ++ return log_event_error_errno(event, token, r, "Failed to add property '%s=%s': %m", + token->value, value ?: "1"); + return token->op == OP_MATCH; + } +@@ -2355,13 +2401,13 @@ static int udev_rule_apply_token_to_event( + + (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated); + if (truncated) { +- log_event_truncated(dev, token, "property name", token->value, "IMPORT", /* is_match = */ true); ++ log_event_truncated(event, token, "property name", token->value, "IMPORT", /* is_match = */ true); + return false; + } + + r = import_parent_into_properties(dev, buf); + if (r < 0) +- return log_event_error_errno(dev, token, r, ++ return log_event_error_errno(event, token, r, + "Failed to import properties '%s' from parent: %m", + buf); + return token->op == (r > 0 ? OP_MATCH : OP_NOMATCH); +@@ -2399,7 +2445,7 @@ static int udev_rule_apply_token_to_event( + else { + _cleanup_free_ char *level_str = NULL; + (void) log_level_to_string_alloc(level, &level_str); +- log_event_debug(dev, token, "Running in test mode, skipping changing maximum log level to %s.", strna(level_str)); ++ log_event_debug(event, token, "Running in test mode, skipping changing maximum log level to %s.", strna(level_str)); + } + + if (level == LOG_DEBUG && !event->log_level_was_debug) { +@@ -2423,7 +2469,7 @@ static int udev_rule_apply_token_to_event( + + (void) udev_event_apply_format(event, token->value, owner, sizeof(owner), false, &truncated); + if (truncated) { +- log_event_truncated(dev, token, "user name", token->value, "OWNER", /* is_match = */ false); ++ log_event_truncated(event, token, "user name", token->value, "OWNER", /* is_match = */ false); + break; + } + +@@ -2431,7 +2477,7 @@ static int udev_rule_apply_token_to_event( + if (r < 0) + log_unknown_owner(dev, token->rule_line, r, "user", owner); + else +- log_event_debug(dev, token, "OWNER %s(%u)", owner, event->uid); ++ log_event_debug(event, token, "OWNER %s(%u)", owner, event->uid); + break; + } + case TK_A_GROUP: { +@@ -2446,7 +2492,7 @@ static int udev_rule_apply_token_to_event( + + (void) udev_event_apply_format(event, token->value, group, sizeof(group), false, &truncated); + if (truncated) { +- log_event_truncated(dev, token, "group name", token->value, "GROUP", /* is_match = */ false); ++ log_event_truncated(event, token, "group name", token->value, "GROUP", /* is_match = */ false); + break; + } + +@@ -2454,7 +2500,7 @@ static int udev_rule_apply_token_to_event( + if (r < 0) + log_unknown_owner(dev, token->rule_line, r, "group", group); + else +- log_event_debug(dev, token, "GROUP %s(%u)", group, event->gid); ++ log_event_debug(event, token, "GROUP %s(%u)", group, event->gid); + break; + } + case TK_A_MODE: { +@@ -2468,15 +2514,15 @@ static int udev_rule_apply_token_to_event( + + (void) udev_event_apply_format(event, token->value, mode_str, sizeof(mode_str), false, &truncated); + if (truncated) { +- log_event_truncated(dev, token, "mode", token->value, "MODE", /* is_match = */ false); ++ log_event_truncated(event, token, "mode", token->value, "MODE", /* is_match = */ false); + break; + } + + r = parse_mode(mode_str, &event->mode); + if (r < 0) +- log_event_error_errno(dev, token, r, "Failed to parse mode '%s', ignoring: %m", mode_str); ++ log_event_error_errno(event, token, r, "Failed to parse mode '%s', ignoring: %m", mode_str); + else +- log_event_debug(dev, token, "MODE %#o", event->mode); ++ log_event_debug(event, token, "MODE %#o", event->mode); + break; + } + case TK_A_OWNER_ID: +@@ -2487,7 +2533,7 @@ static int udev_rule_apply_token_to_event( + if (!token->data) + break; + event->uid = PTR_TO_UID(token->data); +- log_event_debug(dev, token, "OWNER %u", event->uid); ++ log_event_debug(event, token, "OWNER %u", event->uid); + break; + case TK_A_GROUP_ID: + if (event->group_final) +@@ -2497,7 +2543,7 @@ static int udev_rule_apply_token_to_event( + if (!token->data) + break; + event->gid = PTR_TO_GID(token->data); +- log_event_debug(dev, token, "GROUP %u", event->gid); ++ log_event_debug(event, token, "GROUP %u", event->gid); + break; + case TK_A_MODE_ID: + if (event->mode_final) +@@ -2507,7 +2553,7 @@ static int udev_rule_apply_token_to_event( + if (!token->data) + break; + event->mode = PTR_TO_MODE(token->data); +- log_event_debug(dev, token, "MODE %#o", event->mode); ++ log_event_debug(event, token, "MODE %#o", event->mode); + break; + case TK_A_SECLABEL: { + _cleanup_free_ char *name = NULL, *label = NULL; +@@ -2520,7 +2566,7 @@ static int udev_rule_apply_token_to_event( + + (void) udev_event_apply_format(event, token->value, label_str, sizeof(label_str), false, &truncated); + if (truncated) { +- log_event_truncated(dev, token, "security label", token->value, "SECLABEL", /* is_match = */ false); ++ log_event_truncated(event, token, "security label", token->value, "SECLABEL", /* is_match = */ false); + break; + } + +@@ -2538,9 +2584,9 @@ static int udev_rule_apply_token_to_event( + if (r == -ENOMEM) + return log_oom(); + if (r < 0) +- return log_event_error_errno(dev, token, r, "Failed to store SECLABEL{%s}='%s': %m", name, label); ++ return log_event_error_errno(event, token, r, "Failed to store SECLABEL{%s}='%s': %m", name, label); + +- log_event_debug(dev, token, "SECLABEL{%s}='%s'", name, label); ++ log_event_debug(event, token, "SECLABEL{%s}='%s'", name, label); + + TAKE_PTR(name); + TAKE_PTR(label); +@@ -2557,7 +2603,7 @@ static int udev_rule_apply_token_to_event( + break; + r = device_add_property(dev, name, NULL); + if (r < 0) +- return log_event_error_errno(dev, token, r, "Failed to remove property '%s': %m", name); ++ return log_event_error_errno(event, token, r, "Failed to remove property '%s': %m", name); + break; + } + +@@ -2565,7 +2611,7 @@ static int udev_rule_apply_token_to_event( + device_get_property_value_with_fallback(dev, name, event->worker ? event->worker->properties : NULL, &val) >= 0) { + l = strpcpyl_full(&p, l, &truncated, val, " ", NULL); + if (truncated) { +- log_event_warning(dev, token, ++ log_event_warning(event, token, + "The buffer for the property '%s' is full, " + "refusing to append the new value '%s'.", name, token->value); + break; +@@ -2575,7 +2621,7 @@ static int udev_rule_apply_token_to_event( + (void) udev_event_apply_format(event, token->value, p, l, false, &truncated); + if (truncated) { + _cleanup_free_ char *key_with_name = strjoin("ENV{", name, "}"); +- log_event_truncated(dev, token, "property value", token->value, ++ log_event_truncated(event, token, "property value", token->value, + key_with_name ?: "ENV", /* is_match = */ false); + break; + } +@@ -2583,14 +2629,14 @@ static int udev_rule_apply_token_to_event( + if (event->esc == ESCAPE_REPLACE) { + count = udev_replace_chars(p, NULL); + if (count > 0) +- log_event_debug(dev, token, ++ log_event_debug(event, token, + "Replaced %zu slash(es) from result of ENV{%s}%s=\"%s\"", + count, name, token->op == OP_ADD ? "+" : "", token->value); + } + + r = device_add_property(dev, name, value_new); + if (r < 0) +- return log_event_error_errno(dev, token, r, "Failed to add property '%s=%s': %m", name, value_new); ++ return log_event_error_errno(event, token, r, "Failed to add property '%s=%s': %m", name, value_new); + break; + } + case TK_A_TAG: { +@@ -2599,7 +2645,7 @@ static int udev_rule_apply_token_to_event( + + (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated); + if (truncated) { +- log_event_truncated(dev, token, "tag name", token->value, "TAG", /* is_match = */ false); ++ log_event_truncated(event, token, "tag name", token->value, "TAG", /* is_match = */ false); + break; + } + +@@ -2613,7 +2659,7 @@ static int udev_rule_apply_token_to_event( + if (r == -ENOMEM) + return log_oom(); + if (r < 0) +- log_event_warning_errno(dev, token, r, "Failed to add tag '%s', ignoring: %m", buf); ++ log_event_warning_errno(event, token, r, "Failed to add tag '%s', ignoring: %m", buf); + } + break; + } +@@ -2628,7 +2674,7 @@ static int udev_rule_apply_token_to_event( + event->name_final = true; + + if (sd_device_get_ifindex(dev, NULL) < 0) { +- log_event_error(dev, token, ++ log_event_error(event, token, + "Only network interfaces can be renamed, ignoring NAME=\"%s\".", + token->value); + break; +@@ -2636,7 +2682,7 @@ static int udev_rule_apply_token_to_event( + + (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated); + if (truncated) { +- log_event_truncated(dev, token, "network interface name", token->value, "NAME", /* is_match = */ false); ++ log_event_truncated(event, token, "network interface name", token->value, "NAME", /* is_match = */ false); + break; + } + +@@ -2646,7 +2692,7 @@ static int udev_rule_apply_token_to_event( + else + count = udev_replace_chars(buf, "/"); + if (count > 0) +- log_event_debug(dev, token, ++ log_event_debug(event, token, + "Replaced %zu character(s) from result of NAME=\"%s\"", + count, token->value); + } +@@ -2654,7 +2700,7 @@ static int udev_rule_apply_token_to_event( + if (r < 0) + return r; + +- log_event_debug(dev, token, "NAME '%s'", event->name); ++ log_event_debug(event, token, "NAME '%s'", event->name); + break; + } + case TK_A_DEVLINK: { +@@ -2674,7 +2720,7 @@ static int udev_rule_apply_token_to_event( + (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), + /* replace_whitespace = */ event->esc != ESCAPE_NONE, &truncated); + if (truncated) { +- log_event_truncated(dev, token, "symbolic link path", token->value, "SYMLINK", /* is_match = */ false); ++ log_event_truncated(event, token, "symbolic link path", token->value, "SYMLINK", /* is_match = */ false); + break; + } + +@@ -2686,7 +2732,7 @@ static int udev_rule_apply_token_to_event( + else + count = 0; + if (count > 0) +- log_event_debug(dev, token, ++ log_event_debug(event, token, + "Replaced %zu character(s) from result of SYMLINK=\"%s\"", + count, token->value); + +@@ -2708,17 +2754,17 @@ static int udev_rule_apply_token_to_event( + if (r == -ENOMEM) + return log_oom(); + if (r < 0) +- log_event_warning_errno(dev, token, r, "Failed to remove devlink '%s', ignoring: %m", path); ++ log_event_warning_errno(event, token, r, "Failed to remove devlink '%s', ignoring: %m", path); + else if (r > 0) +- log_event_debug(dev, token, "Dropped SYMLINK '%s'", path); ++ log_event_debug(event, token, "Dropped SYMLINK '%s'", path); + } else { + r = device_add_devlink(dev, path); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) +- log_event_warning_errno(dev, token, r, "Failed to add devlink '%s', ignoring: %m", path); ++ log_event_warning_errno(event, token, r, "Failed to add devlink '%s', ignoring: %m", path); + else if (r > 0) +- log_event_debug(dev, token, "Added SYMLINK '%s'", path); ++ log_event_debug(event, token, "Added SYMLINK '%s'", path); + } + } + break; +@@ -2732,7 +2778,7 @@ static int udev_rule_apply_token_to_event( + sd_device_get_syspath(dev, &val) >= 0) { + strscpyl_full(buf, sizeof(buf), &truncated, val, "/", key_name, NULL); + if (truncated) { +- log_event_warning(dev, token, ++ log_event_warning(event, token, + "The path to the attribute '%s/%s' is too long, refusing to set the attribute.", + val, key_name); + break; +@@ -2741,26 +2787,26 @@ static int udev_rule_apply_token_to_event( + + r = attr_subst_subdir(buf); + if (r < 0) { +- log_event_error_errno(dev, token, r, "Could not find file matches '%s', ignoring: %m", buf); ++ log_event_error_errno(event, token, r, "Could not find file matches '%s', ignoring: %m", buf); + break; + } + (void) udev_event_apply_format(event, token->value, value, sizeof(value), false, &truncated); + if (truncated) { +- log_event_truncated(dev, token, "attribute value", token->value, "ATTR", /* is_match = */ false); ++ log_event_truncated(event, token, "attribute value", token->value, "ATTR", /* is_match = */ false); + break; + } + + if (EVENT_MODE_DESTRUCTIVE(event)) { +- log_event_debug(dev, token, "Writing ATTR{'%s'}=\"%s\".", buf, value); ++ log_event_debug(event, token, "Writing ATTR{'%s'}=\"%s\".", buf, value); + r = write_string_file(buf, value, + WRITE_STRING_FILE_VERIFY_ON_FAILURE | + WRITE_STRING_FILE_DISABLE_BUFFER | + WRITE_STRING_FILE_AVOID_NEWLINE | + WRITE_STRING_FILE_VERIFY_IGNORE_NEWLINE); + if (r < 0) +- log_event_error_errno(dev, token, r, "Failed to write ATTR{%s}=\"%s\", ignoring: %m", buf, value); ++ log_event_error_errno(event, token, r, "Failed to write ATTR{%s}=\"%s\", ignoring: %m", buf, value); + } else +- log_event_debug(dev, token, "Running in test mode, skipping writing ATTR{%s}=\"%s\".", buf, value); ++ log_event_debug(event, token, "Running in test mode, skipping writing ATTR{%s}=\"%s\".", buf, value); + + break; + } +@@ -2770,14 +2816,14 @@ static int udev_rule_apply_token_to_event( + + (void) udev_event_apply_format(event, token->data, buf, sizeof(buf), false, &truncated); + if (truncated) { +- log_event_truncated(dev, token, "sysctl entry name", token->data, "SYSCTL", /* is_match = */ false); ++ log_event_truncated(event, token, "sysctl entry name", token->data, "SYSCTL", /* is_match = */ false); + break; + } + + (void) udev_event_apply_format(event, token->value, value, sizeof(value), false, &truncated); + if (truncated) { + _cleanup_free_ char *key_with_name = strjoin("SYSCTL{", buf, "}"); +- log_event_truncated(dev, token, "sysctl value", token->value, ++ log_event_truncated(event, token, "sysctl value", token->value, + key_with_name ?: "SYSCTL", /* is_match = */ false); + break; + } +@@ -2785,12 +2831,12 @@ static int udev_rule_apply_token_to_event( + sysctl_normalize(buf); + + if (EVENT_MODE_DESTRUCTIVE(event)) { +- log_event_debug(dev, token, "Writing SYSCTL{%s}=\"%s\".", buf, value); ++ log_event_debug(event, token, "Writing SYSCTL{%s}=\"%s\".", buf, value); + r = sysctl_write(buf, value); + if (r < 0) +- log_event_error_errno(dev, token, r, "Failed to write SYSCTL{%s}=\"%s\", ignoring: %m", buf, value); ++ log_event_error_errno(event, token, r, "Failed to write SYSCTL{%s}=\"%s\", ignoring: %m", buf, value); + } else +- log_event_debug(dev, token, "Running in test mode, skipping writing SYSCTL{%s}=\"%s\".", buf, value); ++ log_event_debug(event, token, "Running in test mode, skipping writing SYSCTL{%s}=\"%s\".", buf, value); + + break; + } +@@ -2810,7 +2856,7 @@ static int udev_rule_apply_token_to_event( + + (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated); + if (truncated) { +- log_event_truncated(dev, token, "command", token->value, ++ log_event_truncated(event, token, "command", token->value, + token->type == TK_A_RUN_BUILTIN ? "RUN{builtin}" : "RUN{program}", + /* is_match = */ false); + break; +@@ -2824,11 +2870,11 @@ static int udev_rule_apply_token_to_event( + if (r == -ENOMEM) + return log_oom(); + if (r < 0) +- return log_event_error_errno(dev, token, r, "Failed to store command '%s': %m", cmd); ++ return log_event_error_errno(event, token, r, "Failed to store command '%s': %m", cmd); + + TAKE_PTR(cmd); + +- log_event_debug(dev, token, "RUN '%s'", token->value); ++ log_event_debug(event, token, "RUN '%s'", token->value); + break; + } + case TK_A_OPTIONS_STATIC_NODE: +@@ -2841,10 +2887,6 @@ static int udev_rule_apply_token_to_event( + return true; + } + +-static bool token_is_for_parents(UdevRuleToken *token) { +- return token->type >= TK_M_PARENTS_KERNEL && token->type <= TK_M_PARENTS_TAG; +-} +- + static int udev_rule_apply_parent_token_to_event(UdevRuleToken *head_token, UdevEvent *event) { + int r; + diff --git a/0167-udev-rules-logs-result-of-format-substitution.patch b/0167-udev-rules-logs-result-of-format-substitution.patch new file mode 100644 index 0000000..db27c4a --- /dev/null +++ b/0167-udev-rules-logs-result-of-format-substitution.patch @@ -0,0 +1,524 @@ +From 11c7cc1bd95c80d8a92656aa432de4a9cadf69c2 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Sun, 12 Jan 2025 00:12:52 +0900 +Subject: [PATCH] udev-rules: logs result of format substitution + +This also drops redundant token string in log message on truncation. + +No functional change, but should improve debuggability. + +(cherry picked from commit a3ab06ab21528138160eb3d40c3e661fc53a8158) + +Resolves: RHEL-75774 +--- + src/udev/udev-rules.c | 243 ++++++++++++++++++------------------------ + 1 file changed, 105 insertions(+), 138 deletions(-) + +diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c +index c33d17aa47..3a61403338 100644 +--- a/src/udev/udev-rules.c ++++ b/src/udev/udev-rules.c +@@ -297,6 +297,23 @@ static bool token_is_for_parents(UdevRuleToken *token) { + #define log_event_trace(event, ...) \ + _log_event_trace(event, UNIQ_T(e, UNIQ), __VA_ARGS__) + ++#define _log_event_truncated(event, token, token_u, what, format) \ ++ ({ \ ++ UdevRuleToken *token_u = ASSERT_PTR(token); \ ++ \ ++ token_u->type < _TK_M_MAX ? \ ++ log_event_debug(event, token_u, \ ++ "The %s is truncated while substituting into \"%s\", assuming the token fails.", \ ++ what, (const char*) format) : \ ++ log_event_warning( \ ++ event, token_u, \ ++ "The %s is truncated while substituting into \"%s\", refusing to apply the token.", \ ++ what, (const char*) format); \ ++ }) ++ ++#define log_event_truncated(event, token, what, format) \ ++ _log_event_truncated(event, token, UNIQ_T(t, UNIQ), what, format) ++ + /* Mainly used when parsing .rules files. */ + #define log_file_full_errno_zerook(...) \ + log_udev_rule_file_full(NULL, __VA_ARGS__) +@@ -351,26 +368,6 @@ static void log_unknown_owner(sd_device *dev, UdevRuleLine *line, int error, con + log_udev_rule_line_full(dev, line, LOG_ERR, error, "Failed to resolve %s '%s', ignoring: %m", entity, name); + } + +-static void log_event_truncated( +- UdevEvent *event, +- UdevRuleToken *token, +- const char *what, +- const char *format, +- const char *key, +- bool is_match) { +- +- if (is_match) +- log_event_debug(event, token, +- "The %s is truncated while substituting into '%s', " +- "assuming the %s key does not match.", +- what, format, key); +- else +- log_event_warning(event, token, +- "The %s is truncated while substituting into '%s', " +- "refusing to apply the %s key.", +- what, format, key); +-} +- + /*** Other functions ***/ + + static UdevRuleToken* udev_rule_token_free(UdevRuleToken *token) { +@@ -1776,6 +1773,54 @@ bool udev_rules_should_reload(UdevRules *rules) { + return false; + } + ++static bool apply_format_full( ++ UdevEvent *event, ++ UdevRuleToken *token, ++ const char *format, ++ char *result, ++ size_t result_size, ++ bool replace_whitespace, ++ const char *what) { ++ ++ assert(event); ++ assert(token); ++ assert(format); ++ assert(result); ++ assert(what); ++ ++ bool truncated = false; ++ (void) udev_event_apply_format(event, format, result, result_size, replace_whitespace, &truncated); ++ if (truncated) { ++ log_event_truncated(event, token, what, format); ++ return false; ++ } ++ ++ if (event->trace && !streq(format, result)) ++ log_event_trace(event, token, "Format substitution: \"%s\" -> \"%s\"", format, result); ++ ++ return true; ++} ++ ++static bool apply_format_value( ++ UdevEvent *event, ++ UdevRuleToken *token, ++ char *result, ++ size_t result_size, ++ const char *what) { ++ ++ return apply_format_full(event, token, token->value, result, result_size, /* replace_whitespace = */ false, what); ++} ++ ++static bool apply_format_attr( ++ UdevEvent *event, ++ UdevRuleToken *token, ++ char *result, ++ size_t result_size, ++ const char *what) { ++ ++ return apply_format_full(event, token, token->data, result, result_size, /* replace_whitespace = */ false, what); ++} ++ + static bool token_match_string(UdevRuleToken *token, const char *str) { + const char *value; + bool match = false, case_insensitive; +@@ -1834,7 +1879,6 @@ static bool token_match_string(UdevRuleToken *token, const char *str) { + static bool token_match_attr(UdevRuleToken *token, sd_device *dev, UdevEvent *event) { + char nbuf[UDEV_NAME_SIZE], vbuf[UDEV_NAME_SIZE]; + const char *name, *value; +- bool truncated; + + assert(token); + assert(IN_SET(token->type, TK_M_ATTR, TK_M_PARENTS_ATTR)); +@@ -1845,12 +1889,8 @@ static bool token_match_attr(UdevRuleToken *token, sd_device *dev, UdevEvent *ev + + switch (token->attr_subst_type) { + case SUBST_TYPE_FORMAT: +- (void) udev_event_apply_format(event, name, nbuf, sizeof(nbuf), false, &truncated); +- if (truncated) { +- log_event_truncated(event, token, "sysfs attribute name", name, +- token->type == TK_M_ATTR ? "ATTR" : "ATTRS", /* is_match = */ true); ++ if (!apply_format_attr(event, token, nbuf, sizeof(nbuf), "sysfs attribute name")) + return false; +- } + + name = nbuf; + _fallthrough_; +@@ -2118,13 +2158,9 @@ static int udev_rule_apply_token_to_event( + case TK_M_SYSCTL: { + _cleanup_free_ char *value = NULL; + char buf[UDEV_PATH_SIZE]; +- bool truncated; + +- (void) udev_event_apply_format(event, token->data, buf, sizeof(buf), false, &truncated); +- if (truncated) { +- log_event_truncated(event, token, "sysctl entry name", token->data, "SYSCTL", /* is_match = */ true); ++ if (!apply_format_attr(event, token, buf, sizeof(buf), "sysctl entry name")) + return false; +- } + + r = sysctl_read(sysctl_normalize(buf), &value); + if (r < 0 && r != -ENOENT) +@@ -2136,13 +2172,10 @@ static int udev_rule_apply_token_to_event( + mode_t mode = PTR_TO_MODE(token->data); + char buf[UDEV_PATH_SIZE]; + struct stat statbuf; +- bool match, truncated; ++ bool match; + +- (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated); +- if (truncated) { +- log_event_truncated(event, token, "file name", token->value, "TEST", /* is_match = */ true); ++ if (!apply_format_value(event, token, buf, sizeof(buf), "file name")) + return false; +- } + + if (!path_is_absolute(buf) && + udev_resolve_subsys_kernel(buf, buf, sizeof(buf), false) < 0) { +@@ -2153,6 +2186,7 @@ static int udev_rule_apply_token_to_event( + if (r < 0) + return log_event_error_errno(event, token, r, "Failed to get syspath: %m"); + ++ bool truncated; + strscpy_full(tmp, sizeof(tmp), buf, &truncated); + assert(!truncated); + strscpyl_full(buf, sizeof(buf), &truncated, val, "/", tmp, NULL); +@@ -2177,15 +2211,12 @@ static int udev_rule_apply_token_to_event( + } + case TK_M_PROGRAM: { + char buf[UDEV_LINE_SIZE], result[UDEV_LINE_SIZE]; +- bool truncated; + size_t count; + + event->program_result = mfree(event->program_result); +- (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated); +- if (truncated) { +- log_event_truncated(event, token, "command", token->value, "PROGRAM", /* is_match = */ true); ++ ++ if (!apply_format_value(event, token, buf, sizeof(buf), "command")) + return false; +- } + + log_event_debug(event, token, "Running PROGRAM=\"%s\"", buf); + +@@ -2211,13 +2242,9 @@ static int udev_rule_apply_token_to_event( + case TK_M_IMPORT_FILE: { + _cleanup_fclose_ FILE *f = NULL; + char buf[UDEV_PATH_SIZE]; +- bool truncated; + +- (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated); +- if (truncated) { +- log_event_truncated(event, token, "file name to be imported", token->value, "IMPORT", /* is_match = */ true); ++ if (!apply_format_value(event, token, buf, sizeof(buf), "file name to be imported")) + return false; +- } + + log_event_debug(event, token, "Importing properties from '%s'", buf); + +@@ -2264,11 +2291,8 @@ static int udev_rule_apply_token_to_event( + char buf[UDEV_LINE_SIZE], result[UDEV_LINE_SIZE]; + bool truncated; + +- (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated); +- if (truncated) { +- log_event_truncated(event, token, "command", token->value, "IMPORT", /* is_match = */ true); ++ if (!apply_format_value(event, token, buf, sizeof(buf), "command")) + return false; +- } + + log_event_debug(event, token, "Importing properties from results of '%s'", buf); + +@@ -2329,7 +2353,6 @@ static int udev_rule_apply_token_to_event( + assert(cmd >= 0 && cmd < _UDEV_BUILTIN_MAX); + unsigned mask = 1U << (int) cmd; + char buf[UDEV_LINE_SIZE]; +- bool truncated; + + if (udev_builtin_run_once(cmd)) { + /* check if we ran already */ +@@ -2343,11 +2366,8 @@ static int udev_rule_apply_token_to_event( + event->builtin_run |= mask; + } + +- (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated); +- if (truncated) { +- log_event_truncated(event, token, "builtin command", token->value, "IMPORT", /* is_match = */ true); ++ if (!apply_format_value(event, token, buf, sizeof(buf), "builtin command")) + return false; +- } + + log_event_debug(event, token, "Importing properties from results of builtin command '%s'", buf); + +@@ -2397,13 +2417,9 @@ static int udev_rule_apply_token_to_event( + } + case TK_M_IMPORT_PARENT: { + char buf[UDEV_PATH_SIZE]; +- bool truncated; + +- (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated); +- if (truncated) { +- log_event_truncated(event, token, "property name", token->value, "IMPORT", /* is_match = */ true); ++ if (!apply_format_value(event, token, buf, sizeof(buf), "property name")) + return false; +- } + + r = import_parent_into_properties(dev, buf); + if (r < 0) +@@ -2460,18 +2476,14 @@ static int udev_rule_apply_token_to_event( + case TK_A_OWNER: { + char owner[UDEV_NAME_SIZE]; + const char *ow = owner; +- bool truncated; + + if (event->owner_final) + break; + if (token->op == OP_ASSIGN_FINAL) + event->owner_final = true; + +- (void) udev_event_apply_format(event, token->value, owner, sizeof(owner), false, &truncated); +- if (truncated) { +- log_event_truncated(event, token, "user name", token->value, "OWNER", /* is_match = */ false); +- break; +- } ++ if (!apply_format_value(event, token, owner, sizeof(owner), "user name")) ++ return true; + + r = get_user_creds(&ow, &event->uid, NULL, NULL, NULL, USER_CREDS_ALLOW_MISSING); + if (r < 0) +@@ -2483,18 +2495,14 @@ static int udev_rule_apply_token_to_event( + case TK_A_GROUP: { + char group[UDEV_NAME_SIZE]; + const char *gr = group; +- bool truncated; + + if (event->group_final) + break; + if (token->op == OP_ASSIGN_FINAL) + event->group_final = true; + +- (void) udev_event_apply_format(event, token->value, group, sizeof(group), false, &truncated); +- if (truncated) { +- log_event_truncated(event, token, "group name", token->value, "GROUP", /* is_match = */ false); +- break; +- } ++ if (!apply_format_value(event, token, group, sizeof(group), "group name")) ++ return true; + + r = get_group_creds(&gr, &event->gid, USER_CREDS_ALLOW_MISSING); + if (r < 0) +@@ -2505,18 +2513,14 @@ static int udev_rule_apply_token_to_event( + } + case TK_A_MODE: { + char mode_str[UDEV_NAME_SIZE]; +- bool truncated; + + if (event->mode_final) + break; + if (token->op == OP_ASSIGN_FINAL) + event->mode_final = true; + +- (void) udev_event_apply_format(event, token->value, mode_str, sizeof(mode_str), false, &truncated); +- if (truncated) { +- log_event_truncated(event, token, "mode", token->value, "MODE", /* is_match = */ false); +- break; +- } ++ if (!apply_format_value(event, token, mode_str, sizeof(mode_str), "mode")) ++ return true; + + r = parse_mode(mode_str, &event->mode); + if (r < 0) +@@ -2558,17 +2562,13 @@ static int udev_rule_apply_token_to_event( + case TK_A_SECLABEL: { + _cleanup_free_ char *name = NULL, *label = NULL; + char label_str[UDEV_LINE_SIZE] = {}; +- bool truncated; + + name = strdup(token->data); + if (!name) + return log_oom(); + +- (void) udev_event_apply_format(event, token->value, label_str, sizeof(label_str), false, &truncated); +- if (truncated) { +- log_event_truncated(event, token, "security label", token->value, "SECLABEL", /* is_match = */ false); +- break; +- } ++ if (!apply_format_value(event, token, label_str, sizeof(label_str), "security label")) ++ return true; + + if (!isempty(label_str)) + label = strdup(label_str); +@@ -2596,7 +2596,6 @@ static int udev_rule_apply_token_to_event( + const char *val, *name = token->data; + char value_new[UDEV_NAME_SIZE], *p = value_new; + size_t count, l = sizeof(value_new); +- bool truncated; + + if (isempty(token->value)) { + if (token->op == OP_ADD) +@@ -2609,6 +2608,7 @@ static int udev_rule_apply_token_to_event( + + if (token->op == OP_ADD && + device_get_property_value_with_fallback(dev, name, event->worker ? event->worker->properties : NULL, &val) >= 0) { ++ bool truncated; + l = strpcpyl_full(&p, l, &truncated, val, " ", NULL); + if (truncated) { + log_event_warning(event, token, +@@ -2618,13 +2618,8 @@ static int udev_rule_apply_token_to_event( + } + } + +- (void) udev_event_apply_format(event, token->value, p, l, false, &truncated); +- if (truncated) { +- _cleanup_free_ char *key_with_name = strjoin("ENV{", name, "}"); +- log_event_truncated(event, token, "property value", token->value, +- key_with_name ?: "ENV", /* is_match = */ false); +- break; +- } ++ if (!apply_format_value(event, token, p, l, "property value")) ++ return true; + + if (event->esc == ESCAPE_REPLACE) { + count = udev_replace_chars(p, NULL); +@@ -2641,13 +2636,9 @@ static int udev_rule_apply_token_to_event( + } + case TK_A_TAG: { + char buf[UDEV_PATH_SIZE]; +- bool truncated; + +- (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated); +- if (truncated) { +- log_event_truncated(event, token, "tag name", token->value, "TAG", /* is_match = */ false); +- break; +- } ++ if (!apply_format_value(event, token, buf, sizeof(buf), "tag name")) ++ return true; + + if (token->op == OP_ASSIGN) + device_cleanup_tags(dev); +@@ -2665,7 +2656,6 @@ static int udev_rule_apply_token_to_event( + } + case TK_A_NAME: { + char buf[UDEV_PATH_SIZE]; +- bool truncated; + size_t count; + + if (event->name_final) +@@ -2680,11 +2670,8 @@ static int udev_rule_apply_token_to_event( + break; + } + +- (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated); +- if (truncated) { +- log_event_truncated(event, token, "network interface name", token->value, "NAME", /* is_match = */ false); +- break; +- } ++ if (!apply_format_value(event, token, buf, sizeof(buf), "network interface name")) ++ return true; + + if (IN_SET(event->esc, ESCAPE_UNSET, ESCAPE_REPLACE)) { + if (naming_scheme_has(NAMING_REPLACE_STRICTLY)) +@@ -2705,7 +2692,6 @@ static int udev_rule_apply_token_to_event( + } + case TK_A_DEVLINK: { + char buf[UDEV_PATH_SIZE]; +- bool truncated; + size_t count; + + if (event->devlink_final) +@@ -2717,12 +2703,10 @@ static int udev_rule_apply_token_to_event( + if (IN_SET(token->op, OP_ASSIGN, OP_ASSIGN_FINAL)) + device_cleanup_devlinks(dev); + +- (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), +- /* replace_whitespace = */ event->esc != ESCAPE_NONE, &truncated); +- if (truncated) { +- log_event_truncated(event, token, "symbolic link path", token->value, "SYMLINK", /* is_match = */ false); +- break; +- } ++ if (!apply_format_full(event, token, token->value, buf, sizeof(buf), ++ /* replace_whitespace = */ event->esc != ESCAPE_NONE, ++ "symbolic link path")) ++ return true; + + /* By default or string_escape=none, allow multiple symlinks separated by spaces. */ + if (event->esc == ESCAPE_UNSET) +@@ -2772,10 +2756,10 @@ static int udev_rule_apply_token_to_event( + case TK_A_ATTR: { + char buf[UDEV_PATH_SIZE], value[UDEV_NAME_SIZE]; + const char *val, *key_name = token->data; +- bool truncated; + + if (udev_resolve_subsys_kernel(key_name, buf, sizeof(buf), false) < 0 && + sd_device_get_syspath(dev, &val) >= 0) { ++ bool truncated; + strscpyl_full(buf, sizeof(buf), &truncated, val, "/", key_name, NULL); + if (truncated) { + log_event_warning(event, token, +@@ -2790,11 +2774,9 @@ static int udev_rule_apply_token_to_event( + log_event_error_errno(event, token, r, "Could not find file matches '%s', ignoring: %m", buf); + break; + } +- (void) udev_event_apply_format(event, token->value, value, sizeof(value), false, &truncated); +- if (truncated) { +- log_event_truncated(event, token, "attribute value", token->value, "ATTR", /* is_match = */ false); +- break; +- } ++ ++ if (!apply_format_value(event, token, value, sizeof(value), "attribute value")) ++ return true; + + if (EVENT_MODE_DESTRUCTIVE(event)) { + log_event_debug(event, token, "Writing ATTR{'%s'}=\"%s\".", buf, value); +@@ -2812,21 +2794,12 @@ static int udev_rule_apply_token_to_event( + } + case TK_A_SYSCTL: { + char buf[UDEV_PATH_SIZE], value[UDEV_NAME_SIZE]; +- bool truncated; + +- (void) udev_event_apply_format(event, token->data, buf, sizeof(buf), false, &truncated); +- if (truncated) { +- log_event_truncated(event, token, "sysctl entry name", token->data, "SYSCTL", /* is_match = */ false); +- break; +- } ++ if (!apply_format_attr(event, token, buf, sizeof(buf), "sysctl entry name")) ++ return true; + +- (void) udev_event_apply_format(event, token->value, value, sizeof(value), false, &truncated); +- if (truncated) { +- _cleanup_free_ char *key_with_name = strjoin("SYSCTL{", buf, "}"); +- log_event_truncated(event, token, "sysctl value", token->value, +- key_with_name ?: "SYSCTL", /* is_match = */ false); +- break; +- } ++ if (!apply_format_value(event, token, value, sizeof(value), "sysctl value")) ++ return true; + + sysctl_normalize(buf); + +@@ -2844,7 +2817,6 @@ static int udev_rule_apply_token_to_event( + case TK_A_RUN_PROGRAM: { + _cleanup_free_ char *cmd = NULL; + char buf[UDEV_LINE_SIZE]; +- bool truncated; + + if (event->run_final) + break; +@@ -2854,13 +2826,8 @@ static int udev_rule_apply_token_to_event( + if (IN_SET(token->op, OP_ASSIGN, OP_ASSIGN_FINAL)) + ordered_hashmap_clear_free_key(event->run_list); + +- (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated); +- if (truncated) { +- log_event_truncated(event, token, "command", token->value, +- token->type == TK_A_RUN_BUILTIN ? "RUN{builtin}" : "RUN{program}", +- /* is_match = */ false); +- break; +- } ++ if (!apply_format_value(event, token, buf, sizeof(buf), "command")) ++ return true; + + cmd = strdup(buf); + if (!cmd) diff --git a/0168-udev-rules-add-more-trace-logs-for-string-match.patch b/0168-udev-rules-add-more-trace-logs-for-string-match.patch new file mode 100644 index 0000000..b6f3b47 --- /dev/null +++ b/0168-udev-rules-add-more-trace-logs-for-string-match.patch @@ -0,0 +1,205 @@ +From 49cc87a059b24a6c81e954425599a7253c05beb4 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Mon, 13 Jan 2025 04:03:11 +0900 +Subject: [PATCH] udev-rules: add more trace logs for string match + +(cherry picked from commit 0febeccfdc4839ace732280f06005e81f5cadff7) + +Resolves: RHEL-75774 +--- + src/udev/udev-rules.c | 81 ++++++++++++++++++++++++++++++++++--------- + 1 file changed, 65 insertions(+), 16 deletions(-) + +diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c +index 3a61403338..35a3a9cc69 100644 +--- a/src/udev/udev-rules.c ++++ b/src/udev/udev-rules.c +@@ -1821,10 +1821,11 @@ static bool apply_format_attr( + return apply_format_full(event, token, token->data, result, result_size, /* replace_whitespace = */ false, what); + } + +-static bool token_match_string(UdevRuleToken *token, const char *str) { ++static bool token_match_string(UdevEvent *event, UdevRuleToken *token, const char *str, bool log_result) { + const char *value; + bool match = false, case_insensitive; + ++ assert(event); + assert(token); + assert(token->value); + assert(token->type < _TK_M_MAX); +@@ -1873,7 +1874,51 @@ static bool token_match_string(UdevRuleToken *token, const char *str) { + assert_not_reached(); + } + +- return token->op == (match ? OP_MATCH : OP_NOMATCH); ++ bool result = token->op == (match ? OP_MATCH : OP_NOMATCH); ++ ++ if (event->trace) ++ switch (token->match_type & _MATCH_TYPE_MASK) { ++ case MATCH_TYPE_EMPTY: ++ log_event_trace(event, token, "String \"%s\" is%s empty%s", ++ strempty(str), match ? "" : " not", ++ log_result ? result ? ": PASS" : ": FAIL" : "."); ++ break; ++ case MATCH_TYPE_SUBSYSTEM: ++ log_event_trace(event, token, ++ "String \"%s\" matches %s of \"subsystem\", \"class\", or \"bus\"%s", ++ strempty(str), match ? "one" : "neither", ++ log_result ? result ? ": PASS" : ": FAIL" : "."); ++ break; ++ case MATCH_TYPE_PLAIN_WITH_EMPTY: ++ case MATCH_TYPE_PLAIN: ++ case MATCH_TYPE_GLOB_WITH_EMPTY: ++ case MATCH_TYPE_GLOB: { ++ _cleanup_free_ char *joined = NULL; ++ unsigned c = 0; ++ ++ if (IN_SET(token->match_type & _MATCH_TYPE_MASK, MATCH_TYPE_PLAIN_WITH_EMPTY, MATCH_TYPE_GLOB_WITH_EMPTY)) { ++ (void) strextend_with_separator(&joined, ", ", "\"\""); ++ c++; ++ } ++ ++ NULSTR_FOREACH(i, value) { ++ (void) strextendf_with_separator(&joined, ", ", "\"%s\"", i); ++ c++; ++ } ++ ++ assert(c > 0); ++ log_event_trace(event, token, "String \"%s\" %s %s%s", ++ strempty(str), ++ match ? (c > 1 ? "matches one of" : "matches") : (c > 1 ? "matches neither of" : "does not match"), ++ strempty(joined), ++ log_result ? result ? ": PASS" : ": FAIL" : "."); ++ break; ++ } ++ default: ++ assert_not_reached(); ++ } ++ ++ return result; + } + + static bool token_match_attr(UdevRuleToken *token, sd_device *dev, UdevEvent *event) { +@@ -1904,7 +1949,7 @@ static bool token_match_attr(UdevRuleToken *token, sd_device *dev, UdevEvent *ev + value = delete_trailing_chars(vbuf, NULL); + } + +- return token_match_string(token, value); ++ return token_match_string(event, token, value, /* log_result = */ true); + + case SUBST_TYPE_SUBSYS: + if (udev_resolve_subsys_kernel(name, vbuf, sizeof(vbuf), true) < 0) +@@ -1914,7 +1959,7 @@ static bool token_match_attr(UdevRuleToken *token, sd_device *dev, UdevEvent *ev + if (FLAGS_SET(token->match_type, MATCH_REMOVE_TRAILING_WHITESPACE)) + delete_trailing_chars(vbuf, NULL); + +- return token_match_string(token, vbuf); ++ return token_match_string(event, token, vbuf, /* log_result = */ true); + + default: + assert_not_reached(); +@@ -2074,7 +2119,7 @@ static int udev_rule_apply_token_to_event( + if (r < 0) + return log_event_error_errno(event, token, r, "Failed to get uevent action type: %m"); + +- return token_match_string(token, device_action_to_string(a)); ++ return token_match_string(event, token, device_action_to_string(a), /* log_result = */ true); + } + case TK_M_DEVPATH: { + const char *val; +@@ -2083,7 +2128,7 @@ static int udev_rule_apply_token_to_event( + if (r < 0) + return log_event_error_errno(event, token, r, "Failed to get devpath: %m"); + +- return token_match_string(token, val); ++ return token_match_string(event, token, val, /* log_result = */ true); + } + case TK_M_KERNEL: + case TK_M_PARENTS_KERNEL: { +@@ -2093,21 +2138,23 @@ static int udev_rule_apply_token_to_event( + if (r < 0) + return log_event_error_errno(event, token, r, "Failed to get sysname: %m"); + +- return token_match_string(token, val); ++ return token_match_string(event, token, val, /* log_result = */ true); + } + case TK_M_DEVLINK: + FOREACH_DEVICE_DEVLINK(dev, val) +- if (token_match_string(token, strempty(startswith(val, "/dev/"))) == (token->op == OP_MATCH)) ++ if (token_match_string(event, token, strempty(startswith(val, "/dev/")), /* log_result = */ false) == (token->op == OP_MATCH)) + return token->op == OP_MATCH; + return token->op == OP_NOMATCH; ++ + case TK_M_NAME: +- return token_match_string(token, event->name); ++ return token_match_string(event, token, event->name, /* log_result = */ true); ++ + case TK_M_ENV: { + const char *val = NULL; + + (void) device_get_property_value_with_fallback(dev, token->data, event->worker ? event->worker->properties : NULL, &val); + +- return token_match_string(token, val); ++ return token_match_string(event, token, val, /* log_result = */ true); + } + case TK_M_CONST: { + const char *val, *k = token->data; +@@ -2120,14 +2167,15 @@ static int udev_rule_apply_token_to_event( + val = confidential_virtualization_to_string(detect_confidential_virtualization()); + else + assert_not_reached(); +- return token_match_string(token, val); ++ return token_match_string(event, token, val, /* log_result = */ true); + } + case TK_M_TAG: + case TK_M_PARENTS_TAG: + FOREACH_DEVICE_CURRENT_TAG(dev, val) +- if (token_match_string(token, val) == (token->op == OP_MATCH)) ++ if (token_match_string(event, token, val, /* log_result = */ false) == (token->op == OP_MATCH)) + return token->op == OP_MATCH; + return token->op == OP_NOMATCH; ++ + case TK_M_SUBSYSTEM: + case TK_M_PARENTS_SUBSYSTEM: { + const char *val; +@@ -2138,7 +2186,7 @@ static int udev_rule_apply_token_to_event( + else if (r < 0) + return log_event_error_errno(event, token, r, "Failed to get subsystem: %m"); + +- return token_match_string(token, val); ++ return token_match_string(event, token, val, /* log_result = */ true); + } + case TK_M_DRIVER: + case TK_M_PARENTS_DRIVER: { +@@ -2150,11 +2198,12 @@ static int udev_rule_apply_token_to_event( + else if (r < 0) + return log_event_error_errno(event, token, r, "Failed to get driver: %m"); + +- return token_match_string(token, val); ++ return token_match_string(event, token, val, /* log_result = */ true); + } + case TK_M_ATTR: + case TK_M_PARENTS_ATTR: + return token_match_attr(token, dev, event); ++ + case TK_M_SYSCTL: { + _cleanup_free_ char *value = NULL; + char buf[UDEV_PATH_SIZE]; +@@ -2166,7 +2215,7 @@ static int udev_rule_apply_token_to_event( + if (r < 0 && r != -ENOENT) + return log_event_error_errno(event, token, r, "Failed to read sysctl '%s': %m", buf); + +- return token_match_string(token, strstrip(value)); ++ return token_match_string(event, token, strstrip(value), /* log_result = */ true); + } + case TK_M_TEST: { + mode_t mode = PTR_TO_MODE(token->data); +@@ -2429,7 +2478,7 @@ static int udev_rule_apply_token_to_event( + return token->op == (r > 0 ? OP_MATCH : OP_NOMATCH); + } + case TK_M_RESULT: +- return token_match_string(token, event->program_result); ++ return token_match_string(event, token, event->program_result, /* log_result = */ true); + case TK_A_OPTIONS_STRING_ESCAPE_NONE: + event->esc = ESCAPE_NONE; + break; diff --git a/0169-udev-rules-introduce-udev_replace_chars_and_log.patch b/0169-udev-rules-introduce-udev_replace_chars_and_log.patch new file mode 100644 index 0000000..e28599a --- /dev/null +++ b/0169-udev-rules-introduce-udev_replace_chars_and_log.patch @@ -0,0 +1,163 @@ +From 4106dbe04d90031197b4317b7c8ae36e2fb76984 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Wed, 15 Jan 2025 22:09:05 +0900 +Subject: [PATCH] udev-rules: introduce udev_replace_chars_and_log() + +And logs about replacement only when trace logging is enabled. + +(cherry picked from commit a79cd8c2be447367dc2d70615dc9e3e0c91d5cf4) + +Resolves: RHEL-75774 +--- + src/udev/udev-rules.c | 74 +++++++++++++++++++++++-------------------- + 1 file changed, 39 insertions(+), 35 deletions(-) + +diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c +index 35a3a9cc69..53370f6085 100644 +--- a/src/udev/udev-rules.c ++++ b/src/udev/udev-rules.c +@@ -2079,7 +2079,7 @@ static int attr_subst_subdir(char attr[static UDEV_PATH_SIZE]) { + return -ENOENT; + } + +-static size_t udev_replace_ifname(char *str) { ++static size_t udev_replace_ifname_strict(char *str) { + size_t replaced = 0; + + assert(str); +@@ -2095,6 +2095,35 @@ static size_t udev_replace_ifname(char *str) { + return replaced; + } + ++static void udev_replace_ifname(UdevEvent *event, UdevRuleToken *token, char *buf) { ++ assert(event); ++ assert(token); ++ assert(buf); ++ ++ size_t count; ++ if (naming_scheme_has(NAMING_REPLACE_STRICTLY)) ++ count = udev_replace_ifname_strict(buf); ++ else ++ count = udev_replace_chars(buf, "/"); ++ if (count > 0) ++ log_event_trace(event, token, ++ "Replaced %zu character(s) from network interface name, results to \"%s\"", ++ count, buf); ++} ++ ++static void udev_replace_chars_and_log(UdevEvent *event, UdevRuleToken *token, char *buf, const char *allow, const char *what) { ++ assert(event); ++ assert(token); ++ assert(buf); ++ assert(what); ++ ++ size_t count = udev_replace_chars(buf, allow); ++ if (count > 0) ++ log_event_trace(event, token, ++ "Replaced %zu character(s) from %s, results to \"%s\"", ++ count, what, buf); ++} ++ + static int udev_rule_apply_token_to_event( + UdevRuleToken *token, + sd_device *dev, +@@ -2260,7 +2289,6 @@ static int udev_rule_apply_token_to_event( + } + case TK_M_PROGRAM: { + char buf[UDEV_LINE_SIZE], result[UDEV_LINE_SIZE]; +- size_t count; + + event->program_result = mfree(event->program_result); + +@@ -2279,11 +2307,7 @@ static int udev_rule_apply_token_to_event( + } + + delete_trailing_chars(result, "\n"); +- count = udev_replace_chars(result, UDEV_ALLOWED_CHARS_INPUT); +- if (count > 0) +- log_event_debug(event, token, +- "Replaced %zu character(s) in result of \"%s\"", +- count, buf); ++ udev_replace_chars_and_log(event, token, result, UDEV_ALLOWED_CHARS_INPUT, "command output"); + + event->program_result = strdup(result); + return token->op == OP_MATCH; +@@ -2644,7 +2668,7 @@ static int udev_rule_apply_token_to_event( + case TK_A_ENV: { + const char *val, *name = token->data; + char value_new[UDEV_NAME_SIZE], *p = value_new; +- size_t count, l = sizeof(value_new); ++ size_t l = sizeof(value_new); + + if (isempty(token->value)) { + if (token->op == OP_ADD) +@@ -2670,13 +2694,8 @@ static int udev_rule_apply_token_to_event( + if (!apply_format_value(event, token, p, l, "property value")) + return true; + +- if (event->esc == ESCAPE_REPLACE) { +- count = udev_replace_chars(p, NULL); +- if (count > 0) +- log_event_debug(event, token, +- "Replaced %zu slash(es) from result of ENV{%s}%s=\"%s\"", +- count, name, token->op == OP_ADD ? "+" : "", token->value); +- } ++ if (event->esc == ESCAPE_REPLACE) ++ udev_replace_chars_and_log(event, token, p, /* allow = */ NULL, "property value"); + + r = device_add_property(dev, name, value_new); + if (r < 0) +@@ -2705,7 +2724,6 @@ static int udev_rule_apply_token_to_event( + } + case TK_A_NAME: { + char buf[UDEV_PATH_SIZE]; +- size_t count; + + if (event->name_final) + break; +@@ -2722,16 +2740,9 @@ static int udev_rule_apply_token_to_event( + if (!apply_format_value(event, token, buf, sizeof(buf), "network interface name")) + return true; + +- if (IN_SET(event->esc, ESCAPE_UNSET, ESCAPE_REPLACE)) { +- if (naming_scheme_has(NAMING_REPLACE_STRICTLY)) +- count = udev_replace_ifname(buf); +- else +- count = udev_replace_chars(buf, "/"); +- if (count > 0) +- log_event_debug(event, token, +- "Replaced %zu character(s) from result of NAME=\"%s\"", +- count, token->value); +- } ++ if (IN_SET(event->esc, ESCAPE_UNSET, ESCAPE_REPLACE)) ++ udev_replace_ifname(event, token, buf); ++ + r = free_and_strdup_warn(&event->name, buf); + if (r < 0) + return r; +@@ -2741,7 +2752,6 @@ static int udev_rule_apply_token_to_event( + } + case TK_A_DEVLINK: { + char buf[UDEV_PATH_SIZE]; +- size_t count; + + if (event->devlink_final) + break; +@@ -2759,15 +2769,9 @@ static int udev_rule_apply_token_to_event( + + /* By default or string_escape=none, allow multiple symlinks separated by spaces. */ + if (event->esc == ESCAPE_UNSET) +- count = udev_replace_chars(buf, /* allow = */ "/ "); ++ udev_replace_chars_and_log(event, token, buf, /* allow = */ "/ ", "device node symlink"); + else if (event->esc == ESCAPE_REPLACE) +- count = udev_replace_chars(buf, /* allow = */ "/"); +- else +- count = 0; +- if (count > 0) +- log_event_debug(event, token, +- "Replaced %zu character(s) from result of SYMLINK=\"%s\"", +- count, token->value); ++ udev_replace_chars_and_log(event, token, buf, /* allow = */ "/", "device node symlink"); + + for (const char *p = buf;;) { + _cleanup_free_ char *path = NULL; diff --git a/0170-udev-rules-ignore-whole-command-result-if-it-is-too-.patch b/0170-udev-rules-ignore-whole-command-result-if-it-is-too-.patch new file mode 100644 index 0000000..a18736f --- /dev/null +++ b/0170-udev-rules-ignore-whole-command-result-if-it-is-too-.patch @@ -0,0 +1,38 @@ +From 95534ef8f7558b5f7f93991043441adb9c7ddf33 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Wed, 15 Jan 2025 23:43:37 +0900 +Subject: [PATCH] udev-rules: ignore whole command result if it is too long and + does not contain newline + +(cherry picked from commit 68b1e1b61ab333bb4dee4a43373bad54080e755f) + +Resolves: RHEL-75774 +--- + src/udev/udev-rules.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c +index 53370f6085..9aa98a3b3c 100644 +--- a/src/udev/udev-rules.c ++++ b/src/udev/udev-rules.c +@@ -2379,15 +2379,18 @@ static int udev_rule_apply_token_to_event( + } + + if (truncated) { +- bool found = false; ++ log_event_debug(event, token, "Result of \"%s\" is too long and truncated, ignoring the last line of the result.", buf); + + /* Drop the last line. */ ++ bool found = false; + for (char *p = PTR_SUB1(buf + strlen(buf), buf); p; p = PTR_SUB1(p, buf)) + if (strchr(NEWLINE, *p)) { + *p = '\0'; + found = true; +- } else if (found) + break; ++ } ++ if (!found) ++ buf[0] = '\0'; + } + + r = strv_split_newlines_full(&lines, result, EXTRACT_RETAIN_ESCAPE); diff --git a/0171-udev-rules-update-log-messages.patch b/0171-udev-rules-update-log-messages.patch new file mode 100644 index 0000000..683d5a9 --- /dev/null +++ b/0171-udev-rules-update-log-messages.patch @@ -0,0 +1,900 @@ +From 9345b1fd8d04c0b222b94dd68e0f255c7358c792 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Wed, 15 Jan 2025 23:47:05 +0900 +Subject: [PATCH] udev-rules: update log messages + +This also adds trace logs about token result, and skipping assignment +caused by final value already assigned. + +(cherry picked from commit 354d063fbcadb277094e47a79e7cde62ae269199) + +Resolves: RHEL-75774 +--- + src/udev/udev-rules.c | 433 ++++++++++++++++++++++++------------------ + 1 file changed, 248 insertions(+), 185 deletions(-) + +diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c +index 9aa98a3b3c..c5fa2c660c 100644 +--- a/src/udev/udev-rules.c ++++ b/src/udev/udev-rules.c +@@ -297,6 +297,37 @@ static bool token_is_for_parents(UdevRuleToken *token) { + #define log_event_trace(event, ...) \ + _log_event_trace(event, UNIQ_T(e, UNIQ), __VA_ARGS__) + ++#define _log_event_result(event, token, result, result_u) \ ++ ({ \ ++ bool result_u = (result); \ ++ \ ++ log_event_trace(event, token, "%s", \ ++ result_u ? "PASS" : "FAIL"); \ ++ result_u; \ ++ }) ++ ++#define log_event_result(event, token, result) \ ++ _log_event_result(event, token, result, UNIQ_T(r, UNIQ)) ++ ++#define log_event_done(event, token) \ ++ ({ \ ++ log_event_trace(event, token, "DONE"); \ ++ true; \ ++ }) ++ ++#define _log_event_final_set(event, token, token_u) \ ++ ({ \ ++ UdevRuleToken *token_u = ASSERT_PTR(token); \ ++ \ ++ log_event_trace(event, token_u, \ ++ "Already assigned final value, ignoring further %s.", \ ++ token_u->op == OP_REMOVE ? "modification" : "assignment"); \ ++ true; \ ++ }) ++ ++#define log_event_final_set(event, token) \ ++ _log_event_final_set(event, token, UNIQ_T(t, UNIQ)) ++ + #define _log_event_truncated(event, token, token_u, what, format) \ + ({ \ + UdevRuleToken *token_u = ASSERT_PTR(token); \ +@@ -358,16 +389,6 @@ static bool token_is_for_parents(UdevRuleToken *token) { + "Invalid value \"%s\" for %s (char %zu: %s), ignoring.", \ + value, key, offset, hint) + +-static void log_unknown_owner(sd_device *dev, UdevRuleLine *line, int error, const char *entity, const char *name) { +- assert(line); +- ASSERT_NON_ZERO(error); +- +- if (IN_SET(abs(error), ENOENT, ESRCH)) +- log_udev_rule_line_full(dev, line, LOG_ERR, error, "Unknown %s '%s', ignoring.", entity, name); +- else +- log_udev_rule_line_full(dev, line, LOG_ERR, error, "Failed to resolve %s '%s', ignoring: %m", entity, name); +-} +- + /*** Other functions ***/ + + static UdevRuleToken* udev_rule_token_free(UdevRuleToken *token) { +@@ -452,7 +473,11 @@ static int rule_resolve_user(UdevRuleLine *rule_line, const char *name, uid_t *r + + r = get_user_creds(&name, &uid, NULL, NULL, NULL, USER_CREDS_ALLOW_MISSING); + if (r < 0) { +- log_unknown_owner(NULL, rule_line, r, "user", name); ++ if (IN_SET(r, -ENOENT, -ESRCH)) ++ log_line_error_errno(rule_line, r, "Unknown user '%s', ignoring.", name); ++ else ++ log_line_error_errno(rule_line, r, "Failed to resolve user '%s', ignoring: %m", name); ++ + *ret = UID_INVALID; + return 0; + } +@@ -488,7 +513,11 @@ static int rule_resolve_group(UdevRuleLine *rule_line, const char *name, gid_t * + + r = get_group_creds(&name, &gid, USER_CREDS_ALLOW_MISSING); + if (r < 0) { +- log_unknown_owner(NULL, rule_line, r, "group", name); ++ if (IN_SET(r, -ENOENT, -ESRCH)) ++ log_line_error_errno(rule_line, r, "Unknown group '%s', ignoring.", name); ++ else ++ log_line_error_errno(rule_line, r, "Failed to resolve group '%s', ignoring: %m", name); ++ + *ret = GID_INVALID; + return 0; + } +@@ -2011,30 +2040,6 @@ static int get_property_from_string(char *line, char **ret_key, char **ret_value + return 1; + } + +-static int import_parent_into_properties(sd_device *dev, const char *filter) { +- sd_device *parent; +- int r; +- +- assert(dev); +- assert(filter); +- +- r = sd_device_get_parent(dev, &parent); +- if (r == -ENOENT) +- return 0; +- if (r < 0) +- return r; +- +- FOREACH_DEVICE_PROPERTY(parent, key, val) { +- if (fnmatch(filter, key, 0) != 0) +- continue; +- r = device_add_property(dev, key, val); +- if (r < 0) +- return r; +- } +- +- return 1; +-} +- + static int attr_subst_subdir(char attr[static UDEV_PATH_SIZE]) { + _cleanup_closedir_ DIR *dir = NULL; + char buf[UDEV_PATH_SIZE], *p; +@@ -2172,8 +2177,8 @@ static int udev_rule_apply_token_to_event( + case TK_M_DEVLINK: + FOREACH_DEVICE_DEVLINK(dev, val) + if (token_match_string(event, token, strempty(startswith(val, "/dev/")), /* log_result = */ false) == (token->op == OP_MATCH)) +- return token->op == OP_MATCH; +- return token->op == OP_NOMATCH; ++ return log_event_result(event, token, token->op == OP_MATCH); ++ return log_event_result(event, token, token->op == OP_NOMATCH); + + case TK_M_NAME: + return token_match_string(event, token, event->name, /* log_result = */ true); +@@ -2202,8 +2207,8 @@ static int udev_rule_apply_token_to_event( + case TK_M_PARENTS_TAG: + FOREACH_DEVICE_CURRENT_TAG(dev, val) + if (token_match_string(event, token, val, /* log_result = */ false) == (token->op == OP_MATCH)) +- return token->op == OP_MATCH; +- return token->op == OP_NOMATCH; ++ return log_event_result(event, token, token->op == OP_MATCH); ++ return log_event_result(event, token, token->op == OP_NOMATCH); + + case TK_M_SUBSYSTEM: + case TK_M_PARENTS_SUBSYSTEM: { +@@ -2242,7 +2247,7 @@ static int udev_rule_apply_token_to_event( + + r = sysctl_read(sysctl_normalize(buf), &value); + if (r < 0 && r != -ENOENT) +- return log_event_error_errno(event, token, r, "Failed to read sysctl '%s': %m", buf); ++ return log_event_error_errno(event, token, r, "Failed to read sysctl \"%s\": %m", buf); + + return token_match_string(event, token, strstrip(value), /* log_result = */ true); + } +@@ -2269,23 +2274,26 @@ static int udev_rule_apply_token_to_event( + assert(!truncated); + strscpyl_full(buf, sizeof(buf), &truncated, val, "/", tmp, NULL); + if (truncated) +- return false; ++ return log_event_result(event, token, false); + } + + r = attr_subst_subdir(buf); + if (r == -ENOENT) +- return token->op == OP_NOMATCH; ++ return log_event_result(event, token, token->op == OP_NOMATCH); + if (r < 0) +- return log_event_error_errno(event, token, r, "Failed to test for the existence of '%s': %m", buf); ++ return log_event_error_errno(event, token, r, "Failed to test for the existence of \"%s\": %m", buf); + +- if (stat(buf, &statbuf) < 0) +- return token->op == OP_NOMATCH; ++ if (stat(buf, &statbuf) < 0) { ++ if (errno != ENOENT) ++ log_event_warning_errno(event, token, errno, "Failed to stat \"%s\", ignoring: %m", buf); ++ return log_event_result(event, token, token->op == OP_NOMATCH); ++ } + + if (mode == MODE_INVALID) +- return token->op == OP_MATCH; ++ return log_event_result(event, token, token->op == OP_MATCH); + + match = (statbuf.st_mode & mode) > 0; +- return token->op == (match ? OP_MATCH : OP_NOMATCH); ++ return log_event_result(event, token, token->op == (match ? OP_MATCH : OP_NOMATCH)); + } + case TK_M_PROGRAM: { + char buf[UDEV_LINE_SIZE], result[UDEV_LINE_SIZE]; +@@ -2295,7 +2303,7 @@ static int udev_rule_apply_token_to_event( + if (!apply_format_value(event, token, buf, sizeof(buf), "command")) + return false; + +- log_event_debug(event, token, "Running PROGRAM=\"%s\"", buf); ++ log_event_debug(event, token, "Running command \"%s\"", buf); + + r = udev_event_spawn(event, /* accept_failure = */ true, buf, result, sizeof(result), NULL); + if (r != 0) { +@@ -2303,14 +2311,14 @@ static int udev_rule_apply_token_to_event( + log_event_warning_errno(event, token, r, "Failed to execute \"%s\": %m", buf); + else /* returned value is positive when program fails */ + log_event_debug(event, token, "Command \"%s\" returned %d (error)", buf, r); +- return token->op == OP_NOMATCH; ++ return log_event_result(event, token, token->op == OP_NOMATCH); + } + + delete_trailing_chars(result, "\n"); + udev_replace_chars_and_log(event, token, result, UDEV_ALLOWED_CHARS_INPUT, "command output"); + + event->program_result = strdup(result); +- return token->op == OP_MATCH; ++ return log_event_result(event, token, token->op == OP_MATCH); + } + case TK_M_IMPORT_FILE: { + _cleanup_fclose_ FILE *f = NULL; +@@ -2319,13 +2327,13 @@ static int udev_rule_apply_token_to_event( + if (!apply_format_value(event, token, buf, sizeof(buf), "file name to be imported")) + return false; + +- log_event_debug(event, token, "Importing properties from '%s'", buf); ++ log_event_debug(event, token, "Importing properties from \"%s\"", buf); + + f = fopen(buf, "re"); + if (!f) { + if (errno != ENOENT) +- return log_event_error_errno(event, token, errno, "Failed to open '%s': %m", buf); +- return token->op == OP_NOMATCH; ++ return log_event_error_errno(event, token, errno, "Failed to open \"%s\": %m", buf); ++ return log_event_result(event, token, token->op == OP_NOMATCH); + } + + for (;;) { +@@ -2334,16 +2342,16 @@ static int udev_rule_apply_token_to_event( + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) { +- log_event_debug_errno(event, token, r, "Failed to read '%s', ignoring: %m", buf); +- return token->op == OP_NOMATCH; ++ log_event_debug_errno(event, token, r, "Failed to read \"%s\", ignoring: %m", buf); ++ return log_event_result(event, token, token->op == OP_NOMATCH); + } + if (r == 0) +- break; ++ return log_event_result(event, token, token->op == OP_MATCH); + + r = get_property_from_string(line, &key, &value); + if (r < 0) { + log_event_debug_errno(event, token, r, +- "Failed to parse key and value from '%s', ignoring: %m", ++ "Failed to parse key and value from \"%s\", ignoring: %m", + line); + continue; + } +@@ -2355,9 +2363,10 @@ static int udev_rule_apply_token_to_event( + return log_event_error_errno(event, token, r, + "Failed to add property %s=%s: %m", + key, value); ++ log_event_trace(event, token, "Imported property \"%s=%s\".", key, value); + } + +- return token->op == OP_MATCH; ++ assert_not_reached(); + } + case TK_M_IMPORT_PROGRAM: { + _cleanup_strv_free_ char **lines = NULL; +@@ -2367,15 +2376,15 @@ static int udev_rule_apply_token_to_event( + if (!apply_format_value(event, token, buf, sizeof(buf), "command")) + return false; + +- log_event_debug(event, token, "Importing properties from results of '%s'", buf); ++ log_event_debug(event, token, "Importing properties from results of \"%s\"", buf); + + r = udev_event_spawn(event, /* accept_failure = */ true, buf, result, sizeof result, &truncated); + if (r != 0) { + if (r < 0) +- log_event_warning_errno(event, token, r, "Failed to execute '%s', ignoring: %m", buf); ++ log_event_warning_errno(event, token, r, "Failed to execute \"%s\", ignoring: %m", buf); + else /* returned value is positive when program fails */ + log_event_debug(event, token, "Command \"%s\" returned %d (error), ignoring", buf, r); +- return token->op == OP_NOMATCH; ++ return log_event_result(event, token, token->op == OP_NOMATCH); + } + + if (truncated) { +@@ -2399,7 +2408,7 @@ static int udev_rule_apply_token_to_event( + if (r < 0) { + log_event_warning_errno(event, token, r, + "Failed to extract lines from result of command \"%s\", ignoring: %m", buf); +- return false; ++ return log_event_result(event, token, false); + } + + STRV_FOREACH(line, lines) { +@@ -2408,7 +2417,7 @@ static int udev_rule_apply_token_to_event( + r = get_property_from_string(*line, &key, &value); + if (r < 0) { + log_event_debug_errno(event, token, r, +- "Failed to parse key and value from '%s', ignoring: %m", ++ "Failed to parse key and value from \"%s\", ignoring: %m", + *line); + continue; + } +@@ -2420,9 +2429,10 @@ static int udev_rule_apply_token_to_event( + return log_event_error_errno(event, token, r, + "Failed to add property %s=%s: %m", + key, value); ++ log_event_trace(event, token, "Imported property \"%s=%s\".", key, value); + } + +- return token->op == OP_MATCH; ++ return log_event_result(event, token, token->op == OP_MATCH); + } + case TK_M_IMPORT_BUILTIN: { + UdevBuiltinCommand cmd = PTR_TO_UDEV_BUILTIN_CMD(token->data); +@@ -2433,10 +2443,10 @@ static int udev_rule_apply_token_to_event( + if (udev_builtin_run_once(cmd)) { + /* check if we ran already */ + if (event->builtin_run & mask) { +- log_event_debug(event, token, "Skipping builtin '%s' in IMPORT key", ++ log_event_debug(event, token, "Builtin command \"%s\" has already run, skipping.", + udev_builtin_name(cmd)); + /* return the result from earlier run */ +- return token->op == (event->builtin_ret & mask ? OP_NOMATCH : OP_MATCH); ++ return log_event_result(event, token, token->op == (event->builtin_ret & mask ? OP_NOMATCH : OP_MATCH)); + } + /* mark as ran */ + event->builtin_run |= mask; +@@ -2445,34 +2455,36 @@ static int udev_rule_apply_token_to_event( + if (!apply_format_value(event, token, buf, sizeof(buf), "builtin command")) + return false; + +- log_event_debug(event, token, "Importing properties from results of builtin command '%s'", buf); ++ log_event_debug(event, token, "Importing properties from results of builtin command \"%s\".", buf); + + r = udev_builtin_run(event, cmd, buf); + if (r < 0) { + /* remember failure */ +- log_event_debug_errno(event, token, r, "Failed to run builtin '%s': %m", buf); ++ log_event_debug_errno(event, token, r, "Failed to run builtin \"%s\": %m", buf); + event->builtin_ret |= mask; + } +- return token->op == (r >= 0 ? OP_MATCH : OP_NOMATCH); ++ return log_event_result(event, token, token->op == (r >= 0 ? OP_MATCH : OP_NOMATCH)); + } + case TK_M_IMPORT_DB: { + const char *val; + + if (!event->dev_db_clone) +- return token->op == OP_NOMATCH; ++ return log_event_result(event, token, token->op == OP_NOMATCH); + r = sd_device_get_property_value(event->dev_db_clone, token->value, &val); + if (r == -ENOENT) +- return token->op == OP_NOMATCH; ++ return log_event_result(event, token, token->op == OP_NOMATCH); + if (r < 0) + return log_event_error_errno(event, token, r, +- "Failed to get property '%s' from database: %m", ++ "Failed to get property \"%s\" from database: %m", + token->value); + + r = device_add_property(dev, token->value, val); + if (r < 0) +- return log_event_error_errno(event, token, r, "Failed to add property '%s=%s': %m", ++ return log_event_error_errno(event, token, r, "Failed to add property \"%s=%s\": %m", + token->value, val); +- return token->op == OP_MATCH; ++ log_event_trace(event, token, "Imported property \"%s=%s\".", token->value, val); ++ ++ return log_event_result(event, token, token->op == OP_MATCH); + } + case TK_M_IMPORT_CMDLINE: { + _cleanup_free_ char *value = NULL; +@@ -2480,16 +2492,19 @@ static int udev_rule_apply_token_to_event( + r = proc_cmdline_get_key(token->value, PROC_CMDLINE_VALUE_OPTIONAL|PROC_CMDLINE_IGNORE_EFI_OPTIONS, &value); + if (r < 0) + return log_event_error_errno(event, token, r, +- "Failed to read '%s' option from /proc/cmdline: %m", ++ "Failed to read \"%s\" option from /proc/cmdline: %m", + token->value); + if (r == 0) +- return token->op == OP_NOMATCH; ++ return log_event_result(event, token, token->op == OP_NOMATCH); + +- r = device_add_property(dev, token->value, value ?: "1"); ++ const char *val = value ?: "1"; ++ r = device_add_property(dev, token->value, val); + if (r < 0) +- return log_event_error_errno(event, token, r, "Failed to add property '%s=%s': %m", +- token->value, value ?: "1"); +- return token->op == OP_MATCH; ++ return log_event_error_errno(event, token, r, "Failed to add property \"%s=%s\": %m", ++ token->value, val); ++ log_event_trace(event, token, "Imported property \"%s=%s\".", token->value, val); ++ ++ return log_event_result(event, token, token->op == OP_MATCH); + } + case TK_M_IMPORT_PARENT: { + char buf[UDEV_PATH_SIZE]; +@@ -2497,35 +2512,56 @@ static int udev_rule_apply_token_to_event( + if (!apply_format_value(event, token, buf, sizeof(buf), "property name")) + return false; + +- r = import_parent_into_properties(dev, buf); ++ sd_device *parent; ++ r = sd_device_get_parent(dev, &parent); ++ if (ERRNO_IS_NEG_DEVICE_ABSENT(r)) ++ return log_event_result(event, token, token->op == OP_NOMATCH); + if (r < 0) +- return log_event_error_errno(event, token, r, +- "Failed to import properties '%s' from parent: %m", +- buf); +- return token->op == (r > 0 ? OP_MATCH : OP_NOMATCH); ++ return log_event_error_errno(event, token, r, "Failed to get parent device: %m"); ++ ++ bool have = false; ++ FOREACH_DEVICE_PROPERTY(parent, key, val) { ++ if (fnmatch(buf, key, 0) != 0) ++ continue; ++ ++ r = device_add_property(dev, key, val); ++ if (r < 0) ++ return log_event_error_errno(event, token, r, "Failed to add property \"%s=%s\": %m", key, val); ++ log_event_trace(event, token, "Imported property \"%s=%s\".", key, val); ++ have = true; ++ } ++ ++ return log_event_result(event, token, token->op == (have ? OP_MATCH : OP_NOMATCH)); + } + case TK_M_RESULT: + return token_match_string(event, token, event->program_result, /* log_result = */ true); ++ + case TK_A_OPTIONS_STRING_ESCAPE_NONE: + event->esc = ESCAPE_NONE; +- break; ++ return log_event_done(event, token); ++ + case TK_A_OPTIONS_STRING_ESCAPE_REPLACE: + event->esc = ESCAPE_REPLACE; +- break; ++ return log_event_done(event, token); ++ + case TK_A_OPTIONS_DB_PERSIST: + device_set_db_persist(dev); +- break; ++ return log_event_done(event, token); ++ + case TK_A_OPTIONS_INOTIFY_WATCH: + if (event->inotify_watch_final) +- break; ++ return log_event_final_set(event, token); ++ + if (token->op == OP_ASSIGN_FINAL) + event->inotify_watch_final = true; + + event->inotify_watch = token->data; +- break; ++ return log_event_done(event, token); ++ + case TK_A_OPTIONS_DEVLINK_PRIORITY: + device_set_devlink_priority(dev, PTR_TO_INT(token->data)); +- break; ++ return log_event_done(event, token); ++ + case TK_A_OPTIONS_LOG_LEVEL: { + int level = PTR_TO_INT(token->data); + +@@ -2547,14 +2583,15 @@ static int udev_rule_apply_token_to_event( + event->log_level_was_debug = true; + } + +- break; ++ return log_event_done(event, token); + } + case TK_A_OWNER: { + char owner[UDEV_NAME_SIZE]; + const char *ow = owner; + + if (event->owner_final) +- break; ++ return log_event_final_set(event, token); ++ + if (token->op == OP_ASSIGN_FINAL) + event->owner_final = true; + +@@ -2562,18 +2599,21 @@ static int udev_rule_apply_token_to_event( + return true; + + r = get_user_creds(&ow, &event->uid, NULL, NULL, NULL, USER_CREDS_ALLOW_MISSING); +- if (r < 0) +- log_unknown_owner(dev, token->rule_line, r, "user", owner); ++ if (IN_SET(r, -ENOENT, -ESRCH)) ++ log_event_error_errno(event, token, r, "Unknown user \"%s\", ignoring.", owner); ++ else if (r < 0) ++ log_event_error_errno(event, token, r, "Failed to resolve user \"%s\", ignoring: %m", owner); + else +- log_event_debug(event, token, "OWNER %s(%u)", owner, event->uid); +- break; ++ log_event_debug(event, token, "Set owner: %s(%u)", owner, event->uid); ++ return true; + } + case TK_A_GROUP: { + char group[UDEV_NAME_SIZE]; + const char *gr = group; + + if (event->group_final) +- break; ++ return log_event_final_set(event, token); ++ + if (token->op == OP_ASSIGN_FINAL) + event->group_final = true; + +@@ -2581,17 +2621,20 @@ static int udev_rule_apply_token_to_event( + return true; + + r = get_group_creds(&gr, &event->gid, USER_CREDS_ALLOW_MISSING); +- if (r < 0) +- log_unknown_owner(dev, token->rule_line, r, "group", group); ++ if (IN_SET(r, -ENOENT, -ESRCH)) ++ log_event_error_errno(event, token, r, "Unknown group \"%s\", ignoring.", group); ++ else if (r < 0) ++ log_event_error_errno(event, token, r, "Failed to resolve group \"%s\", ignoring: %m", group); + else +- log_event_debug(event, token, "GROUP %s(%u)", group, event->gid); +- break; ++ log_event_debug(event, token, "Set group: %s(%u)", group, event->gid); ++ return true; + } + case TK_A_MODE: { + char mode_str[UDEV_NAME_SIZE]; + + if (event->mode_final) +- break; ++ return log_event_final_set(event, token); ++ + if (token->op == OP_ASSIGN_FINAL) + event->mode_final = true; + +@@ -2600,41 +2643,44 @@ static int udev_rule_apply_token_to_event( + + r = parse_mode(mode_str, &event->mode); + if (r < 0) +- log_event_error_errno(event, token, r, "Failed to parse mode '%s', ignoring: %m", mode_str); ++ log_event_error_errno(event, token, r, "Failed to parse mode \"%s\", ignoring: %m", mode_str); + else +- log_event_debug(event, token, "MODE %#o", event->mode); +- break; ++ log_event_debug(event, token, "Set mode: %#o", event->mode); ++ return true; + } + case TK_A_OWNER_ID: + if (event->owner_final) +- break; ++ return log_event_final_set(event, token); ++ + if (token->op == OP_ASSIGN_FINAL) + event->owner_final = true; +- if (!token->data) +- break; +- event->uid = PTR_TO_UID(token->data); +- log_event_debug(event, token, "OWNER %u", event->uid); +- break; ++ ++ event->uid = PTR_TO_UID(ASSERT_PTR(token->data)); ++ log_event_debug(event, token, "Set owner ID: %u", event->uid); ++ return true; ++ + case TK_A_GROUP_ID: + if (event->group_final) +- break; ++ return log_event_final_set(event, token); ++ + if (token->op == OP_ASSIGN_FINAL) + event->group_final = true; +- if (!token->data) +- break; +- event->gid = PTR_TO_GID(token->data); +- log_event_debug(event, token, "GROUP %u", event->gid); +- break; ++ ++ event->gid = PTR_TO_GID(ASSERT_PTR(token->data)); ++ log_event_debug(event, token, "Set group ID: %u", event->gid); ++ return true; ++ + case TK_A_MODE_ID: + if (event->mode_final) +- break; ++ return log_event_final_set(event, token); ++ + if (token->op == OP_ASSIGN_FINAL) + event->mode_final = true; +- if (!token->data) +- break; +- event->mode = PTR_TO_MODE(token->data); +- log_event_debug(event, token, "MODE %#o", event->mode); +- break; ++ ++ event->mode = PTR_TO_MODE(ASSERT_PTR(token->data)); ++ log_event_debug(event, token, "Set mode: %#o", event->mode); ++ return true; ++ + case TK_A_SECLABEL: { + _cleanup_free_ char *name = NULL, *label = NULL; + char label_str[UDEV_LINE_SIZE] = {}; +@@ -2660,13 +2706,13 @@ static int udev_rule_apply_token_to_event( + if (r == -ENOMEM) + return log_oom(); + if (r < 0) +- return log_event_error_errno(event, token, r, "Failed to store SECLABEL{%s}='%s': %m", name, label); ++ return log_event_error_errno(event, token, r, "Failed to store security label \"%s=%s\": %m", name, label); + +- log_event_debug(event, token, "SECLABEL{%s}='%s'", name, label); ++ log_event_debug(event, token, "Set security label: %s=%s", name, label); + + TAKE_PTR(name); + TAKE_PTR(label); +- break; ++ return true; + } + case TK_A_ENV: { + const char *val, *name = token->data; +@@ -2675,11 +2721,13 @@ static int udev_rule_apply_token_to_event( + + if (isempty(token->value)) { + if (token->op == OP_ADD) +- break; ++ return log_event_done(event, token); ++ + r = device_add_property(dev, name, NULL); + if (r < 0) +- return log_event_error_errno(event, token, r, "Failed to remove property '%s': %m", name); +- break; ++ return log_event_error_errno(event, token, r, "Failed to remove property \"%s\": %m", name); ++ log_event_trace(event, token, "Removed property \"%s\".", name); ++ return true; + } + + if (token->op == OP_ADD && +@@ -2688,9 +2736,9 @@ static int udev_rule_apply_token_to_event( + l = strpcpyl_full(&p, l, &truncated, val, " ", NULL); + if (truncated) { + log_event_warning(event, token, +- "The buffer for the property '%s' is full, " +- "refusing to append the new value '%s'.", name, token->value); +- break; ++ "The buffer for the property is full, refusing to append new property \"%s=%s\".", ++ name, token->value); ++ return true; + } + } + +@@ -2702,8 +2750,9 @@ static int udev_rule_apply_token_to_event( + + r = device_add_property(dev, name, value_new); + if (r < 0) +- return log_event_error_errno(event, token, r, "Failed to add property '%s=%s': %m", name, value_new); +- break; ++ return log_event_error_errno(event, token, r, "Failed to set property \"%s=%s\": %m", name, value_new); ++ log_event_trace(event, token, "Set property \"%s=%s\".", name, value_new); ++ return true; + } + case TK_A_TAG: { + char buf[UDEV_PATH_SIZE]; +@@ -2711,33 +2760,39 @@ static int udev_rule_apply_token_to_event( + if (!apply_format_value(event, token, buf, sizeof(buf), "tag name")) + return true; + ++ if (token->op == OP_REMOVE) { ++ device_remove_tag(dev, buf); ++ log_event_trace(event, token, "Removed tag \"%s\".", buf); ++ return true; ++ } ++ ++ assert(IN_SET(token->op, OP_ASSIGN, OP_ADD)); ++ + if (token->op == OP_ASSIGN) + device_cleanup_tags(dev); + +- if (token->op == OP_REMOVE) +- device_remove_tag(dev, buf); +- else { +- r = device_add_tag(dev, buf, true); +- if (r == -ENOMEM) +- return log_oom(); +- if (r < 0) +- log_event_warning_errno(event, token, r, "Failed to add tag '%s', ignoring: %m", buf); +- } +- break; ++ r = device_add_tag(dev, buf, /* both = */ true); ++ if (r == -ENOMEM) ++ return log_oom(); ++ if (r < 0) ++ log_event_warning_errno(event, token, r, "Failed to %s tag \"%s\", ignoring: %m", ++ token->op == OP_ASSIGN ? "set" : "add", buf); ++ else ++ log_event_trace(event, token, "%s tag \"%s\".", token->op == OP_ASSIGN ? "Set" : "Added", buf); ++ return true; + } + case TK_A_NAME: { + char buf[UDEV_PATH_SIZE]; + + if (event->name_final) +- break; ++ return log_event_final_set(event, token); ++ + if (token->op == OP_ASSIGN_FINAL) + event->name_final = true; + + if (sd_device_get_ifindex(dev, NULL) < 0) { +- log_event_error(event, token, +- "Only network interfaces can be renamed, ignoring NAME=\"%s\".", +- token->value); +- break; ++ log_event_warning(event, token, "Only network interfaces can be renamed, ignoring."); ++ return true; + } + + if (!apply_format_value(event, token, buf, sizeof(buf), "network interface name")) +@@ -2750,18 +2805,23 @@ static int udev_rule_apply_token_to_event( + if (r < 0) + return r; + +- log_event_debug(event, token, "NAME '%s'", event->name); +- break; ++ log_event_debug(event, token, "Set network interface name: %s", event->name); ++ return true; + } + case TK_A_DEVLINK: { + char buf[UDEV_PATH_SIZE]; + + if (event->devlink_final) +- break; +- if (sd_device_get_devnum(dev, NULL) < 0) +- break; ++ return log_event_final_set(event, token); ++ ++ if (sd_device_get_devnum(dev, NULL) < 0) { ++ log_event_debug(event, token, "Device does not have device node, ignoring to manage device node symlink."); ++ return true; ++ } ++ + if (token->op == OP_ASSIGN_FINAL) + event->devlink_final = true; ++ + if (IN_SET(token->op, OP_ASSIGN, OP_ASSIGN_FINAL)) + device_cleanup_devlinks(dev); + +@@ -2783,31 +2843,31 @@ static int udev_rule_apply_token_to_event( + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { +- log_warning_errno(r, "Failed to extract first path in SYMLINK=, ignoring: %m"); +- break; ++ log_warning_errno(r, "Failed to extract first path in device node symlinks, ignoring: %m"); ++ return true; + } + if (r == 0) +- break; ++ return true; + + if (token->op == OP_REMOVE) { + r = device_remove_devlink(dev, path); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) +- log_event_warning_errno(event, token, r, "Failed to remove devlink '%s', ignoring: %m", path); ++ log_event_warning_errno(event, token, r, "Failed to remove device node symlink \"%s\", ignoring: %m", path); + else if (r > 0) +- log_event_debug(event, token, "Dropped SYMLINK '%s'", path); ++ log_event_debug(event, token, "Removed device node symlink \"%s\"", path); + } else { + r = device_add_devlink(dev, path); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) +- log_event_warning_errno(event, token, r, "Failed to add devlink '%s', ignoring: %m", path); ++ log_event_warning_errno(event, token, r, "Failed to add device node symlink \"%s\", ignoring: %m", path); + else if (r > 0) +- log_event_debug(event, token, "Added SYMLINK '%s'", path); ++ log_event_debug(event, token, "Added device node symlink \"%s\".", path); + } + } +- break; ++ assert_not_reached(); + } + case TK_A_ATTR: { + char buf[UDEV_PATH_SIZE], value[UDEV_NAME_SIZE]; +@@ -2819,34 +2879,36 @@ static int udev_rule_apply_token_to_event( + strscpyl_full(buf, sizeof(buf), &truncated, val, "/", key_name, NULL); + if (truncated) { + log_event_warning(event, token, +- "The path to the attribute '%s/%s' is too long, refusing to set the attribute.", ++ "The path to the attribute \"%s/%s\" is too long, refusing to set the attribute.", + val, key_name); +- break; ++ return true; + } + } + + r = attr_subst_subdir(buf); + if (r < 0) { +- log_event_error_errno(event, token, r, "Could not find file matches '%s', ignoring: %m", buf); +- break; ++ log_event_error_errno(event, token, r, "Could not find file matches \"%s\", ignoring: %m", buf); ++ return true; + } + + if (!apply_format_value(event, token, value, sizeof(value), "attribute value")) + return true; + + if (EVENT_MODE_DESTRUCTIVE(event)) { +- log_event_debug(event, token, "Writing ATTR{'%s'}=\"%s\".", buf, value); ++ log_event_debug(event, token, "Writing \"%s\" to sysfs attribute \"%s\".", value, buf); + r = write_string_file(buf, value, + WRITE_STRING_FILE_VERIFY_ON_FAILURE | + WRITE_STRING_FILE_DISABLE_BUFFER | + WRITE_STRING_FILE_AVOID_NEWLINE | + WRITE_STRING_FILE_VERIFY_IGNORE_NEWLINE); + if (r < 0) +- log_event_error_errno(event, token, r, "Failed to write ATTR{%s}=\"%s\", ignoring: %m", buf, value); ++ log_event_error_errno(event, token, r, "Failed to write \"%s\" to sysfs attribute \"%s\", ignoring: %m", value, buf); ++ else ++ log_event_done(event, token); + } else +- log_event_debug(event, token, "Running in test mode, skipping writing ATTR{%s}=\"%s\".", buf, value); ++ log_event_debug(event, token, "Running in test mode, skipping writing \"%s\" to sysfs attribute \"%s\".", value, buf); + +- break; ++ return true; + } + case TK_A_SYSCTL: { + char buf[UDEV_PATH_SIZE], value[UDEV_NAME_SIZE]; +@@ -2860,14 +2922,16 @@ static int udev_rule_apply_token_to_event( + sysctl_normalize(buf); + + if (EVENT_MODE_DESTRUCTIVE(event)) { +- log_event_debug(event, token, "Writing SYSCTL{%s}=\"%s\".", buf, value); ++ log_event_debug(event, token, "Writing \"%s\" to sysctl entry \"%s\".", value, buf); + r = sysctl_write(buf, value); + if (r < 0) +- log_event_error_errno(event, token, r, "Failed to write SYSCTL{%s}=\"%s\", ignoring: %m", buf, value); ++ log_event_error_errno(event, token, r, "Failed to write \"%s\" to sysctl entry \"%s\", ignoring: %m", value, buf); ++ else ++ log_event_done(event, token); + } else +- log_event_debug(event, token, "Running in test mode, skipping writing SYSCTL{%s}=\"%s\".", buf, value); ++ log_event_debug(event, token, "Running in test mode, skipping writing \"%s\" to sysctl entry \"%s\".", value, buf); + +- break; ++ return true; + } + case TK_A_RUN_BUILTIN: + case TK_A_RUN_PROGRAM: { +@@ -2875,7 +2939,8 @@ static int udev_rule_apply_token_to_event( + char buf[UDEV_LINE_SIZE]; + + if (event->run_final) +- break; ++ return log_event_final_set(event, token); ++ + if (token->op == OP_ASSIGN_FINAL) + event->run_final = true; + +@@ -2890,24 +2955,22 @@ static int udev_rule_apply_token_to_event( + return log_oom(); + + r = ordered_hashmap_ensure_put(&event->run_list, NULL, cmd, token->data); +- if (r == -ENOMEM) +- return log_oom(); + if (r < 0) +- return log_event_error_errno(event, token, r, "Failed to store command '%s': %m", cmd); ++ return log_event_error_errno(event, token, r, "Failed to store command \"%s\": %m", cmd); + ++ log_event_debug(event, token, "Set command: %s", cmd); + TAKE_PTR(cmd); +- +- log_event_debug(event, token, "RUN '%s'", token->value); +- break; ++ return true; + } + case TK_A_OPTIONS_STATIC_NODE: + /* do nothing for events. */ +- break; ++ return true; ++ + default: + assert_not_reached(); + } + +- return true; ++ assert_not_reached(); + } + + static int udev_rule_apply_parent_token_to_event(UdevRuleToken *head_token, UdevEvent *event) { diff --git a/0172-udev-rules-add-trace-logs-for-GOTO-and-parent-condit.patch b/0172-udev-rules-add-trace-logs-for-GOTO-and-parent-condit.patch new file mode 100644 index 0000000..5a63580 --- /dev/null +++ b/0172-udev-rules-add-trace-logs-for-GOTO-and-parent-condit.patch @@ -0,0 +1,103 @@ +From 7f14a15e480fd4392bc86f7927c9b14dfe833d83 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Mon, 13 Jan 2025 05:18:25 +0900 +Subject: [PATCH] udev-rules: add trace logs for GOTO and parent conditions + +(cherry picked from commit c547b9e278b86cd2318cb69319aaadad9004d96a) + +Resolves: RHEL-75774 +--- + src/udev/udev-rules.c | 48 ++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 43 insertions(+), 5 deletions(-) + +diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c +index c5fa2c660c..4f2021b8c4 100644 +--- a/src/udev/udev-rules.c ++++ b/src/udev/udev-rules.c +@@ -345,6 +345,20 @@ static bool token_is_for_parents(UdevRuleToken *token) { + #define log_event_truncated(event, token, what, format) \ + _log_event_truncated(event, token, UNIQ_T(t, UNIQ), what, format) + ++#define _log_event_line(event, event_u, line, ...) \ ++ ({ \ ++ UdevEvent *event_u = ASSERT_PTR(event); \ ++ \ ++ event_u->trace ? \ ++ log_udev_rule_line_full( \ ++ event_u->dev, line, \ ++ LOG_DEBUG, 0, __VA_ARGS__) : \ ++ 0; \ ++ }) ++ ++#define log_event_line(event, line, ...) \ ++ _log_event_line(event, UNIQ_T(e, UNIQ), line, __VA_ARGS__) ++ + /* Mainly used when parsing .rules files. */ + #define log_file_full_errno_zerook(...) \ + log_udev_rule_file_full(NULL, __VA_ARGS__) +@@ -2977,14 +2991,30 @@ static int udev_rule_apply_parent_token_to_event(UdevRuleToken *head_token, Udev + int r; + + assert(head_token); ++ assert(token_is_for_parents(head_token)); + assert(event); + ++ UdevRuleLine *line = head_token->rule_line; ++ if (event->trace) { ++ _cleanup_free_ char *joined = NULL; ++ ++ LIST_FOREACH(tokens, token, head_token) ++ if (token_is_for_parents(token)) ++ (void) strextend_with_separator(&joined, ", ", token->token_str); ++ else ++ break; ++ ++ log_event_line(event, line, "Checking conditions for parent devices: %s", strna(joined)); ++ } ++ + event->dev_parent = ASSERT_PTR(event->dev); + + for (;;) { + LIST_FOREACH(tokens, token, head_token) { +- if (!token_is_for_parents(token)) +- return true; /* All parent tokens match. */ ++ if (!token_is_for_parents(token)) { ++ r = 1; /* avoid false maybe-uninitialized warning */ ++ break; /* All parent tokens match. */ ++ } + + r = udev_rule_apply_token_to_event(token, event->dev_parent, event); + if (r < 0) +@@ -2992,12 +3022,18 @@ static int udev_rule_apply_parent_token_to_event(UdevRuleToken *head_token, Udev + if (r == 0) + break; + } +- if (r > 0) +- /* All parent tokens match, and no more token (except for GOTO) in the line. */ ++ if (r > 0) { ++ if (event->trace) { ++ const char *s = NULL; ++ (void) sd_device_get_syspath(event->dev_parent, &s); ++ log_event_line(event, line, "Parent device \"%s\" passed all parent conditions.", strna(s)); ++ } + return true; ++ } + + if (sd_device_get_parent(event->dev_parent, &event->dev_parent) < 0) { + event->dev_parent = NULL; ++ log_event_line(event, line, "No parent device passed parent conditions."); + return false; + } + } +@@ -3054,8 +3090,10 @@ static int udev_rule_apply_line_to_event( + return r; + } + +- if (line->goto_line) ++ if (line->goto_line) { ++ log_event_line(event, line, "GOTO=%s", strna(line->goto_label)); + *next_line = line->goto_line; /* update next_line only when the line has GOTO token. */ ++ } + + return 0; + } diff --git a/systemd.spec b/systemd.spec index 1ed02b7..c3585ef 100644 --- a/systemd.spec +++ b/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: 3%{?dist} +Release: 4%{?dist} %global stable %(c="%version"; [ "$c" = "${c#*.*}" ]; echo $?) @@ -252,6 +252,35 @@ Patch0140: 0140-netif-naming-scheme-rename-rhel-10.0-to-rhel-10.0.be.patch Patch0141: 0141-net-naming-scheme-disable-NAMING_FIRMWARE_NODE_SUN.patch Patch0142: 0142-netif-naming-scheme-introduce-rhel-10.0-scheme.patch Patch0143: 0143-udev-net_id-introduce-naming-scheme-for-RHEL-9.6.patch +Patch0144: 0144-ci-use-ubuntu-22-04-for-deploy-of-man-pages.patch +Patch0145: 0145-tree-wide-Fix-python-formatting.patch +Patch0146: 0146-ci-fix-Packit.patch +Patch0147: 0147-ci-drop-testing-farm-test.patch +Patch0148: 0148-dbus-stash-the-subscriber-list-when-we-disconenct-fr.patch +Patch0149: 0149-manager-s-deserialized_subscribed-subscribed_as_strv.patch +Patch0150: 0150-shared-bus-util-move-bus_message_read_id128-to-bus-m.patch +Patch0151: 0151-shared-bus-util-move-bus_message_hash_ops-to-bus-mes.patch +Patch0152: 0152-shared-bus-util-move-string-set-append-get-funcs-to-.patch +Patch0153: 0153-shared-serialize-make-input-params-const.patch +Patch0154: 0154-shared-serialize-introduce-serialize_id128.patch +Patch0155: 0155-bus-util-do-not-reset-the-count-returned-by-sd_bus_t.patch +Patch0156: 0156-core-manager-use-FOREACH_ARRAY-at-one-more-place.patch +Patch0157: 0157-core-manager-drop-duplicate-bus-track-deserializatio.patch +Patch0158: 0158-bus-util-introduce-bus_get_instance_id.patch +Patch0159: 0159-core-serialize-API-bus-id-and-validate-before-deseri.patch +Patch0160: 0160-core-manager-restore-bus-track-deserialization-clean.patch +Patch0161: 0161-shared-bus-util-add-missing-set.h-include.patch +Patch0162: 0162-udevadm-test-add-missing-oom-check.patch +Patch0163: 0163-udev-rules-replace-type-func-type-func.patch +Patch0164: 0164-udev-rules-do-not-change-maximum-log-level-when-runn.patch +Patch0165: 0165-udevadm-test-introduce-v-verbose-option-to-show-verb.patch +Patch0166: 0166-udev-rules-show-original-token-string-in-log_event_e.patch +Patch0167: 0167-udev-rules-logs-result-of-format-substitution.patch +Patch0168: 0168-udev-rules-add-more-trace-logs-for-string-match.patch +Patch0169: 0169-udev-rules-introduce-udev_replace_chars_and_log.patch +Patch0170: 0170-udev-rules-ignore-whole-command-result-if-it-is-too-.patch +Patch0171: 0171-udev-rules-update-log-messages.patch +Patch0172: 0172-udev-rules-add-trace-logs-for-GOTO-and-parent-condit.patch # Downstream-only patches (9000–9999) @@ -1182,6 +1211,37 @@ rm -f .file-list-* rm -f %{name}.lang %changelog +* Thu Jan 30 2025 systemd maintenance team - 257-4 +- ci: use ubuntu 22:04 for deploy of man pages (RHEL-57603) +- tree-wide: Fix python formatting (RHEL-57603) +- ci: fix Packit (RHEL-57603) +- ci: drop testing farm test (RHEL-57603) +- dbus: stash the subscriber list when we disconenct from the bus (RHEL-73780) +- manager: s/deserialized_subscribed/subscribed_as_strv (RHEL-73780) +- shared/bus-util: move bus_message_read_id128() to bus-message-util (RHEL-73780) +- shared/bus-util: move bus_message_hash_ops to bus-message-util (RHEL-73780) +- shared/bus-util: move string set append/get funcs to bus-message-util and bus-get-properties, respectively (RHEL-73780) +- shared/serialize: make input params const (RHEL-73780) +- shared/serialize: introduce serialize_id128() (RHEL-73780) +- bus-util: do not reset the count returned by sd_bus_track_count_name() (RHEL-73780) +- core/manager: use FOREACH_ARRAY at one more place (RHEL-73780) +- core/manager: drop duplicate bus track deserialization (RHEL-73780) +- bus-util: introduce bus_get_instance_id() (RHEL-73780) +- core: serialize API bus id and validate before deserializing bus tracks (RHEL-73780) +- core/manager: restore bus track deserialization cleanup in manager_reload() (RHEL-73780) +- shared/bus-util: add missing `set.h` include (RHEL-73780) +- udevadm-test: add missing oom check (RHEL-75774) +- udev-rules: replace 'type *func()' -> 'type* func()' (RHEL-75774) +- udev-rules: do not change maximum log level when running in test mode (RHEL-75774) +- udevadm-test: introduce -v/--verbose option to show verbose log messages (RHEL-75774) +- udev-rules: show original token string in log_event_error() and friends (RHEL-75774) +- udev-rules: logs result of format substitution (RHEL-75774) +- udev-rules: add more trace logs for string match (RHEL-75774) +- udev-rules: introduce udev_replace_chars_and_log() (RHEL-75774) +- udev-rules: ignore whole command result if it is too long and does not contain newline (RHEL-75774) +- udev-rules: update log messages (RHEL-75774) +- udev-rules: add trace logs for GOTO and parent conditions (RHEL-75774) + * Wed Jan 08 2025 Jan Macku - 257-3 - udev/net_id: introduce naming scheme for RHEL-9.6 (RHEL-44417) - Rebase to new upstream stable release v257.2 (RHEL-71409)