public inbox for gentoo-dev@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-dev] [PATCH] eclass/linux-mod.eclass: add module signing support
@ 2018-09-21  5:13 Georgy Yakovlev
  2018-09-21 12:58 ` Alexander Tsoy
  2018-10-01  8:48 ` [gentoo-dev] [PATCH 1/2] " Georgy Yakovlev
  0 siblings, 2 replies; 7+ messages in thread
From: Georgy Yakovlev @ 2018-09-21  5:13 UTC (permalink / raw
  To: gentoo-dev; +Cc: Georgy Yakovlev

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.

Closes: https://bugs.gentoo.org/447352
Signed-off-by: Georgy Yakovlev <gyakovlev@gentoo.org>
---
 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 e5b5ec782f0..540b55286f8 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: <filename>
+# @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 <weeve@gentoo.org>, 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



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [gentoo-dev] [PATCH] eclass/linux-mod.eclass: add module signing support
  2018-09-21  5:13 [gentoo-dev] [PATCH] eclass/linux-mod.eclass: add module signing support Georgy Yakovlev
@ 2018-09-21 12:58 ` Alexander Tsoy
  2018-09-21 22:59   ` Chí-Thanh Christopher Nguyễn
  2018-09-22  2:22   ` Georgy Yakovlev
  2018-10-01  8:48 ` [gentoo-dev] [PATCH 1/2] " Georgy Yakovlev
  1 sibling, 2 replies; 7+ messages in thread
From: Alexander Tsoy @ 2018-09-21 12:58 UTC (permalink / raw
  To: gentoo-dev

В Чт, 20/09/2018 в 22:13 -0700, Georgy Yakovlev пишет:
> ----------------->%-------------------
> @@ -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}}${MODUL
> ES_OPTIONAL_USE}"
> +IUSE="module-sign kernel_linux
> ${MODULES_OPTIONAL_USE:+${_modules_optional_use_iuse_default}}${MODUL
> ES_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 ) )
> +	)

It should depend on the proper openssl slot: dev-libs/openssl:0

>  	${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: <filename>
> +# @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"

Yet another way to screw up modules building. It relies on some binary
in the kernel build dir that may break after openssl update (e.g.
soname change).


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [gentoo-dev] [PATCH] eclass/linux-mod.eclass: add module signing support
  2018-09-21 12:58 ` Alexander Tsoy
@ 2018-09-21 22:59   ` Chí-Thanh Christopher Nguyễn
  2018-09-22  2:30     ` Georgy Yakovlev
  2018-09-22  2:22   ` Georgy Yakovlev
  1 sibling, 1 reply; 7+ messages in thread
From: Chí-Thanh Christopher Nguyễn @ 2018-09-21 22:59 UTC (permalink / raw
  To: gentoo-dev

Alexander Tsoy schrieb:
>> +	sign_binary_path="${KV_OUT_DIR}/scripts/sign-file"
> 
> Yet another way to screw up modules building. It relies on some binary
> in the kernel build dir that may break after openssl update (e.g.
> soname change).

Maybe the sign-file application could be packaged, for example as part of 
sys-apps/linux-misc-apps.


Best regards,
Chí-Thanh Christopher Nguyễn


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [gentoo-dev] [PATCH] eclass/linux-mod.eclass: add module signing support
  2018-09-21 12:58 ` Alexander Tsoy
  2018-09-21 22:59   ` Chí-Thanh Christopher Nguyễn
@ 2018-09-22  2:22   ` Georgy Yakovlev
  1 sibling, 0 replies; 7+ messages in thread
From: Georgy Yakovlev @ 2018-09-22  2:22 UTC (permalink / raw
  To: gentoo-dev

[-- Attachment #1: Type: text/plain, Size: 4689 bytes --]

On Friday, September 21, 2018 5:58:00 AM PDT Alexander Tsoy wrote:
> В Чт, 20/09/2018 в 22:13 -0700, Georgy Yakovlev пишет:
> > ----------------->%-------------------
> > @@ -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}}${MODUL
> > ES_OPTIONAL_USE}"
> > +IUSE="module-sign kernel_linux
> > ${MODULES_OPTIONAL_USE:+${_modules_optional_use_iuse_default}}${MODUL
> > ES_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 ) )
> > +	)
> 
> It should depend on the proper openssl slot: dev-libs/openssl:0
Thanks for suggestion.
Not sure, all it does is it makes sure -lcrypto works while building module. 
libcrypto is not required to load the module.
Adding slot build dep to a package with a module does not make a lot of sense 
to me, but probably does not hurt either.
> 
> >  	${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: <filename>
> > +# @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"
> 
> Yet another way to screw up modules building. It relies on some binary
> in the kernel build dir that may break after openssl update (e.g.
> soname change).

openssl soname rarely changes and a user likely to build kernel first (thus 
re-building sign-file binary) and update modules later (probably with @module-
rebuild).
Last ABI change was in 2016 (still masked in gentoo), and in 2010 before that.
It's unlikely to encounter an abi changing openssl upgrade and a random module 
rebuild while updating unless a user updates very infrequently.

simple workaround:

cd /usr/src/linux && rm scripts/sign-file && make scripts

I can probably add this to die message and/or create a news item/wiki article.

The whole eclass relies on kernel build dir to be available with exact same 
configuration to build modules, not just the signing part.

As an example, using kernel gcc plugins situation is much worse, but still not 
a big deal, just rebuild a kernel after upgrading gcc to be able to build out-
of tree modules.
sign-file binary is rather simple and is not that picky and rarely breaks. At 
least what's what I observe while testing this patch.
I build kernels weekly (and rebuilding modules) and have not seen a single 
problem related to signing.

I'll post rebased/updated patch with latest changes happened to eclass to 
support EAPI7.

-- 
Regads,
Georgy Yakovlev
Gentoo Linux Developer

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [gentoo-dev] [PATCH] eclass/linux-mod.eclass: add module signing support
  2018-09-21 22:59   ` Chí-Thanh Christopher Nguyễn
@ 2018-09-22  2:30     ` Georgy Yakovlev
  0 siblings, 0 replies; 7+ messages in thread
From: Georgy Yakovlev @ 2018-09-22  2:30 UTC (permalink / raw
  To: gentoo-dev

[-- Attachment #1: Type: text/plain, Size: 1001 bytes --]

On Friday, September 21, 2018 3:59:26 PM PDT Chí-Thanh Christopher Nguyễn 
wrote:
> Alexander Tsoy schrieb:
> >> +	sign_binary_path="${KV_OUT_DIR}/scripts/sign-file"
> > 
> > Yet another way to screw up modules building. It relies on some binary
> > in the kernel build dir that may break after openssl update (e.g.
> > soname change).
> 
> Maybe the sign-file application could be packaged, for example as part of
> sys-apps/linux-misc-apps.
> 
> 
> Best regards,
> Chí-Thanh Christopher Nguyễn

linux-mod.eclass already relies on full kernel build dir to be available to 
build modules.

and depending on another ebuild means that it has to be keyworded on different 
arches to actually support signing on those arches.

simple kbuild approach is better IMO, if a system can build a kernel and 
modules means it can sign it.
Maintaining separate package, especially with kernel update pace will be a 
nightmare.

-- 
Regads,
Georgy Yakovlev
Gentoo Linux Developer

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [gentoo-dev] [PATCH 1/2] eclass/linux-mod.eclass: add module signing support
  2018-09-21  5:13 [gentoo-dev] [PATCH] eclass/linux-mod.eclass: add module signing support Georgy Yakovlev
  2018-09-21 12:58 ` Alexander Tsoy
@ 2018-10-01  8:48 ` Georgy Yakovlev
  2018-10-01  8:48   ` [gentoo-dev] [PATCH 2/2] profiles: mask module signing for testing Georgy Yakovlev
  1 sibling, 1 reply; 7+ messages in thread
From: Georgy Yakovlev @ 2018-10-01  8:48 UTC (permalink / raw
  To: gentoo-dev; +Cc: Georgy Yakovlev

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 <gyakovlev@gentoo.org>
---
 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: <filename>
+# @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 <weeve@gentoo.org>, 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



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [gentoo-dev] [PATCH 2/2] profiles: mask module signing for testing
  2018-10-01  8:48 ` [gentoo-dev] [PATCH 1/2] " Georgy Yakovlev
@ 2018-10-01  8:48   ` Georgy Yakovlev
  0 siblings, 0 replies; 7+ messages in thread
From: Georgy Yakovlev @ 2018-10-01  8:48 UTC (permalink / raw
  To: gentoo-dev; +Cc: Georgy Yakovlev

Signed-off-by: Georgy Yakovlev <gyakovlev@gentoo.org>
---
 profiles/base/use.mask | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/profiles/base/use.mask b/profiles/base/use.mask
index 6082a468925..374cdbe85fe 100644
--- a/profiles/base/use.mask
+++ b/profiles/base/use.mask
@@ -4,6 +4,10 @@
 # This file is only for generic masks. For arch-specific masks (i.e.
 # mask everywhere, unmask on arch/*) use arch/base.
 
+# Georgy Yakovlev <gyakovlev@gentoo.org> (01 Oct 2018)
+# mask module signing for testing
+module-sign
+
 # Aaron W. Swenson <titanofold@gentoo.org> (09 Sep 2018)
 # Mask PostgreSQL 12 while in (pre-)alpha.
 postgres_targets_postgres12
-- 
2.19.0



^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2018-10-01  8:49 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-09-21  5:13 [gentoo-dev] [PATCH] eclass/linux-mod.eclass: add module signing support Georgy Yakovlev
2018-09-21 12:58 ` Alexander Tsoy
2018-09-21 22:59   ` Chí-Thanh Christopher Nguyễn
2018-09-22  2:30     ` Georgy Yakovlev
2018-09-22  2:22   ` Georgy Yakovlev
2018-10-01  8:48 ` [gentoo-dev] [PATCH 1/2] " Georgy Yakovlev
2018-10-01  8:48   ` [gentoo-dev] [PATCH 2/2] profiles: mask module signing for testing Georgy Yakovlev

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox