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
This commit is contained in:
Julia Kreger 2023-03-02 08:43:50 -08:00
parent 47dc5a9834
commit 4633da7750
4 changed files with 53 additions and 1 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.