diff --git a/files.systemd b/files.systemd index a53901b8..c49c7460 100644 --- a/files.systemd +++ b/files.systemd @@ -465,6 +465,7 @@ %{_systemd_util_dir}/systemd-timedated %{_systemd_util_dir}/systemd-timesyncd %{_systemd_util_dir}/systemd-update-done +%{_systemd_util_dir}/systemd-update-helper %{_systemd_util_dir}/systemd-update-utmp %{_systemd_util_dir}/systemd-user-runtime-dir %{_systemd_util_dir}/systemd-user-sessions diff --git a/fixlet-systemd-post.sh b/fixlet-systemd-post.sh index 185a5167..bfccf634 100644 --- a/fixlet-systemd-post.sh +++ b/fixlet-systemd-post.sh @@ -162,6 +162,10 @@ migrate_sysconfig_i18n() { migrate_keyboard; rv+=$? migrate_language; rv+=$? + if [ $rv -gt 0 ]; then + echo >&2 "Failed to migrate i18n settings from /etc/sysconfig, ignoring." + fi + return $rv } @@ -207,13 +211,58 @@ fix_pre_210() { done } -r=0 -fix_pre_210 || { - r=1 -} -migrate_sysconfig_i18n || { - echo >&2 "Failed to migrate i18n settings from /etc/sysconfig, continuing..." - r=1 +# +# /etc/machine-id might have been created writeable incorrectly (boo#1092269). +# +# Note: run at each package update. +# +fix_machine_id_perms() { + if [ "$(stat -c%a /etc/machine-id)" != 444 ]; then + echo "Incorrect file mode bits for /etc/machine-id which should be 0444, fixing..." + chmod 444 /etc/machine-id + fi } +# +# v228 wrongly set world writable suid root permissions on timestamp files used +# by permanent timers. Fix the timestamps that might have been created by the +# affected versions of systemd (bsc#1020601). +# +# Note: run at each package update. +# +fix_bsc_1020601() { + for stamp in $(ls /var/lib/systemd/timers/stamp-*.timer 2>/dev/null); do + chmod 0644 $stamp + done + + # Same for user lingering created by logind. + for username in $(ls /var/lib/systemd/linger/* 2>/dev/null); do + chmod 0644 $username + done +} + +# +# Due to the fact that DynamicUser= was turned ON during v235 and then switched +# back to off in v240, /var/lib/systemd/timesync might be a symlink pointing to +# /var/lib/private/systemd/timesync, which is inaccessible for systemd-timesync +# user as /var/lib/private is 0700 root:root, see +# https://github.com/systemd/systemd/issues/11329 for details. +# +# Note: only TW might be affected by this bug. +# Note: run at each package update. +# +fix_issue_11329() { + if [ -L %{_localstatedir}/lib/systemd/timesync ]; then + rm %{_localstatedir}/lib/systemd/timesync + mv %{_localstatedir}/lib/private/systemd/timesync %{_localstatedir}/lib/systemd/timesync + fi +} + +r=0 +fix_machine_id_perms || r=1 +fix_pre_210 || r=1 +migrate_sysconfig_i18n || r=1 +fix_bsc_1020601 || r=1 +fix_issue_11329 || r=1 + exit $r diff --git a/systemd-update-helper b/systemd-update-helper new file mode 100644 index 00000000..3cc7909b --- /dev/null +++ b/systemd-update-helper @@ -0,0 +1,163 @@ +#!/usr/bin/env bash +# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# This helper is aimed at being used by the systemd rpm macros only. +# +set -eu +set -o pipefail + +command="${1:?}" +shift + +command -v systemctl >/dev/null || exit 0 + +case "$command" in + mark-install-system-units) + mkdir -p /run/systemd/rpm/needs-preset + + for unit in "$@" ; do + if [ ! -e /usr/lib/systemd/system/"$unit" ]; then + touch /run/systemd/rpm/needs-preset/"$unit" + fi + done + ;; + + install-system-units) + units=() + + for unit in "$@" ; do + if [ -e /run/systemd/rpm/needs-preset/"$unit" ]; then + rm /run/systemd/rpm/needs-preset/"$unit" + units+=("$unit") + fi + done + + [ ${#units[*]} -gt 0 ] && + systemctl --no-reload preset "${units[@]}" + ;; + + mark-install-user-units) + mkdir -p /run/systemd/rpm/needs-user-preset + + for unit in "$@" ; do + if [ ! -e /usr/lib/systemd/user/"$unit" ]; then + touch /run/systemd/rpm/needs-user-preset/"$unit" + fi + done + ;; + + install-user-units) + units=() + + for unit in "$@" ; do + if [ -e /run/systemd/rpm/needs-user-preset/"$unit" ]; then + rm /run/systemd/rpm/needs-user-preset/"$unit" + units+=("$unit") + fi + done + + [ ${#units[*]} -gt 0 ] && + systemctl --no-reload preset --global "$@" || : + ;; + + remove-system-units) + if [ -d /run/systemd/system ]; then + systemctl --no-reload disable --now --no-warn "$@" + else + systemctl --no-reload disable --no-warn "$@" + fi + ;; + + remove-user-units) + systemctl --global disable --no-warn "$@" + + [ -d /run/systemd/system ] || exit 0 + + users=$(systemctl list-units 'user@*' --legend=no | sed -n -r 's/.*user@([0-9]+).service.*/\1/p') + for user in $users; do + SYSTEMD_BUS_TIMEOUT=15s \ + systemctl --user -M "$user@" disable --now --no-warn "$@" & + done + wait + ;; + + mark-restart-system-units) + [ -d /run/systemd/system ] || exit 0 + + for unit in "$@"; do + systemctl set-property "$unit" Markers=+needs-restart & + done + wait + ;; + + mark-restart-user-units) + [ -d /run/systemd/system ] || exit 0 + + users=$(systemctl list-units 'user@*' --legend=no | sed -n -r 's/.*user@([0-9]+).service.*/\1/p') + for user in $users; do + for unit in "$@"; do + SYSTEMD_BUS_TIMEOUT=15s \ + systemctl --user -M "$user@" set-property "$unit" Markers=+needs-restart & + done + done + wait + ;; + + system-reload-restart|system-reload|system-restart) + if [ -n "$*" ]; then + echo >&2 "Unexpected arguments for '$command': $*" + exit 2 + fi + + [ -d /run/systemd/system ] || exit 0 + + if [[ "$command" =~ reload ]]; then + systemctl daemon-reload + fi + + if [[ "$command" =~ restart ]]; then + systemctl reload-or-restart --marked + fi + ;; + + user-reload-restart|user-reload|user-restart|user-reexec) + if [ -n "$*" ]; then + echo >&2 "Unexpected arguments for '$command': $*" + exit 2 + fi + + [ -d /run/systemd/system ] || exit 0 + + users=$(systemctl list-units 'user@*' --legend=no | sed -n -r 's/.*user@([0-9]+).service.*/\1/p') + + if [[ "$command" =~ reexec ]]; then + for user in $users; do + SYSTEMD_BUS_TIMEOUT=15s \ + systemctl --user -M "$user@" daemon-reexec & + done + wait + fi + + if [[ "$command" =~ reload ]]; then + for user in $users; do + SYSTEMD_BUS_TIMEOUT=15s \ + systemctl --user -M "$user@" daemon-reload & + done + wait + fi + + if [[ "$command" =~ restart ]]; then + for user in $users; do + SYSTEMD_BUS_TIMEOUT=15s \ + systemctl --user -M "$user@" reload-or-restart --marked & + done + wait + fi + ;; + + *) + echo >&2 "Unknown verb '$command'" + exit 3 + ;; +esac diff --git a/systemd.changes b/systemd.changes index 7818ebfa..37a133b8 100644 --- a/systemd.changes +++ b/systemd.changes @@ -1,3 +1,45 @@ +------------------------------------------------------------------- +Tue May 9 14:25:04 UTC 2023 - Franck Bui + +- Move more packaging fixups in the fixlet script. + +------------------------------------------------------------------- +Tue May 9 13:59:56 UTC 2023 - Franck Bui + +- Provide (Lua-based) file triggers and adapt systemd.spec accordingly (boo#1133764) + + More specifically, file triggers handle automatically installations or updates + of files for sysusers, tmpfiles, hwdb, journal catalog, udev rules, sysctl and + binfmt. + + Therefore it makes a bunch of systemd rpm macros (such as %udev_hwdb_update, + %udev_rules_update, %journal_catalog_update, %tmpfiles_create, + %sysusers_create and so on) not needed anymore. However before considering + simplifying your spec files beware that these changes are not available in SLE + yet and will probably never reach the current releases (latest one being + SLE15-SP5 as of this writing). + + Macros dealing with unit restart/enabling (such as %systemd_pre, + %service_add_pre, %service_del_postun, ...) are still needed though. However + reloading of systemd instances (and thus restarting of units) are delayed + until the very end of the package install/update transaction and is now done + only once. + + Nevertheless to fully take advantage of file triggers, users have to activate + a specific zypper transaction backend which is still considered as + experimental, see bsc#1041742 for details. + +- Provide a (slighlty) customized version of systemd-update-helper. Some of the + systemd rpm macros rely now on the helper and delegate their work to it. Hence + we don't need to rebuild all packages anymore when the content of the rpm + macros must be updated/fixed. + +------------------------------------------------------------------- +Tue May 9 12:37:31 UTC 2023 - Franck Bui + +- Drop an old fix for the persistent net rules (only needed on SLE). Factory + (fortunately) dropped the persistent net rule generator long time ago. + ------------------------------------------------------------------- Thu May 4 15:20:49 UTC 2023 - Franck Bui diff --git a/systemd.spec b/systemd.spec index 80b5f468..2dc5ad78 100644 --- a/systemd.spec +++ b/systemd.spec @@ -68,7 +68,7 @@ %bcond_without testsuite %endif # Kept to ease migrations toward SLE -%bcond_with filetriggers +%bcond_without filetriggers %bcond_with split_usr Name: systemd%{?mini} @@ -168,11 +168,13 @@ Obsoletes: systemd-analyze < 201 Source0: systemd-v%{version}%{archive_version}.tar.xz Source1: systemd-rpmlintrc Source2: systemd-user +Source3: systemd-update-helper %if %{with sysvcompat} Source4: systemd-sysv-install %endif Source5: tmpfiles-suse.conf Source6: baselibs.conf +Source7: triggers.systemd Source11: after-local.service Source14: kbd-model-map.legacy @@ -758,6 +760,7 @@ rm %{buildroot}%{_sbindir}/resolvconf rm %{buildroot}%{_mandir}/man1/resolvconf.1* %endif +install -m0755 -D %{SOURCE3} %{buildroot}/%{_systemd_util_dir}/systemd-update-helper %if %{with sysvcompat} install -m0755 -D %{SOURCE4} %{buildroot}/%{_systemd_util_dir}/systemd-sysv-install %endif @@ -983,12 +986,6 @@ if [ $1 -eq 1 ]; then chmod 444 %{_sysconfdir}/machine-id fi -# /etc/machine-id might have been created writeable incorrectly (boo#1092269). -if [ "$(stat -c%a %{_sysconfdir}/machine-id)" != 444 ]; then - echo "Incorrect file mode bits for /etc/machine-id which should be 0444, fixing..." - chmod 444 %{_sysconfdir}/machine-id -fi - %if %{without bootstrap} pam-config --add --systemd || : # Run ldconfig for nss-systemd and nss-myhostname NSS modules. @@ -1034,35 +1031,11 @@ if [ $1 -gt 1 ]; then %systemd_post systemd-journald-audit.socket fi -# v228 wrongly set world writable suid root permissions on timestamp files used -# by permanent timers. Fix the timestamps that might have been created by the -# affected versions of systemd (bsc#1020601). -for stamp in $(ls /var/lib/systemd/timers/stamp-*.timer 2>/dev/null); do - chmod 0644 $stamp -done - -# Same for user lingering created by logind. -for username in $(ls /var/lib/systemd/linger/* 2>/dev/null); do - chmod 0644 $username -done - -# Due to the fact that DynamicUser= was turned ON during v235 and then switched -# back to off in v240, /var/lib/systemd/timesync might be a symlink pointing to -# /var/lib/private/systemd/timesync, which is inaccessible for systemd-timesync -# user as /var/lib/private is 0700 root:root, see -# https://github.com/systemd/systemd/issues/11329 for details. Note: only TW -# users might be affected by this bug. -if [ -L %{_localstatedir}/lib/systemd/timesync ]; then - rm %{_localstatedir}/lib/systemd/timesync - mv %{_localstatedir}/lib/private/systemd/timesync %{_localstatedir}/lib/systemd/timesync -fi - # Run the hacks/fixups to clean up old garbages left by (very) old versions of # systemd. %{_systemd_util_dir}/rpm/fixlet-systemd-post.sh $1 || : %postun -# daemon-reload is implied by systemd_postun_with_restart %systemd_postun_with_restart systemd-journald.service %systemd_postun_with_restart systemd-timesyncd.service # Avoid restarting logind until fixed upstream (issue #1163) @@ -1083,23 +1056,13 @@ fi %post -n udev%{?mini} %regenerate_initrd_post +%if %{without filetriggers} %udev_hwdb_update - %tmpfiles_create systemd-pstore.conf - -# Units listed below can be enabled at installation accoding to their preset -# setting. +%endif %systemd_post remote-cryptsetup.target %systemd_post systemd-pstore.service -# add KERNEL name match to existing persistent net rules -sed -ri '/KERNEL/ ! { s/NAME="(eth|wlan|ath)([0-9]+)"/KERNEL=="\1*", NAME="\1\2"/}' \ - /etc/udev/rules.d/70-persistent-net.rules 2>/dev/null || : - -# cleanup old stuff -rm -f /etc/sysconfig/udev -rm -f /etc/udev/rules.d/{20,55,65}-cdrom.rules - %preun -n udev%{?mini} %systemd_preun systemd-udevd.service systemd-udevd-{control,kernel}.socket %systemd_preun systemd-pstore.service @@ -1146,7 +1109,9 @@ rm -f /etc/udev/rules.d/{20,55,65}-cdrom.rules %endif %post container +%if %{without filetriggers} %tmpfiles_create systemd-nspawn.conf +%endif %if %{with machined} %systemd_post machines.target %ldconfig @@ -1194,8 +1159,10 @@ rm -f /etc/udev/rules.d/{20,55,65}-cdrom.rules %post network %if %{with networkd} +%if %{without filetriggers} %sysusers_create systemd-network.conf %tmpfiles_create systemd-network.conf +%endif %systemd_post systemd-networkd.service %systemd_post systemd-networkd-wait-online.service %endif @@ -1230,7 +1197,9 @@ rm -f /etc/udev/rules.d/{20,55,65}-cdrom.rules %systemd_pre systemd-portabled.service %post portable +%if %{without filetriggers} %tmpfiles_create portables.conf +%endif %systemd_post systemd-portabled.service %preun portable @@ -1263,6 +1232,11 @@ rm -f /etc/udev/rules.d/{20,55,65}-cdrom.rules %systemd_postun systemd-userdbd.service systemd-userdbd.socket %endif +# File trigger definitions +%if %{with filetriggers} +%include %{SOURCE7} +%endif + %files %defattr(-,root,root) %include %{SOURCE200} diff --git a/triggers.systemd b/triggers.systemd new file mode 100644 index 00000000..0aeea905 --- /dev/null +++ b/triggers.systemd @@ -0,0 +1,126 @@ +# -*- Mode: rpm-spec; indent-tabs-mode: nil -*- */ +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# This file is part of systemd. +# Copyright © 2018 Neal Gompa + +# The contents of this are an example to be copied into systemd.spec. +# +# Minimum rpm version supported: 4.14.0 + +%transfiletriggerin -P 900900 -p -- /usr/lib/systemd/system /etc/systemd/system +-- This script will run after any package is initially installed or +-- upgraded. We care about the case where a package is initially +-- installed, because other cases are covered by the *un scriptlets, +-- so sometimes we will reload needlessly. +pid = posix.fork() +if pid == 0 then + assert(posix.exec("/usr/lib/systemd/systemd-update-helper", "system-reload-restart")) +elseif pid > 0 then + posix.wait(pid) +end + +%transfiletriggerin -P 900899 -p -- /usr/lib/systemd/user /etc/systemd/user +pid = posix.fork() +if pid == 0 then + assert(posix.exec("/usr/lib/systemd/systemd-update-helper", "user-reload-restart")) +elseif pid > 0 then + posix.wait(pid) +end + +%transfiletriggerpostun -P 1000100 -p -- /usr/lib/systemd/system /etc/systemd/system +-- On removal, we need to run daemon-reload after any units have been +-- removed. +-- On upgrade, we need to run daemon-reload after any new unit files +-- have been installed, but before %postun scripts in packages get +-- executed. +pid = posix.fork() +if pid == 0 then + assert(posix.exec("/usr/lib/systemd/systemd-update-helper", "system-reload")) +elseif pid > 0 then + posix.wait(pid) +end + +%transfiletriggerpostun -P 1000100 -p -- /usr/lib/systemd/system /etc/systemd/system +-- Execute daemon-reload in user managers. +pid = posix.fork() +if pid == 0 then + assert(posix.exec("/usr/lib/systemd/systemd-update-helper", "user-reload")) +elseif pid > 0 then + posix.wait(pid) +end + +%transfiletriggerpostun -P 10000 -p -- /usr/lib/systemd/system /etc/systemd/system +-- We restart remaining system services that should be restarted here. +pid = posix.fork() +if pid == 0 then + assert(posix.exec("/usr/lib/systemd/systemd-update-helper", "system-restart")) +elseif pid > 0 then + posix.wait(pid) +end + +%transfiletriggerpostun -P 9999 -p -- /usr/lib/systemd/user /etc/systemd/user +-- We restart remaining user services that should be restarted here. +pid = posix.fork() +if pid == 0 then + assert(posix.exec("/usr/lib/systemd/systemd-update-helper", "user-restart")) +elseif pid > 0 then + posix.wait(pid) +end + +%transfiletriggerin -P 100700 -p -- /usr/lib/sysusers.d +-- This script will process files installed in /usr/lib/sysusers.d to create +-- specified users automatically. The priority is set such that it +-- will run before the tmpfiles file trigger. +assert(rpm.execute("systemd-sysusers")) + +%if %{without bootstrap} +%transfiletriggerin -P 1000700 -n udev -p -- /usr/lib/udev/hwdb.d +-- This script will automatically invoke hwdb update if files have been +-- installed or updated in /usr/lib/udev/hwdb.d. +assert(rpm.execute("systemd-hwdb", "update")) +%endif + +%transfiletriggerin -P 1000700 -p -- /usr/lib/systemd/catalog +-- This script will automatically invoke journal catalog update if files +-- have been installed or updated in /usr/lib/systemd/catalog. +assert(rpm.execute("journalctl", "--update-catalog")) + +%transfiletriggerin -P 1000700 -p -- /usr/lib/binfmt.d +-- This script will automatically apply binfmt rules if files have been +-- installed or updated in /usr/lib/binfmt.d. +if posix.access("/run/systemd/system") then + pid = posix.fork() + if pid == 0 then + assert(posix.exec("/usr/lib/systemd/systemd-binfmt")) + elseif pid > 0 then + posix.wait(pid) + end +end + +%transfiletriggerin -P 1000600 -p -- /usr/lib/tmpfiles.d +-- This script will process files installed in /usr/lib/tmpfiles.d to create +-- tmpfiles automatically. The priority is set such that it will run +-- after the sysusers file trigger, but before any other triggers. +assert(rpm.execute("systemd-tmpfiles", "--create")) + +%if %{without bootstrap} +%transfiletriggerin -P 1000600 -n udev -p -- /usr/lib/udev/rules.d +-- This script will automatically update udev with new rules if files +-- have been installed or updated in /usr/lib/udev/rules.d. +if posix.access("/run/udev/control") then + assert(rpm.execute("udevadm", "control", "--reload")) +end +%endif + +%transfiletriggerin -P 1000500 -p -- /usr/lib/sysctl.d +-- This script will automatically apply sysctl rules if files have been +-- installed or updated in /usr/lib/sysctl.d. +if posix.access("/run/systemd/system") then + pid = posix.fork() + if pid == 0 then + assert(posix.exec("/usr/lib/systemd/systemd-sysctl")) + elseif pid > 0 then + posix.wait(pid) + end +end