diff --git a/kernel/module-internal.h b/kernel/module-internal.h index 6114a13419b..24f9247b7d0 100644 --- a/kernel/module-internal.h +++ b/kernel/module-internal.h @@ -11,5 +11,4 @@ extern struct key *modsign_keyring; -extern int mod_verify_sig(const void *mod, unsigned long modlen, - const void *sig, unsigned long siglen); +extern int mod_verify_sig(const void *mod, unsigned long *_modlen); diff --git a/kernel/module.c b/kernel/module.c index 0e2da8695f8..6085f5ef88e 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -2421,25 +2421,17 @@ static inline void kmemleak_load_module(const struct module *mod, #ifdef CONFIG_MODULE_SIG static int module_sig_check(struct load_info *info, - const void *mod, unsigned long *len) + const void *mod, unsigned long *_len) { int err = -ENOKEY; - const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1; - const void *p = mod, *end = mod + *len; + unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1; + unsigned long len = *_len; - /* Poor man's memmem. */ - while ((p = memchr(p, MODULE_SIG_STRING[0], end - p))) { - if (p + markerlen > end) - break; - - if (memcmp(p, MODULE_SIG_STRING, markerlen) == 0) { - const void *sig = p + markerlen; - /* Truncate module up to signature. */ - *len = p - mod; - err = mod_verify_sig(mod, *len, sig, end - sig); - break; - } - p++; + if (len > markerlen && + memcmp(mod + len - markerlen, MODULE_SIG_STRING, markerlen) == 0) { + /* We truncate the module to discard the signature */ + *_len -= markerlen; + err = mod_verify_sig(mod, _len); } if (!err) { diff --git a/kernel/module_signing.c b/kernel/module_signing.c index 6b09f6983ac..d492a23df99 100644 --- a/kernel/module_signing.c +++ b/kernel/module_signing.c @@ -183,27 +183,33 @@ static struct key *request_asymmetric_key(const char *signer, size_t signer_len, /* * Verify the signature on a module. */ -int mod_verify_sig(const void *mod, unsigned long modlen, - const void *sig, unsigned long siglen) +int mod_verify_sig(const void *mod, unsigned long *_modlen) { struct public_key_signature *pks; struct module_signature ms; struct key *key; - size_t sig_len; + const void *sig; + size_t modlen = *_modlen, sig_len; int ret; - pr_devel("==>%s(,%lu,,%lu,)\n", __func__, modlen, siglen); + pr_devel("==>%s(,%lu)\n", __func__, modlen); - if (siglen <= sizeof(ms)) + if (modlen <= sizeof(ms)) return -EBADMSG; - memcpy(&ms, sig + (siglen - sizeof(ms)), sizeof(ms)); - siglen -= sizeof(ms); + memcpy(&ms, mod + (modlen - sizeof(ms)), sizeof(ms)); + modlen -= sizeof(ms); sig_len = be32_to_cpu(ms.sig_len); - if (sig_len >= siglen || - siglen - sig_len != (size_t)ms.signer_len + ms.key_id_len) + if (sig_len >= modlen) return -EBADMSG; + modlen -= sig_len; + if ((size_t)ms.signer_len + ms.key_id_len >= modlen) + return -EBADMSG; + modlen -= (size_t)ms.signer_len + ms.key_id_len; + + *_modlen = modlen; + sig = mod + modlen; /* For the moment, only support RSA and X.509 identifiers */ if (ms.algo != PKEY_ALGO_RSA || diff --git a/scripts/sign-file b/scripts/sign-file index d37d1309531..87ca59d36e7 100755 --- a/scripts/sign-file +++ b/scripts/sign-file @@ -403,11 +403,11 @@ my $info = pack("CCCCCxxxN", if ($verbose) { print "Size of unsigned module: ", length($unsigned_module), "\n"; - print "Size of magic number : ", length($magic_number), "\n"; print "Size of signer's name : ", length($signers_name), "\n"; print "Size of key identifier : ", length($key_identifier), "\n"; print "Size of signature : ", length($signature), "\n"; print "Size of informaton : ", length($info), "\n"; + print "Size of magic number : ", length($magic_number), "\n"; print "Signer's name : '", $signers_name, "'\n"; print "Digest : $dgst\n"; } @@ -416,11 +416,11 @@ open(FD, ">$dest") || die $dest; binmode FD; print FD $unsigned_module, - $magic_number, $signers_name, $key_identifier, $signature, - $info + $info, + $magic_number ; close FD || die $dest;