From 92337a56eaee72228a73846a65660cae1c98cc88 Mon Sep 17 00:00:00 2001 From: Zhixiong Chi Date: Thu, 5 May 2022 02:41:42 -0700 Subject: [PATCH] kpatch: Add the signature for livepatch kernel modules As the commit [https://review.opendev.org/c/starlingx/kernel/+/838284] shows, once lockdown feature for secure boot was enabled, the unsigned kernel modules' loading will fail with the error 'Operation not permitted'. For livepatched kernel module we also need to sign the module so that we can insmod the module successfully when the command 'kpatch load xxx.ko' or 'systemctl start kpatch.service' is executed. Add '-k/--keydir' to support the customzied pubkey/privkey pairs. Drop some unused variables for starlingx platform. Signed-off-by: Zhixiong Chi --- kpatch-build/kpatch-build | 54 ++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 18 deletions(-) diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build index 3c721ea..8a9fa03 100755 --- a/kpatch-build/kpatch-build +++ b/kpatch-build/kpatch-build @@ -49,6 +49,11 @@ ENVFILE="$TEMPDIR/kpatch-build.env" LOGFILE="$CACHEDIR/build.log" RELEASE_FILE=/etc/os-release LINUXSRCDIR=/usr/src +KVERSION=$(uname -r) +KEYDIR="${LINUXSRCDIR}/kernels/${KVERSION}" +SIGNTOOLDIR=(/usr/lib/linux*-kbuild-*/scripts) +SIGNTOOL="sign-file" +SIGHASH="sha256" DEBUG=0 SKIPCLEANUP=0 SKIPCOMPILERCHECK=0 @@ -523,6 +528,19 @@ module_name_string() { echo "${1//[^a-zA-Z0-9_-]/-}" | cut -c 1-48 } +# Sign the generated livepatched kernel module +sign_module() { + local module=${1} + PRIVKEY="${KEYDIR}/signing_key.pem" + PUBKEY="${KEYDIR}/signing_key.x509" + SIGNTOOL_ABSPATH=$(find "${SIGNTOOLDIR[@]}" -name "${SIGNTOOL}") + [[ ! -e "${SIGNTOOL_ABSPATH}" ]] && die "can't find ${SIGNTOOL}." + [[ ! -e "${PRIVKEY}" ]] && die "can't find privkey ${PRIVKEY}." + [[ ! -e "${PUBKEY}" ]] && die "can't find publickey ${PUBKEY}." + + "${SIGNTOOL_ABSPATH}" "${SIGHASH}" "${PRIVKEY}" "${PUBKEY}" "${module}" || die "Sign module ${module} failed!" +} + usage() { echo "usage: $(basename "$0") [options] " >&2 echo " patchN Input patchfile(s)" >&2 @@ -547,7 +565,7 @@ usage() { echo " (not recommended)" >&2 } -options="$(getopt -o ha:r:s:c:v:j:t:n:o:de:R -l "help,archversion:,sourcerpm:,sourcedir:,config:,vmlinux:,jobs:,target:,name:,output:,oot-module:,debug,skip-gcc-check,skip-compiler-check,skip-cleanup,non-replace" -- "$@")" || die "getopt failed" +options="$(getopt -o ha:r:s:c:v:j:t:n:o:k:de:R -l "help,archversion:,sourcerpm:,sourcedir:,config:,vmlinux:,jobs:,target:,name:,output:,keydir:,oot-module:,debug,skip-gcc-check,skip-compiler-check,skip-cleanup,non-replace" -- "$@")" || die "getopt failed" eval set -- "$options" @@ -599,6 +617,11 @@ while [[ $# -gt 0 ]]; do BASE="$(readlink -f "$2")" shift ;; + -k|--keydir) + [[ ! -d "$2" ]] && die "keydir '$2' not found" + KEYDIR="$(readlink -f "$2")" + shift + ;; -d|--debug) DEBUG=$((DEBUG + 1)) if [[ $DEBUG -eq 1 ]]; then @@ -785,22 +808,7 @@ else echo "Debian/Ubuntu distribution detected" - if [[ "$DISTRO" = ubuntu ]]; then - - # url may be changed for a different mirror - url="http://archive.ubuntu.com/ubuntu/pool/main/l" - sublevel="SUBLEVEL = 0" - - elif [[ "$DISTRO" = debian ]]; then - - # url may be changed for a different mirror - url="http://ftp.debian.org/debian/pool/main/l" - sublevel="SUBLEVEL = 0" - fi - - pkgname="$(dpkg-query -W -f='${Source}' "linux-image-$ARCHVERSION" | sed s/-signed//)" - pkgver="$(dpkg-query -W -f='${Version}' "linux-image-$ARCHVERSION")" - dscname="${pkgname}_${pkgver}.dsc" + sublevel="SUBLEVEL = 0" clean_cache @@ -815,7 +823,7 @@ else KSRCVER="${KVER%.*}" KSRCNAME="$LINUXSRCDIR/linux-source-$KSRCVER.tar.xz" if [[ -e "$KSRCNAME" ]]; then - tar xvf $KSRCNAME + tar xvf "${KSRCNAME}" 2>&1 | logger || die mv "linux-source-$KSRCVER" "$SRCDIR" || die fi # Due to the ostree mechanism, we need add the prefix for kernel config here @@ -977,6 +985,14 @@ else MAKEVARS+=("LD=${KPATCH_CC_PREFIX}ld") fi +# Adjust the kconfig +KCONFIGACK="" +KCONFIGCOUNT=$(make listnewconfig | wc -l) +while [[ "${KCONFIGCOUNT}" -gt 0 ]]; do + KCONFIGACK=${KCONFIGACK}"\n" + let KCONFIGCOUNT-- +done +echo -e "${KCONFIGACK}" | make -f ./Makefile syncconfig 2>&1 | logger || die # $TARGETS used as list, no quotes. # shellcheck disable=SC2086 @@ -1257,6 +1273,8 @@ UNDEFINED=$(comm -23 <(sort -u "${TEMPDIR}"/undefined_references) \ cp -f "$TEMPDIR/patch/$MODNAME.ko" "$BASE" || die +sign_module "${BASE}/${MODNAME}.ko" | logger + [[ "$DEBUG" -eq 0 && "$SKIPCLEANUP" -eq 0 ]] && rm -f "$LOGFILE" echo "SUCCESS" -- 2.34.1