From 313a8e71910f3bf557ae1f4077ec92ace47ffe2e Mon Sep 17 00:00:00 2001 From: rabi Date: Mon, 27 Jul 2026 14:36:10 +0530 Subject: [PATCH] Patch bootc FIPS dracut boot handling bootc non-LUKS single-root deployments can fail FIPS boot because dracut's `01fips` module assumes `/boot` can be mounted read-only as a separate device. On bootc single-root layouts that mount can fail before the kernel HMAC check runs. Patch the image at build time so dracut falls back to bind-mounting the existing /boot tree when the default mount path fails. This is an image-side workaround for the current bootc single-root FIPS boot path; the underlying fix should eventually land upstream in dracut, bootc, or their interaction. Signed-off-by: rabi --- bootc/Containerfile | 4 +++ bootc/README.rst | 4 +++ bootc/patch-dracut-fips.py | 64 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+) create mode 100644 bootc/patch-dracut-fips.py diff --git a/bootc/Containerfile b/bootc/Containerfile index 4e02be0..78575dc 100644 --- a/bootc/Containerfile +++ b/bootc/Containerfile @@ -144,6 +144,10 @@ RUN --mount=type=secret,id=rhsm,dst=/var/tmp/rhsm-script.sh \ (subscription-manager unregister || true) && \ systemctl enable $ENABLE_UNITS +COPY patch-dracut-fips.py /usr/local/bin/patch-dracut-fips.py +RUN python3 /usr/local/bin/patch-dracut-fips.py && \ + bash -n /usr/lib/dracut/modules.d/01fips/fips.sh + # Configure FIPS ARG FIPS=1 diff --git a/bootc/README.rst b/bootc/README.rst index 0de328d..5c95bf7 100644 --- a/bootc/README.rst +++ b/bootc/README.rst @@ -28,6 +28,10 @@ then run the following commands:: To continue using CentOS Stream 9, leave the defaults in place and run ``make build`` (the default tag is ``latest``). +FIPS-enabled images include a build-time patch to dracut's ``01fips`` module +so bootc deployments on single-root layouts can bind-mount the existing +``/boot`` tree when the standard read-only device mount fails. + To build a RHEL 9 based bootc EDPM container image using internal repositories, install the required certificates then run the following commands:: diff --git a/bootc/patch-dracut-fips.py b/bootc/patch-dracut-fips.py new file mode 100644 index 0000000..bb8af91 --- /dev/null +++ b/bootc/patch-dracut-fips.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 + +"""Patch dracut's FIPS boot handling for bootc single-root layouts.""" + +from pathlib import Path +import re +import sys + + +FIPS_SH = Path("/usr/lib/dracut/modules.d/01fips/fips.sh") +PATTERNS = ( + re.compile( + r'(?ms)^([ \t]*)if ! mount -oro "\$boot" /boot; then\n' + r'(?:.*\n)*?^\1FIPS_MOUNTED_BOOT=1\n' + ), + re.compile( + r'(?m)^([ \t]*)mount -oro "\$boot" /boot \|\| return 1\n' + r'^\1FIPS_MOUNTED_BOOT=1\n' + ), +) + + +def main() -> int: + text = FIPS_SH.read_text() + + if 'Device mount failed, bind-mounting ${_bp} to /boot' in text: + print(f"{FIPS_SH} already patched") + return 0 + + match = pattern = None + for candidate in PATTERNS: + match = candidate.search(text) + if match: + pattern = candidate + break + + if not match or pattern is None: + print(f"expected mount_boot block not found in {FIPS_SH}", file=sys.stderr) + return 1 + + indent = match.group(1) + replacement = "\n".join([ + f'{indent}if ! mount -oro "$boot" /boot; then', + f'{indent} local _bp', + f'{indent} for _bp in /sysroot/sysroot/boot /sysroot/boot; do', + f'{indent} if [ -d "${{_bp}}/ostree" ]; then', + f'{indent} fips_info "Device mount failed, bind-mounting ${{_bp}} to /boot"', + f'{indent} if mount --bind "${{_bp}}" /boot; then', + f'{indent} break', + f'{indent} fi', + f'{indent} fi', + f'{indent} done', + f'{indent} ismounted /boot || return 1', + f'{indent}fi', + f'{indent}FIPS_MOUNTED_BOOT=1', + "", + ]) + FIPS_SH.write_text(pattern.sub(replacement, text, count=1)) + print(f"patched {FIPS_SH}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main())