LLM (Claude) consulted context:
Summary:
available_ids() in /usr/lib/grub/grub-multi-install deduplicates multiple
/dev/disk/by-id/* aliases for the same physical device via sort -k2 -s -u,
keyed on the resolved realpath. Because the key is identical for all aliases of
one device, the stable sort's tie-break falls through to the original iteration
order of the /dev/disk/by-id/* glob — and glob expansion order is
locale-collation-dependent (LC_COLLATE). No locale is pinned anywhere in the
script, so which by-id alias is selected as "canonical" for a given device
depends on the invoking shell's ambient locale.
Impact:
grub-efi/install_devices is user/administrator-facing persistent debconf state,
consulted and rewritten on every grub-efi-* postinst run (fresh install,
upgrade, dpkg-reconfigure). On systems with multiple ESPs where by-id aliasing
is ambiguous (e.g. NVMe devices exposing both nvme-eui.* and
nvme-<model>_<serial>-part* names for the same namespace), the set of physical
devices targeted for GRUB installation doesn't change across runs, but the
specific alias string stored for each device can — purely as a function of
which locale happened to be active during that particular postinst/reconfigure
invocation. This:
* produces spurious/inconsistent install_devices values across
otherwise-identical maintenance operations,
* makes the stored debconf value unsuitable as a stable identifier for any
tooling (fleet management, OTA scripts, config auditing) that compares it
across runs rather than resolving each entry to a realpath before comparing,
* is silent — nothing surfaces to the administrator indicating the alias
changed underneath them.
Steps to reproduce:
* On a system with ≥2 ESP-typed partitions where at least one backing device
exposes multiple /dev/disk/by-id/* aliases for the same partition (e.g. NVMe
with both EUI and model/serial naming schemes),
* sudo LC_ALL=C dpkg-reconfigure grub-efi-arm64, note the resulting
debconf-show grub-efi-arm64 | grep install_devices output,
* sudo LC_ALL=en_US.UTF-8 dpkg-reconfigure grub-efi-arm64 (with en_US.UTF-8
generated/available), note the output again,
* Compare.
Actual result:
LC_ALL=C:
grub-efi/install_devices:
/dev/disk/by-id/nvme-Micron_7450_MTFDKBA480TFR_254954CD71E8-part1,
/dev/disk/by-id/nvme-Micron_7450_MTFDKBA480TFR_254954CD7CF6-part1
LC_ALL=en_US.UTF-8:
grub-efi/install_devices:
/dev/disk/by-id/nvme-eui.000000000000000100a0752554cd71e8-part1,
/dev/disk/by-id/nvme-eui.000000000000000100a0752554cd7cf6-part1
Expected result:
The stored value for a given set of physical devices should be identical
regardless of the invoking locale.
Root cause:
In available_ids() (/usr/lib/grub/grub-multi-install):
sh
cached_available_ids="$(
for path in /dev/disk/by-id/*; do
[ -e "$path" ] || continue
printf '%s %s\n' "$path" "$(readlink -f "$path")"
done | sort -k2 -s -u | cut -d' ' -f1
)"
No LC_COLLATE/LC_ALL is pinned before the glob or the sort. sort -s -u
on a tied key (field 2, the realpath) preserves first-seen input order —
so the result depends entirely on the shell's glob expansion order for
/dev/disk/by-id/*, which is strcoll()-based and locale-sensitive.
Suggested fix:
Pin locale before the glob/sort so alias selection is deterministic. Two
options worth the maintainer's judgment call rather than dictated here:
LC_ALL=C — simplest, guarantees determinism, but also forces C for LC_MESSAGES
etc. for anything else evaluated in that scope, which could affect translated
debconf prompt text if that scope is ever widened.
LC_COLLATE=C specifically — narrower, fixes only the sort/glob-ordering
dependency without touching message localization, arguably the more surgical
fix.
Separately worth considering: since downstream consumers of
install_devices (the disks-changed reconciliation logic later in the
same script) already compare entries by readlink -f realpath rather than
by string, would it be more robust for available_ids()/device_to_id() to
guarantee a canonical scheme preference (e.g. always prefer non-nvme-
eui.* names when multiple aliases exist) rather than relying on sort-
order-as-tiebreak at all? That would make the stored value locale-
independent by construction rather than by pinning locale at just this
one call site, and be more resilient if this dedup logic is ever copy-
pasted elsewhere without the pin.
** Description changed:
grub-multi-install is not locale stable, which means, for systems with
multiple ESPs, running:
sudo LC_ALL=C dpkg-reconfigure grub-efi-arm64
and
sudo LC_ALL=en_US.UTF-8 dpkg-reconfigure grub-efi-arm64
stores different output in grub-efi/install_devices, for example:
with LC_ALL=C:
* grub-efi/install_devices:
/dev/disk/by-id/nvme-Micron_7450_MTFDKBA480TFR_254954CD71E8-part1,
/dev/disk/by-id/nvme-Micron_7450_MTFDKBA480TFR_254954CD7CF6-part1
with LC_ALL=en_US.UTF-8:
* grub-efi/install_devices:
/dev/disk/by-id/nvme-eui.000000000000000100a0752554cd71e8-part1,
/dev/disk/by-id/nvme-eui.000000000000000100a0752554cd7cf6-part1
+ note that, options selected in LC_ALL=C are not checked in
+ LC_ALL=en_US.UTF-8, all the available ESP listed are unselected.
+
---
This can cause issues that grub-efi/install_devices are overwritten with
incorrect values when GRUB is upgraded and reinstalled with locales
different from C
--
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/2164992
Title:
install_devices alias selection in grub-multi-install is not locale-
stable, causing spurious reconfiguration across locales
To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/grub2/+bug/2164992/+subscriptions
--
ubuntu-bugs mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs