Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

MODSIGN: Move the magic string to the end of a module and eliminate the search

Emit the magic string that indicates a module has a signature after the
signature data instead of before it. This allows module_sig_check() to
be made simpler and faster by the elimination of the search for the
magic string. Instead we just need to do a single memcmp().

This works because at the end of the signature data there is the
fixed-length signature information block. This block then falls
immediately prior to the magic number.

From the contents of the information block, it is trivial to calculate
the size of the signature data and thus the size of the actual module
data.

Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

David Howells and committed by
Linus Torvalds
caabe240 b6bb324d

+27 -30
+1 -2
kernel/module-internal.h
··· 11 11 12 12 extern struct key *modsign_keyring; 13 13 14 - extern int mod_verify_sig(const void *mod, unsigned long modlen, 15 - const void *sig, unsigned long siglen); 14 + extern int mod_verify_sig(const void *mod, unsigned long *_modlen);
+8 -16
kernel/module.c
··· 2421 2421 2422 2422 #ifdef CONFIG_MODULE_SIG 2423 2423 static int module_sig_check(struct load_info *info, 2424 - const void *mod, unsigned long *len) 2424 + const void *mod, unsigned long *_len) 2425 2425 { 2426 2426 int err = -ENOKEY; 2427 - const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1; 2428 - const void *p = mod, *end = mod + *len; 2427 + unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1; 2428 + unsigned long len = *_len; 2429 2429 2430 - /* Poor man's memmem. */ 2431 - while ((p = memchr(p, MODULE_SIG_STRING[0], end - p))) { 2432 - if (p + markerlen > end) 2433 - break; 2434 - 2435 - if (memcmp(p, MODULE_SIG_STRING, markerlen) == 0) { 2436 - const void *sig = p + markerlen; 2437 - /* Truncate module up to signature. */ 2438 - *len = p - mod; 2439 - err = mod_verify_sig(mod, *len, sig, end - sig); 2440 - break; 2441 - } 2442 - p++; 2430 + if (len > markerlen && 2431 + memcmp(mod + len - markerlen, MODULE_SIG_STRING, markerlen) == 0) { 2432 + /* We truncate the module to discard the signature */ 2433 + *_len -= markerlen; 2434 + err = mod_verify_sig(mod, _len); 2443 2435 } 2444 2436 2445 2437 if (!err) {
+15 -9
kernel/module_signing.c
··· 183 183 /* 184 184 * Verify the signature on a module. 185 185 */ 186 - int mod_verify_sig(const void *mod, unsigned long modlen, 187 - const void *sig, unsigned long siglen) 186 + int mod_verify_sig(const void *mod, unsigned long *_modlen) 188 187 { 189 188 struct public_key_signature *pks; 190 189 struct module_signature ms; 191 190 struct key *key; 192 - size_t sig_len; 191 + const void *sig; 192 + size_t modlen = *_modlen, sig_len; 193 193 int ret; 194 194 195 - pr_devel("==>%s(,%lu,,%lu,)\n", __func__, modlen, siglen); 195 + pr_devel("==>%s(,%lu)\n", __func__, modlen); 196 196 197 - if (siglen <= sizeof(ms)) 197 + if (modlen <= sizeof(ms)) 198 198 return -EBADMSG; 199 199 200 - memcpy(&ms, sig + (siglen - sizeof(ms)), sizeof(ms)); 201 - siglen -= sizeof(ms); 200 + memcpy(&ms, mod + (modlen - sizeof(ms)), sizeof(ms)); 201 + modlen -= sizeof(ms); 202 202 203 203 sig_len = be32_to_cpu(ms.sig_len); 204 - if (sig_len >= siglen || 205 - siglen - sig_len != (size_t)ms.signer_len + ms.key_id_len) 204 + if (sig_len >= modlen) 206 205 return -EBADMSG; 206 + modlen -= sig_len; 207 + if ((size_t)ms.signer_len + ms.key_id_len >= modlen) 208 + return -EBADMSG; 209 + modlen -= (size_t)ms.signer_len + ms.key_id_len; 210 + 211 + *_modlen = modlen; 212 + sig = mod + modlen; 207 213 208 214 /* For the moment, only support RSA and X.509 identifiers */ 209 215 if (ms.algo != PKEY_ALGO_RSA ||
+3 -3
scripts/sign-file
··· 403 403 404 404 if ($verbose) { 405 405 print "Size of unsigned module: ", length($unsigned_module), "\n"; 406 - print "Size of magic number : ", length($magic_number), "\n"; 407 406 print "Size of signer's name : ", length($signers_name), "\n"; 408 407 print "Size of key identifier : ", length($key_identifier), "\n"; 409 408 print "Size of signature : ", length($signature), "\n"; 410 409 print "Size of informaton : ", length($info), "\n"; 410 + print "Size of magic number : ", length($magic_number), "\n"; 411 411 print "Signer's name : '", $signers_name, "'\n"; 412 412 print "Digest : $dgst\n"; 413 413 } ··· 416 416 binmode FD; 417 417 print FD 418 418 $unsigned_module, 419 - $magic_number, 420 419 $signers_name, 421 420 $key_identifier, 422 421 $signature, 423 - $info 422 + $info, 423 + $magic_number 424 424 ; 425 425 close FD || die $dest; 426 426