grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] Change "efi" to "EFI" in grub-mkrescue for secure boot


From: Askar Safin
Subject: [PATCH] Change "efi" to "EFI" in grub-mkrescue for secure boot
Date: Fri, 6 Sep 2024 16:15:10 +0300

Hi. I propose changing "efi" to "EFI" in grub-mkrescue, because this is needed 
for secure boot. Please, apply patch below. Here is why.

First of all, iso9660 file system is case sensitive from GRUB point of view. I. 
e. if you have directory named "efi" in iso9660, then GRUB command "ls /EFI" 
will not work.

Second, it seems that "EFI", as opposed to "efi", is standard among Linux CDs. 
I examined the following .iso files:

- Debian installer
- Debian live image
- Ubuntu live image
- Fedora network install

All they have "EFI", as opposed to "efi".

And main argument: I'm aware of one example when "EFI" is hard-coded in signed 
secure boot GRUB binary. Debian has 4 signed GRUB binaries. All they are 
generated here: 
https://sources.debian.org/src/grub2/2.12-5/debian/build-efi-images/ . One of 
them, grubx64.efi is created using "grub-mkimage ... -p /EFI/debian". The 
binary is signed, so I cannot change it if I want secure boot support. So if I 
want to use this binary, I should have directory named exactly "EFI".

You may say: "But grub-mkrescue doesn't support secure boot". Yes, it doesn't 
support it. But I think this patch will simplify adding secure boot support by 
distributions.

Now let me describe in detail why I need all this. Also I will show you results 
of additional experiments.

I attempted to create bootable GRUB disk using grub-mkrescue. I wanted the disk 
to support secure boot. I failed. I don't remember why. It is possible that 
this EFI vs efi issue was one of the problems. So I resorted to writing script, 
which replaces grub-mkrescue. This is simplified version of that script. Note: 
this is simplification written specially for presenting here. So I 
intentionally dropped things I would not drop in real code.

====
#!/bin/bash
# This script is merely demonstration created specially to present on GRUB 
mailing list. So it intentionally drops some important things
# This script can be run on any Linux distro
# This script creates isohybrid disk, which supports UEFI booting
# The disk can be used both as CD image and as USB disk image
# So, in total 2 boot modes are supported: UEFI-CD and UEFI-USB
# Secure boot is supported
# This script can be run on any Linux distro (but was tested on Debian only).
# The script doesn't rely on specific files present in specific places, it 
downloads all its dependencies
# This script doesn't support "EFI file system transposition" ( 
https://lists.gnu.org/archive/html/grub-devel/2022-06/msg00024.html ). This is 
intentional, because this is just a demo
# The script was tested in Qemu only. Also secure boot was not tested
{
  # This is just boilerplate I insert to all my bash scripts
  set -e
  set -u
  set -o pipefail
  shopt -s inherit_errexit
  shopt -s nullglob
  export LC_ALL=C.UTF-8

  if [ $# != 1 ]; then
    echo "Usage: ${0##*/} OUT" >&2
    exit 1
  fi

  OUT="$1"

  DIR="$(mktemp -d /tmp/grub-XXXXXX)"

  mkdir -p "$DIR/esp/EFI/boot" "$DIR/esp/EFI/debian" 
"$DIR/main-root/EFI/debian" "$DIR/main-root/boot/grub"
  wget -O "$DIR/esp/EFI/boot/bootx64.efi" 
'https://sources.debian.org/src/shim-signed/latest/shimx64.efi.signed/'
  wget -O "$DIR/grub-efi-amd64-signed.deb" 
'https://deb.debian.org/debian/pool/main/g/grub-efi-amd64-signed/grub-efi-amd64-signed_1+2.12+5_amd64.deb'
  ar p "$DIR/grub-efi-amd64-signed.deb" data.tar.xz > "$DIR/data.tar.xz"
  tar -xf "$DIR/data.tar.xz" --to-stdout 
./usr/lib/grub/x86_64-efi-signed/grubx64.efi.signed > 
"$DIR/esp/EFI/boot/grubx64.efi"
  cat << "EOF" > "$DIR/esp/EFI/debian/grub.cfg"
echo "This is /EFI/debian/grub.cfg from ESP"
echo "Testing shows that this file is loaded during UEFI-USB"
sleep 10
EOF
  mkfs.vfat -C "$DIR/main-root/boot/grub/efi.img" 10000
  mcopy -s -i "$DIR/main-root/boot/grub/efi.img" "$DIR/esp/EFI" ::/
  cat << "EOF" > "$DIR/main-root/EFI/debian/grub.cfg"
echo "This is /EFI/debian/grub.cfg from main file system (iso9660)"
echo "Testing shows that this file is loaded during UEFI-CD"
sleep 10
EOF
  # I don't know why this "$DIR/main-root/zero" is needed. Anyway this is just 
a demo
  dd if=/dev/zero of="$DIR/main-root/zero" bs=1M count=1
  xorriso -as mkisofs -b /zero -no-emul-boot --efi-boot /boot/grub/efi.img 
-efi-boot-part --efi-boot-image -o "$OUT" -r "$DIR/main-root"
  rm -r "$DIR"
  exit 0
}
====

While testing this script I noticed this: if I boot from disk (i. e. using 
"-drive" Qemu option), then "grub.cfg" is read from ESP, i. e. FAT. But if I 
boot from CD (i. e. using "-cdrom" Qemu option), then "grub.cfg" is read from 
main .iso partition, i. e. iso9660. I don't know whether this is expected 
behavior or just a bug.

FAT is case insensitive from GRUB point of view. But iso9660 is case sensitive. 
So, the file (in case of CD boot) must be named exactly /EFI/debian/grub.cfg. 
Name /efi/debian/grub.cfg will not work, I tested this. I. e. I replaced "EFI" 
with "efi" everywhere in the script above and I saw that in case of UEFI-CD 
file /efi/debian/grub.cfg is not read anymore. (Again: I checked in my 
experiments nearly all statements I made in this letter.)

So, grub-mkrescue is incompatible with Debian's signed GRUB image 
"grubx64.efi". So, if someone tries to create their custom .iso using 
grub-mkrescue with secure boot support with that grubx64.efi, they will likely 
fail. And they will have to resort to reimplementing grub-mkrescue (this is 
what I did with script above). For this reason I suggest replacing "efi" with 
"EFI" in grub-mkrescue.

You may say: "But why choose this signed binary? Debian has 3 other signed 
binaries". Yes, it has. But all these 3 binaries contain complicated logic for 
finding config. I don't like this. So I choose grubx64.efi for my personal GRUB 
disk. Yes, I can choose from other 3 binaries. But I still think that this 
patch is good thing. It allows one to choose grubx64.efi. I. e. this patch 
allows new uses without removing existing ones.

Also, I kindly ask for making new GRUB release after applying this patch. This 
is because I possibly will try to add secure boot support to Debian version of 
GRUB. So I need GRUB to be released first. Of course, if I do this, I will 
again think about what of these 4 binaries I should choose.

I send this letter to grub-devel. Also I CC Pete Batard, because it seems my 
work is somehow related to his work on grub-mkrescue ( 
https://lists.gnu.org/archive/html/grub-devel/2022-06/msg00024.html ). I CC 
Thomas Schmitt, because my work seems to be related to xorriso. I CC Adrian, 
because I think the problem I talk about is the problem, which prevented 
supergrubdisk from making image for CD with secure boot support ( 
https://github.com/supergrub/supergrub/commit/25414fcbbcb47c1d8616fa18d20409d570145b8f
 ).

Signed-off-by: Askar Safin <safinaskar@zohomail.com>
---
 util/grub-mkrescue.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/util/grub-mkrescue.c b/util/grub-mkrescue.c
index 6dc71a8a1..c78647ebe 100644
--- a/util/grub-mkrescue.c
+++ b/util/grub-mkrescue.c
@@ -771,8 +771,12 @@ main (int argc, char *argv[])
       || source_dirs[GRUB_INSTALL_PLATFORM_RISCV64_EFI])
     {
       FILE *f;
-      char *efidir_efi = grub_util_path_concat (2, iso9660_dir, "efi");
-      char *efidir_efi_boot = grub_util_path_concat (3, iso9660_dir, "efi", 
"boot");
+
+      /* This directory should be named "EFI", not "efi". See September 2024 
grub-devel discussion for details
+         ( https://lists.gnu.org/archive/html/grub-devel/2024-09/index.html )
+       */
+      char *efidir_efi = grub_util_path_concat (2, iso9660_dir, "EFI");
+      char *efidir_efi_boot = grub_util_path_concat (3, iso9660_dir, "EFI", 
"boot");
       char *imgname, *img32, *img64, *img_mac = NULL;
       char *efiimgfat, *iso_uuid_file, *diskdir, *diskdir_uuid;
       grub_install_mkdir_p (efidir_efi_boot);
-- 
2.43.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]