From: Vitaly Kuznetsov vkuznets@redhat.com
redhat: Add sub-RPM with a EFI unified kernel image for virtual machines
The new 'kernel-unified-virt' sub-RPM is added on x86_64 targets.
This contains an EFI application that provides a combined vmlinux, initrd and cmdline, as a so called 'unified kernel image'. The spec for this is defined by the boot loader specification
https://uapi-group.org/specifications/specs/boot_loader_specification/
The key benefit of a unified kernel is that its secure boot signature covers the initrd and cmdline contents, allowing a trustworthy measured boot process with attestation, which is not practical with locally generated initrds/cmdlines.
Since the initrd is pre-generated its contents have to be very generic, to be usable on a wide variety of deployments. To make this problem tractable, the sub-RPM targets only usage in virtual machines. With such a restriction, the initrd only needs a very small set of block driver modules present, in order to be usable across KVM, Hyper-V and Xen hypervisors which will cover essentially all common public and private clouds.
Similarly the kernel cmdline cannot contain any host specific data, which means the root filesystem to mount needs to be able to be automatically detected. A virtual machine image intending to use this unified kernel package thus needs to comply with the discoverable partitions specification:
https://uapi-group.org/specifications/specs/discoverable_partitions_specific...
Based-on-patch-by: Daniel P. Berrangé berrange@redhat.com Based-on-patch-by: Gerd Hoffmann kraxel@redhat.com Signed-off-by: Vitaly Kuznetsov vkuznets@redhat.com
diff --git a/redhat/Makefile b/redhat/Makefile index blahblah..blahblah 100644 --- a/redhat/Makefile +++ b/redhat/Makefile @@ -639,6 +639,7 @@ sources-rh: $(TARBALL) generate-testpatch-tmp setup-source dist-configs-check ../Makefile.rhelver \ README.rst \ kernel-local \ + dracut-virt.conf \ $(SOURCES)/ @if [ "$(RELEASED_KERNEL)" -ne 0 ]; then \ cp keys/redhatsecureboot{301,501,ca5,ca1}.cer $(SOURCES)/; \ diff --git a/redhat/dracut-virt.conf b/redhat/dracut-virt.conf new file mode 100644 index blahblah..blahblah 100644 --- /dev/null +++ b/redhat/dracut-virt.conf @@ -0,0 +1,35 @@ +# generic + compressed please +hostonly="no" +compress="xz" + +# VMs can't update microcode anyway +early_microcode="no" + +# modules: basics +dracutmodules+=" base systemd systemd-initrd dracut-systemd dbus dbus-broker usrmount shutdown " + +# modules: storage support +dracutmodules+=" dm lvm rootfs-block fs-lib " + +# modules: tpm and crypto +dracutmodules+=" crypt crypt-loop tpm2-tss " + +# drivers: virtual buses, pci +drivers+=" virtio-pci virtio-mmio " # qemu-kvm +drivers+=" hv-vmbus pci-hyperv " # hyperv +drivers+=" xen-pcifront " # xen + +# drivers: storage +drivers+=" ahci nvme sd_mod sr_mod " # generic +drivers+=" virtio-blk virtio-scsi " # qemu-kvm +drivers+=" hv-storvsc " # hyperv +drivers+=" xen-blkfront " # xen + +# root encryption +drivers+=" dm_crypt " + +# filesystems +filesystems+=" vfat ext4 xfs overlay " + +# systemd-pcrphase +install_items+=" /lib/systemd/system/systemd-pcrphase-initrd.service /usr/lib/systemd/systemd-pcrphase /usr/lib/systemd/system/initrd.target.wants/systemd-pcrphase-initrd.service " diff --git a/redhat/kernel.spec.template b/redhat/kernel.spec.template index blahblah..blahblah 100755 --- a/redhat/kernel.spec.template +++ b/redhat/kernel.spec.template @@ -91,6 +91,12 @@ Summary: The Linux kernel %global zipmodules 1 %endif
+%ifarch x86_64 +%global efiuki 1 +%else +%global efiuki 0 +%endif + %if %{zipmodules} %global zipsed -e 's/.ko$/.ko.xz/' %endif @@ -699,6 +705,21 @@ BuildRequires: llvm BuildRequires: lld %endif
+%if %{efiuki} +BuildRequires: dracut +# For dracut UEFI uki binaries +BuildRequires: binutils +# For the initrd +BuildRequires: lvm2 +%if 0%{?fedora} > 37 +BuildRequires: systemd-boot-unsigned +%endif +# For systemd-stub and systemd-pcrphase +BuildRequires: systemd-udev >= 252-1 +# For TPM operations in UKI initramfs +BuildRequires: tpm2-tools +%endif + # Because this is the kernel, it's hard to get a single upstream URL # to represent the base without needing to do a bunch of patching. This # tarball is generated from a src-git tree. If you want to see the @@ -826,6 +847,8 @@ Source82: update_scripts.sh Source84: mod-internal.list Source85: mod-partner.list
+Source86: dracut-virt.conf + Source100: rheldup3.x509 Source101: rhelkpatch1.x509
@@ -1331,6 +1354,13 @@ Requires: kernel-%{?1:%{1}-}-modules-core-uname-r = %{KVERREL}%{?1:+%{1}}\ %endif\ %{expand:%%kernel_debuginfo_package %{?1:%{1}}}\ %endif\ +%if %{efiuki}\ +%package %{?1:%{1}-}uki-virt\ +Summary: %{variant_summary} unified kernel image for virtual machines\ +Provides: installonlypkg(kernel)\ +Provides: kernel-%{?1:%{1}-}uname-r = %{KVERREL}%{?1:+%{1}}\ +Requires: kernel%{?1:-%{1}}-modules-core-uname-r = %{KVERREL}%{?1:+%{1}}\ +%endif\ %{nil}
# @@ -1400,6 +1430,14 @@ Linux operating system. The kernel handles the basic functions of the operating system: memory allocation, process allocation, device input and output, etc.
+%if %{efiuki} +%description debug-uki-virt +Prebuilt debug unified kernel image for virtual machines. + +%description uki-virt +Prebuilt default unified kernel image for virtual machines. +%endif + %if %{with_ipaclones} %kernel_ipaclones_package %endif @@ -2180,6 +2218,45 @@ BuildKernel() { touch lib/modules/$KernelVer/modules.builtin fi
+%if %{efiuki} + popd + + KernelUnifiedImageDir="$RPM_BUILD_ROOT/lib/modules/$KernelVer" + KernelUnifiedImage="$KernelUnifiedImageDir/$InstallName-virt.efi" + + mkdir -p $KernelUnifiedImageDir + + dracut --conf=%{SOURCE86} \ + --confdir=$(mktemp -d) \ + --verbose \ + --kver "$KernelVer" \ + --kmoddir "$RPM_BUILD_ROOT/lib/modules/$KernelVer/" \ + --logfile=$(mktemp) \ + --uefi \ + --kernel-image $(realpath $KernelImage) \ + --kernel-cmdline 'console=tty0 console=ttyS0' \ + $KernelUnifiedImage + +%if %{signkernel} + + %pesign -s -i $KernelUnifiedImage -o $KernelUnifiedImage.tmp -a %{secureboot_ca_0} -c %{secureboot_key_0} -n %{pesign_name_0} + %pesign -s -i $KernelUnifiedImage.tmp -o $KernelUnifiedImage.signed -a %{secureboot_ca_1} -c %{secureboot_key_1} -n %{pesign_name_1} + rm -f $KernelUnifiedImage.tmp + + if [ ! -s $KernelUnifiedImage.signed ]; then + echo "pesigning failed" + exit 1 + fi + mv $KernelUnifiedImage.signed $KernelUnifiedImage + +# signkernel +%endif + + pushd $RPM_BUILD_ROOT + +# efiuki +%endif + remove_depmod_files
# Go back and find all of the various directories in the tree. We use this @@ -2873,12 +2950,14 @@ fi\ # It also defines a %%postun script that does the same thing. # %%kernel_modules_core_post [<subpackage>] # +# FIXME: /bin/kernel-install can't handle UKIs (yet), so cleanup depmod files in %postun for now. +# %define kernel_modules_core_post() \ %{expand:%%posttrans %{?1:%{1}-}modules-core}\ /sbin/depmod -a %{KVERREL}%{?1:+%{1}}\ %{nil}\ %{expand:%%postun %{?1:%{1}-}modules-core}\ -/sbin/depmod -a %{KVERREL}%{?1:+%{1}}\ +rm -f /lib/modules/%{KVERREL}%{?1:+%{1}}/modules.*\ %{nil}
# This macro defines a %%posttrans script for a kernel package. @@ -2926,6 +3005,20 @@ mkdir -p %{_localstatedir}/lib/rpm-state/%{name}\ touch %{_localstatedir}/lib/rpm-state/%{name}/installing_core_%{KVERREL}%{?-v:+%{-v*}}\ %{nil}
+# +# This macro defines scripts for a kernel*-uki-virt package +# +# FIXME: /bin/kernel-install can't handle UKIs (yet), so just cp/rm as temporary stop-gap +# +%define kernel_uki_virt_scripts() \ +%{expand:%%posttrans %{?1:%{1}-}uki-virt}\ +mkdir -p /boot/efi/EFI/Linux\ +cp /lib/modules/%{KVERREL}%{?1:+%{1}}/vmlinuz-virt.efi /boot/efi/EFI/Linux/vmlinuz-%{KVERREL}%{?1:+%{1}}-virt.efi\ +%{nil}\ +%{expand:%%postun %{?1:%{1}-}uki-virt}\ +rm -f /boot/efi/EFI/Linux/vmlinuz-%{KVERREL}%{?1:+%{1}}-virt.efi\ +%{nil} + # # This macro defines a %%preun script for a kernel package. # %%kernel_variant_preun <subpackage> @@ -2939,6 +3032,10 @@ then\ fi\ %{nil}
+%if %{efiuki} +%kernel_uki_virt_scripts +%endif + %kernel_variant_preun %kernel_variant_post -r kernel-smp
@@ -2948,6 +3045,9 @@ fi\ %endif
%if %{with_debug} +%if %{efiuki} +%kernel_uki_virt_scripts debug +%endif %kernel_variant_preun debug %kernel_variant_post -v debug %endif @@ -3188,6 +3288,11 @@ fi %{expand:%%files -f debuginfo%{?3}.list %{?3:%{3}-}debuginfo}\ %endif\ %endif\ +%if %{efiuki}\ +%{expand:%%files %{?3:%{3}-}uki-virt}\ +/lib/modules/%{KVERREL}%{?3:+%{3}}/%{?-k:%{-k*}}%{!?-k:vmlinuz}-virt.efi\ +%ghost /%{image_install_path}/efi/EFI/Linux/%{?-k:%{-k*}}%{!?-k:vmlinuz}-%{KVERREL}%{?3:+%{3}}-virt.efi\ +%endif\ %if %{?3:1} %{!?3:0}\ %{expand:%%files %{3}}\ %endif\
-- https://gitlab.com/cki-project/kernel-ark/-/merge_requests/2175
From: Vitaly Kuznetsov on gitlab.com https://gitlab.com/cki-project/kernel-ark/-/merge_requests/2175#note_1267085...
@jmflinuxtx could you please take a look? Is there anything blocking this MR?
From: Justin M. Forbes on gitlab.com https://gitlab.com/cki-project/kernel-ark/-/merge_requests/2175#note_1267373...
@vkuznets It needs a proper RHEL ack because it changes RHEL as well. I asked Herton to follow up today. I have been holding my ack because mine would technically "satisfy the requirements" but I am not RHEL.
From: Vitaly Kuznetsov on gitlab.com https://gitlab.com/cki-project/kernel-ark/-/merge_requests/2175#note_1267401...
I see @hertonrk-rh ACKed, thanks! We're sorting out a minor conflict in RHEL between UKI (https://gitlab.com/redhat/centos-stream/src/kernel/centos- stream-9/-/merge_requests/1736) and 64-k paging on ARM (https://gitlab.com/redhat/centos-stream/src/kernel/centos- stream-9/-/merge_requests/1820) -- which is RHEL-only. This will make things differ a bit between RHEL and ARK/Fedora but not much. I'll try my best to keep things synchronized whenever possible.
From: Justin M. Forbes on gitlab.com https://gitlab.com/cki-project/kernel-ark/-/merge_requests/2175#note_1271181...
While this is working for Fedora it is failing for ELN (RHEL) kernels with: `dracut: Can't find a uefi stub '/usr/lib/systemd/boot/efi/linuxx64.efi.stub' to create a UEFI executable`
From: Vitaly Kuznetsov on gitlab.com https://gitlab.com/cki-project/kernel-ark/-/merge_requests/2175#note_1271653...
Sorry about that! I wasn't exactly sure what's the buildroot for ELN. In CS9, systemd-stub (linuxx64.efi.stub) lives in 'systemd-udev' but in F38 it has traveled to 'systemd-boot-unsigned' so we have
+%if 0%{?fedora} > 37 +BuildRequires: systemd-boot-unsigned +%endif
apparently, this doesn't work for ELN. I guess something like the following should do the job +%if 0%{?fedora} > 37 || 0%{?eln} +BuildRequires: systemd-boot-unsigned +%endif
do we need a new MR or can we just fix things up here?
From: Patrick Talbert on gitlab.com https://gitlab.com/cki-project/kernel-ark/-/merge_requests/2175#note_1271744...
This was merged two days ago so nothing new can be done here; it must be a new MR.
From: Daniel P. Berrangé on gitlab.com https://gitlab.com/cki-project/kernel-ark/-/merge_requests/2175#note_1271895...
While it is possible, it is almost never correct to use %{?eln} in spec file conditional checks. Instead %{?rhel} is preferred. The condition "%{?rhel} > 9" should evaluate true for today's ELN, and a future RHEL-10 which will inherit today's ELN content.
https://docs.fedoraproject.org/en- US/eln/ftbfs/#_accounting_for_differences_between_fedora_and_rhel
From: Justin M. Forbes on gitlab.com https://gitlab.com/cki-project/kernel-ark/-/merge_requests/2175#note_1272255...
I believe the correct method is just to change the buildreq to systemd-boot- unsigned for everything, and add a note to redhat/rebase-notes.txt to revert that new MR for stable fedora until F37 is EOL. os-build does not build kernels for anything other than rawhide, and when I do branch for stable Fedora, that branch will not build kernels for ELN/RHEL, so the current behavior is correct.
From: Vitaly Kuznetsov on gitlab.com https://gitlab.com/cki-project/kernel-ark/-/merge_requests/2175#note_1272284...
OK, I've created https://gitlab.com/cki-project/kernel- ark/-/merge_requests/2284
kernel@lists.fedoraproject.org