diff --git a/SOURCES/almalinuxdup1.x509 b/SOURCES/almalinuxdup1.x509 new file mode 100644 index 000000000..29720140f Binary files /dev/null and b/SOURCES/almalinuxdup1.x509 differ diff --git a/SOURCES/almalinuxkpatch1.x509 b/SOURCES/almalinuxkpatch1.x509 new file mode 100644 index 000000000..129261029 Binary files /dev/null and b/SOURCES/almalinuxkpatch1.x509 differ diff --git a/SOURCES/almalinuxsecurebootca0.cer b/SOURCES/almalinuxsecurebootca0.cer new file mode 100644 index 000000000..6a4e99b9e Binary files /dev/null and b/SOURCES/almalinuxsecurebootca0.cer differ diff --git a/SOURCES/mod-sign.sh b/SOURCES/mod-sign.sh new file mode 100755 index 000000000..a7891414b --- /dev/null +++ b/SOURCES/mod-sign.sh @@ -0,0 +1,69 @@ +#! /bin/bash + +# The modules_sign target checks for corresponding .o files for every .ko that +# is signed. This doesn't work for package builds which re-use the same build +# directory for every variant, and the .config may change between variants. +# So instead of using this script to just sign lib/modules/$KernelVer/extra, +# sign all .ko in the buildroot. + +# This essentially duplicates the 'modules_sign' Kbuild target and runs the +# same commands for those modules. + +MODSECKEY=$1 +MODPUBKEY=$2 +moddir=$3 + + + +modules=$(find "$moddir" -type f -name '*.ko*') + +NPROC=$(nproc) +[ -z "$NPROC" ] && NPROC=1 + +# NB: this loop runs 2000+ iterations. Try to be fast. +echo "$modules" | xargs -r -n16 -P $NPROC sh -c " +for mod; do + module_basename=\${mod:0:-3} + module_suffix=\${mod: -3} + + if [[ "\$module_suffix" == ".xz" ]]; then + unxz \$mod + ./scripts/sign-file sha256 $MODSECKEY $MODPUBKEY \$module_basename + xz -f \$module_basename + elif [[ "\$module_suffix" == ".gz" ]]; then + gunzip \$mod + ./scripts/sign-file sha256 $MODSECKEY $MODPUBKEY \$module_basename + gzip -9f \$module_basename + else + ./scripts/sign-file sha256 $MODSECKEY $MODPUBKEY \$mod + fi + + rm -f \$module_basename.sig \$module_basename.dig +done +" DUMMYARG0 # xargs appends ARG1 ARG2..., which go into $mod in for loop. + +RANDOMMOD=$(echo "$modules" | sort -R | head -n 1) +rand_module_basename=${RANDOMMOD:0:-3} +rand_module_suffix=${RANDOMMOD: -3} +if [[ "$rand_module_suffix" == ".xz" ]]; then + unxz $RANDOMMOD +elif [[ "$rand_module_suffix" == ".gz" ]]; then + gunzip $RANDOMMOD +else + rand_module_basename=$RANDOMMOD +fi +if [ "~Module signature appended~" != "$(tail -c 28 "$rand_module_basename")" ]; then + echo "*****************************" + echo "*** Modules are unsigned! ***" + echo "*****************************" + exit 1 +fi +if [[ "$rand_module_suffix" == ".xz" ]]; then + xz -f $rand_module_basename +elif [[ "$rand_module_suffix" == ".gz" ]]; then + gzip -9f $rand_module_basename +else + true +fi + +exit 0 diff --git a/SOURCES/x509.genkey b/SOURCES/x509.genkey new file mode 100644 index 000000000..4c34491f9 --- /dev/null +++ b/SOURCES/x509.genkey @@ -0,0 +1,16 @@ +[ req ] +default_bits = 3072 +distinguished_name = req_distinguished_name +prompt = no +x509_extensions = myexts + +[ req_distinguished_name ] +O = AlmaLinux +CN = AlmaLinux kernel signing key +emailAddress = security@almalinux.org + +[ myexts ] +basicConstraints=critical,CA:FALSE +keyUsage=digitalSignature +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid diff --git a/SPECS/kernel-ml-6.8.spec b/SPECS/kernel-ml-6.8.spec index ab80aadff..a86c01be5 100644 --- a/SPECS/kernel-ml-6.8.spec +++ b/SPECS/kernel-ml-6.8.spec @@ -34,11 +34,17 @@ # vsdo install %define with_vdso_install %{?_without_vdso_install: 0} %{?!_without_vdso_install: 1} +# Compress modules on all architectures that build modules. +%ifarch x86_64 +%global zipmodules 1 +%else +%global zipmodules 0 +%endif + # Kernel-ml, devel, headers, perf, tools and bpftool. %ifarch x86_64 %define with_doc 0 %define doc_build_fail true -%define zipmodules 1 ### as of kernel-ml-6.5.4, no more bpftool -ay %define with_bpftool 0 %endif @@ -51,7 +57,6 @@ %define with_tools 0 %define with_bpftool 0 %define with_vdso_install 0 -%define zipmodules 0 %endif # Compressed modules. @@ -72,6 +77,21 @@ # Set pkg_release. %define pkg_release 1%{?dist}%{?buildid} +# Architectures upon which we can sign the kernel +# for secure boot authentication. +%ifarch x86_64 || aarch64 +%global signkernel 1 +%else +%global signkernel 0 +%endif + +# Sign modules on all architectures that build modules. +%ifarch x86_64 || aarch64 +%global signmodules 1 +%else +%global signmodules 0 +%endif + %define KVERREL %{pkg_version}-%{pkg_release}.%{_target_cpu} # Packages that need to be present before kernel-ml is installed @@ -80,7 +100,7 @@ %define initrd_prereq dracut >= 027 Name: kernel-ml -Summary: The Linux kernel. (The core of any Linux-based operating system.) +Summary: Alternative AlmaLinux kernel based on the "mainline" branch. (The core of any Linux-based operating system.) Group: System Environment/Kernel License: GPLv2 URL: https://www.kernel.org/ @@ -112,6 +132,12 @@ BuildRequires: asciidoc gettext libcap-devel libnl3-devel ncurses-devel pciutils %if %{with_bpftool} BuildRequires: binutils-devel python3-docutils zlib-devel %endif +%if %{signkernel} || %{signmodules} +BuildRequires: openssl +%if %{signkernel} +BuildRequires: nss-tools, pesign >= 0.10-4 +%endif +%endif BuildConflicts: rhbuildsys(DiskFree) < 500Mb # Sources. @@ -126,9 +152,18 @@ Source7: filter-x86_64.sh Source8: filter-modules.sh Source9: generate_bls_conf.sh -# To build .src.rpm, run with '--with src' -%if %{?_with_src:0}%{!?_with_src:1} -NoSource: 0 +Source21: mod-sign.sh +Source23: x509.genkey + +Source100: almalinuxdup1.x509 +Source101: almalinuxkpatch1.x509 +Source102: almalinuxsecurebootca0.cer + +%if %{signkernel} +%define secureboot_ca_0 %{SOURCE102} +%define secureboot_key_0 %{SOURCE102} + +%define pesign_name_0 almalinuxsecurebootca0 %endif %description @@ -408,6 +443,20 @@ fi %{__rm} -f newoptions-el8-%{_target_cpu}.txt %endif +# Add DUP and kpatch certificates to system trusted keys for RHEL. +%if %{signkernel} || %{signmodules} +openssl x509 -inform der -in %{SOURCE100} -out rheldup3.pem +openssl x509 -inform der -in %{SOURCE101} -out rhelkpatch1.pem +cat rheldup3.pem rhelkpatch1.pem > certs/rhel.pem +for i in config-%{version}-*; do + sed -i 's@CONFIG_SYSTEM_TRUSTED_KEYS="*"@CONFIG_SYSTEM_TRUSTED_KEYS="certs/rhel.pem"@' $i +done +%else +for i in config-%{version}-*; do + sed -i 's@CONFIG_SYSTEM_TRUSTED_KEYS="*"@CONFIG_SYSTEM_TRUSTED_KEYS=""@' $i +done +%endif + %{__mv} COPYING COPYING-%{version} # Do not use ambiguous python shebangs. RHEL 8 now has a new script @@ -436,6 +485,10 @@ pushd linux-%{KVERREL} > /dev/null %{__make} -s ARCH=%{_target_cpu} oldconfig +%if %{signkernel} || %{signmodules} +cp %{SOURCE23} certs/ +%endif + %{__make} -s ARCH=%{_target_cpu} %{?_smp_mflags} bzImage %{__make} -s ARCH=%{_target_cpu} %{?_smp_mflags} modules || exit 1 @@ -535,6 +588,11 @@ KernelVer=%{version}-%{release}.%{_target_cpu} %define __spec_install_post \ %{__arch_install_post} \ %{__os_install_post} \ + if [ "%{signmodules}" -eq "1" ]; then \ + cd linux-%{KVERREL} \ + %{SOURCE21} certs/signing_key.pem.sign certs/signing_key.x509.sign $RPM_BUILD_ROOT/lib/modules/%{KVERREL}/ \ + cd - \ + fi \ if [ "%{zipmodules}" -eq "1" ]; then \ %{_bindir}/find $RPM_BUILD_ROOT/lib/modules/ -name '*.ko' -type f | \ %{_bindir}/xargs --no-run-if-empty -P%{zcpu} %{__xz} \ @@ -551,6 +609,31 @@ KernelVer=%{version}-%{release}.%{_target_cpu} # into consideration when performing disk space calculations. (See bz #530778) dd if=/dev/zero of=$RPM_BUILD_ROOT/boot/initramfs-$KernelVer.img bs=1M count=20 +%if %{signkernel} +# Sign the kernel image if we're using EFI. +# aarch64 kernels are gziped EFI images. +%ifarch x86_64 +SignImage=arch/x86/boot/bzImage +%endif + +%ifarch aarch64 +SignImage=arch/arm64/boot/Image +%endif + +%pesign -s -i $SignImage -o vmlinuz.signed -a %{secureboot_ca_0} -c %{secureboot_key_0} -n %{pesign_name_0} + +if [ ! -s vmlinuz.signed ]; then + echo "pesigning failed" + exit 1 +fi + +mv vmlinuz.signed $SignImage + +%ifarch aarch64 +gzip -f9 $SignImage +%endif +%endif + %{__cp} arch/x86/boot/bzImage $RPM_BUILD_ROOT/boot/vmlinuz-$KernelVer %{__chmod} 755 $RPM_BUILD_ROOT/boot/vmlinuz-$KernelVer %{__cp} $RPM_BUILD_ROOT/boot/vmlinuz-$KernelVer $RPM_BUILD_ROOT/lib/modules/$KernelVer/vmlinuz @@ -778,6 +861,18 @@ popd > /dev/null %{_bindir}/find $RPM_BUILD_ROOT/usr/src/kernels -name '.*.cmd' -type f | \ %{_bindir}/xargs --no-run-if-empty %{__rm} -f +# Red Hat UEFI Secure Boot CA certificate, which can be used to authenticate the kernel. +mkdir -p $RPM_BUILD_ROOT%{_datadir}/doc/%{name}-keys/%{KVERREL} +%if %{signkernel} +install -m 0644 %{secureboot_ca_0} $RPM_BUILD_ROOT%{_datadir}/doc/%{name}-keys/%{KVERREL}/kernel-signing-ca.cer +%endif + +%if %{signmodules} +# Save the signing keys so that we can sign the modules in __modsign_install_post. +cp certs/signing_key.pem certs/signing_key.pem.sign +cp certs/signing_key.x509 certs/signing_key.x509.sign +%endif + # Create a boot loader script configuration file for this kernel. %{SOURCE9} $KernelVer $RPM_BUILD_ROOT "" %endif @@ -1115,6 +1210,7 @@ fi /lib/modules/%{KVERREL}%{?3:+%{3}}/updates\ /lib/modules/%{KVERREL}%{?3:+%{3}}/weak-updates\ /lib/modules/%{KVERREL}%{?3:+%{3}}/bls.conf\ +%{_datadir}/doc/%{name}-keys/%{KVERREL}%{?3:+%{3}}\ %if %{1}\ /lib/modules/%{KVERREL}%{?3:+%{3}}/vdso\ %if 0\