diff --git a/overlay.d/05core/usr/lib/dracut/modules.d/35coreos-ignition/coreos-boot-edit.service b/overlay.d/05core/usr/lib/dracut/modules.d/35coreos-ignition/coreos-boot-edit.service index bc2d9ec9ea..ad9a66b34e 100644 --- a/overlay.d/05core/usr/lib/dracut/modules.d/35coreos-ignition/coreos-boot-edit.service +++ b/overlay.d/05core/usr/lib/dracut/modules.d/35coreos-ignition/coreos-boot-edit.service @@ -10,8 +10,13 @@ OnFailureJobMode=isolate # Since we are mounting /boot, require the device first. This isn't strictly # necessary since we run late, but on principle let's make clear the dependency. -Requires=dev-disk-by\x2dlabel-boot.device -After=dev-disk-by\x2dlabel-boot.device + +# Requires=dev-disk-by\x2dlabel-boot.device +# After=dev-disk-by\x2dlabel-boot.device + +After=boot-part-discovered.target +ConditionFileNotEmpty=/run/coreos/boot-partition-status + # Start after Ignition has finished After=ignition-files.service # As above, this isn't strictly necessary, but on principle. diff --git a/overlay.d/05core/usr/lib/dracut/modules.d/35coreos-ignition/coreos-diskful-generator b/overlay.d/05core/usr/lib/dracut/modules.d/35coreos-ignition/coreos-diskful-generator index b869866431..1d741853c3 100755 --- a/overlay.d/05core/usr/lib/dracut/modules.d/35coreos-ignition/coreos-diskful-generator +++ b/overlay.d/05core/usr/lib/dracut/modules.d/35coreos-ignition/coreos-diskful-generator @@ -109,8 +109,8 @@ mkdir -p "${UNIT_DIR}/coreos-ignition-setup-user.service.d" mkdir -p "${UNIT_DIR}/coreos-copy-firstboot-network.service.d" cat > "${UNIT_DIR}/coreos-ignition-setup-user.service.d/diskful.conf" < "${UNIT_DIR}/ostree-prepare-root.service.d/10-live.conf" < "${UNIT_DIR}/coreos-root-setup.service.d/10-live.conf" < "$BOOT_STATUS_FILE" + else + echo "Boot partition not found" + fi +fi diff --git a/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-check-rootfs-size.service b/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-check-rootfs-size.service index 340b4d4251..9d29bdc5c1 100644 --- a/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-check-rootfs-size.service +++ b/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-check-rootfs-size.service @@ -2,11 +2,12 @@ Description=Ignition OSTree: Check Root Filesystem Size Documentation=https://docs.fedoraproject.org/en-US/fedora-coreos/storage/ DefaultDependencies=false -ConditionKernelCommandLine=ostree +ConditionKernelCommandLine=|ostree +ConditionKernelCommandLine=|composefs ConditionPathExists=!/run/ostree-live After=ignition-ostree-growfs.service -After=ostree-prepare-root.service -Requires=ostree-prepare-root.service +After=coreos-root-setup.service +Requires=coreos-root-setup.service # Allow Ignition config to blank out the warning Before=ignition-files.service diff --git a/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-growfs.service b/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-growfs.service index 3674431ff8..1ea3084b9f 100644 --- a/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-growfs.service +++ b/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-growfs.service @@ -1,7 +1,8 @@ [Unit] Description=Ignition OSTree: Grow Root Filesystem DefaultDependencies=false -ConditionKernelCommandLine=ostree +ConditionKernelCommandLine=|ostree +ConditionKernelCommandLine=|composefs ConditionPathExists=!/run/ostree-live Before=initrd-root-fs.target Before=sysroot.mount diff --git a/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-mount-var.service b/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-mount-var.service index 09d6c15ab3..1cb3d39d14 100644 --- a/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-mount-var.service +++ b/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-mount-var.service @@ -1,6 +1,7 @@ [Unit] Description=Mount OSTree /var DefaultDependencies=false +# We do not need this for composefs ConditionKernelCommandLine=ostree ConditionPathExists=!/run/ostree-live diff --git a/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-transposefs-autosave-xfs.service b/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-transposefs-autosave-xfs.service index e955c4a69a..8a5272b752 100644 --- a/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-transposefs-autosave-xfs.service +++ b/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-transposefs-autosave-xfs.service @@ -13,7 +13,8 @@ Before=ignition-ostree-transposefs-restore.service OnFailure=emergency.target OnFailureJobMode=isolate -ConditionKernelCommandLine=ostree +ConditionKernelCommandLine=|ostree +ConditionKernelCommandLine=|composefs # only run if ignition-ostree-growfs ran since that's when pathological cases occur ConditionPathExists=/run/ignition-ostree-growfs.stamp diff --git a/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-transposefs-detect.service b/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-transposefs-detect.service index 389dc9eedf..cde1efd379 100644 --- a/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-transposefs-detect.service +++ b/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-transposefs-detect.service @@ -5,7 +5,8 @@ After=ignition-fetch.service Before=ignition-disks.service Before=initrd-root-fs.target Before=sysroot.mount -ConditionKernelCommandLine=ostree +ConditionKernelCommandLine=|ostree +ConditionKernelCommandLine=|composefs OnFailure=emergency.target OnFailureJobMode=isolate diff --git a/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-transposefs-restore.service b/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-transposefs-restore.service index eef3c064c7..349155ce0d 100644 --- a/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-transposefs-restore.service +++ b/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-transposefs-restore.service @@ -12,7 +12,8 @@ Before=sysroot.mount OnFailure=emergency.target OnFailureJobMode=isolate -ConditionKernelCommandLine=ostree +ConditionKernelCommandLine=|ostree +ConditionKernelCommandLine=|composefs ConditionPathIsDirectory=/run/ignition-ostree-transposefs [Service] diff --git a/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-transposefs-save.service b/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-transposefs-save.service index bc03499ecb..02b8d5478a 100644 --- a/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-transposefs-save.service +++ b/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-transposefs-save.service @@ -3,7 +3,8 @@ Description=Ignition OSTree: Save Partitions DefaultDependencies=false After=ignition-ostree-transposefs-detect.service Before=ignition-disks.service -ConditionKernelCommandLine=ostree +ConditionKernelCommandLine=|ostree +ConditionKernelCommandLine=|composefs ConditionPathIsDirectory=/run/ignition-ostree-transposefs # Any services looking at mounts need to order after this # because it causes device re-probing. diff --git a/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-transposefs.sh b/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-transposefs.sh index 7bec45c936..e21c7bca5a 100755 --- a/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-transposefs.sh +++ b/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-transposefs.sh @@ -306,9 +306,32 @@ case "${1:-}" in if [ -d "${saved_root}" ]; then echo "Restoring rootfs from RAM..." mount_and_restore_filesystem_by_label root /sysroot "${saved_root}" + chcon -v --reference "${saved_root}" /sysroot # the root of the fs itself - chattr +i $(ls -d /sysroot/ostree/deploy/*/deploy/*/) + + cfs_digest=$(karg composefs) + + if [[ "$cfs_digest" == "" ]]; then + chattr +i $(ls -d /sysroot/ostree/deploy/*/deploy/*/) + elif [[ ${cfs_digest:0:1} != "?" ]]; then + echo "Re-enabling fsverity on composefs repo..." + # tmpfs has no fsverity, so we need to reenable fsverity + hash_alg="" + + if [[ $cfs_digest =~ ^[0-9a-fA-F]{64}$ ]]; then + hash_alg="sha256" + elif [[ $cfs_digest =~ ^[0-9a-fA-F]{128}$ ]]; then + hash_alg="sha512" + else + echo "Bad verity in cmdline '$cfs_digest'" + exit 1 + fi + + echo "Enabling fs-verity again..." + find /sysroot/composefs/objects -type f -exec fsverity enable {} --hash-alg $hash_alg \; + fi fi + if [ -d "${saved_boot}" ]; then echo "Restoring bootfs from RAM..." mount_and_restore_filesystem_by_label boot /sysroot/boot "${saved_boot}" diff --git a/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-uuid-boot.service b/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-uuid-boot.service index 85448c2a67..7ce368ad80 100644 --- a/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-uuid-boot.service +++ b/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-uuid-boot.service @@ -13,9 +13,14 @@ Before=ignition-kargs.service # If we're going to reprovision the bootfs, then there's no need to restamp ConditionKernelCommandLine=!bootfs.roothash +# TODO(Johan-Lieber1): This Before=systemd-fsck@dev-disk-by\x2dlabel-boot.service -Requires=dev-disk-by\x2dlabel-boot.device -After=dev-disk-by\x2dlabel-boot.device +# Requires=dev-disk-by\x2dlabel-boot.device +# After=dev-disk-by\x2dlabel-boot.device + +# Make sure boot partition actually exists +After=boot-part-discovered.target +ConditionFileNotEmpty=/run/coreos/boot-partition-status [Service] Type=oneshot diff --git a/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-uuid-root.service b/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-uuid-root.service index 80ecf9d42a..0198a81961 100644 --- a/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-uuid-root.service +++ b/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-uuid-root.service @@ -2,7 +2,8 @@ Description=Ignition OSTree: Regenerate Filesystem UUID (root) # These conditions match those generated in coreos-diskful-generator DefaultDependencies=false -ConditionKernelCommandLine=ostree +ConditionKernelCommandLine=|ostree +ConditionKernelCommandLine=|composefs ConditionPathExists=!/run/ostree-live Before=sysroot.mount initrd-root-fs.target After=ignition-disks.service diff --git a/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/module-setup.sh b/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/module-setup.sh index ba22090993..7cbcbce1a8 100755 --- a/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/module-setup.sh +++ b/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/module-setup.sh @@ -77,7 +77,8 @@ install() { rm \ sed \ sfdisk \ - find + find \ + fsverity # In some cases we had to vendor gdisk in Ignition. # If this is the case here use that one. @@ -121,5 +122,11 @@ install() { inst_script "$moddir/ignition-ostree-mount-state-overlays.sh" \ /usr/libexec/ignition-ostree-mount-state-overlays + inst_simple "$moddir/boot-part-discovery.target" "$systemdsystemunitdir/boot-part-discovery.target" + + install_ignition_unit boot-part-discovery.service + inst_script "$moddir/boot-part-discovery.sh" \ + /usr/libexec/boot-part-discovery.sh + inst_script "$moddir/coreos-relabel" /usr/bin/coreos-relabel } diff --git a/overlay.d/05core/usr/lib/systemd/system-generators/coreos-boot-mount-generator b/overlay.d/05core/usr/lib/systemd/system-generators/coreos-boot-mount-generator index 7955f903ac..87fc29482f 100755 --- a/overlay.d/05core/usr/lib/systemd/system-generators/coreos-boot-mount-generator +++ b/overlay.d/05core/usr/lib/systemd/system-generators/coreos-boot-mount-generator @@ -3,6 +3,7 @@ export PATH="/usr/bin:/usr/sbin:${PATH}" set -euo pipefail . /usr/lib/coreos/generator-lib.sh +. /usr/libexec/boot-part-discovery.sh # Turn out if you boot with "root=..." $UNIT_DIR is not writable. [ -w "${UNIT_DIR}" ] || { @@ -31,6 +32,16 @@ if [ "${rootfstype}" = "virtiofs" ]; then exit 0 fi +# Do not create dynamic mount service for /boot if there +# is no /boot partition +# +# Using just After=boot-part-discovery.target won't work +# as we have What=/dev/disk/by-label/boot in the Mount section +# which prompts systemd to wait for udev +if ! boot_part_exists; then + exit 0 +fi + add_wants() { local name="$1"; shift local wants_dir="${UNIT_DIR}/local-fs.target.wants" diff --git a/overlay.d/05core/usr/lib/systemd/system/coreos-ignition-firstboot-complete.service b/overlay.d/05core/usr/lib/systemd/system/coreos-ignition-firstboot-complete.service index be0456fa22..7f615b39ed 100644 --- a/overlay.d/05core/usr/lib/systemd/system/coreos-ignition-firstboot-complete.service +++ b/overlay.d/05core/usr/lib/systemd/system/coreos-ignition-firstboot-complete.service @@ -6,8 +6,6 @@ ConditionPathExists=!/run/ostree-live # This condition is required for cases where a soft-reboot is issued on the # firstboot. Soft reboot do not change the kernel or its command-line arguments, # which would cause this service to fail after the soft-reboot completes. -ConditionPathExists=/boot/ignition.firstboot -RequiresMountsFor=/boot [Service] Type=oneshot diff --git "a/overlay.d/05core/usr/lib/systemd/system/systemd-fsck@dev-disk-by\\x2dlabel-boot.service.d/override.conf" "b/overlay.d/05core/usr/lib/systemd/system/systemd-fsck@dev-disk-by\\x2dlabel-boot.service.d/override.conf" new file mode 100644 index 0000000000..b36c5fb9dd --- /dev/null +++ "b/overlay.d/05core/usr/lib/systemd/system/systemd-fsck@dev-disk-by\\x2dlabel-boot.service.d/override.conf" @@ -0,0 +1,3 @@ +[Unit] +After=boot-part-discovered.target +ConditionFileNotEmpty=/run/coreos/boot-partition-status diff --git a/overlay.d/05core/usr/libexec/coreos-ignition-firstboot-complete b/overlay.d/05core/usr/libexec/coreos-ignition-firstboot-complete index e1963f08d8..40424c67b8 100755 --- a/overlay.d/05core/usr/libexec/coreos-ignition-firstboot-complete +++ b/overlay.d/05core/usr/libexec/coreos-ignition-firstboot-complete @@ -1,17 +1,127 @@ #!/bin/bash set -euo pipefail -mount -o remount,rw /boot +ESP_MOUNT=/var/tmp/efi -# We're done provisioning. Remove the whole /boot/ignition directory if present, -# which may include a baked Ignition config. See -# https://github.com/coreos/fedora-coreos-tracker/issues/889. -rm -rf /boot/ignition +BOOTC_STATUS="$(bootc status --json)" -# Regarding the lack of `-f` for rm ; we should have only run if GRUB detected -# this file. Fail if we are unable to remove it, rather than risking rerunning -# Ignition at next boot. -rm /boot/ignition.firstboot +IS_COMPOSEFS=false +BOOTLOADER="" +BOOT_TYPE="" + +if [[ $(jq -r '.status.booted.composefs' <<< "$BOOTC_STATUS") != null ]]; then + IS_COMPOSEFS=true + BOOT_TYPE=$(jq -r '.status.booted.composefs.bootType' <<< "$BOOTC_STATUS" | tr '[:upper:]' '[:lower:]') + BOOTLOADER=$(jq -r '.status.booted.composefs.bootloader' <<< "$BOOTC_STATUS" | tr '[:upper:]' '[:lower:]') +fi + +handle_ignition_grub() { + mount -o remount,rw /boot + + # We're done provisioning. Remove the whole /boot/ignition directory if present, + # which may include a baked Ignition config. See + # https://github.com/coreos/fedora-coreos-tracker/issues/889. + rm -rf /boot/ignition + + # Regarding the lack of `-f` for rm ; we should have only run if GRUB detected + # this file. Fail if we are unable to remove it, rather than risking rerunning + # Ignition at next boot. + rm /boot/ignition.firstboot +} + +# Mounts ESP at /var/tmp/efi +mount_esp() { + mkdir -p $ESP_MOUNT + + local LSBLK_JSON + local ESP_DEV + LSBLK_JSON="$(lsblk -o path,parttype,name --json)" + + while read -r part; do + parttype="$(jq -r '.parttype // empty' <<<"$part" | tr '[:lower:]' '[:upper:]')" + path="$(jq -r '.path // empty' <<<"$part")" + + if [[ -z "$parttype" ]]; then + echo "Partition '$path' has no parttype" + continue + fi + + if [[ "$parttype" == "C12A7328-F81F-11D2-BA4B-00A0C93EC93B" ]]; then + ESP_DEV="$path" + break + fi + done < <(echo "$LSBLK_JSON" | jq -c '.blockdevices[].children[]?') + + if [[ "$ESP_DEV" == "" ]]; then + echo "ESP not found" + exit 1 + fi + + mount "$ESP_DEV" $ESP_MOUNT +} + +# Unounts ESP and deletes /var/tmp/efi +unmount_esp() { + umount $ESP_MOUNT + rmdir $ESP_MOUNT +} + +# simply remove the UKI addon +# TODO: Maybe this can be done in bootc +handle_ignition_uki() { + mount_esp + + local verity + verity=$(jq -r '.status.booted.composefs.verity' <<< "$BOOTC_STATUS") + + rm -rf "/var/tmp/efi/EFI/Linux/bootc/bootc_composefs-${verity}.efi.extra.d/ignition.addon.efi" + + unmount_esp +} + +handle_ignition_composefs() { + # We have a few cases here + # 1. systemd-boot + BLS + # 2. systemd-boot + UKI + # 3. grub + BLS + # 4. grub + UKI + # + # Both the UKI cases are the same and we just need to + # remove the UKI addon + # + # systemd-boot BLS doesn't accept variables in the config files + # so we handle it differently + # + # grub BLS should be the same as ostree + if [[ $BOOTLOADER == "grub" && $BOOT_TYPE == "bls" ]]; then + handle_ignition_grub + return + fi + + # UKI + if [[ $BOOT_TYPE == "uki" ]]; then + handle_ignition_uki + return + fi + + # systemd-boot BLS + # TODO: Maybe better to put this in bootc + mount_esp + + local verity + verity=$(jq -r '.status.booted.composefs.verity' <<< "$BOOTC_STATUS") + + boot_entry=$(ls "$ESP_MOUNT/loader/entries") + sed -i 's;ignition.firstboot;;' "$ESP_MOUNT/loader/entries/$boot_entry" + + unmount_esp +} + +if $IS_COMPOSEFS; then + handle_ignition_composefs +else + handle_ignition_grub +fi # rdcore zipl checks for /boot/ignition.firstboot if [[ $(uname -m) = s390x ]]; then diff --git a/tests/kola/composefs/enabled b/tests/kola/composefs/enabled index ce42cee0cc..ce014d73f2 100755 --- a/tests/kola/composefs/enabled +++ b/tests/kola/composefs/enabled @@ -19,6 +19,6 @@ if [ "${rootfs}" != "overlay" ]; then fatal "Error: Expected overlay on /, found: ${rootfs}" fi -journalctl -u ostree-prepare-root.service | grep -q "composefs: mounted successfully" +journalctl -u coreos-root-setup.service | grep -q "composefs: mounted successfully" ok "composefs is on"