1 |
On Sat, 2018-04-14 at 14:25 -0700, Georgy Yakovlev wrote: |
2 |
|
3 |
Second version, with safety checks and simplified logic. |
4 |
Fixed most issues of the first patch. |
5 |
|
6 |
Now only use single optional make.conf variable with the path to the |
7 |
key. |
8 |
Rest of parameters are magically extracted from .config or derived from |
9 |
the key itself. So generally it just works. |
10 |
|
11 |
got rid of STRIP_MASK, all signing happens in pkg_preinst, that way the |
12 |
checksum of installed file is calculated with signature appended. |
13 |
now works for packages that do not use linux-mod_src_install (zfs & co) |
14 |
|
15 |
|
16 |
Thanks to NP-Hardass for initial review and suggestions. |
17 |
|
18 |
|
19 |
> Hi, |
20 |
> |
21 |
> There is an old bug[1] to support |
22 |
> linux kernel module signing at install. |
23 |
> |
24 |
> And here is my first attempt to modify an eclass. |
25 |
> Need proper input on it and a kick in the right direction. |
26 |
> |
27 |
> Add 3 variables, settable by users if they keep keys somewhere safe. |
28 |
> Otherwise it just works with the auto-generated keys |
29 |
> if CONFIG_MODULE_SIG=y and vars are unset. |
30 |
> |
31 |
> eclass will die if kernel requires a signed module, |
32 |
> but signing is not requested. |
33 |
> |
34 |
> |
35 |
> Known problems: |
36 |
> |
37 |
> Packages that do not use linux-mod_src_install() will not sign |
38 |
> the modules, |
39 |
> But those packages will still inherit module-sign useflag. |
40 |
> It's misleading and I'm not sure how to fix that. |
41 |
> Examples : sys-kernel/spl, sys-fs/zfs-kmod |
42 |
> |
43 |
> May need additional handling of KBUILD_SIGN_PIN variable[2], |
44 |
> which can be set to hold the passphrase to the key. But it may end up |
45 |
> in vdb environment files, not sure how to handle that or if it worth |
46 |
> it |
47 |
> |
48 |
> not eapi-7 ready because of STRIP_MASK usage. |
49 |
> will need to cover this case as well, probably later. |
50 |
> |
51 |
> older (<4.3.3) kernels use perl to sign modules, not sure if it's |
52 |
> worth |
53 |
> supporting old kernels, there is no gentoo-sources in the tree old |
54 |
> enough, except masked 4.1 |
55 |
> there are old vanilla-sources that will be affected by this. |
56 |
> |
57 |
> |
58 |
> [1] https://bugs.gentoo.org/447352 |
59 |
> [2] https://www.kernel.org/doc/html/v4.16/admin-guide/module-signing.html |
60 |
|
61 |
diff --git a/eclass/linux-mod.eclass b/eclass/linux-mod.eclass |
62 |
index bf580cf4cfa9..8197654081cc 100644 |
63 |
--- a/eclass/linux-mod.eclass |
64 |
+++ b/eclass/linux-mod.eclass |
65 |
@@ -132,6 +132,16 @@ |
66 |
# @DESCRIPTION: |
67 |
# It's a read-only variable. It contains the extension of the kernel modules. |
68 |
|
69 |
+# @ECLASS-VARIABLE: KERNEL_MODULE_SIG_KEY |
70 |
+# @DEFAULT_UNSET |
71 |
+# @DESCRIPTION: |
72 |
+# A string, containing absolute path to the private key file. |
73 |
+# Defaults to value of CONFIG_MODULE_SIG_KEY extracted from .config |
74 |
+# Can be set by user in make.conf |
75 |
+# Example: |
76 |
+# KERNEL_MODULE_SIG_KEY="/secure/location/keys/kernel.pem" |
77 |
+# Assumes that "/secure/location/keys/kernel.x509" is a matching pubkey. |
78 |
+ |
79 |
inherit eutils linux-info multilib |
80 |
EXPORT_FUNCTIONS pkg_setup pkg_preinst pkg_postinst src_install src_compile pkg_postrm |
81 |
|
82 |
@@ -144,12 +154,13 @@ esac |
83 |
0) die "EAPI=${EAPI} is not supported with MODULES_OPTIONAL_USE_IUSE_DEFAULT due to lack of IUSE defaults" ;; |
84 |
esac |
85 |
|
86 |
-IUSE="kernel_linux ${MODULES_OPTIONAL_USE:+${_modules_optional_use_iuse_default}}${MODULES_OPTIONAL_USE}" |
87 |
+IUSE="module-sign kernel_linux ${MODULES_OPTIONAL_USE:+${_modules_optional_use_iuse_default}}${MODULES_OPTIONAL_USE}" |
88 |
SLOT="0" |
89 |
RDEPEND="${MODULES_OPTIONAL_USE}${MODULES_OPTIONAL_USE:+? (} kernel_linux? ( virtual/modutils ) ${MODULES_OPTIONAL_USE:+)}" |
90 |
DEPEND="${RDEPEND} |
91 |
${MODULES_OPTIONAL_USE}${MODULES_OPTIONAL_USE:+? (} |
92 |
sys-apps/sed |
93 |
+ module-sign? ( || ( dev-libs/openssl dev-libs/libressl ) ) |
94 |
kernel_linux? ( virtual/linux-sources ) |
95 |
${MODULES_OPTIONAL_USE:+)}" |
96 |
|
97 |
@@ -352,6 +363,93 @@ get-KERNEL_CC() { |
98 |
echo "${kernel_cc}" |
99 |
} |
100 |
|
101 |
+# @FUNCTION: check_sig_force |
102 |
+# @INTERNAL |
103 |
+# @DESCRIPTION: |
104 |
+# Check if kernel requires module signing and die |
105 |
+# if module is not going to be signed. |
106 |
+check_sig_force() { |
107 |
+ debug-print-function ${FUNCNAME} $* |
108 |
+ |
109 |
+ if linux_chkconfig_present MODULE_SIG_FORCE; then |
110 |
+ if use !module-sign; then |
111 |
+ ewarn "kernel .config has MODULE_SIG_FORCE=y option set" |
112 |
+ ewarn "This means that kernel requires all modules" |
113 |
+ ewarn "to be signed and verified before loading" |
114 |
+ ewarn "please enable USE=\"module-sign\" or reconfigure your kernel" |
115 |
+ ewarn "otherwise loading the module will fail" |
116 |
+ die "signature required" |
117 |
+ fi |
118 |
+ fi |
119 |
+} |
120 |
+ |
121 |
+# @FUNCTION: sign_module |
122 |
+# @INTERNAL |
123 |
+# @DESCRIPTION: |
124 |
+# Sign a kernel module |
125 |
+# @USAGE: <filename> |
126 |
+sign_module() { |
127 |
+ debug-print-function ${FUNCNAME} $* |
128 |
+ |
129 |
+ local dotconfig_sig_hash dotconfig_sig_key |
130 |
+ local sign_binary_path sig_key_path sig_x509_path |
131 |
+ local module |
132 |
+ |
133 |
+ # extract values from kernel .config |
134 |
+ # extracted key path is not full, e.g. "certs/signing_key.pem" |
135 |
+ dotconfig_sig_hash="$(linux_chkconfig_string MODULE_SIG_HASH)" |
136 |
+ dotconfig_sig_key="$(linux_chkconfig_string MODULE_SIG_KEY)" |
137 |
+ |
138 |
+ # strip out double quotes, sign-file binary chokes on them |
139 |
+ dotconfig_sig_hash=${dotconfig_sig_hash//\"/} |
140 |
+ dotconfig_sig_key=${dotconfig_sig_key//\"/} |
141 |
+ |
142 |
+ sign_binary_path="${KV_OUT_DIR}/scripts/sign-file" |
143 |
+ sig_key_path="${KERNEL_MODULE_SIG_KEY:-${KV_OUT_DIR}/${dotconfig_sig_key}}" |
144 |
+ sig_x509_path="${sig_key_path/.pem/.x509}" |
145 |
+ |
146 |
+ module=$(basename "${1%.${KV_OBJ}}") |
147 |
+ |
148 |
+ # some checks, because sign-file is dumb and produces cryptic errors |
149 |
+ [ -w "${1}" ] || die "${1} not found or not writable" |
150 |
+ grep -qFL '~Module signature appended~' "${1}" && die "${module} already signed" |
151 |
+ [ -x "${sign_binary_path}" ] || die "${sign_binary_path} not found or not executable" |
152 |
+ [ -e "${sig_key_path}" ] || die "Private key ${sig_key_path} not found or not readable" |
153 |
+ [ -e "${sig_x509_path}" ] || die "Public key ${sig_x509_path} not found or not readable" |
154 |
+ |
155 |
+ einfo "Signing ${module} using ${sig_key_path}:${dotconfig_sig_hash}" |
156 |
+ "${sign_binary_path}" \ |
157 |
+ "${dotconfig_sig_hash}" "${sig_key_path}" "${sig_x509_path}" \ |
158 |
+ "${1}" || die "Signing ${module} failed" |
159 |
+} |
160 |
+ |
161 |
+# @FUNCTION: sign_all_modules |
162 |
+# @INTERNAL |
163 |
+# @DESCRIPTION: |
164 |
+# Signs all unsigned modules |
165 |
+# Must be called in pkg_preinst. |
166 |
+sign_all_modules() { |
167 |
+ debug-print-function ${FUNCNAME} $* |
168 |
+ |
169 |
+ [ -z "${KV_OBJ}" ] && set_kvobj; |
170 |
+ require_configured_kernel; |
171 |
+ check_kernel_built; |
172 |
+ |
173 |
+ local module |
174 |
+ local modules |
175 |
+ |
176 |
+ pushd "${ED}" > /dev/null || die |
177 |
+ modules=$(find "lib/modules/${KV_FULL}" -name "*.${KV_OBJ}" 2>/dev/null) |
178 |
+ if [[ -n ${modules} ]]; then |
179 |
+ for module in ${modules}; do |
180 |
+ sign_module "${module}" |
181 |
+ done |
182 |
+ else |
183 |
+ ewarn 'QA: list of modules to sign is empty, pease report a bug' |
184 |
+ fi |
185 |
+ popd > /dev/null || die |
186 |
+} |
187 |
+ |
188 |
# internal function |
189 |
# |
190 |
# FUNCTION: |
191 |
@@ -583,12 +681,16 @@ linux-mod_pkg_setup() { |
192 |
# External modules use kernel symbols (bug #591832) |
193 |
CONFIG_CHECK+=" !TRIM_UNUSED_KSYMS" |
194 |
|
195 |
+ # if signature is requested, check if kernel actually supports it |
196 |
+ use module-sign && CONFIG_CHECK+=" MODULE_SIG" |
197 |
+ |
198 |
linux-info_pkg_setup; |
199 |
require_configured_kernel |
200 |
check_kernel_built; |
201 |
strip_modulenames; |
202 |
[[ -n ${MODULE_NAMES} ]] && check_modules_supported |
203 |
set_kvobj; |
204 |
+ check_sig_force; |
205 |
# Commented out with permission from johnm until a fixed version for arches |
206 |
# who intentionally use different kernel and userland compilers can be |
207 |
# introduced - Jason Wever <weeve@g.o>, 23 Oct 2005 |
208 |
@@ -716,8 +818,8 @@ linux-mod_src_install() { |
209 |
|
210 |
einfo "Installing ${modulename} module" |
211 |
cd "${objdir}" || die "${objdir} does not exist" |
212 |
- insinto /lib/modules/${KV_FULL}/${libdir} |
213 |
- doins ${modulename}.${KV_OBJ} || die "doins ${modulename}.${KV_OBJ} failed" |
214 |
+ insinto /lib/modules/"${KV_FULL}/${libdir}" |
215 |
+ doins "${modulename}.${KV_OBJ}" || die "doins ${modulename}.${KV_OBJ} failed" |
216 |
cd "${OLDPWD}" |
217 |
|
218 |
generate_modulesd "${objdir}/${modulename}" |
219 |
@@ -733,6 +835,8 @@ linux-mod_pkg_preinst() { |
220 |
|
221 |
[ -d "${D}lib/modules" ] && UPDATE_DEPMOD=true || UPDATE_DEPMOD=false |
222 |
[ -d "${D}lib/modules" ] && UPDATE_MODULEDB=true || UPDATE_MODULEDB=false |
223 |
+ check_sig_force |
224 |
+ use module-sign && sign_all_modules |
225 |
} |
226 |
|
227 |
# @FUNCTION: linux-mod_pkg_postinst |