From 4a91fd14e5e27c712f9da831e1fd04c020e3129a Mon Sep 17 00:00:00 2001 From: Simon de Vlieger Date: Sun, 27 Sep 2026 09:36:27 +0200 Subject: [PATCH] kernel-install: `/usr` for tries `90-loaderentry.install` and `90-uki-copy.install` either read from `$KERNEL_INSTALL_CONF_ROOT` *or* `/etc/kernel/tries` while other parts in those plugins (e.g. `cmdline` or `devicetree`) check `/usr` as well. Adjust the check for `tries` to: 1. If `KERNEL_INSTALL_CONF_ROOT` is nonempty, read `tries` *only* from it. 2. Use `/etc/kernel/tries` if it exists and is a file. 2. Use `/run/kernel/tries` if it exists and is a file. 3. Use `/usr/lib/kernel/tries`. This allows for package-based systems that want to ship without `/etc` to use the tries mechanism. --- man/kernel-install.xml | 8 ++- src/kernel-install/90-loaderentry.install.in | 10 +++- src/kernel-install/90-uki-copy.install | 10 +++- src/kernel-install/test-kernel-install.sh | 53 ++++++++++++++++++++ 4 files changed, 77 insertions(+), 4 deletions(-) diff --git a/man/kernel-install.xml b/man/kernel-install.xml index 26ae87f1d42..6f087015dc3 100644 --- a/man/kernel-install.xml +++ b/man/kernel-install.xml @@ -722,16 +722,20 @@ /etc/kernel/tries + /run/kernel/tries + /usr/lib/kernel/tries Read by 90-loaderentry.install and - 90-uki-copy.install. If this file exists, a numeric value is read from it and - the naming of the generated entry file or UKI is altered to include it as + 90-uki-copy.install. A numeric value is read from the first file found, and + the generated entry file or UKI is named to include it as $BOOT/loader/entries/ENTRY-TOKEN-KERNEL-VERSION+TRIES.conf or $BOOT/EFI/Linux/ENTRY-TOKEN-KERNEL-VERSION+TRIES.efi, respectively. This is useful for boot loaders such as systemd-boot7 which implement boot attempt counting with a counter embedded in the entry file name. + A symlink to /dev/null disables boot counting, overriding files lower in the + search order. $KERNEL_INSTALL_CONF_ROOT may be used to override the search path; see below for details. diff --git a/src/kernel-install/90-loaderentry.install.in b/src/kernel-install/90-loaderentry.install.in index 196ba1d59a8..cdcbfea652a 100755 --- a/src/kernel-install/90-loaderentry.install.in +++ b/src/kernel-install/90-loaderentry.install.in @@ -130,7 +130,15 @@ if [ -n "$DEVICETREE_FILE" ]; then } fi -TRIES_FILE="${KERNEL_INSTALL_CONF_ROOT:-/etc/kernel}/tries" +if [ -n "$KERNEL_INSTALL_CONF_ROOT" ]; then + TRIES_FILE="$KERNEL_INSTALL_CONF_ROOT/tries" +elif [ -e /etc/kernel/tries ]; then + TRIES_FILE=/etc/kernel/tries +elif [ -e /run/kernel/tries ]; then + TRIES_FILE=/run/kernel/tries +else + TRIES_FILE=/usr/lib/kernel/tries +fi if [ -f "$TRIES_FILE" ]; then TRIES= diff --git a/src/kernel-install/90-uki-copy.install b/src/kernel-install/90-uki-copy.install index e719ecbd234..d291ccd3c4f 100755 --- a/src/kernel-install/90-uki-copy.install +++ b/src/kernel-install/90-uki-copy.install @@ -60,7 +60,15 @@ if ! [ -d "$UKI_DIR" ]; then mkdir -p "$UKI_DIR" fi -TRIES_FILE="${KERNEL_INSTALL_CONF_ROOT:-/etc/kernel}/tries" +if [ -n "$KERNEL_INSTALL_CONF_ROOT" ]; then + TRIES_FILE="$KERNEL_INSTALL_CONF_ROOT/tries" +elif [ -e /etc/kernel/tries ]; then + TRIES_FILE=/etc/kernel/tries +elif [ -e /run/kernel/tries ]; then + TRIES_FILE=/run/kernel/tries +else + TRIES_FILE=/usr/lib/kernel/tries +fi if [ -f "$TRIES_FILE" ]; then # 'read' fails if it hits the end of the file before a newline, even though it assigned TRIES, so diff --git a/src/kernel-install/test-kernel-install.sh b/src/kernel-install/test-kernel-install.sh index a542569e4a9..f3addef2392 100755 --- a/src/kernel-install/test-kernel-install.sh +++ b/src/kernel-install/test-kernel-install.sh @@ -508,3 +508,56 @@ cmp "$D/sources/fake.efi" "$D/uki-boot/EFI/Linux/the-token-2.0.0+3.efi" ( ! uki_copy_add 2>"$D/err" ) grep -qF "$D/uki-conf/tries does not contain an integer." "$D/err" test -f "$D/uki-boot/EFI/Linux/the-token-2.0.0+3.efi" + +########################################### +# Test tries search precedence without depending on the host's configuration +########################################### +mkdir -p "$D/tries-etc" "$D/tries-run" "$D/tries-usr" "$D/tries-conf" "$D/tries-staging" "$D/tries-entry" +for plugin in "$loaderentry_install" "$uki_copy_install"; do + sed -e "s|/etc/kernel/|$D/tries-etc/|g" -e "s|/run/kernel/|$D/tries-run/|g" \ + -e "s|/usr/lib/kernel/|$D/tries-usr/|g" \ + "$plugin" >"$D/${plugin##*/}" + chmod +x "$D/${plugin##*/}" +done + +check_tries_search() { + local name="$1" suffix="$2" conf_root="$3" + + KERNEL_INSTALL_CONF_ROOT="$conf_root" \ + KERNEL_INSTALL_LAYOUT=bls \ + KERNEL_INSTALL_VERBOSE=0 \ + KERNEL_INSTALL_MACHINE_ID="$MACHINE_ID" \ + KERNEL_INSTALL_ENTRY_TOKEN=the-token \ + KERNEL_INSTALL_ENTRY_NAME="$name" \ + KERNEL_INSTALL_BOOT_ROOT="$D/tries-boot" \ + KERNEL_INSTALL_STAGING_AREA="$D/tries-staging" \ + BOOT_MNT="$D/tries-boot" \ + "$D/${loaderentry_install##*/}" add 2.0.0 "$D/tries-entry" "$D/sources/linux" + test -f "$D/tries-boot/loader/entries/$name$suffix.conf" + + KERNEL_INSTALL_CONF_ROOT="$conf_root" \ + KERNEL_INSTALL_LAYOUT=uki \ + KERNEL_INSTALL_VERBOSE=0 \ + KERNEL_INSTALL_ENTRY_TOKEN=the-token \ + KERNEL_INSTALL_ENTRY_NAME="$name" \ + KERNEL_INSTALL_BOOT_ROOT="$D/tries-boot" \ + KERNEL_INSTALL_STAGING_AREA="$D/tries-staging" \ + "$D/${uki_copy_install##*/}" add 2.0.0 "$D/tries-entry" "$D/sources/fake.efi" + test -f "$D/tries-boot/EFI/Linux/$name$suffix.efi" +} + +echo 3 >"$D/tries-usr/tries" +check_tries_search usr +3 '' +echo 4 >"$D/tries-run/tries" +check_tries_search run +4 '' +echo 5 >"$D/tries-etc/tries" +check_tries_search etc +5 '' +check_tries_search conf-missing '' "$D/tries-conf" +rm "$D/tries-etc/tries" +ln -s /dev/null "$D/tries-etc/tries" +check_tries_search masked '' '' +rm "$D/tries-etc/tries" "$D/tries-run/tries" +ln -s /dev/null "$D/tries-run/tries" +check_tries_search run-masked '' '' +echo 7 >"$D/tries-conf/tries" +check_tries_search conf +7 "$D/tries-conf"