Skip to content

Commit

Permalink
feat(fips): add support for UKIs
Browse files Browse the repository at this point in the history
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\<install-tag>-<uname-r>.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 <[email protected]>

(cherry picked from commit 72684ff519be4f29c45cbb0f84759e645b0ac4be)

Resolves: RHEL-56885
  • Loading branch information
vittyvk authored and pvalena committed Nov 27, 2024
1 parent cb1c0c9 commit e843e16
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 1 deletion.
51 changes: 51 additions & 0 deletions modules.d/01fips/fips.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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=
Expand Down Expand Up @@ -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\<intall-tag>-<uname-r>.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/<entry-token-or-machine-id>-<uname-r>.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
Expand Down Expand Up @@ -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)"

Expand Down
2 changes: 1 addition & 1 deletion modules.d/01fips/module-setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down

0 comments on commit e843e16

Please sign in to comment.