From 4633da7750342df3488fcdf4861f4308647557ac Mon Sep 17 00:00:00 2001 From: Julia Kreger Date: Thu, 2 Mar 2023 08:43:50 -0800 Subject: [PATCH] Correct boot path to cover FIPS usage cases When your booting a Linux system using dracut, i.e. with any redhat style distribution, dracut's internal code looks to validate the kernel hmac signature in before proceeding to userspace. It does this by looking at the /boot/ folder file for the kernel hmac file. And it normally does this with the root filesystem. Except if the kernel is not on the root filesystem and is instead on a /boot filesystem, this breaks horribly. This is compounded because DIB enables the operator to restructure the OS image/layout to fit their needs. In order for this to be navigated, as dracut is written, we need to pass a "boot=" argument to the kernel. So now we attempt to purge any prior boot entry in the disk image content, which is good because any filesystem operations invalidate it, and then we attempt to identify the boot filesystem, and save a boot kernel command line parameter so the resulting image can boot properly if FIPS was enabled in the prior image. Regex developed with https://sed.js.org utilizing stdin: VAR="quiet boot=UUID=173c759f-1302-48a3-9d51-a17784c21e03 text" VAR="quiet boot=PARTUUID=173c759f-1302-48a3-9d51-a17784c21e03" VAR="quiet boot=PARTUUID=173c759f-1302-48a3-9d51-a17784c21e03 reboot=meow" VAR="quiet boot=UUID=/dev/sda1 text" VAR="quiet boot=/dev/sda1" VAR="quiet boot=/dev/sda1 reboot=meow" VAR="quiet after_boot=1 reboot=meow boot=/dev/sda1" VAR="quiet after_boot=1 reboot=meow" Which resulted in stdout: VAR="quiet text" VAR="quiet" VAR="quiet reboot=meow" VAR="quiet text" VAR="quiet" VAR="quiet reboot=meow" VAR="quiet after_boot=1 reboot=meow" VAR="quiet after_boot=1 reboot=meow" Change-Id: I9034c21e84deda2ba2c0ec0d1d6d6595ed10bed4 --- diskimage_builder/block_device/blockdevice.py | 14 +++++++++++ .../bootloader/finalise.d/50-bootloader | 25 ++++++++++++++++++- diskimage_builder/lib/disk-image-create | 5 ++++ ...t-kernel-commandline-1f94e49884c517c0.yaml | 10 ++++++++ 4 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 releasenotes/notes/fix-grub-boot-kernel-commandline-1f94e49884c517c0.yaml diff --git a/diskimage_builder/block_device/blockdevice.py b/diskimage_builder/block_device/blockdevice.py index 8b859310..99f23be9 100644 --- a/diskimage_builder/block_device/blockdevice.py +++ b/diskimage_builder/block_device/blockdevice.py @@ -316,6 +316,20 @@ class BlockDevice(object): print("%s" % root_fs['type']) return 0 + if symbol == "boot-label": + try: + boot_mount = self._config_get_mount("/boot") + boot_fs = self._config_get_mkfs(boot_mount['base']) + # If not explicitly defined, we appear to fallback + # to name for a label, which we can only get from the + # resulting filesystem config. + boot_label = boot_fs.get('label', boot_fs.get('name', '')) + except AssertionError: + boot_label = '' + logger.debug("boot-label [%s]", boot_label) + print("%s" % boot_label) + return 0 + if symbol == 'mount-points': mount_points = self._config_get_all_mount_points() # we return the mountpoints joined by a pipe, because it is not diff --git a/diskimage_builder/elements/bootloader/finalise.d/50-bootloader b/diskimage_builder/elements/bootloader/finalise.d/50-bootloader index 3e243325..d1956723 100755 --- a/diskimage_builder/elements/bootloader/finalise.d/50-bootloader +++ b/diskimage_builder/elements/bootloader/finalise.d/50-bootloader @@ -88,6 +88,29 @@ echo "GRUB_TIMEOUT=${DIB_GRUB_TIMEOUT:-5}" >>/etc/default/grub echo 'GRUB_TERMINAL="serial console"' >>/etc/default/grub echo 'GRUB_GFXPAYLOAD_LINUX=auto' >>/etc/default/grub +# NOTE(TheJulia): We need to remove any boot entry from the /etc/default/grub +# file that may already exist, such as what was added by fips being setup on +# either in the source image or by by an element, as we repack the image. +# with new filesystems. +# Matches any element which looks like " boot=" and the associated value +# in order for us to have a clean starting point to put a value in place, +# if applicable. +# Removes entry trailing with a space, or any entry where boot is set as +# the last argument on the line. +sed -i 's/\ boot=[0-9A-Za-z/=\-]\+//' /etc/default/grub +# NOTE(TheJulia): When using FIPS, dracut wants to evaluate +# the hmac files for the kernel checksum. However, if /boot is +# located on a separate filesystem from the root filesystem, +# than this fails. As a result, we need to identify IF /boot +# is a separate filesystem, and convey this fact as a boot +# argument so dracut does not halt the system on boot. + +if [[ -n "${DIB_BOOT_LABEL}" ]]; then + BOOT_FS="boot=LABEL=${DIB_BOOT_LABEL}" +else + BOOT_FS="" +fi + if [[ -n "${DIB_BOOTLOADER_SERIAL_CONSOLE}" ]]; then SERIAL_CONSOLE="${DIB_BOOTLOADER_SERIAL_CONSOLE}" elif [[ "powerpc ppc64 ppc64le" =~ "$ARCH" ]]; then @@ -100,7 +123,7 @@ else fi GRUB_CMDLINE_LINUX_DEFAULT="console=tty0 console=${SERIAL_CONSOLE} no_timer_check" -echo "GRUB_CMDLINE_LINUX_DEFAULT=\"${GRUB_CMDLINE_LINUX_DEFAULT} ${DIB_BOOTLOADER_DEFAULT_CMDLINE}\"" >>/etc/default/grub +echo "GRUB_CMDLINE_LINUX_DEFAULT=\"${GRUB_CMDLINE_LINUX_DEFAULT} ${DIB_BOOTLOADER_DEFAULT_CMDLINE} ${BOOT_FS}\"" >>/etc/default/grub echo 'GRUB_SERIAL_COMMAND="serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1"' >>/etc/default/grub # os-prober leaks /dev/sda into config file in dual-boot host diff --git a/diskimage_builder/lib/disk-image-create b/diskimage_builder/lib/disk-image-create index d5a0396e..a79686a4 100644 --- a/diskimage_builder/lib/disk-image-create +++ b/diskimage_builder/lib/disk-image-create @@ -343,6 +343,11 @@ export DIB_ROOT_LABEL DIB_ROOT_FSTYPE=$(${DIB_BLOCK_DEVICE} getval root-fstype) export DIB_ROOT_FSTYPE +# Need to get the boot device label because, if defined, we may +# need to update boot configuration in some cases +DIB_BOOT_LABEL=$(${DIB_BLOCK_DEVICE} getval boot-label) +export DIB_BOOT_LABEL + # retrieve mount points so we can reuse in elements DIB_MOUNTPOINTS=$(${DIB_BLOCK_DEVICE} getval mount-points) export DIB_MOUNTPOINTS diff --git a/releasenotes/notes/fix-grub-boot-kernel-commandline-1f94e49884c517c0.yaml b/releasenotes/notes/fix-grub-boot-kernel-commandline-1f94e49884c517c0.yaml new file mode 100644 index 00000000..51682fea --- /dev/null +++ b/releasenotes/notes/fix-grub-boot-kernel-commandline-1f94e49884c517c0.yaml @@ -0,0 +1,10 @@ +--- +fixes: + - | + Fixes the GRUB2 bootloader kernel command line where a prior ``boot`` + parameter could cause issues with bootloader configuration when + an image is rebuilt and the ``bootloader`` element is utilized. + We now remove any prior ``boot`` parameter in */etc/default/grub* + when executing the ``bootloader`` element, and then assert a + valid entry ``boot`` parameter if a */boot* partition is defined + as part of the image build.