]> git.ipfire.org Git - thirdparty/dracut.git/blobdiff - dracut.sh
feat(dracut): add --sbat option to add sbat policy to UKI
[thirdparty/dracut.git] / dracut.sh
index 1f6f0aee80c9904bbf8e74c1e62fbecc482f31af..fe2954a044d2ee7fc37f7314ffc2d4626c87c16a 100755 (executable)
--- a/dracut.sh
+++ b/dracut.sh
@@ -272,6 +272,10 @@ Creates initial ramdisk images for preloading modules
                         Use [FILE] as a splash image when creating an UEFI
                          executable. Requires bitmap (.bmp) image format.
   --kernel-image [FILE] Location of the kernel image.
+  --sbat [PARAMETERS]   The SBAT parameters to be added to .sbat.
+                         The string "sbat,1,SBAT Version,sbat,1,
+                         https://github.com/rhboot/shim/blob/main/SBAT.md" is
+                         already added by default.
   --regenerate-all      Regenerate all initramfs images at the default location
                          for the kernel versions found on the system.
   -p, --parallel        Use parallel processing if possible (currently only
@@ -463,6 +467,7 @@ rearrange_params() {
             --long uefi-stub: \
             --long uefi-splash-image: \
             --long kernel-image: \
+            --long sbat: \
             --long no-hostonly-i18n \
             --long hostonly-i18n \
             --long hostonly-nics: \
@@ -840,6 +845,11 @@ while :; do
             PARMS_TO_STORE+=" '$2'"
             shift
             ;;
+        --sbat)
+            sbat_l="$2"
+            PARMS_TO_STORE+=" '$2'"
+            shift
+            ;;
         --no-machineid)
             machine_id_l="no"
             ;;
@@ -1079,6 +1089,7 @@ drivers_dir="${drivers_dir%"${drivers_dir##*[!/]}"}"
 [[ $uefi_stub_l ]] && uefi_stub="$uefi_stub_l"
 [[ $uefi_splash_image_l ]] && uefi_splash_image="$uefi_splash_image_l"
 [[ $kernel_image_l ]] && kernel_image="$kernel_image_l"
+[[ $sbat_l ]] && sbat="$sbat_l"
 [[ $machine_id_l ]] && machine_id="$machine_id_l"
 
 if ! [[ $outfile ]]; then
@@ -1087,8 +1098,9 @@ if ! [[ $outfile ]]; then
             || [[ -d "$dracutsysrootdir"/boot/Default ]] \
             || [[ -d "$dracutsysrootdir"/boot/efi/Default ]]; then
             MACHINE_ID="Default"
-        elif [[ -f "$dracutsysrootdir"/etc/machine-id ]]; then
+        elif [[ -s "$dracutsysrootdir"/etc/machine-id ]]; then
             read -r MACHINE_ID < "$dracutsysrootdir"/etc/machine-id
+            [[ $MACHINE_ID == "uninitialized" ]] && MACHINE_ID="Default"
         else
             MACHINE_ID="Default"
         fi
@@ -1376,8 +1388,7 @@ dinfo "Executing: $dracut_cmd ${dracut_args[*]}"
 
 [[ $do_list == yes ]] && {
     for mod in "$dracutbasedir"/modules.d/*; do
-        [[ -d $mod ]] || continue
-        [[ -e $mod/install || -e $mod/installkernel || -e $mod/module-setup.sh ]] || continue
+        [[ -e $mod/module-setup.sh ]] || continue
         printf "%s\n" "${mod##*/??}"
     done
     exit 0
@@ -1391,12 +1402,13 @@ esac
 abs_outfile=$(readlink -f "$outfile") && outfile="$abs_outfile"
 
 # Helper function to set global variables
-# set_global_var <pkg_config> <var> <value[:check_file]> [<value[:check_file]>] ...
+# set_global_var <pkg_config> <pkg_var[:exported_var]> <value[:check_file]> [<value[:check_file]>] ...
 set_global_var() {
     local _pkgconfig="$1"
-    local _var="$2"
+    local _pkgvar="${2%:*}"
+    local _var="${2#*:}"
     [[ -z ${!_var} || ! -d ${dracutsysrootdir}${!_var} ]] \
-        && export "$_var"="$(pkg-config "$_pkgconfig" --variable="$_var" 2> /dev/null)"
+        && export "$_var"="$(pkg-config "$_pkgconfig" --variable="$_pkgvar" 2> /dev/null)"
     if [[ -z ${!_var} || ! -d ${dracutsysrootdir}${!_var} ]]; then
         shift 2
         if (($# == 1)); then
@@ -1433,6 +1445,7 @@ set_global_var "udev" "udevrulesdir" "${udevdir}/rules.d"
 set_global_var "udev" "udevrulesconfdir" "${udevconfdir}/rules.d"
 
 # systemd global variables
+set_global_var "systemd" "prefix:systemdprefix" "/usr"
 set_global_var "systemd" "systemdutildir" "/lib/systemd:/lib/systemd/systemd-udevd" "/usr/lib/systemd:/usr/lib/systemd/systemd-udevd"
 set_global_var "systemd" "systemdutilconfdir" "/etc/systemd"
 set_global_var "systemd" "environment" "/usr/lib/environment.d"
@@ -1523,7 +1536,7 @@ if [[ ! $print_cmdline ]]; then
         esac
 
         if ! [[ -s $uefi_stub ]]; then
-            uefi_stub="$dracutsysrootdir${systemdutildir}/boot/efi/linux${EFI_MACHINE_TYPE_NAME}.efi.stub"
+            uefi_stub="$dracutsysrootdir${systemdprefix}/lib/systemd/boot/efi/linux${EFI_MACHINE_TYPE_NAME}.efi.stub"
         fi
 
         if ! [[ -s $uefi_stub ]]; then
@@ -2081,7 +2094,7 @@ done
 
 if [[ $do_hardlink == yes ]] && command -v hardlink > /dev/null; then
     dinfo "*** Hardlinking files ***"
-    hardlink "$initdir" 2>&1 | dinfo
+    hardlink "$initdir" 2>&1 | ddebug
     dinfo "*** Hardlinking files done ***"
 fi
 
@@ -2450,6 +2463,24 @@ fi
 
 umask 077
 
+SBAT_DEFAULT="sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md"
+sbat_out=$uefi_outdir/uki.sbat
+
+clean_sbat_string() {
+    local inp=$1
+    local temp=$uefi_outdir/temp.sbat
+    sed "/${SBAT_DEFAULT//\//\\/}/d" "$inp" > "$temp"
+    [[ -s $temp ]] && cat "$temp" >> "$sbat_out"
+    rm "$temp"
+}
+
+get_sbat_string() {
+    local inp=$1
+    local out=$uefi_outdir/$2
+    objcopy -O binary --only-section=.sbat "$inp" "$out"
+    clean_sbat_string "$out"
+}
+
 if [[ $uefi == yes ]]; then
     if [[ $kernel_cmdline ]]; then
         echo -n "$kernel_cmdline" > "$uefi_outdir/cmdline.txt"
@@ -2464,7 +2495,7 @@ if [[ $uefi == yes ]]; then
         fi
     fi
 
-    offs=$(objdump -h "$uefi_stub" 2> /dev/null | awk 'NF==7 {size=strtonum("0x"$3);\
+    offs=$(objdump -h "$uefi_stub" 2> /dev/null | gawk 'NF==7 {size=strtonum("0x"$3);
                 offset=strtonum("0x"$4)} END {print size + offset}')
     if [[ $offs -eq 0 ]]; then
         dfatal "Failed to get the size of $uefi_stub to create UEFI image file"
@@ -2472,7 +2503,7 @@ if [[ $uefi == yes ]]; then
     fi
     align=$(pe_get_section_align "$uefi_stub")
     if [[ $? -eq 1 ]]; then
-        dfatal "Failed to get the sectionAlignment of the stub PE header to create the UEFI image file"
+        dfatal "Failed to get the SectionAlignment of the stub PE header to create the UEFI image file"
         exit 1
     fi
     offs=$((offs + "$align" - offs % "$align"))
@@ -2504,18 +2535,40 @@ if [[ $uefi == yes ]]; then
         unset uefi_splash_image
     fi
 
+    echo "$SBAT_DEFAULT" > "$sbat_out"
+    if [[ -n $sbat ]]; then
+        echo "$sbat" | sed "/${SBAT_DEFAULT//\//\\/}/d" >> "$sbat_out"
+    fi
+    get_sbat_string "$kernel_image" kernel.sbat
+    get_sbat_string "$uefi_stub" stub.sbat
+
+    uefi_sbat_offs="${offs}"
+    offs=$((offs + $(stat -Lc%s "$sbat_out")))
+    offs=$((offs + "$align" - offs % "$align"))
     uefi_linux_offs="${offs}"
     offs=$((offs + $(stat -Lc%s "$kernel_image")))
     offs=$((offs + "$align" - offs % "$align"))
     uefi_initrd_offs="${offs}"
 
+    base_image=$(pe_get_image_base "$uefi_stub")
+    if [[ $? -eq 1 ]]; then
+        dfatal "Failed to get ImageBase data of $uefi_stub to create UEFI image file"
+        exit 1
+    fi
+
+    tmp_uefi_stub=$uefi_outdir/elf.stub
+    cp "$uefi_stub" "$tmp_uefi_stub"
+    objcopy --remove-section .sbat "$tmp_uefi_stub" &> /dev/null
+
     if objcopy \
         ${uefi_osrelease:+--add-section .osrel="$uefi_osrelease" --change-section-vma .osrel=$(printf 0x%x "$uefi_osrelease_offs")} \
         ${uefi_cmdline:+--add-section .cmdline="$uefi_cmdline" --change-section-vma .cmdline=$(printf 0x%x "$uefi_cmdline_offs")} \
         ${uefi_splash_image:+--add-section .splash="$uefi_splash_image" --change-section-vma .splash=$(printf 0x%x "$uefi_splash_offs")} \
+        --add-section .sbat="$sbat_out" --change-section-vma .sbat="$(printf 0x%x "$uefi_sbat_offs")" \
         --add-section .linux="$kernel_image" --change-section-vma .linux="$(printf 0x%x "$uefi_linux_offs")" \
         --add-section .initrd="${DRACUT_TMPDIR}/initramfs.img" --change-section-vma .initrd="$(printf 0x%x "$uefi_initrd_offs")" \
-        "$uefi_stub" "${uefi_outdir}/linux.efi"; then
+        --image-base="$(printf 0x%x "$base_image")" \
+        "$tmp_uefi_stub" "${uefi_outdir}/linux.efi"; then
         if [[ -n ${uefi_secureboot_key} && -n ${uefi_secureboot_cert} ]]; then
             if sbsign \
                 ${uefi_secureboot_engine:+--engine "$uefi_secureboot_engine"} \
@@ -2584,6 +2637,9 @@ freeze_ok_for_fstype() {
         zfs)
             return 1
             ;;
+        tmpfs)
+            return 1
+            ;;
         btrfs)
             freeze_ok_for_btrfs "$outfile"
             ;;