Gentoo Archives: gentoo-dev

From: Georgy Yakovlev <ya@×××××××.net>
To: gentoo-dev@l.g.o
Subject: Re: [gentoo-dev] Re: [PATCH] linux-mod.eclass: support module signing
Date: Fri, 20 Apr 2018 08:02:12
Message-Id: 1524211318.12380.2.camel@sysdump.net
In Reply to: Re: [gentoo-dev] Re: [PATCH] linux-mod.eclass: support module signing by "Michał Górny"
1 Version 3 with fixes as requested by mgorny, thanks for review!
2
3 Overall I think eclass needs some love, as and uses semicolons, single
4 square brackets, quoting and eclass descriptions are a bit
5 inconsistent, but that's out of scope of this patch right now.
6 I think all the new code I've added follows up-to-date standards now
7 and no longer uses old syntax.
8
9
10
11 diff --git a/eclass/linux-mod.eclass b/eclass/linux-mod.eclass
12 index bf580cf4cfa9..5df15561b9e6 100644
13 --- a/eclass/linux-mod.eclass
14 +++ b/eclass/linux-mod.eclass
15 @@ -132,6 +132,16 @@
16 # @DESCRIPTION:
17 # It's a read-only variable. It contains the extension of the kernel modules.
18
19 +# @ECLASS-VARIABLE: KERNEL_MODULE_SIG_KEY
20 +# @USER_VARIABLE
21 +# @DEFAULT_UNSET
22 +# @DESCRIPTION:
23 +# A string, containing absolute path to the private key file.
24 +# Defaults to value of CONFIG_MODULE_SIG_KEY extracted from .config
25 +# Example:
26 +# KERNEL_MODULE_SIG_KEY="/secure/location/keys/kernel.pem"
27 +# Assumes that "/secure/location/keys/kernel.x509" is a matching pubkey.
28 +
29 inherit eutils linux-info multilib
30 EXPORT_FUNCTIONS pkg_setup pkg_preinst pkg_postinst src_install src_compile pkg_postrm
31
32 @@ -144,12 +154,13 @@ esac
33 0) die "EAPI=${EAPI} is not supported with MODULES_OPTIONAL_USE_IUSE_DEFAULT due to lack of IUSE defaults" ;;
34 esac
35
36 -IUSE="kernel_linux ${MODULES_OPTIONAL_USE:+${_modules_optional_use_iuse_default}}${MODULES_OPTIONAL_USE}"
37 +IUSE="module-sign kernel_linux ${MODULES_OPTIONAL_USE:+${_modules_optional_use_iuse_default}}${MODULES_OPTIONAL_USE}"
38 SLOT="0"
39 RDEPEND="${MODULES_OPTIONAL_USE}${MODULES_OPTIONAL_USE:+? (} kernel_linux? ( virtual/modutils ) ${MODULES_OPTIONAL_USE:+)}"
40 DEPEND="${RDEPEND}
41 ${MODULES_OPTIONAL_USE}${MODULES_OPTIONAL_USE:+? (}
42 sys-apps/sed
43 + module-sign? ( || ( dev-libs/openssl dev-libs/libressl ) )
44 kernel_linux? ( virtual/linux-sources )
45 ${MODULES_OPTIONAL_USE:+)}"
46
47 @@ -352,6 +363,84 @@ get-KERNEL_CC() {
48 echo "${kernel_cc}"
49 }
50
51 +# @FUNCTION: _check_sig_force
52 +# @INTERNAL
53 +# @DESCRIPTION:
54 +# Check if kernel requires module signing and die
55 +# if module is not going to be signed.
56 +_check_sig_force() {
57 + debug-print-function ${FUNCNAME} "${@}"
58 +
59 + if linux_chkconfig_present MODULE_SIG_FORCE; then
60 + if use !module-sign; then
61 + eerror "kernel .config has MODULE_SIG_FORCE=y option set"
62 + eerror "This means that kernel requires all modules"
63 + eerror "to be signed and verified before loading"
64 + eerror "please enable USE=\"module-sign\" or reconfigure your kernel"
65 + eerror "otherwise loading the module will fail"
66 + die "signature required"
67 + fi
68 + fi
69 +}
70 +
71 +# @FUNCTION: _sign_module
72 +# @INTERNAL
73 +# @USAGE: <filename>
74 +# @DESCRIPTION:
75 +# Sign a kernel module
76 +_sign_module() {
77 + debug-print-function ${FUNCNAME} "${@}"
78 +
79 + local dotconfig_sig_hash dotconfig_sig_key
80 + local sign_binary_path sig_key_path sig_x509_path
81 + local module
82 +
83 + # extract values from kernel .config
84 + # extracted key path is not full, e.g. "certs/signing_key.pem"
85 + dotconfig_sig_hash="$(linux_chkconfig_string MODULE_SIG_HASH)"
86 + dotconfig_sig_key="$(linux_chkconfig_string MODULE_SIG_KEY)"
87 +
88 + # strip out double quotes, sign-file binary chokes on them
89 + dotconfig_sig_hash=${dotconfig_sig_hash//\"/}
90 + dotconfig_sig_key=${dotconfig_sig_key//\"/}
91 +
92 + sign_binary_path="${KV_OUT_DIR}/scripts/sign-file"
93 + sig_key_path="${KERNEL_MODULE_SIG_KEY:-${KV_OUT_DIR}/${dotconfig_sig_key}}"
94 + sig_x509_path="${sig_key_path/.pem/.x509}"
95 +
96 + module=${1##*/}
97 +
98 + # some checks, because sign-file is dumb and produces cryptic errors
99 + [[ -w "${1}" ]] || die "${1} not found or not writable"
100 + grep -qFL '~Module signature appended~' "${1}" && die "${module} already signed"
101 + [[ -x "${sign_binary_path}" ]] || die "${sign_binary_path} not found or not executable"
102 + [[ -r "${sig_key_path}" ]] || die "Private key ${sig_key_path} not found or not readable"
103 + [[ -r "${sig_x509_path}" ]] || die "Public key ${sig_x509_path} not found or not readable"
104 +
105 + einfo "Signing ${module} using ${sig_key_path}:${dotconfig_sig_hash}"
106 + "${sign_binary_path}" \
107 + "${dotconfig_sig_hash}" "${sig_key_path}" "${sig_x509_path}" \
108 + "${1}" || die "Signing ${module} failed"
109 +}
110 +
111 +# @FUNCTION: _sign_all_modules
112 +# @INTERNAL
113 +# @DESCRIPTION:
114 +# Signs all unsigned modules
115 +# Must be called in pkg_preinst.
116 +_sign_all_modules() {
117 + debug-print-function ${FUNCNAME} "${@}"
118 +
119 + [[ -z "${KV_OBJ}" ]] && set_kvobj
120 + require_configured_kernel
121 + check_kernel_built
122 +
123 + local module
124 + while read -rd '' module; do
125 + _sign_module "${module}"
126 + done < <(find "${ED}/lib/modules/${KV_FULL}" -name "*.${KV_OBJ}" -print0)
127 +}
128 +
129 # internal function
130 #
131 # FUNCTION:
132 @@ -583,12 +672,16 @@ linux-mod_pkg_setup() {
133 # External modules use kernel symbols (bug #591832)
134 CONFIG_CHECK+=" !TRIM_UNUSED_KSYMS"
135
136 + # if signature is requested, check if kernel actually supports it
137 + use module-sign && CONFIG_CHECK+=" MODULE_SIG"
138 +
139 linux-info_pkg_setup;
140 require_configured_kernel
141 check_kernel_built;
142 strip_modulenames;
143 [[ -n ${MODULE_NAMES} ]] && check_modules_supported
144 set_kvobj;
145 + _check_sig_force
146 # Commented out with permission from johnm until a fixed version for arches
147 # who intentionally use different kernel and userland compilers can be
148 # introduced - Jason Wever <weeve@g.o>, 23 Oct 2005
149 @@ -716,8 +809,8 @@ linux-mod_src_install() {
150
151 einfo "Installing ${modulename} module"
152 cd "${objdir}" || die "${objdir} does not exist"
153 - insinto /lib/modules/${KV_FULL}/${libdir}
154 - doins ${modulename}.${KV_OBJ} || die "doins ${modulename}.${KV_OBJ} failed"
155 + insinto /lib/modules/"${KV_FULL}/${libdir}"
156 + doins "${modulename}.${KV_OBJ}" || die "doins ${modulename}.${KV_OBJ} failed"
157 cd "${OLDPWD}"
158
159 generate_modulesd "${objdir}/${modulename}"
160 @@ -733,6 +826,8 @@ linux-mod_pkg_preinst() {
161
162 [ -d "${D}lib/modules" ] && UPDATE_DEPMOD=true || UPDATE_DEPMOD=false
163 [ -d "${D}lib/modules" ] && UPDATE_MODULEDB=true || UPDATE_MODULEDB=false
164 + _check_sig_force
165 + use module-sign && _sign_all_modules
166 }
167
168 # @FUNCTION: linux-mod_pkg_postinst