From 492bc949e16f78fad9f274744c72bc2fd0161d84 Mon Sep 17 00:00:00 2001 From: Vitaly Kuznetsov Date: Fri, 9 Aug 2024 12:49:05 +0200 Subject: [PATCH] feat(fips): add support for UKIs Kernel integrity check in FIPS module is incompatible with UKIs as neither /boot/vmlinuz-`uname-r` nor /boot/.vmlinuz-`uname-r`.hmac are present. UKI is placed to $ESP\EFI\Linux\-.efi and if a .hmac file is present next to it, it is possible to do similar check. Note, UKIs have a 'one size fits all' command line and 'boot=' is not expected to be set. Luckily, if the UKI is systemd-stub based then we can expect 'LoaderDevicePartUUID' variable containing PARTUUID of the ESP to be set. Mount it to /boot using the existing logic. Signed-off-by: Vitaly Kuznetsov (cherry picked from commit 72684ff519be4f29c45cbb0f84759e645b0ac4be) Resolves: RHEL-56885 --- modules.d/01fips/fips.sh | 51 ++++++++++++++++++++++++++++++++++++++++ modules.d/01fips/module-setup.sh | 2 +- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/modules.d/01fips/fips.sh b/modules.d/01fips/fips.sh index 05631c8a..3889dc0c 100755 --- a/modules.d/01fips/fips.sh +++ b/modules.d/01fips/fips.sh @@ -14,9 +14,22 @@ else } fi +# Checks if a systemd-based UKI is running and ESP UUID is set +is_uki() { + [ -f /sys/firmware/efi/efivars/StubFeatures-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f ] \ + && [ -f /sys/firmware/efi/efivars/LoaderDevicePartUUID-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f ] +} + mount_boot() { boot=$(getarg boot=) + if is_uki && [ -z "$boot" ]; then + # efivar file has 4 bytes header and contain UCS-2 data. Note, 'cat' is required + # as sys/firmware/efi/efivars/ files are 'special' and don't allow 'seeking'. + # shellcheck disable=SC2002 + boot="PARTUUID=$(cat /sys/firmware/efi/efivars/LoaderDevicePartUUID-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f | tail -c +5 | tr -d '\0' | tr 'A-F' 'a-f')" + fi + if [ -n "$boot" ]; then if [ -d /boot ] && ismounted /boot; then boot_dev= @@ -81,6 +94,41 @@ do_rhevh_check() { return 0 } +do_uki_check() { + local KVER + local uki_checked=0 + + KVER="$(uname -r)" + # UKI are placed in $ESP\EFI\Linux\-.efi + if ! [ "$FIPS_MOUNTED_BOOT" = 1 ]; then + warn "Failed to mount ESP for doing UKI integrity check" + return 1 + fi + + for UKIpath in /boot/EFI/Linux/*-"$KVER".efi; do + # UKIs are installed to $ESP/EFI/Linux/-.efi + # and in some cases (e.g. when the image is used as a template for creating new + # VMs) entry-token-or-machine-id can change. To make sure the running UKI is + # always checked, check all UKIs which match the 'uname -r' of the running kernel + # and fail the whole check if any of the matching UKIs are corrupted. + + [ -r "$UKIpath" ] || break + + local UKI="${UKIpath##*/}" + local UKIHMAC=."$UKI".hmac + + fips_info "checking $UKIHMAC" + (cd /boot/EFI/Linux/ && sha512hmac -c "$UKIHMAC") || return 1 + uki_checked=1 + done + + if [ "$uki_checked" = 0 ]; then + warn "Failed for find UKI for checking" + return 1 + fi + return 0 +} + nonfatal_modprobe() { modprobe "$1" 2>&1 > /dev/stdout \ | while read -r line || [ -n "$line" ]; do @@ -133,6 +181,9 @@ do_fips() { elif [ -e "/run/install/repo/images/pxeboot/vmlinuz" ]; then # This is a boot.iso with the .hmac inside the install.img do_rhevh_check /run/install/repo/images/pxeboot/vmlinuz || return 1 + elif is_uki; then + # This is a UKI + do_uki_check || return 1 else BOOT_IMAGE="$(getarg BOOT_IMAGE)" diff --git a/modules.d/01fips/module-setup.sh b/modules.d/01fips/module-setup.sh index 91612ff3..a090bc88 100755 --- a/modules.d/01fips/module-setup.sh +++ b/modules.d/01fips/module-setup.sh @@ -67,7 +67,7 @@ install() { inst_hook pre-udev 01 "$moddir/fips-load-crypto.sh" inst_script "$moddir/fips.sh" /sbin/fips.sh - inst_multiple sha512hmac rmmod insmod mount uname umount grep sed sort + inst_multiple sha512hmac rmmod insmod mount uname umount grep sed cut find sort cat tail tr inst_simple /etc/system-fips