summaryrefslogtreecommitdiff
path: root/eclass
diff options
context:
space:
mode:
authorNowa Ammerlaan <nowa@gentoo.org>2025-01-09 19:22:39 +0100
committerNowa Ammerlaan <nowa@gentoo.org>2025-01-10 17:44:19 +0100
commit422a7e51c1e1a7774e406e3f0856b4e415fee46f (patch)
tree93bf71d3be96812f57dc86f565462ea46cc3f39b /eclass
parentmedia-gfx/freecad: new revision 1.0.0-r3 (diff)
downloadgentoo-422a7e51c1e1a7774e406e3f0856b4e415fee46f.tar.gz
gentoo-422a7e51c1e1a7774e406e3f0856b4e415fee46f.tar.bz2
gentoo-422a7e51c1e1a7774e406e3f0856b4e415fee46f.zip
kernel-install.eclass: verify uki/kernel image before installing
This avoids accidentally installing a kernel image or generic UKI with an invalid signature in both gentoo-kernel and gentoo-kernel-bin. This means we will catch regressions such as described below earlier, notably it will now error out when building the binpkgs for gentoo-kernel-bin. We also add some logic to recover from the case where the kernel image is larger then it should be. This may be the case with ukify>=257 because starting from this version onwards the space that the kernel needs to extract and run is reserved in the .linux section of the UKI as padding. Objcopy unfortunately copies this padding along with the rest of the data, invalidating the signature. In previous versions of ukify this was not an issue because the .linux section was always the last section in the UKI and you could therefore usually get away with not reserving the extra required space. Sbverify helpfully reports a warning about this padding with the exact size the kernel image should have. We use this to strip the padding from the kernel image, and verify if the signature problem is now resolved. There may be a better way to do this that does not involve parsing the output of sbverify, but I have not been able to find any. See-also: https://github.com/systemd/systemd/issues/35851 See-also: https://forums.gentoo.org/viewtopic-t-1172386.html Signed-off-by: Nowa Ammerlaan <nowa@gentoo.org>
Diffstat (limited to 'eclass')
-rw-r--r--eclass/kernel-install.eclass59
1 files changed, 56 insertions, 3 deletions
diff --git a/eclass/kernel-install.eclass b/eclass/kernel-install.eclass
index 1cc2bd0bb737..cf34007844a8 100644
--- a/eclass/kernel-install.eclass
+++ b/eclass/kernel-install.eclass
@@ -204,6 +204,7 @@ if [[ ${KERNEL_IUSE_GENERIC_UKI} ]]; then
"
IDEPEND="
generic-uki? (
+ app-crypt/sbsigntools
>=sys-kernel/installkernel-14[-dracut(-),-ugrd(-),-ukify(-)]
)
!generic-uki? (
@@ -660,13 +661,65 @@ kernel-install_extract_from_uki() {
local extract_type=${1}
local uki=${2}
local out=${3}
+ local out_temp=${T}/${extract_type}-section-dumped
# objcopy overwrites input if there is no output, dump the output in T.
# We unfortunately cannot use /dev/null here
$(tc-getOBJCOPY) "${uki}" "${T}/dump.efi" \
- --dump-section ".${extract_type}=${out}" ||
- die "Failed to extract ${extract_type}"
- chmod 644 "${out}" || die
+ --dump-section ".${extract_type}=${out_temp}" ||
+ die "Failed to extract ${extract_type}"
+
+ # Sanity checks for kernel images
+ if [[ ${extract_type} == linux ]] &&
+ { ! in_iuse secureboot || use secureboot ;}
+ then
+ # Extract the used SECUREBOOT_SIGN_CERT to verify the kernel image
+ local cert=${T}/pcrpkey
+ kernel-install_extract_from_uki pcrpkey "${uki}" "${cert}"
+ if [[ $(head -n1 "${cert}") != "-----BEGIN CERTIFICATE-----" ]]; then
+ # This is a DER format certificate, convert it to PEM
+ openssl x509 \
+ -inform DER -in "${cert}" \
+ -outform PEM -out "${cert}" ||
+ die "Failed to convert pcrpkey to PEM format"
+ fi
+
+ # Check if the signature on the UKI is valid
+ sbverify --cert "${cert}" "${uki}" ||
+ die "ERROR: UKI signature is invalid"
+
+ # Check if the signature on the kernel image is valid
+ local sbverify_err=$(
+ sbverify --cert "${cert}" "${out_temp}" 2>&1 >/dev/null
+ )
+
+ # Check if there was a padding warning
+ if [[ ${sbverify_err} == "warning: data remaining"*": gaps between PE/COFF sections?"* ]]
+ then
+ # https://github.com/systemd/systemd/issues/35851
+ local proper_size=${sbverify_err#"warning: data remaining["}
+ proper_size=${proper_size%" vs"*}
+ # Strip the padding
+ head "${out_temp}" --bytes "${proper_size}" \
+ >"${out_temp}_trimmed" || die
+ # Check if the signature verifies now
+ sbverify_err=$(
+ sbverify --cert "${cert}" "${out_temp}_trimmed" 2>&1 >/dev/null
+ )
+ [[ -z ${sbverify_err} ]] && out_temp=${out_temp}_trimmed
+ fi
+
+ # Something has gone wrong, stop here to prevent installing a kernel
+ # with an invalid signature or a completely broken kernel image.
+ if [[ -n ${sbverify_err} ]]; then
+ eerror "${sbverify_err}"
+ die "ERROR: Kernel image signature is invalid"
+ else
+ einfo "Signature verification OK"
+ fi
+ fi
+
+ install -m 644 "${out_temp}" "${out}" || die
}
# @FUNCTION: kernel-install_install_all