Bug 41959 - grub-efi-autoupdate для removable
Summary: grub-efi-autoupdate для removable
Status: ASSIGNED
Alias: None
Product: Sisyphus
Classification: Development
Component: grub-efi (show other bugs)
Version: unstable
Hardware: all Linux
: P5 normal
Assignee: Egor Ignatov
QA Contact: qa-sisyphus
URL:
Keywords:
Depends on:
Blocks: 46625
  Show dependency tree
 
Reported: 2022-02-15 18:18 MSK by Ivan A. Melnikov
Modified: 2024-02-20 01:56 MSK (History)
7 users (show)

See Also:


Attachments
EFI/BOOT/grub.cfg такой же признак removable, как и EFI/BOOT/grub*.efi (1.18 KB, patch)
2023-08-11 12:10 MSK, Антон Мидюков
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Ivan A. Melnikov 2022-02-15 18:18:46 MSK
По мотивам обсуждения в #41945

Коммит [1] добавляет в grub-efi-autoupdate обновление конфигураций, использующих grub-install --removable. 

[1] http://git.altlinux.org/gears/g/grub.git?a=commitdiff;h=3af85716bdb15e6434d37e76ff3e29a02eba3425

Однако в таких ситуациях не используется путь $EFI_DIR/EFI/BOOT/grub*.efi; вместо этого grub использует путь для efi-загрузчика по-умолчанию, определённый спецификацией UEFI: $EFI_DIR/EFI/BOOT/BOOT*.EFI. Исправление могло бы быть тривиальным:

http://git.altlinux.org/people/iv/packages/?p=grub.git;a=commitdiff;h=e2f359146bc70c0b0e2c4793b8d83d0ac373ad8a

Однако такой вариант заменяет на grub не только старый grub, но и любой другой загрузчик, включая, например, переименованный shim (что ломает secure boot).

Надо как-то разрулить эту ситуацию.
Comment 1 Николай Костригин 2022-02-15 18:23:34 MSK
Продублирую еще хвост оригинального треда:

(Ответ для Anton Farygin на комментарий #15)
> А почему в этом месте нельзя проверить оба варианта ?
>  $EFI_DIR/EFI/BOOT/BOOT*.EFI и GRUB*.EFI ?

Проверить можно.
Просто напомню, что наличие EFI/BOOT - это не только признак "--removable" установки после того, как его добавили для объезда ошибок в некоторых новых UEFI-прошивках (где основная загрузочная запись пропадала при отсутствии EFI\BOOT).

Раньше в усложнении условий в efi-boot-autoupdate не было необходимости, а сейчас просто придется рассмотреть все возможные варианты.
Comment 2 Антон Мидюков 2022-05-11 15:10:31 MSK
Николай, напоминаю об этой проблеме.
Comment 3 Антон Мидюков 2022-05-27 12:52:23 MSK
(Ответ для Ivan A. Melnikov на комментарий #0)
> Однако такой вариант заменяет на grub не только старый grub, но и любой
> другой загрузчик, включая, например, переименованный shim (что ломает secure
> boot).

Определить, что там grub, а не другой загрузчик можно по наличию EFI/BOOT/grub.cfg
Для того, чтобы отличить --removable от --force-extra-removable, нужно смотреть, есть ли каталог EFI/altlinux (уже же делается). Если есть, то не --removable.

Можно попробовать так:

diff --git a/grub-efi-autoupdate b/grub-efi-autoupdate
index 844788721..180259aac 100755
--- a/grub-efi-autoupdate
+++ b/grub-efi-autoupdate
@@ -25,9 +25,9 @@ GRUB_REMOVABLE=
 
 if ! stat $EFI_DIR/EFI/$DIST/grub*.efi > /dev/null 2>&1; then
 	echo "$EFI_DIR/EFI/$DIST/grub*.efi is missing, not fatal yet."
-	if ! stat $EFI_DIR/EFI/BOOT/grub*.efi > /dev/null 2>&1; then
+	if ! stat $EFI_DIR/EFI/BOOT/grub.cfg > /dev/null 2>&1; then
 		echo
-		echo "$EFI_DIR/EFI/BOOT/grub*.efi is missing too. Fatal."
+		echo "$EFI_DIR/EFI/BOOT/grub.cfg is missing too. Fatal."
 		echo "Nothing to update. Please run: grub-install && grub-efi-autoupdate"
 		echo
 		echo "If your system lacks NVRAM or you are getting persistent errors, please"
Comment 4 Ivan A. Melnikov 2022-05-27 15:21:44 MSK
(In reply to Антон Мидюков from comment #3)
> Определить, что там grub, а не другой загрузчик можно по наличию
> EFI/BOOT/grub.cfg

У меня на riscv64 такого нет.

# find /boot/efi/EFI -type f
/boot/efi/EFI/altlinux/grubriscv64.efi
/boot/efi/EFI/BOOT/BOOTRISCV64.EFI
Comment 5 Антон Мидюков 2022-05-27 15:45:23 MSK
(Ответ для Ivan A. Melnikov на комментарий #4)
> (In reply to Антон Мидюков from comment #3)
> > Определить, что там grub, а не другой загрузчик можно по наличию
> > EFI/BOOT/grub.cfg
> 
> У меня на riscv64 такого нет.
> 
> # find /boot/efi/EFI -type f
> /boot/efi/EFI/altlinux/grubriscv64.efi
> /boot/efi/EFI/BOOT/BOOTRISCV64.EFI

Да, и на aarch64. А если выполнить
grub-install --removable

то появится. Причина в опции --no-uefi-secure-boot, с которой собираются на aarch64 и riscv64. Надо её убрать из tar2fs.
Comment 6 Ivan A. Melnikov 2022-05-27 16:16:38 MSK
(In reply to Антон Мидюков from comment #5)
> (Ответ для Ivan A. Melnikov на комментарий #4)
> > (In reply to Антон Мидюков from comment #3)
> > > Определить, что там grub, а не другой загрузчик можно по наличию
> > > EFI/BOOT/grub.cfg
> > 
> > У меня на riscv64 такого нет.
> > 
> > # find /boot/efi/EFI -type f
> > /boot/efi/EFI/altlinux/grubriscv64.efi
> > /boot/efi/EFI/BOOT/BOOTRISCV64.EFI
> 
> Да, и на aarch64. А если выполнить
> grub-install --removable
> 
> то появится.

[root@unmatched1 ~]# grub-install --removable
Installing for riscv64-efi platform.
Installation finished. No error reported.
[root@unmatched1 ~]# find /boot/efi/EFI -type f
/boot/efi/EFI/altlinux/grubriscv64.efi
/boot/efi/EFI/BOOT/BOOTRISCV64.EFI

HiFive Unmatched, загружалась grub'ом.
Comment 7 Антон Мидюков 2022-05-27 17:15:39 MSK
(Ответ для Ivan A. Melnikov на комментарий #6)
> (In reply to Антон Мидюков from comment #5)
> > (Ответ для Ivan A. Melnikov на комментарий #4)
> > > (In reply to Антон Мидюков from comment #3)
> > > > Определить, что там grub, а не другой загрузчик можно по наличию
> > > > EFI/BOOT/grub.cfg
> > > 
> > > У меня на riscv64 такого нет.
> > > 
> > > # find /boot/efi/EFI -type f
> > > /boot/efi/EFI/altlinux/grubriscv64.efi
> > > /boot/efi/EFI/BOOT/BOOTRISCV64.EFI
> > 
> > Да, и на aarch64. А если выполнить
> > grub-install --removable
> > 
> > то появится.
> 
> [root@unmatched1 ~]# grub-install --removable
> Installing for riscv64-efi platform.
> Installation finished. No error reported.
> [root@unmatched1 ~]# find /boot/efi/EFI -type f
> /boot/efi/EFI/altlinux/grubriscv64.efi
> /boot/efi/EFI/BOOT/BOOTRISCV64.EFI
> 
> HiFive Unmatched, загружалась grub'ом.

Действительно так. Если запустить
grub-install --removable -v

то в конце будет
grub-install: info: No Secure Boot: installing core image.
grub-install: info: copying `/boot/grub/riscv64-efi/core.efi' -> `/boot/efi/EFI/BOOT/BOOTRISCV64.EFI'.

Т.е. grub.cfg записывается, если grub подписан. Наличие shim при этом не требуется, что показывает пример aarch64.

Итого: идея с ориентиром на EFI/BOOT/grub.cfg не подходит.
Comment 8 Николай Костригин 2022-05-27 17:21:57 MSK
(Ответ для Ivan A. Melnikov на комментарий #0)
> По мотивам обсуждения в #41945
> 
> Коммит [1] добавляет в grub-efi-autoupdate обновление конфигураций,
> использующих grub-install --removable. 
> 
> [1]
> http://git.altlinux.org/gears/g/grub.git?a=commitdiff;
> h=3af85716bdb15e6434d37e76ff3e29a02eba3425
> 
> Однако в таких ситуациях не используется путь $EFI_DIR/EFI/BOOT/grub*.efi;
> вместо этого grub использует путь для efi-загрузчика по-умолчанию,
> определённый спецификацией UEFI: $EFI_DIR/EFI/BOOT/BOOT*.EFI. Исправление
> могло бы быть тривиальным:
> 
> http://git.altlinux.org/people/iv/packages/?p=grub.git;a=commitdiff;
> h=e2f359146bc70c0b0e2c4793b8d83d0ac373ad8a
> 
> Однако такой вариант заменяет на grub не только старый grub, но и любой
> другой загрузчик, включая, например, переименованный shim (что ломает secure
> boot).
> 
> Надо как-то разрулить эту ситуацию.

На x86_64 под именем BOOT*.EFI прячется SHIM*.EFI, можно дополнительно проверить еще и наличие grub*.efi и делать выводы где мы оказались.
Или усложнить скрипт платформозависимыми суффиксами и выстраивать поведение на из основе.
Comment 9 Ivan A. Melnikov 2022-05-28 08:49:29 MSK
Проблема в том, что под именем BOOT*.EFI может быть всё, что угодно. Даже собранное пользователем ядро с efistub, которое он сам туда положил. Поэтому заменять BOOT*.EFI на grub из нового пакета можно только если это grub из старого пакета.

Как понять, что BOOT*.EFI это grub из старого пакета? На данный момент -- никак. Никакой информации о том, что из себя представлял старый grub, у grub-efi-autoupdate просто нет, а косвенные признаки ненадёжны.

Значит, нужно где-то оставить эту информацию.

Предлагаю сделать это сурово, брутально и бессердечно: grub-install --removable должен, когда копирует grub в BOOT*.EFI, положить рядом файл с его контрольной суммой, скажем $EFI_DIR/EFI/BOOT/alt.grub.sha1. Или в /etc/ где-нибудь, если в $EFI_DIR страшно. И если такгого файла нет или контрольные суммы не совпадают, ничего не делать.
Comment 10 Антон Мидюков 2022-05-30 17:09:29 MSK
А давайте подумаем ещё с другой стороны. В принципе, чем нас не устраивает grub-install --force-extra-removable? Мне кажется, что только тем, что он лезет в NVRAM.
Отсюда вопрос: а действительно ли нужно лезть в NVRAM при выполнении grub-efi-autoupdate? В самой NVRAM же обновляем только информацию, где находится EFI-бинарик. Его местоположение же не меняется? Тогда в чём необходимость? Если необходимости нет, то можно добавить --no-nvram. И тогда будем при сборке img указывать --force-extra-removable --no-nvram вместо --removable. Собственно, это и сейчас можно делать, но не нравится только то, что grub-efi-autoupdate тогда лезет в NVRAM, которого нет.
Comment 11 Антон Мидюков 2022-05-30 20:13:56 MSK
(Ответ для Антон Мидюков на комментарий #10)
> А давайте подумаем ещё с другой стороны. В принципе, чем нас не устраивает
> grub-install --force-extra-removable? Мне кажется, что только тем, что он
> лезет в NVRAM.
> Отсюда вопрос: а действительно ли нужно лезть в NVRAM при выполнении
> grub-efi-autoupdate? В самой NVRAM же обновляем только информацию, где
> находится EFI-бинарик. Его местоположение же не меняется? Тогда в чём
> необходимость? Если необходимости нет, то можно добавить --no-nvram. И тогда
> будем при сборке img указывать --force-extra-removable --no-nvram вместо
> --removable. Собственно, это и сейчас можно делать, но не нравится только
> то, что grub-efi-autoupdate тогда лезет в NVRAM, которого нет.

У --removable и --force-extra-removable разное поведение при использовании c опцией --uefi-secure-boot. В первом случае создаётся EFI/BOOT/grub.cfg, во втором - не создаётся, из-за чего не грузится. С --no-uefi-secure-boot EFI/BOOT/grub.cfg не нужен.

Но, если вернуться к коду, то выдумывать ничего не надо. Есть надёжный признак определения removable - $EFI_DIR/EFI/BOOT/grub*.efi
И на самом деле вопрос другой: почему работает неправильно --removable в режиме --no-uefi-secure-boot? В этом режиме grub*.efi должен быть скопирован в два места: в $EFI_DIR/EFI/BOOT/grub*.efi и $EFI_DIR/EFI/BOOT/BOOT*.efi
Вот такое решение напрашивается.
Comment 12 Антон Мидюков 2023-08-11 12:10:23 MSK
Created attachment 14057 [details]
EFI/BOOT/grub.cfg такой же признак removable, как и EFI/BOOT/grub*.efi

Предлагаю вернуться к первоначальной мысли про /EFI/BOOT/grub.cfg
Его можно создавать при сборке образа и при установке в alterator-grub.
Comment 13 Ivan A. Melnikov 2023-08-11 13:24:14 MSK
(In reply to Ivan A. Melnikov from comment #9)
> Проблема в том, что под именем BOOT*.EFI может быть всё, что угодно. Даже
> собранное пользователем ядро с efistub, которое он сам туда положил.

Как обработается этот use case? Мне он важен.
Comment 14 Антон Мидюков 2023-08-11 20:01:04 MSK
(Ответ для Ivan A. Melnikov на комментарий #13)
> (In reply to Ivan A. Melnikov from comment #9)
> > Проблема в том, что под именем BOOT*.EFI может быть всё, что угодно. Даже
> > собранное пользователем ядро с efistub, которое он сам туда положил.
> 
> Как обработается этот use case? Мне он важен.

Если EFI/BOOT/grub.cfg нет, то не затрётся EFI/BOOT/BOOT*.EFI.
EFI/BOOT/grub.cfg не появится сам.
Comment 15 Ivan A. Melnikov 2023-08-11 23:12:36 MSK
Распишу сценарий подробнее.

1. Пользователь поставил дистрибутив Альт. Появился EFI/BOOT/grub.cfg.

2. Пользователь понял, что ядро альта его не устраивает, и собрал своё. Поскольку в особенностях нашего grub он не понимает (а кто в них понимает?), ядро он собрал сразу с efi stub и загружает его без загрузчика. EFI/BOOT/grub.cfg не удалил, так как откуда бы он узнал, что его нужно удалить.

3. Через пару месяцев с очередным dist-upgrade обновился grub и, увидев EFI/BOOT/grub.cfg, затёр что смог.

Пункты 1 и 2 основаны на реальных событиях, такие пользователи у одноплатников есть.
Comment 16 Антон Мидюков 2023-08-12 03:15:24 MSK
(Ответ для Ivan A. Melnikov на комментарий #15)
> Распишу сценарий подробнее.
> 
> 1. Пользователь поставил дистрибутив Альт. Появился EFI/BOOT/grub.cfg.
> 
> 2. Пользователь понял, что ядро альта его не устраивает, и собрал своё.
> Поскольку в особенностях нашего grub он не понимает (а кто в них понимает?),
> ядро он собрал сразу с efi stub и загружает его без загрузчика.
> EFI/BOOT/grub.cfg не удалил, так как откуда бы он узнал, что его нужно
> удалить.

Не пользуешься grub, удали его.

> 
> 3. Через пару месяцев с очередным dist-upgrade обновился grub и, увидев
> EFI/BOOT/grub.cfg, затёр что смог.
> 
> Пункты 1 и 2 основаны на реальных событиях, такие пользователи у
> одноплатников есть.

Что за одноплатник такой?
Comment 17 Egor Ignatov 2023-08-17 13:27:12 MSK
Коллеги, попробовал разобраться в этой проблеме.
Получается нас интересует пропуск автообновления grub, когда:
1. grub был установлен с --removable (нет директории altlinux)
2. установка была с --no-uefi-secure-boot (установлен только grub как BOOT/BOOT<efiarch>.EFI)
3. BOOT<efiarch>.EFI не является grub

Как по мне проблема надумана и пользователь, который собрал на свой страх и риск ядро с efi stub и загружает его без загрузчика должен создать себе отдельный boot entry или удалить grub на системах без NVRAM. В grub-efi-autoupdate можно добавить warning, что BOOT<efiarch>.EFI обновлен и перезаписан на grub или shim.

(In reply to Ivan A. Melnikov from comment #9)
> Предлагаю сделать это сурово, брутально и бессердечно: grub-install
> --removable должен, когда копирует grub в BOOT*.EFI, положить рядом файл с
> его контрольной суммой, скажем $EFI_DIR/EFI/BOOT/alt.grub.sha1. Или в /etc/
> где-нибудь, если в $EFI_DIR страшно. И если такгого файла нет или
> контрольные суммы не совпадают, ничего не делать.

С другой стороны можно действительно добавить создание файла с чексуммой в grub-efi-autoupdate сразу после grub-install и проверку в начало.
Например как-то так:
grub-install -v 2>&1 | grep -o "/boot/efi[^']*" | xargs md5sum
Comment 18 Антон Мидюков 2023-08-17 20:38:33 MSK
(Ответ для Egor Ignatov на комментарий #17)
> Коллеги, попробовал разобраться в этой проблеме.
> Получается нас интересует пропуск автообновления grub, когда:
> 1. grub был установлен с --removable (нет директории altlinux)

Если есть shim, то grub обновляется. А вот если его нет, то не обновляется.
И наличие директории altlinux обновиться не поможет. grub обновится только в ней.
Так что мы хотим, чтобы обновление происходило, если в BOOT/BOOT<efiarch>.EFI действительно grub.
На системах без NVRAM --removable у нас стандартный вариант установки. Кроме того, для переносного SSD это тоже стандартный вариант, так как записываться в NVRAM противопоказано.

> 2. установка была с --no-uefi-secure-boot (установлен только grub как
> BOOT/BOOT<efiarch>.EFI)

На riscv64 не получается установиться с --uefi-secure-boot, так как grub не подписан. grub.cfg всегда встраивается.

> 3. BOOT<efiarch>.EFI не является grub
> 
> Как по мне проблема надумана и пользователь, который собрал на свой страх и
> риск ядро с efi stub и загружает его без загрузчика должен создать себе
> отдельный boot entry или удалить grub на системах без NVRAM. В
> grub-efi-autoupdate можно добавить warning, что BOOT<efiarch>.EFI обновлен и
> перезаписан на grub или shim.
> 

Да, warning не помешает.

> (In reply to Ivan A. Melnikov from comment #9)
> > Предлагаю сделать это сурово, брутально и бессердечно: grub-install
> > --removable должен, когда копирует grub в BOOT*.EFI, положить рядом файл с
> > его контрольной суммой, скажем $EFI_DIR/EFI/BOOT/alt.grub.sha1. Или в /etc/
> > где-нибудь, если в $EFI_DIR страшно. И если такгого файла нет или
> > контрольные суммы не совпадают, ничего не делать.
> 
> С другой стороны можно действительно добавить создание файла с чексуммой в
> grub-efi-autoupdate сразу после grub-install и проверку в начало.
> Например как-то так:
> grub-install -v 2>&1 | grep -o "/boot/efi[^']*" | xargs md5sum

Но можно и так. Только создание контрольной суммы будет при каком условии происходить? Если только в grub-efi-autoupdate, то как она появится в первый раз? При установке grub-efi-autoupdate не используется. Придётся реализовывать при установке и сборке образа.
Comment 19 Egor Ignatov 2023-08-18 16:22:30 MSK
Вообще целостность $EFI_DIR/EFI/BOOT/BOOT*.EFI и/или $EFI_DIR/EFI/BOOT/GRUB*.EFI можно проверять в %pre скрипте grub-efi, таким образом можно определить, что мы обновляем именно наш grub старой версии, а не собранный пользователем. Но тогда, наверное, нужно еще и в %pre shim-signed делать проверку.
Comment 20 Антон Мидюков 2024-02-17 08:28:42 MSK
(Ответ для Egor Ignatov на комментарий #19)
> Вообще целостность $EFI_DIR/EFI/BOOT/BOOT*.EFI и/или
> $EFI_DIR/EFI/BOOT/GRUB*.EFI можно проверять в %pre скрипте grub-efi, таким
> образом можно определить, что мы обновляем именно наш grub старой версии, а
> не собранный пользователем. Но тогда, наверное, нужно еще и в %pre
> shim-signed делать проверку.

Давайте уже решим эту багу как-нибудь.
Она актуальна для кейса установки на ESP из RAID1 c суперблоком 0.9 или 1.0.
В этом случае совершенно естественно, что ставим в режиме removable, так как наш grub не может сделать записи в NVRAM для каждого раздела. Да и если бы и мог, всё равно после замены одного из диска требовалось вы вручную делать grub-efi-autoupdate.
Comment 21 Leonid Krivoshein 2024-02-20 01:56:54 MSK
grub-efi-autoupdate для removable -- лишь часть политики установки и обновления grub-efi, которую имеет смысл поменять накануне 11.0. Детали ("зачем, почему?") можно обсудить в devel@, тут коротко предлагаю такой план:

1. На шагах разметки и установки загрузчика имеющийся ESP проверяется на предмет не только FAT, но и NTFS. Последнее нарушает стандарт и требует обязательного конвертирования в FAT.

2. Нужно проверять, есть ли раздел ESP. Если нет, только тогда его создаём. А если есть, я бы очищал его полностью. Но можно спросить пользователя, нужно ли его сохранить? По мне, так лучше его молча бэкапить.

3. Ориентироваться на EFI/<efi_distributor> по умолчанию не следует, если только пользователь об этом явно не попросит. Очень сильно этого могут захотеть лишь те, кто, во-первых, понимает, зачем им это надо, во-вторых, используют несколько ОС на машине, в-третьих, знает, что их UEFI Firmware очень хорошо справляется с задачей управляения записями NVRAM, включая вывод более удобных меню, нежели это делает grub-efi.

4. Исходя из вышесказанного, вариант установки grub-efi по умолчанию только в EFI/BOOT, т.е. как в сабже c --removable, как у всех Linux-дистрибутивов и главное, как у Windows. С полной перезаписью того, что там есть. Не важно, наше оно, чьё-то ещё или ядро EFI STUB, ставится с нуля или обновляется, grub-efi сам найдёт всё, что было на диске, и сделает своё меню, обычно более юзабельное, чем во встроенной firmware.

5. Значимые переменные конфигурации grub-efi хранятся в /etc/sysconfig/grub2 (grub-common), наши grub'овские скрипты патчены под него всё равно, так что не надо придумывать никаких контрольных сумм. Всё, что мы установили, с какими параметрами, сохраняется тут, и если включено автообновление (по умолчанию д.б. включено), то берётся снова отсюда. grub-efi не всегда реально удалить из-за цепочки зависимостей, так что любителям под себя перезаточить содержимое /EFI/BOOT -- велкам на ВиКи и руками лопатить данный конфиг.