Bug#1087359: grub-mkconfig_lib's version_sort doesn't just sort by version

AP debian at inml.grue.cc
Tue Nov 12 01:17:15 GMT 2024


Source: grub
Version: 0.97-80
Severity: normal
Tags: patch

Dear Maintainer,

*** Reporter, please consider answering these questions, where appropriate ***

   * What led up to the situation?

Finding that my kernel-* symlinks for kernels in the past weren't being put
in their proper place. Primarily the one that is meant to be the default.

   * What exactly did you do (or not do) that was effective (or
     ineffective)?

I tried using vmlinuz-* symlinks with high enough version numbers to sort
appropriately.

   * What was the outcome of this action?

update-initramfs finds them and tries to build their initrd.img files and tends to fail.

   * What outcome did you expect instead?

Them to be ignored and everything to go smoothly. Instead update-initramfs considers
the symlinks to be kernels that require initrd.img rebuild.

*** End of the template - remove these template lines ***

Whilst update-initramfs can probably be "fixed" to deal with this by ignoring symlinks
another solution came to mind when I looked into grub's scripts in greater depth.

/etc/grub.d/10_linux gathers linux kernels according to "/boot/vmlinuz-* /boot/vmlinux-*
/vmlinuz-* /vmlinux-* /boot/kernel-*". This is great and what I wanted to utilise BUT
it appears that /usr/lib/grub/grub-mkconfig_lib's version_sort sorts by, effectively,
alphanumeric-version which means that each prefix gets its own version sort and then
they are all put together according to the result of an alphanumeric sorts.

Thus you get this:

$ ls /boot/kernel-* /boot/vmlinuz-* | sort -V
/boot/kernel-99.97.99-test
/boot/kernel-99.99.97-ancient
/boot/kernel-99.99.98-old
/boot/kernel-99.99.99-current
/boot/vmlinuz-6.1.0-26-amd64
/boot/vmlinuz-6.7.0-local.20240108-141500
/boot/vmlinuz-6.8.7-local.20240427-110130
/boot/vmlinuz-6.9.2-local.20240526-193145
/boot/vmlinuz-6.10.0-local.20240715-224153
/boot/vmlinuz-6.10.2-local.20240731-010223
/boot/vmlinuz-6.10.9-local.20240909-171114
/boot/vmlinuz-6.10.11+bpo-amd64
/boot/vmlinuz-6.10.14-local.20241021-023441
/boot/vmlinuz-6.11.0-local.20240926-141105
/boot/vmlinuz-6.11.0-local.20240926-150409
/boot/vmlinuz-6.11.1-local.20241003-204800
/boot/vmlinuz-6.11.2-local.20241008-004432
/boot/vmlinuz-6.11.4-local.20241018-163800

This means the reverse sort of the list that is used to get the menu winds up getting
/boot/vmlinuz-6.11.4-local.20241018-163800 as the default member and not /boot/kernel-99.99.99-current.

The solution here would be to use the fields feature of sort so then you'd get the
kernel list being:

$ ls /boot/kernel-* /boot/vmlinuz-* | sort -V -t - -k 2
/boot/vmlinuz-6.1.0-26-amd64
/boot/vmlinuz-6.7.0-local.20240108-141500
/boot/vmlinuz-6.8.7-local.20240427-110130
/boot/vmlinuz-6.9.2-local.20240526-193145
/boot/vmlinuz-6.10.0-local.20240715-224153
/boot/vmlinuz-6.10.2-local.20240731-010223
/boot/vmlinuz-6.10.9-local.20240909-171114
/boot/vmlinuz-6.10.11+bpo-amd64
/boot/vmlinuz-6.10.14-local.20241021-023441
/boot/vmlinuz-6.11.0-local.20240926-141105
/boot/vmlinuz-6.11.0-local.20240926-150409
/boot/vmlinuz-6.11.1-local.20241003-204800
/boot/vmlinuz-6.11.2-local.20241008-004432
/boot/vmlinuz-6.11.4-local.20241018-163800
/boot/kernel-99.97.99-test
/boot/kernel-99.99.97-ancient
/boot/kernel-99.99.98-old
/boot/kernel-99.99.99-current

This results in the kernels being purely sorted by version and, so, the reverse sort
gets /boot/kernel-99.99.99-current on top as is wanted and THAT becomes the default
menu item.

Hope this makes sense :)

Patch below.

--- grub-mkconfig_lib.old       2024-11-12 12:01:03.394026357 +1100
+++ grub-mkconfig_lib   2024-11-12 12:09:35.611560029 +1100
@@ -226,18 +226,34 @@
 
 version_sort ()
 {
-  case $version_sort_sort_has_v in
-    yes)
+  case $version_sort_sort_has_v.$version_sort_sort_has_tk in
+    yes.yes)
+      LC_ALL=C sort -V -t - -k 2 "$@";;
+    yes.no)
       LC_ALL=C sort -V "$@";;
-    no)
+    no.yes)
+      LC_ALL=C sort -n -t - -k 2 "$@";;
+    no.no)
       LC_ALL=C sort -n "$@";;
     *)
       if sort -V </dev/null > /dev/null 2>&1; then
         version_sort_sort_has_v=yes
-       LC_ALL=C sort -V "$@"
+        if sort -V -t 1 -k 2 </dev/null > /dev/null 2>&1; then
+          version_sort_sort_has_tk=yes
+          LC_ALL=C sort -V -t - -k 2 "$@"
+        else
+          version_sort_sort_has_tk=no
+          LC_ALL=C sort -V "$@"
+        fi
       else
         version_sort_sort_has_v=no
-        LC_ALL=C sort -n "$@"
+        if sort -n -t 1 -k 2 </dev/null > /dev/null 2>&1; then
+          version_sort_sort_has_tk=yes
+          LC_ALL=C sort -n -t - -k 2 "$@"
+        else
+          version_sort_sort_has_tk=no
+          LC_ALL=C sort -n "$@"
+        fi
       fi;;
    esac
 }


-- System Information:
Debian Release: 12.7
  APT prefers stable-updates
  APT policy: (500, 'stable-updates'), (500, 'stable-security'), (500, 'stable')
Architecture: amd64 (x86_64)

Kernel: Linux 6.11.1-local.20241001-142734 (SMP w/2 CPU threads)
Locale: LANG=en_AU.UTF-8, LC_CTYPE=en_AU.UTF-8 (charmap=UTF-8), LANGUAGE=en_AU:en
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)



More information about the Pkg-grub-devel mailing list