From 33d4065b8b1f6ab0a4d18b3afbdd71ae4f62e503 Mon Sep 17 00:00:00 2001 From: Mayank Singh Date: Mon, 17 Aug 2026 08:07:39 +0000 Subject: [PATCH 1/3] acl: add TPM libraries and fix decrypt-root ordering --- ...-decrypt-root-fix-firstboot-ordering.patch | 24 +++++++++++++++++++ acl/SPECS/bootengine/bootengine.spec | 8 ++++++- .../rpm/additional_files/99-acl.conf | 5 ++++ 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 acl/SPECS/bootengine/0003-decrypt-root-fix-firstboot-ordering.patch diff --git a/acl/SPECS/bootengine/0003-decrypt-root-fix-firstboot-ordering.patch b/acl/SPECS/bootengine/0003-decrypt-root-fix-firstboot-ordering.patch new file mode 100644 index 00000000000..bb27fde9644 --- /dev/null +++ b/acl/SPECS/bootengine/0003-decrypt-root-fix-firstboot-ordering.patch @@ -0,0 +1,24 @@ +From b5153c74f62233438a72710673c0e53e3e1af7de Mon Sep 17 00:00:00 2001 +From: Mayank Singh +Date: Mon, 17 Aug 2026 00:00:00 +0000 +Subject: [PATCH] decrypt-root: fix first-boot ordering race + +Decrypt ROOT before initramfs waits for or mounts it. Remove the +ignition-disks ordering that creates a first-boot cycle and can drop the +decryption job. +--- + dracut/31decrypt-root/decrypt-root.service | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/dracut/31decrypt-root/decrypt-root.service b/dracut/31decrypt-root/decrypt-root.service +index 54f941a..7702f00 100644 +--- a/dracut/31decrypt-root/decrypt-root.service ++++ b/dracut/31decrypt-root/decrypt-root.service +@@ -7 +7 @@ +-After=systemd-networkd.service dev-disk-by\x2dpartlabel-ROOT.device ignition-disks.service ++After=systemd-networkd.service dev-disk-by\x2dpartlabel-ROOT.device +@@ -8,0 +9,3 @@ ++# Decrypt ROOT before initramfs waits for or mounts it. ++Before=cryptsetup.target initrd-root-device.target sysroot.mount ++# Avoid ignition-disks.service here; it creates a first-boot ordering cycle. + diff --git a/acl/SPECS/bootengine/bootengine.spec b/acl/SPECS/bootengine/bootengine.spec index 96b36ce0395..8d257133d60 100644 --- a/acl/SPECS/bootengine/bootengine.spec +++ b/acl/SPECS/bootengine/bootengine.spec @@ -2,7 +2,7 @@ Name: bootengine Version: 0.0.38 -Release: 2%{?dist} +Release: 3%{?dist} Summary: Flatcar bootengine dracut modules and helper utilities License: BSD-2-Clause @@ -12,6 +12,7 @@ URL: https://github.com/flatcar/bootengine Source0: https://github.com/flatcar/bootengine/archive/%{commit_hash}.tar.gz#/%{name}-%{version}.tar.gz Patch0: 0001-modify-tests.patch Patch1: 0002-delete-UKI-firstboot-addon-after-Ignition.patch +Patch2: 0003-decrypt-root-fix-firstboot-ordering.patch BuildArch: noarch BuildRequires: dracut Requires: util-linux @@ -72,6 +73,11 @@ chmod +x \ %{_sbindir}/update-bootengine %changelog +* Mon Aug 17 2026 Mayank Singh - 0.0.38-3 +- decrypt-root: fix first-boot ordering race that dropped the decryption job + and fell through to the dracut emergency shell (Before= root-device/sysroot, + drop After=ignition-disks.service). + * Tue May 06 2026 Lanze Liu - 0.0.38-2 - Update firstboot addon removal to use glob pattern for UAPI UKI naming diff --git a/build_library/rpm/additional_files/99-acl.conf b/build_library/rpm/additional_files/99-acl.conf index 8720ba0f174..b40b74dedd5 100644 --- a/build_library/rpm/additional_files/99-acl.conf +++ b/build_library/rpm/additional_files/99-acl.conf @@ -34,6 +34,11 @@ install_items+=" /usr/sbin/dmsetup " # Cryptsetup libraries (required for veritysetup and crypt module) install_items+=" /usr/lib/libcryptsetup.so.12 /usr/lib64/libcryptsetup.so.12 " install_items+=" /usr/sbin/cryptsetup " +# TPM2 libs for LUKS root auto-unlock. systemd-cryptsetup dlopen()s these at +# runtime, so dracut's ldd scan misses them and so we are adding them. +install_items+=" /usr/lib64/libtss2-esys.so.0 /usr/lib64/libtss2-sys.so.1 " +install_items+=" /usr/lib64/libtss2-mu.so.0 /usr/lib64/libtss2-rc.so.0 " +install_items+=" /usr/lib64/libtss2-tctildr.so.0 /usr/lib64/libtss2-tcti-device.so.0 " # dm-verity tool install_items+=" /usr/sbin/veritysetup " # systemd-veritysetup binary (dracut should include it via module, but be explicit) From f06bd5dacc49e720def97d47d7c2d606d8e44687 Mon Sep 17 00:00:00 2001 From: Mayank Singh Date: Mon, 17 Aug 2026 18:31:32 +0000 Subject: [PATCH 2/3] oem-azure: make chrony Hyper-V PTP optional for CVMs --- .../coreos-base/oem-azure/files/chrony-azure-ptp | 16 ++++++++++++++++ .../oem-azure/files/chrony-hyperv.conf | 4 +++- .../coreos-base/oem-azure/files/chrony.conf | 13 ++++++++----- .../coreos-base/oem-azure/files/manglefs_rpm.sh | 16 ++++++++++++++-- 4 files changed, 41 insertions(+), 8 deletions(-) create mode 100755 sdk_container/src/third_party/coreos-overlay/coreos-base/oem-azure/files/chrony-azure-ptp diff --git a/sdk_container/src/third_party/coreos-overlay/coreos-base/oem-azure/files/chrony-azure-ptp b/sdk_container/src/third_party/coreos-overlay/coreos-base/oem-azure/files/chrony-azure-ptp new file mode 100755 index 00000000000..408ba461aaa --- /dev/null +++ b/sdk_container/src/third_party/coreos-overlay/coreos-base/oem-azure/files/chrony-azure-ptp @@ -0,0 +1,16 @@ +#!/bin/bash + +set -euo pipefail + +config_dir="/run/chrony/conf.d" +config_file="${config_dir}/azure-ptp.conf" + +install -d -m 0755 "${config_dir}" + +if [[ -e /dev/ptp_hyperv ]]; then + printf '%s\n' \ + 'refclock PHC /dev/ptp_hyperv poll 3 dpoll -2 offset 0 stratum 2 prefer' \ + > "${config_file}" +else + rm -f "${config_file}" +fi diff --git a/sdk_container/src/third_party/coreos-overlay/coreos-base/oem-azure/files/chrony-hyperv.conf b/sdk_container/src/third_party/coreos-overlay/coreos-base/oem-azure/files/chrony-hyperv.conf index 9e2fd604a58..9d09ab15377 100644 --- a/sdk_container/src/third_party/coreos-overlay/coreos-base/oem-azure/files/chrony-hyperv.conf +++ b/sdk_container/src/third_party/coreos-overlay/coreos-base/oem-azure/files/chrony-hyperv.conf @@ -1,4 +1,6 @@ -# This should only be used when chronyd is configured to use the /dev/ptp_hyperv device [Unit] Wants=dev-ptp_hyperv.device After=dev-ptp_hyperv.device + +[Service] +ExecStartPre=/usr/libexec/chrony-azure-ptp diff --git a/sdk_container/src/third_party/coreos-overlay/coreos-base/oem-azure/files/chrony.conf b/sdk_container/src/third_party/coreos-overlay/coreos-base/oem-azure/files/chrony.conf index b5714071aff..306d1d4e01a 100644 --- a/sdk_container/src/third_party/coreos-overlay/coreos-base/oem-azure/files/chrony.conf +++ b/sdk_container/src/third_party/coreos-overlay/coreos-base/oem-azure/files/chrony.conf @@ -5,6 +5,9 @@ # Include configuration files found in /etc/chrony/conf.d. confdir /etc/chrony/conf.d +# Include runtime configuration generated for Azure platform devices. +confdir /run/chrony/conf.d + # This will use (up to): # - 2 sources from 2.ubuntu.pool.ntp.org which is ipv6 enabled as well # - 1 source from [013].ubuntu.pool.ntp.org each (ipv4 only atm) @@ -25,6 +28,9 @@ sourcedir /run/chrony-dhcp # Use NTP sources found in /etc/chrony/sources.d. sourcedir /etc/chrony/sources.d +# Match the Azure Linux 3.0 RPM fallback when Hyper-V PTP is unavailable. +server time.windows.com iburst + # This directive specify the location of the file containing ID/key pairs for # NTP authentication. #keyfile /etc/chrony/chrony.keys @@ -58,8 +64,5 @@ makestep 1.0 -1 # leap-smeared time. leapsectz right/UTC -# Azure hosts are synchronized to internal Microsoft time servers -# that take their time from Microsoft-owned Stratum 1 devices. -# The Hyper-V drivers surface this time source as a PTP-based -# time source in the guest. This configures chrony to use it. -refclock PHC /dev/ptp_hyperv poll 3 dpoll -2 offset 0 stratum 2 +# /run/chrony/conf.d/azure-ptp.conf is generated before chronyd starts when +# the Hyper-V PTP device is available. diff --git a/sdk_container/src/third_party/coreos-overlay/coreos-base/oem-azure/files/manglefs_rpm.sh b/sdk_container/src/third_party/coreos-overlay/coreos-base/oem-azure/files/manglefs_rpm.sh index c8c243fa20e..a0cc1238377 100644 --- a/sdk_container/src/third_party/coreos-overlay/coreos-base/oem-azure/files/manglefs_rpm.sh +++ b/sdk_container/src/third_party/coreos-overlay/coreos-base/oem-azure/files/manglefs_rpm.sh @@ -55,18 +55,30 @@ if [[ -f "${rootfs}/usr/lib/systemd/system/chronyd.service" ]]; then sed -i \ 's|^ExecStart=/usr/sbin/chronyd $OPTIONS$|ExecStart=/usr/sbin/chronyd -f /usr/lib/chrony/chrony.conf $OPTIONS|' \ "${rootfs}/usr/lib/systemd/system/chronyd.service" + + # Azure Linux 3.0 adds remove-daemon-state, but its chrony-helper does not + # implement that command. Preserve update-daemon for DHCP-provided sources. + sed -i \ + '\|^ExecStopPost=.*/chrony-helper remove-daemon-state$|d' \ + "${rootfs}/usr/lib/systemd/system/chronyd.service" fi # Copy Azure-optimized chrony.conf from this directory. # Overwrites the RPM default that manglefs already moved from /etc. -# Key differences: makestep 1.0 -1 (always-step), PTP refclock for Hyper-V clock. +# Key differences: always-step, network fallback, and optional Hyper-V PTP. # Copy Azure-optimized chrony.conf to /usr/lib/chrony/chrony.conf if [[ -f "${script_dir}/chrony.conf" ]]; then cp "${script_dir}/chrony.conf" "${rootfs}/usr/lib/chrony/chrony.conf" fi -# chronyd.service drop-in (Wants/After dev-ptp_hyperv.device) +# Generate the optional Hyper-V PTP source before chronyd starts. +if [[ -f "${script_dir}/chrony-azure-ptp" ]]; then + install -D -m 0755 "${script_dir}/chrony-azure-ptp" \ + "${rootfs}/usr/libexec/chrony-azure-ptp" +fi + +# chronyd.service drop-in for optional Hyper-V PTP configuration. if [[ -f "${script_dir}/chrony-hyperv.conf" ]]; then mkdir -p "${rootfs}/usr/lib/systemd/system/chronyd.service.d" cp "${script_dir}/chrony-hyperv.conf" \ From 1675739ab51b29bdc940f05932f066f845b4d2b7 Mon Sep 17 00:00:00 2001 From: Mayank Singh Date: Thu, 3 Sep 2026 06:22:48 +0000 Subject: [PATCH 3/3] incporporate review comments --- ...-decrypt-root-fix-firstboot-ordering.patch | 33 ++++++++++--------- acl/SPECS/bootengine/bootengine.spec | 7 ++-- .../oem-azure/files/chrony-azure-ptp | 2 +- .../oem-azure/files/chrony-hyperv.conf | 4 +-- .../coreos-base/oem-azure/files/chrony.conf | 20 ++--------- .../oem-azure/files/manglefs_rpm.sh | 27 ++++++++++----- 6 files changed, 44 insertions(+), 49 deletions(-) diff --git a/acl/SPECS/bootengine/0003-decrypt-root-fix-firstboot-ordering.patch b/acl/SPECS/bootengine/0003-decrypt-root-fix-firstboot-ordering.patch index bb27fde9644..b7f942f6940 100644 --- a/acl/SPECS/bootengine/0003-decrypt-root-fix-firstboot-ordering.patch +++ b/acl/SPECS/bootengine/0003-decrypt-root-fix-firstboot-ordering.patch @@ -1,24 +1,25 @@ From b5153c74f62233438a72710673c0e53e3e1af7de Mon Sep 17 00:00:00 2001 From: Mayank Singh -Date: Mon, 17 Aug 2026 00:00:00 +0000 -Subject: [PATCH] decrypt-root: fix first-boot ordering race +Date: Thu, 13 Aug 2026 00:00:00 +0000 +Subject: [PATCH] decrypt-root: order unlock before root-device wait -Decrypt ROOT before initramfs waits for or mounts it. Remove the -ignition-disks ordering that creates a first-boot cycle and can drop the -decryption job. +Keep Ignition's disks stage ahead of root decryption because it can provision +LUKS volumes, then decrypt ROOT before initramfs waits for the root device. --- - dracut/31decrypt-root/decrypt-root.service | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) + dracut/31decrypt-root/decrypt-root.service | 2 ++ + 1 file changed, 2 insertions(+) diff --git a/dracut/31decrypt-root/decrypt-root.service b/dracut/31decrypt-root/decrypt-root.service -index 54f941a..7702f00 100644 +index 54f941a..226d3d3 100644 --- a/dracut/31decrypt-root/decrypt-root.service +++ b/dracut/31decrypt-root/decrypt-root.service -@@ -7 +7 @@ --After=systemd-networkd.service dev-disk-by\x2dpartlabel-ROOT.device ignition-disks.service -+After=systemd-networkd.service dev-disk-by\x2dpartlabel-ROOT.device -@@ -8,0 +9,3 @@ -+# Decrypt ROOT before initramfs waits for or mounts it. -+Before=cryptsetup.target initrd-root-device.target sysroot.mount -+# Avoid ignition-disks.service here; it creates a first-boot ordering cycle. - +@@ -4,5 +4,7 @@ Description=Generate and execute a systemd-cryptsetup service to decrypt the ROOT partition + DefaultDependencies=no ++# Decrypt ROOT before initramfs waits for it. ++Before=initrd-root-device.target + # If systemd-networkd.service is used in the initramfs, then we should run after it, since the ROOT partition + # might use network-bound encryption. + After=systemd-networkd.service dev-disk-by\x2dpartlabel-ROOT.device ignition-disks.service + Wants=dev-disk-by\x2dpartlabel-ROOT.device +-- +2.43.0 diff --git a/acl/SPECS/bootengine/bootengine.spec b/acl/SPECS/bootengine/bootengine.spec index 8d257133d60..90a943f7006 100644 --- a/acl/SPECS/bootengine/bootengine.spec +++ b/acl/SPECS/bootengine/bootengine.spec @@ -73,10 +73,9 @@ chmod +x \ %{_sbindir}/update-bootengine %changelog -* Mon Aug 17 2026 Mayank Singh - 0.0.38-3 -- decrypt-root: fix first-boot ordering race that dropped the decryption job - and fell through to the dracut emergency shell (Before= root-device/sysroot, - drop After=ignition-disks.service). +* Thu Aug 13 2026 Mayank Singh - 0.0.38-3 +- decrypt-root: run after Ignition disk provisioning and before initramfs waits + for the encrypted root device. * Tue May 06 2026 Lanze Liu - 0.0.38-2 - Update firstboot addon removal to use glob pattern for UAPI UKI naming diff --git a/sdk_container/src/third_party/coreos-overlay/coreos-base/oem-azure/files/chrony-azure-ptp b/sdk_container/src/third_party/coreos-overlay/coreos-base/oem-azure/files/chrony-azure-ptp index 408ba461aaa..8a72a102f4a 100755 --- a/sdk_container/src/third_party/coreos-overlay/coreos-base/oem-azure/files/chrony-azure-ptp +++ b/sdk_container/src/third_party/coreos-overlay/coreos-base/oem-azure/files/chrony-azure-ptp @@ -2,7 +2,7 @@ set -euo pipefail -config_dir="/run/chrony/conf.d" +config_dir="/run/chrony-azure/conf.d" config_file="${config_dir}/azure-ptp.conf" install -d -m 0755 "${config_dir}" diff --git a/sdk_container/src/third_party/coreos-overlay/coreos-base/oem-azure/files/chrony-hyperv.conf b/sdk_container/src/third_party/coreos-overlay/coreos-base/oem-azure/files/chrony-hyperv.conf index 9d09ab15377..8b9dbee05a3 100644 --- a/sdk_container/src/third_party/coreos-overlay/coreos-base/oem-azure/files/chrony-hyperv.conf +++ b/sdk_container/src/third_party/coreos-overlay/coreos-base/oem-azure/files/chrony-hyperv.conf @@ -1,6 +1,6 @@ [Unit] -Wants=dev-ptp_hyperv.device +# Order after the PTP device if present without waiting for it when unavailable. After=dev-ptp_hyperv.device [Service] -ExecStartPre=/usr/libexec/chrony-azure-ptp +ExecStartPre=-/usr/libexec/chrony-azure-ptp diff --git a/sdk_container/src/third_party/coreos-overlay/coreos-base/oem-azure/files/chrony.conf b/sdk_container/src/third_party/coreos-overlay/coreos-base/oem-azure/files/chrony.conf index 306d1d4e01a..c0aa93f1ca7 100644 --- a/sdk_container/src/third_party/coreos-overlay/coreos-base/oem-azure/files/chrony.conf +++ b/sdk_container/src/third_party/coreos-overlay/coreos-base/oem-azure/files/chrony.conf @@ -6,21 +6,7 @@ confdir /etc/chrony/conf.d # Include runtime configuration generated for Azure platform devices. -confdir /run/chrony/conf.d - -# This will use (up to): -# - 2 sources from 2.ubuntu.pool.ntp.org which is ipv6 enabled as well -# - 1 source from [013].ubuntu.pool.ntp.org each (ipv4 only atm) -# This means by default, up to 2 dual-stack and up to 3 additional IPv4-only -# sources will be used. -# At the same time it retains some protection against one of the entries being -# down (compare to just using one of the lines). -# -# See http://www.pool.ntp.org/join.html for more information. -#pool 0.flatcar.pool.ntp.org iburst maxsources 1 -#pool 1.flatcar.pool.ntp.org iburst maxsources 1 -#pool 2.flatcar.pool.ntp.org iburst maxsources 2 -#pool 3.flatcar.pool.ntp.org iburst maxsources 1 +confdir /run/chrony-azure/conf.d # Use time sources from DHCP. sourcedir /run/chrony-dhcp @@ -28,7 +14,7 @@ sourcedir /run/chrony-dhcp # Use NTP sources found in /etc/chrony/sources.d. sourcedir /etc/chrony/sources.d -# Match the Azure Linux 3.0 RPM fallback when Hyper-V PTP is unavailable. +# Retain the Azure Linux 3.0 public fallback. server time.windows.com iburst # This directive specify the location of the file containing ID/key pairs for @@ -64,5 +50,5 @@ makestep 1.0 -1 # leap-smeared time. leapsectz right/UTC -# /run/chrony/conf.d/azure-ptp.conf is generated before chronyd starts when +# /run/chrony-azure/conf.d/azure-ptp.conf is generated before chronyd starts when # the Hyper-V PTP device is available. diff --git a/sdk_container/src/third_party/coreos-overlay/coreos-base/oem-azure/files/manglefs_rpm.sh b/sdk_container/src/third_party/coreos-overlay/coreos-base/oem-azure/files/manglefs_rpm.sh index a0cc1238377..529a6d071eb 100644 --- a/sdk_container/src/third_party/coreos-overlay/coreos-base/oem-azure/files/manglefs_rpm.sh +++ b/sdk_container/src/third_party/coreos-overlay/coreos-base/oem-azure/files/manglefs_rpm.sh @@ -56,8 +56,13 @@ if [[ -f "${rootfs}/usr/lib/systemd/system/chronyd.service" ]]; then 's|^ExecStart=/usr/sbin/chronyd $OPTIONS$|ExecStart=/usr/sbin/chronyd -f /usr/lib/chrony/chrony.conf $OPTIONS|' \ "${rootfs}/usr/lib/systemd/system/chronyd.service" - # Azure Linux 3.0 adds remove-daemon-state, but its chrony-helper does not - # implement that command. Preserve update-daemon for DHCP-provided sources. + # Azure Linux adds this command, but its chrony-helper does not implement it, + # leaving chronyd failed after a clean stop. + if ! grep -qE '^ExecStopPost=.*/chrony-helper remove-daemon-state$' \ + "${rootfs}/usr/lib/systemd/system/chronyd.service"; then + echo "ERROR: expected chrony-helper remove-daemon-state line not found" >&2 + exit 1 + fi sed -i \ '\|^ExecStopPost=.*/chrony-helper remove-daemon-state$|d' \ "${rootfs}/usr/lib/systemd/system/chronyd.service" @@ -73,17 +78,21 @@ if [[ -f "${script_dir}/chrony.conf" ]]; then fi # Generate the optional Hyper-V PTP source before chronyd starts. -if [[ -f "${script_dir}/chrony-azure-ptp" ]]; then - install -D -m 0755 "${script_dir}/chrony-azure-ptp" \ - "${rootfs}/usr/libexec/chrony-azure-ptp" +if [[ ! -f "${script_dir}/chrony-azure-ptp" ]]; then + echo "ERROR: missing ${script_dir}/chrony-azure-ptp" >&2 + exit 1 fi +install -D -m 0755 "${script_dir}/chrony-azure-ptp" \ + "${rootfs}/usr/libexec/chrony-azure-ptp" # chronyd.service drop-in for optional Hyper-V PTP configuration. -if [[ -f "${script_dir}/chrony-hyperv.conf" ]]; then - mkdir -p "${rootfs}/usr/lib/systemd/system/chronyd.service.d" - cp "${script_dir}/chrony-hyperv.conf" \ - "${rootfs}/usr/lib/systemd/system/chronyd.service.d/" +if [[ ! -f "${script_dir}/chrony-hyperv.conf" ]]; then + echo "ERROR: missing ${script_dir}/chrony-hyperv.conf" >&2 + exit 1 fi +mkdir -p "${rootfs}/usr/lib/systemd/system/chronyd.service.d" +cp "${script_dir}/chrony-hyperv.conf" \ + "${rootfs}/usr/lib/systemd/system/chronyd.service.d/" # Chrony tmpfiles: /var/lib/chrony dir + /etc/chrony.keys copy-on-boot if [[ -f "${script_dir}/var-chrony.conf" ]]; then