Gentoo Archives: gentoo-dev

From: Georgy Yakovlev <gyakovlev@g.o>
To: gentoo-dev@l.g.o
Cc: Georgy Yakovlev <gyakovlev@g.o>
Subject: [gentoo-dev] [PATCH] eclass/linux-mod.eclass: add module signing support
Date: Fri, 21 Sep 2018 05:13:15
Message-Id: 20180921051304.115704-1-gyakovlev@gentoo.org
1 This commit adds some eclass variables and private functions
2 and a new global useflag.
3
4 Example config, part of make.conf
5 USE="... module-sign ..."
6 KERNEL_MODULE_SIG_KEY="/secure/location/kernel.pem"
7
8 And possible kernel options:
9
10 CONFIG_MODULE_SIG=y
11 CONFIG_MODULE_SIG_FORCE=y
12 CONFIG_MODULE_SIG_ALL=y
13 CONFIG_MODULE_SIG_SHA512=y
14 CONFIG_MODULE_SIG_HASH="sha512"
15
16 NOTE to libressl users: libressl does not support anything
17 except CONFIG_MODULE_SIG_SHA1=y CONFIG_MODULE_SIG_HASH="sha1"
18
19 Even if user does not follow key creation procedure and
20 just enables module encryption while configuring kernel eclass "just works".
21
22 All the signing happens in pkg_preinst.
23 This means that binpkg users are expected to
24 have keys and sign modules on target system, not on builder.
25
26 I've been using this since March and have not encountered
27 a single problem with various out-of-tree kernel modules
28 Tested so far:
29 virtualbox-modules
30 nvidia-drivers
31 zfs & co
32 wireguard
33 and many more
34
35 If an ebuild uses Kbuild and/or runs linux-mod_pkg_preinst(), signing should work.
36
37 All the signing happens as root, this means user can have the
38 keys stored with secure permissions and mount as required.
39
40 If user configured kernel to require signed modules the eclass
41 will detect it and refuse to emerge if useflag is not enabled.
42
43 I'll appreciate your testing and feedbak.
44
45 NOTE to amdgpu users: if you use CONFIG_HSA_AMD, you'll want to have
46 CONFIG_HSA_AMD=y
47
48 having it as a module fails to sing for some reason, it's something in
49 kernel/kbuild and not related to this eclass change.
50
51 Closes: https://bugs.gentoo.org/447352
52 Signed-off-by: Georgy Yakovlev <gyakovlev@g.o>
53 ---
54 eclass/linux-mod.eclass | 109 ++++++++++++++++++++++++++++++++++++++--
55 profiles/use.desc | 1 +
56 2 files changed, 106 insertions(+), 4 deletions(-)
57
58 diff --git a/eclass/linux-mod.eclass b/eclass/linux-mod.eclass
59 index e5b5ec782f0..540b55286f8 100644
60 --- a/eclass/linux-mod.eclass
61 +++ b/eclass/linux-mod.eclass
62 @@ -132,6 +132,20 @@
63 # @DESCRIPTION:
64 # It's a read-only variable. It contains the extension of the kernel modules.
65
66 +# @ECLASS-VARIABLE: KERNEL_MODULE_SIG_KEY
67 +# @USER_VARIABLE
68 +# @DEFAULT_UNSET
69 +# @DESCRIPTION:
70 +# A string, containing absolute path to the private key file.
71 +# eclass will use value of CONFIG_MODULE_SIG_KEY extracted from .config
72 +# if KERNEL_MODULE_SIG_KEY is not set by user.
73 +#
74 +# Example:
75 +# @CODE
76 +# KERNEL_MODULE_SIG_KEY="/secure/location/kernel.pem"
77 +# @CODE
78 +# Assumes that "/secure/location/kernel.x509" public key file exists.
79 +
80 inherit eutils linux-info multilib
81 EXPORT_FUNCTIONS pkg_setup pkg_preinst pkg_postinst src_install src_compile pkg_postrm
82
83 @@ -144,13 +158,16 @@ esac
84 0) die "EAPI=${EAPI} is not supported with MODULES_OPTIONAL_USE_IUSE_DEFAULT due to lack of IUSE defaults" ;;
85 esac
86
87 -IUSE="kernel_linux ${MODULES_OPTIONAL_USE:+${_modules_optional_use_iuse_default}}${MODULES_OPTIONAL_USE}"
88 +IUSE="module-sign kernel_linux ${MODULES_OPTIONAL_USE:+${_modules_optional_use_iuse_default}}${MODULES_OPTIONAL_USE}"
89 SLOT="0"
90 RDEPEND="${MODULES_OPTIONAL_USE}${MODULES_OPTIONAL_USE:+? (} kernel_linux? ( virtual/modutils ) ${MODULES_OPTIONAL_USE:+)}"
91 DEPEND="${RDEPEND}
92 ${MODULES_OPTIONAL_USE}${MODULES_OPTIONAL_USE:+? (}
93 sys-apps/sed
94 - kernel_linux? ( virtual/linux-sources virtual/libelf )
95 + kernel_linux? (
96 + virtual/linux-sources virtual/libelf
97 + module-sign? ( || ( dev-libs/openssl dev-libs/libressl ) )
98 + )
99 ${MODULES_OPTIONAL_USE:+)}"
100
101 # eclass utilities
102 @@ -352,6 +369,84 @@ get-KERNEL_CC() {
103 echo "${kernel_cc}"
104 }
105
106 +# @FUNCTION: _check_sig_force
107 +# @INTERNAL
108 +# @DESCRIPTION:
109 +# Check if kernel requires module signing and die
110 +# if modules are not going to be signed.
111 +_check_sig_force() {
112 + debug-print-function ${FUNCNAME} "${@}"
113 +
114 + if linux_chkconfig_present MODULE_SIG_FORCE; then
115 + if use !module-sign; then
116 + eerror "kernel .config has MODULE_SIG_FORCE=y option set"
117 + eerror "This means that kernel requires all modules"
118 + eerror "to be signed and verified before loading"
119 + eerror "please enable USE=\"module-sign\" or reconfigure your kernel"
120 + eerror "otherwise loading the module will fail"
121 + die "signature required"
122 + fi
123 + fi
124 +}
125 +
126 +# @FUNCTION: _sign_module
127 +# @INTERNAL
128 +# @USAGE: <filename>
129 +# @DESCRIPTION:
130 +# Sign a kernel module
131 +_sign_module() {
132 + debug-print-function ${FUNCNAME} "${@}"
133 +
134 + local dotconfig_sig_hash dotconfig_sig_key
135 + local sign_binary_path sig_key_path sig_x509_path
136 + local module
137 +
138 + # extract values from kernel .config
139 + # extracted key path is not full, e.g. "certs/signing_key.pem"
140 + dotconfig_sig_hash="$(linux_chkconfig_string MODULE_SIG_HASH)"
141 + dotconfig_sig_key="$(linux_chkconfig_string MODULE_SIG_KEY)"
142 +
143 + # sign-file binary chokes on double quotes
144 + dotconfig_sig_hash=${dotconfig_sig_hash//\"/}
145 + dotconfig_sig_key=${dotconfig_sig_key//\"/}
146 +
147 + sign_binary_path="${KV_OUT_DIR}/scripts/sign-file"
148 + sig_key_path="${KERNEL_MODULE_SIG_KEY:-${KV_OUT_DIR}/${dotconfig_sig_key}}"
149 + sig_x509_path="${sig_key_path/.pem/.x509}"
150 +
151 + module=${1##*/}
152 +
153 + # some checks, because sign-file is dumb and produces cryptic errors
154 + [[ -w "${1}" ]] || die "${1} not found or not writable"
155 + grep -qFL '~Module signature appended~' "${1}" && die "${module} already signed"
156 + [[ -x "${sign_binary_path}" ]] || die "${sign_binary_path} not found or not executable"
157 + [[ -r "${sig_key_path}" ]] || die "Private key ${sig_key_path} not found or not readable"
158 + [[ -r "${sig_x509_path}" ]] || die "Public key ${sig_x509_path} not found or not readable"
159 +
160 + einfo "Signing ${module} using ${sig_key_path}:${dotconfig_sig_hash}"
161 + "${sign_binary_path}" \
162 + "${dotconfig_sig_hash}" "${sig_key_path}" "${sig_x509_path}" \
163 + "${1}" || die "Signing ${module} failed"
164 +}
165 +
166 +# @FUNCTION: _sign_all_modules
167 +# @INTERNAL
168 +# @DESCRIPTION:
169 +# Signs all unsigned modules it finds in installation image
170 +# Called by linux-mod_pkg_preinst
171 +_sign_all_modules() {
172 + debug-print-function ${FUNCNAME} "${@}"
173 +
174 + [[ -z "${KV_OBJ}" ]] && set_kvobj
175 + require_configured_kernel
176 + check_kernel_built
177 +
178 + local module
179 + while read -rd '' module; do
180 + _sign_module "${module}"
181 + done < <(find "${ED}/lib/modules/${KV_FULL}" -name "*.${KV_OBJ}" -print0)
182 +}
183 +
184 # internal function
185 #
186 # FUNCTION:
187 @@ -583,12 +678,16 @@ linux-mod_pkg_setup() {
188 # External modules use kernel symbols (bug #591832)
189 CONFIG_CHECK+=" !TRIM_UNUSED_KSYMS"
190
191 + # if signature is requested, check if kernel actually supports it
192 + use module-sign && CONFIG_CHECK+=" MODULE_SIG"
193 +
194 linux-info_pkg_setup;
195 require_configured_kernel
196 check_kernel_built;
197 strip_modulenames;
198 [[ -n ${MODULE_NAMES} ]] && check_modules_supported
199 set_kvobj;
200 + _check_sig_force
201 # Commented out with permission from johnm until a fixed version for arches
202 # who intentionally use different kernel and userland compilers can be
203 # introduced - Jason Wever <weeve@g.o>, 23 Oct 2005
204 @@ -716,8 +815,8 @@ linux-mod_src_install() {
205
206 einfo "Installing ${modulename} module"
207 cd "${objdir}" || die "${objdir} does not exist"
208 - insinto /lib/modules/${KV_FULL}/${libdir}
209 - doins ${modulename}.${KV_OBJ} || die "doins ${modulename}.${KV_OBJ} failed"
210 + insinto /lib/modules/"${KV_FULL}/${libdir}"
211 + doins "${modulename}.${KV_OBJ}" || die "doins ${modulename}.${KV_OBJ} failed"
212 cd "${OLDPWD}"
213
214 generate_modulesd "${objdir}/${modulename}"
215 @@ -733,6 +832,8 @@ linux-mod_pkg_preinst() {
216
217 [ -d "${D}lib/modules" ] && UPDATE_DEPMOD=true || UPDATE_DEPMOD=false
218 [ -d "${D}lib/modules" ] && UPDATE_MODULEDB=true || UPDATE_MODULEDB=false
219 + _check_sig_force
220 + use module-sign && _sign_all_modules
221 }
222
223 # @FUNCTION: linux-mod_pkg_postinst
224 diff --git a/profiles/use.desc b/profiles/use.desc
225 index b03b5b9dade..d1da37c45fc 100644
226 --- a/profiles/use.desc
227 +++ b/profiles/use.desc
228 @@ -207,6 +207,7 @@ mms - Support for Microsoft Media Server (MMS) streams
229 mng - Add support for libmng (MNG images)
230 modplug - Add libmodplug support for playing SoundTracker-style music files
231 modules - Build the kernel modules
232 +module-sign - Sign the kernel modules
233 mono - Build Mono bindings to support dotnet type stuff
234 motif - Add support for the Motif toolkit
235 mozilla - Add support for the Mozilla web-browser
236 --
237 2.19.0

Replies