From: Emanuele Giuseppe Esposito <eesposit@xxxxxxxxxx> redhat/kernel.spec: add uki_addons to create UKI kernel cmdline addons Upstream Status: RHEL-Only The folder redhat/addons will contain all addons configs specifying the UKI kernel cmdline addons to be created in the next build. An addon config is simply a .addon plain text file, where any line is taken as kernel cmdline, except for the ones starting with '#', which will be automatically ignored. redhat/scripts/uki_addons.py will take care of parsing all configs and folders in redhat/addons and call 'ukify' to create the actual addons. The output addon filename will be a concatenation of all folders in redhat/addons that are part of the addon config path. For example, an addon config redhat/addons/1/2/3/test.addon will result in generating 1-2-3-test.addon.efi. It is also possible to add .sbat to all the generated addons, by populating redhat/addons/sbat/sbat.conf. Syntax is same as the addons config. At build time, Makefile will create a tar.gz archive (addons.tar.gz) containing all the files in redhat/addons. It will then passed to the kernel specfile that will extract the addons from it and generate the UKI kernel cmdline addons. Signed-off-by: Emanuele Giuseppe Esposito <eesposit@xxxxxxxxxx> diff --git a/redhat/Makefile b/redhat/Makefile index blahblah..blahblah 100644 --- a/redhat/Makefile +++ b/redhat/Makefile @@ -679,6 +679,7 @@ sources-rh: $(TARBALL) generate-testpatch-tmp setup-source dist-configs-check @sed -e "s/%%SPECKVERSION%%/$(SPECKVERSION)/" \ -e "s/%%SPECKPATCHLEVEL%%/$(SPECKPATCHLEVEL)/" \ scripts/gating/rpminspect.yaml > $(SOURCES)/rpminspect.yaml + @tar -czf addons.tar.gz addons @cp scripts/kernel-tools/kvm_stat.logrotate \ keys/rhel*.x509 \ kabi/check-kabi \ @@ -690,6 +691,7 @@ sources-rh: $(TARBALL) generate-testpatch-tmp setup-source dist-configs-check scripts/mod/mod-partner.list \ scripts/mod/mod-sign.sh \ scripts/mod/mod-kvm.list \ + scripts/uki_addons.py \ configs/flavors \ configs/generate_all_configs.sh \ configs/merge.py \ @@ -698,6 +700,7 @@ sources-rh: $(TARBALL) generate-testpatch-tmp setup-source dist-configs-check README.rst \ kernel-local \ dracut-virt.conf \ + addons.tar.gz \ $(SOURCES)/ @cat $$(ls -1 $(SPECPACKAGE_NAME).changelog-* | sort -t '.' -k 3 -n -r) \ > $(SOURCES)/kernel.changelog diff --git a/redhat/addons/sbat/.gitkeep b/redhat/addons/sbat/.gitkeep new file mode 100644 index blahblah..blahblah 100644 --- /dev/null +++ b/redhat/addons/sbat/.gitkeep diff --git a/redhat/kernel.spec.template b/redhat/kernel.spec.template index blahblah..blahblah 100644 --- a/redhat/kernel.spec.template +++ b/redhat/kernel.spec.template @@ -792,6 +792,8 @@ BuildRequires: binutils BuildRequires: lvm2 BuildRequires: systemd-boot-unsigned # For systemd-stub and systemd-pcrphase +BuildRequires: systemd-ukify +# For UKI kernel cmdline addons BuildRequires: systemd-udev >= 252-1 # For TPM operations in UKI initramfs BuildRequires: tpm2-tools @@ -933,6 +935,9 @@ Source86: dracut-virt.conf Source87: flavors +Source151: uki_addons.py +Source152: addons.tar.gz + Source100: rheldup3.x509 Source101: rhelkpatch1.x509 @@ -2537,6 +2542,18 @@ BuildKernel() { fi mv $KernelUnifiedImage.signed $KernelUnifiedImage + tar -xvf %{SOURCE152} -C $KernelUnifiedImageDir + KernelAddonsDir="$KernelUnifiedImageDir/addons" + KernelAddonsDirOut="$RPM_BUILD_ROOT/usr/lib/linux/extra.d" + mkdir -p $KernelAddonsDirOut + python3 %{SOURCE151} $KernelAddonsDir $KernelAddonsDirOut + for addon in "$KernelAddonsDirOut"/*; do + %pesign -s -i $addon -o $addon.signed -a %{secureboot_ca_1} -c %{secureboot_key_1} -n %{pesign_name_1} + rm -f $addon + mv $addon.signed $addon + done + rm -rf $KernelAddonsDir + # signkernel %endif @@ -3692,6 +3709,7 @@ fi\ /lib/modules/%{KVERREL}%{?3:+%{3}}/config\ /lib/modules/%{KVERREL}%{?3:+%{3}}/modules.builtin*\ %attr(0644, root, root) /lib/modules/%{KVERREL}%{?3:+%{3}}/%{?-k:%{-k*}}%{!?-k:vmlinuz}-virt.efi\ +/usr/lib/linux/extra.d/*.addon.efi\ %ghost /%{image_install_path}/efi/EFI/Linux/%{?-k:%{-k*}}%{!?-k:*}-%{KVERREL}%{?3:+%{3}}.efi\ %endif\ %endif\ diff --git a/redhat/scripts/uki_addons.py b/redhat/scripts/uki_addons.py new file mode 100644 index blahblah..blahblah 100644 --- /dev/null +++ b/redhat/scripts/uki_addons.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python3 +# +# This script recursively inspects a given uki directory, and creates an addon +# for each file found. +# +# Usage: python uki_addons.py input_dir out_dir +# +# This tool requires the systemd-ukify and systemd-boot yum packages. +# +# Addon file +#----------- +# Each addon terminates with .addon +# Each addon contains only two types of lines: +# Lines beginning with '#' are description and thus ignored +# All other lines are command line to be added. +# The name of the end resulting addon is taken from the folder hierarchy. +# For example, and addon in input_dir/test/test2/hello.addon will result in +# an UKI addon file generated in out_dir called hello-test-test2.addon.efi +# +# sbat.conf +#---------- +# This file is containing the sbat string for *all* addons being created. +# This file is optional, but when used has to be put in out_dir/sbat/sbat.conf. +# It follows the same syntax as the addon files, meaning '#' is comment and +# the rest is taken as sbat string and feed to ukify. + +import os +import sys +import collections +import subprocess + +SYSTEMD_STUB_PATH = '/usr/lib/systemd/boot/efi/addonx64.efi.stub' +UKIFY_PATH = '/usr/lib/systemd/ukify' +SBAT_LOCATION = '/sbat/sbat.conf' + +def usage(err): + print(f'Usage: {os.path.basename(__file__)} input_dir output_dir') + print(f'Error:{err}') + sys.exit(1) + +def check_clean_arguments(in_dir, out_dir): + # Remove end '/' + if in_dir[-1:] == '/': + in_dir = in_dir[:-1] + if out_dir[-1:] == '/': + out_dir = out_dir[:-1] + if not os.path.isdir(in_dir): + usage(f'in_dir {in_dir} is not a dir, or does not exist!') + if not os.path.isdir(out_dir): + usage(f'out_dir_dir {out_dir} is not a dir, or does not exist!') + return in_dir, out_dir + +UKICmdlineAddon = collections.namedtuple('UKICmdlineAddon', ['name', 'cmdline']) +uki_addon_list = [] + +def parse_addon_conf(path, rstrip=True): + with open(path, 'r') as addons: + lines = addons.readlines() + cmdline = '' + for l in lines: + l = l.lstrip() + if not l: + continue + if l[0] == '#': + continue + if rstrip: + l = l.rstrip() + ' ' + cmdline += l + if cmdline == '': + return '' + return cmdline + +def parse_in_dir(in_dir): + for (dirpath, _, filenames) in os.walk(in_dir): + # remove in_dir from path, don't use it for the addon name + addon_name = dirpath.replace(in_dir, "", 1) + # remove the '/' added by walk after in_dir + addon_name = addon_name.replace("/", "",1) + # transform remaining '/' in '-' + addon_name = addon_name.replace("/", "-") + for addon_f in filenames: + if addon_f.endswith('.addon'): + addon_full_name = addon_name + if addon_full_name != '': + addon_full_name += '-' + addon_full_name += addon_f + '.efi' + cmdline = parse_addon_conf(dirpath+'/'+addon_f) + if cmdline: + uki_addon_list.append(UKICmdlineAddon(addon_full_name, cmdline)) + +def parse_sbat(in_dir): + sbat_loc = in_dir + SBAT_LOCATION + if not os.path.isfile(sbat_loc): + return + return parse_addon_conf(sbat_loc, rstrip=False) + +def main(in_dir, out_dir): + sbat_string = parse_sbat(in_dir) + for uki_addon in uki_addon_list: + out_path = out_dir + '/' + uki_addon.name + cmd = [ + f'{UKIFY_PATH}', 'build', + f'--stub={SYSTEMD_STUB_PATH}', + f'--cmdline="{uki_addon.cmdline}"', + f'--output={out_path}'] + if sbat_string: + cmd.append('--sbat="' + sbat_string.rstrip() +'"') + + print(cmd) + subprocess.check_call(cmd, text=True) + +if __name__ == "__main__": + argc = len(sys.argv) - 1 + if argc != 2: + usage('too few or too many parameters!') + + in_dir = sys.argv[1] + out_dir = sys.argv[2] + + in_dir, out_dir = check_clean_arguments(in_dir, out_dir) + parse_in_dir(in_dir) + main(in_dir, out_dir) + + -- https://gitlab.com/cki-project/kernel-ark/-/merge_requests/2917 -- _______________________________________________ kernel mailing list -- kernel@xxxxxxxxxxxxxxxxxxxxxxx To unsubscribe send an email to kernel-leave@xxxxxxxxxxxxxxxxxxxxxxx Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/ List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedoraproject.org/archives/list/kernel@xxxxxxxxxxxxxxxxxxxxxxx Do not reply to spam, report it: https://pagure.io/fedora-infrastructure/new_issue