From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by finch.gentoo.org (Postfix) with ESMTPS id 54D8E138334 for ; Mon, 1 Oct 2018 08:48:40 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id 2EEE8E0937; Mon, 1 Oct 2018 08:48:34 +0000 (UTC) Received: from smtp.gentoo.org (smtp.gentoo.org [140.211.166.183]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id C3A93E092C for ; Mon, 1 Oct 2018 08:48:33 +0000 (UTC) Received: from reaper.local.sysdump.net (ip72-194-88-79.oc.oc.cox.net [72.194.88.79]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: gyakovlev) by smtp.gentoo.org (Postfix) with ESMTPSA id EAF7F335D13; Mon, 1 Oct 2018 08:48:31 +0000 (UTC) From: Georgy Yakovlev To: gentoo-dev@lists.gentoo.org Cc: Georgy Yakovlev Subject: [gentoo-dev] [PATCH 1/2] eclass/linux-mod.eclass: add module signing support Date: Mon, 1 Oct 2018 01:48:13 -0700 Message-Id: <20181001084814.55877-1-gyakovlev@gentoo.org> X-Mailer: git-send-email 2.19.0 In-Reply-To: <20180921051304.115704-1-gyakovlev@gentoo.org> References: <20180921051304.115704-1-gyakovlev@gentoo.org> Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-dev@lists.gentoo.org Reply-to: gentoo-dev@lists.gentoo.org MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Archives-Salt: a6564b1c-0b65-4d1f-a8b5-c1fd724a8706 X-Archives-Hash: 57d3ce99990c103387a4e26485955780 This commit adds some eclass variables and private functions and a new global useflag. Example config, part of make.conf USE="... module-sign ..." KERNEL_MODULE_SIG_KEY="/secure/location/kernel.pem" And possible kernel options: CONFIG_MODULE_SIG=y CONFIG_MODULE_SIG_FORCE=y CONFIG_MODULE_SIG_ALL=y CONFIG_MODULE_SIG_SHA512=y CONFIG_MODULE_SIG_HASH="sha512" NOTE to libressl users: libressl does not support anything except CONFIG_MODULE_SIG_SHA1=y CONFIG_MODULE_SIG_HASH="sha1" Even if user does not follow key creation procedure and just enables module encryption while configuring kernel eclass "just works". All the signing happens in pkg_preinst. This means that binpkg users are expected to have keys and sign modules on target system, not on builder. I've been using this since March and have not encountered a single problem with various out-of-tree kernel modules Tested so far: virtualbox-modules nvidia-drivers zfs & co wireguard and many more If an ebuild uses Kbuild and/or runs linux-mod_pkg_preinst(), signing should work. All the signing happens as root, this means user can have the keys stored with secure permissions and mount as required. If user configured kernel to require signed modules the eclass will detect it and refuse to emerge if useflag is not enabled. I'll appreciate your testing and feedbak. NOTE to amdgpu users: if you use CONFIG_HSA_AMD, you'll want to have CONFIG_HSA_AMD=y having it as a module fails to sing for some reason, it's something in kernel/kbuild and not related to this eclass change. Bug: https://bugs.gentoo.org/447352 Signed-off-by: Georgy Yakovlev --- eclass/linux-mod.eclass | 109 ++++++++++++++++++++++++++++++++++++++-- profiles/use.desc | 1 + 2 files changed, 106 insertions(+), 4 deletions(-) diff --git a/eclass/linux-mod.eclass b/eclass/linux-mod.eclass index 920790b8db9..de43f2d234e 100644 --- a/eclass/linux-mod.eclass +++ b/eclass/linux-mod.eclass @@ -132,6 +132,20 @@ # @DESCRIPTION: # It's a read-only variable. It contains the extension of the kernel modules. +# @ECLASS-VARIABLE: KERNEL_MODULE_SIG_KEY +# @USER_VARIABLE +# @DEFAULT_UNSET +# @DESCRIPTION: +# A string, containing absolute path to the private key file. +# eclass will use value of CONFIG_MODULE_SIG_KEY extracted from .config +# if KERNEL_MODULE_SIG_KEY is not set by user. +# +# Example: +# @CODE +# KERNEL_MODULE_SIG_KEY="/secure/location/kernel.pem" +# @CODE +# Assumes that "/secure/location/kernel.x509" public key file exists. + inherit eutils linux-info multilib EXPORT_FUNCTIONS pkg_setup pkg_preinst pkg_postinst src_install src_compile pkg_postrm @@ -144,13 +158,16 @@ esac 0) die "EAPI=${EAPI} is not supported with MODULES_OPTIONAL_USE_IUSE_DEFAULT due to lack of IUSE defaults" ;; esac -IUSE="kernel_linux ${MODULES_OPTIONAL_USE:+${_modules_optional_use_iuse_default}}${MODULES_OPTIONAL_USE}" +IUSE="module-sign kernel_linux ${MODULES_OPTIONAL_USE:+${_modules_optional_use_iuse_default}}${MODULES_OPTIONAL_USE}" SLOT="0" RDEPEND="${MODULES_OPTIONAL_USE}${MODULES_OPTIONAL_USE:+? (} kernel_linux? ( virtual/modutils ) ${MODULES_OPTIONAL_USE:+)}" DEPEND="${RDEPEND} ${MODULES_OPTIONAL_USE}${MODULES_OPTIONAL_USE:+? (} sys-apps/sed - kernel_linux? ( virtual/linux-sources virtual/libelf ) + kernel_linux? ( + virtual/linux-sources virtual/libelf + module-sign? ( || ( dev-libs/openssl dev-libs/libressl ) ) + ) ${MODULES_OPTIONAL_USE:+)}" # eclass utilities @@ -352,6 +369,84 @@ get-KERNEL_CC() { echo "${kernel_cc}" } +# @FUNCTION: _check_sig_force +# @INTERNAL +# @DESCRIPTION: +# Check if kernel requires module signing and die +# if modules are not going to be signed. +_check_sig_force() { + debug-print-function ${FUNCNAME} "${@}" + + if linux_chkconfig_present MODULE_SIG_FORCE; then + if use !module-sign; then + eerror "kernel .config has MODULE_SIG_FORCE=y option set" + eerror "This means that kernel requires all modules" + eerror "to be signed and verified before loading" + eerror "please enable USE=\"module-sign\" or reconfigure your kernel" + eerror "otherwise loading the module will fail" + die "signature required" + fi + fi +} + +# @FUNCTION: _sign_module +# @INTERNAL +# @USAGE: +# @DESCRIPTION: +# Sign a kernel module +_sign_module() { + debug-print-function ${FUNCNAME} "${@}" + + local dotconfig_sig_hash dotconfig_sig_key + local sign_binary_path sig_key_path sig_x509_path + local module + + # extract values from kernel .config + # extracted key path is not full, e.g. "certs/signing_key.pem" + dotconfig_sig_hash="$(linux_chkconfig_string MODULE_SIG_HASH)" + dotconfig_sig_key="$(linux_chkconfig_string MODULE_SIG_KEY)" + + # sign-file binary chokes on double quotes + dotconfig_sig_hash=${dotconfig_sig_hash//\"/} + dotconfig_sig_key=${dotconfig_sig_key//\"/} + + sign_binary_path="${KV_OUT_DIR}/scripts/sign-file" + sig_key_path="${KERNEL_MODULE_SIG_KEY:-${KV_OUT_DIR}/${dotconfig_sig_key}}" + sig_x509_path="${sig_key_path/.pem/.x509}" + + module=${1##*/} + + # some checks, because sign-file is dumb and produces cryptic errors + [[ -w "${1}" ]] || die "${1} not found or not writable" + grep -qFL '~Module signature appended~' "${1}" && die "${module} already signed" + [[ -x "${sign_binary_path}" ]] || die "${sign_binary_path} not found or not executable" + [[ -r "${sig_key_path}" ]] || die "Private key ${sig_key_path} not found or not readable" + [[ -r "${sig_x509_path}" ]] || die "Public key ${sig_x509_path} not found or not readable" + + einfo "Signing ${module} using ${sig_key_path}:${dotconfig_sig_hash}" + "${sign_binary_path}" \ + "${dotconfig_sig_hash}" "${sig_key_path}" "${sig_x509_path}" \ + "${1}" || die "Signing ${module} failed" +} + +# @FUNCTION: _sign_all_modules +# @INTERNAL +# @DESCRIPTION: +# Signs all unsigned modules it finds in installation image +# Called by linux-mod_pkg_preinst +_sign_all_modules() { + debug-print-function ${FUNCNAME} "${@}" + + [[ -z "${KV_OBJ}" ]] && set_kvobj + require_configured_kernel + check_kernel_built + + local module + while read -rd '' module; do + _sign_module "${module}" + done < <(find "${ED}/lib/modules/${KV_FULL}" -name "*.${KV_OBJ}" -print0) +} + # internal function # # FUNCTION: @@ -583,12 +678,16 @@ linux-mod_pkg_setup() { # External modules use kernel symbols (bug #591832) CONFIG_CHECK+=" !TRIM_UNUSED_KSYMS" + # if signature is requested, check if kernel actually supports it + use module-sign && CONFIG_CHECK+=" MODULE_SIG" + linux-info_pkg_setup; require_configured_kernel check_kernel_built; strip_modulenames; [[ -n ${MODULE_NAMES} ]] && check_modules_supported set_kvobj; + _check_sig_force # Commented out with permission from johnm until a fixed version for arches # who intentionally use different kernel and userland compilers can be # introduced - Jason Wever , 23 Oct 2005 @@ -716,8 +815,8 @@ linux-mod_src_install() { einfo "Installing ${modulename} module" cd "${objdir}" || die "${objdir} does not exist" - insinto /lib/modules/${KV_FULL}/${libdir} - doins ${modulename}.${KV_OBJ} || die "doins ${modulename}.${KV_OBJ} failed" + insinto /lib/modules/"${KV_FULL}/${libdir}" + doins "${modulename}.${KV_OBJ}" || die "doins ${modulename}.${KV_OBJ} failed" cd "${OLDPWD}" generate_modulesd "${objdir}/${modulename}" @@ -733,6 +832,8 @@ linux-mod_pkg_preinst() { [ -d "${D%/}/lib/modules" ] && UPDATE_DEPMOD=true || UPDATE_DEPMOD=false [ -d "${D%/}/lib/modules" ] && UPDATE_MODULEDB=true || UPDATE_MODULEDB=false + _check_sig_force + use module-sign && _sign_all_modules } # @FUNCTION: linux-mod_pkg_postinst diff --git a/profiles/use.desc b/profiles/use.desc index b03b5b9dade..d1da37c45fc 100644 --- a/profiles/use.desc +++ b/profiles/use.desc @@ -207,6 +207,7 @@ mms - Support for Microsoft Media Server (MMS) streams mng - Add support for libmng (MNG images) modplug - Add libmodplug support for playing SoundTracker-style music files modules - Build the kernel modules +module-sign - Sign the kernel modules mono - Build Mono bindings to support dotnet type stuff motif - Add support for the Motif toolkit mozilla - Add support for the Mozilla web-browser -- 2.19.0