Skip to content

Commit caabe24

Browse files
dhowellstorvalds
authored andcommitted
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>
1 parent b6bb324 commit caabe24

4 files changed

Lines changed: 28 additions & 31 deletions

File tree

kernel/module-internal.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,4 @@
1111

1212
extern struct key *modsign_keyring;
1313

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);

kernel/module.c

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2421,25 +2421,17 @@ static inline void kmemleak_load_module(const struct module *mod,
24212421

24222422
#ifdef CONFIG_MODULE_SIG
24232423
static int module_sig_check(struct load_info *info,
2424-
const void *mod, unsigned long *len)
2424+
const void *mod, unsigned long *_len)
24252425
{
24262426
int err = -ENOKEY;
2427-
const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1;
2428-
const void *p = mod, *end = mod + *len;
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++;
2427+
unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1;
2428+
unsigned long len = *_len;
2429+
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);
24432435
}
24442436

24452437
if (!err) {

kernel/module_signing.c

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -183,27 +183,33 @@ static struct key *request_asymmetric_key(const char *signer, size_t signer_len,
183183
/*
184184
* Verify the signature on a module.
185185
*/
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)
188187
{
189188
struct public_key_signature *pks;
190189
struct module_signature ms;
191190
struct key *key;
192-
size_t sig_len;
191+
const void *sig;
192+
size_t modlen = *_modlen, sig_len;
193193
int ret;
194194

195-
pr_devel("==>%s(,%lu,,%lu,)\n", __func__, modlen, siglen);
195+
pr_devel("==>%s(,%lu)\n", __func__, modlen);
196196

197-
if (siglen <= sizeof(ms))
197+
if (modlen <= sizeof(ms))
198198
return -EBADMSG;
199199

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);
202202

203203
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)
206205
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;
207213

208214
/* For the moment, only support RSA and X.509 identifiers */
209215
if (ms.algo != PKEY_ALGO_RSA ||

scripts/sign-file

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -403,11 +403,11 @@ my $info = pack("CCCCCxxxN",
403403

404404
if ($verbose) {
405405
print "Size of unsigned module: ", length($unsigned_module), "\n";
406-
print "Size of magic number : ", length($magic_number), "\n";
407406
print "Size of signer's name : ", length($signers_name), "\n";
408407
print "Size of key identifier : ", length($key_identifier), "\n";
409408
print "Size of signature : ", length($signature), "\n";
410409
print "Size of informaton : ", length($info), "\n";
410+
print "Size of magic number : ", length($magic_number), "\n";
411411
print "Signer's name : '", $signers_name, "'\n";
412412
print "Digest : $dgst\n";
413413
}
@@ -416,11 +416,11 @@ open(FD, ">$dest") || die $dest;
416416
binmode FD;
417417
print FD
418418
$unsigned_module,
419-
$magic_number,
420419
$signers_name,
421420
$key_identifier,
422421
$signature,
423-
$info
422+
$info,
423+
$magic_number
424424
;
425425
close FD || die $dest;
426426

0 commit comments

Comments
 (0)