diff --git a/configure.ac b/configure.ac index c4a7e2a..9dae4a6 100644 --- a/configure.ac +++ b/configure.ac @@ -925,6 +925,7 @@ AC_OUTPUT([ Doxyfile Makefile rpmrc macros platform rpmpopt scripts/brp-cleanup scripts/brp-compress scripts/brp-debuginfo + scripts/brp-sign-kmodules scripts/brp-fix-perms scripts/brp-fixup scripts/brp-verify_elf diff --git a/scripts/Makefile.am b/scripts/Makefile.am index f593455..92ffd18 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -7,7 +7,7 @@ EXTRA_DIST = \ debuginfo.req debuginfo.req.files debuginfo.prov debuginfo.prov.files \ functions find-package .provides.sh \ find-debuginfo-files process-debuginfo \ - find-scriptlet-requires \ + find-scriptlet-requires brp-sign-kmodules \ brp-adjust_libraries brp-alt brp-bytecompile_python \ brp-check_contents brp-cleanup brp-compress brp-debuginfo \ brp-fix-perms brp-fixup brp-hardlink_pyo_pyc \ @@ -78,6 +78,7 @@ install-data-local: $(INSTALL) -m755 brp-verify-info $(DESTDIR)$(configdir)/brp.d/040-verify-info.brp $(INSTALL) -m755 brp-adjust_libraries $(DESTDIR)$(configdir)/brp.d/048-adjust_libraries.brp $(INSTALL) -m755 brp-debuginfo $(DESTDIR)$(configdir)/brp.d/056-debuginfo.brp + $(INSTALL) -m755 brp-sign-kmodules $(DESTDIR)$(configdir)/brp.d/057-brp-sign-kmodules.brp $(INSTALL) -m755 process-debuginfo $(DESTDIR)$(configdir)/process-debuginfo $(INSTALL) -m755 brp-verify_elf $(DESTDIR)$(configdir)/brp.d/064-verify_elf.brp $(INSTALL) -m755 brp-bytecompile_python $(DESTDIR)$(configdir)/brp.d/072-bytecompile_python.brp diff --git a/scripts/brp-sign-kmodules.in b/scripts/brp-sign-kmodules.in new file mode 100755 index 0000000..d9e1dd3 --- /dev/null +++ b/scripts/brp-sign-kmodules.in @@ -0,0 +1,132 @@ +#!/bin/sh -e +# +# brp-sign-kmodules - sign Linux kernel modules +# +# Copyright (C) 2020 Vitaly Chikunov +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +. @RPMCONFIGDIR@/functions +ValidateBuildRoot + +cd "$RPM_BUILD_ROOT" || exit + +# We need modules and kernel tree to work. +[ -d lib/modules ] || exit 0 +[ -d boot ] || exit 0 + +# Find kernel build root. +kbuilddir=$(find "$RPM_BUILD_DIR" -depth -maxdepth 3 -type f -name MAINTAINERS -print -quit) +kbuilddir=${kbuilddir%/*} +if [ -z "$kbuilddir" ]; then + Warning "Kernel source directory not found." + exit 0 +fi + +# Determine build time `.config'. Allow 2 levels for builds in O=subdir. +kconfig=$(find "$kbuilddir" -depth -maxdepth 2 -type f -name .config -print -quit) +if [ -z "$kconfig" ]; then + Warning "Kernel build output directory not found." + exit 0 +fi + +# Kernel output dir (from O=) +koutput=${kconfig%/.config} + +# Working requirement. +if [ ! -x "$koutput/scripts/sign-file" ]; then + Warning "scripts/sign-file executable not found." + exit 0 +fi + +get_config() { + "$kbuilddir/scripts/config" --file "$kconfig" -s "$1" +} + +MODULE_SIG_ALL=$( get_config MODULE_SIG_ALL) +MODULE_SIG_HASH=$(get_config MODULE_SIG_HASH) +MODULE_SIG_KEY=$( get_config MODULE_SIG_KEY) +MODULE_SIG_CERT=certs/signing_key.x509 + +if [ "$MODULE_SIG_ALL" != "y" ]; then + Warning "Module signing is not enabled (CONFIG_MODULE_SIG_ALL=$MODULE_SIG_ALL)" + exit 0 +fi +if [ -z "$MODULE_SIG_HASH" ] || [ "$MODULE_SIG_HASH" = undef ]; then + Warning "Module signing hash is not set (CONFIG_MODULE_SIG_HASH)" + exit 0 +fi +if [ -z "$MODULE_SIG_KEY" ] || [ "$MODULE_SIG_KEY" = undef ]; then + Warning "Module signing key is not set (CONFIG_MODULE_SIG_KEY)" + exit 0 +fi + +sig_key=$koutput/$MODULE_SIG_KEY +if [ ! -f "$sig_key" ]; then + Warning "Signing key not found (CONFIG_MODULE_SIG_KEY=\"$MODULE_SIG_KEY\")" + exit 0 +fi + +sig_cert=$koutput/$MODULE_SIG_CERT +if [ ! -f "$sig_cert" ]; then + Warning "Signing cert not found (expected $MODULE_SIG_CERT)" + exit 0 +fi + +find "$RPM_BUILD_ROOT/lib/modules" -name '*.ko*' > .kmodules +num=$(wc -l < .kmodules) +if [ $num -eq 0 ]; then + Warning "No kernel modules found for singing." + exit 0 +fi + +# Verify that singing is working to avoid flooding with errors later. +cd "$koutput" +t=$(mktemp) +if ! scripts/sign-file "$MODULE_SIG_HASH" "$MODULE_SIG_KEY" "$MODULE_SIG_CERT" "$t"; then + Warning "Test signing failed (scripts/sign-file error)." + exit 0 +fi +rm "$t" +cd "$RPM_BUILD_ROOT" + +# Determine if we should uncompress. +read f < .kmodules +rezip= +if [ -z "${f#*.ko.[gx]z}" ]; then + rezip=${f##*.} + rezip=${rezip/gz/gzip} +fi + +if [ -n "$rezip" ]; then + Info "Uncompress ($rezip) $num modules before signing." + xargs -P$(nproc) $rezip --decompress < .kmodules +fi + +cd "$koutput" +Info "Signing $num modules in $RPM_BUILD_ROOT (hash $MODULE_SIG_HASH key $MODULE_SIG_KEY)" + +sed 's/\.ko\.[xg]z$/.ko/' < "$RPM_BUILD_ROOT/.kmodules" \ +| xargs -P$(nproc) -n1 scripts/sign-file "$MODULE_SIG_HASH" "$MODULE_SIG_KEY" "$MODULE_SIG_CERT" + +cd "$RPM_BUILD_ROOT" + +if [ -n "$rezip" ]; then + Info "Compress ($rezip) $num modules after signing." + sed 's/\.ko\.[xg]z$/.ko/' < .kmodules | xargs -P$(nproc) $rezip +fi + +rm .kmodules