1 /* module-verify-sig.c: module signature checker
3 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 * - Derived from GregKH's RSA module signer
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
13 #include <linux/config.h>
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/slab.h>
17 #include <linux/elf.h>
18 #include <linux/crypto.h>
19 #include <linux/crypto/ksign.h>
20 #include "module-verify.h"
25 #define _debug(FMT, ...) printk(FMT, ##__VA_ARGS__)
27 #define _debug(FMT, ...) do {} while (0)
31 #define count_and_csum(C, __p,__n) \
34 for (__loop = 0; __loop < __n; __loop++) { \
35 (C)->csum += __p[__loop]; \
36 (C)->xcsum += __p[__loop]; \
38 (C)->signed_size += __n; \
41 #define count_and_csum(C, __p,__n) \
43 (C)->signed_size += __n; \
47 #define crypto_digest_update_data(C,PTR,N) \
50 uint8_t *__p = (uint8_t *)(PTR); \
51 count_and_csum((C), __p, __n); \
52 crypto_digest_update_kernel((C)->digest, __p, __n); \
55 #define crypto_digest_update_val(C,VAL) \
57 size_t __n = sizeof(VAL); \
58 uint8_t *__p = (uint8_t *)&(VAL); \
59 count_and_csum((C), __p, __n); \
60 crypto_digest_update_kernel((C)->digest, __p, __n); \
63 static int module_verify_canonicalise(struct module_verify_data *mvdata);
65 static int extract_elf_rela(struct module_verify_data *mvdata,
67 const Elf_Rela *relatab, size_t nrels,
70 static int extract_elf_rel(struct module_verify_data *mvdata,
72 const Elf_Rel *reltab, size_t nrels,
75 static int signedonly;
77 /*****************************************************************************/
79 * verify a module's signature
81 int module_verify_signature(struct module_verify_data *mvdata)
83 const Elf_Shdr *sechdrs = mvdata->sections;
84 const char *secstrings = mvdata->secstrings;
89 for (i = 1; i < mvdata->nsects; i++) {
90 switch (sechdrs[i].sh_type) {
92 if (strcmp(mvdata->secstrings + sechdrs[i].sh_name,
93 ".module_sig") == 0) {
94 mvdata->sig_index = i;
100 if (mvdata->sig_index <= 0)
103 sig = mvdata->buffer + sechdrs[mvdata->sig_index].sh_offset;
104 sig_size = sechdrs[mvdata->sig_index].sh_size;
106 _debug("sig in section %d (size %d)\n",
107 mvdata->sig_index, sig_size);
109 /* produce a canonicalisation map for the sections */
110 ret = module_verify_canonicalise(mvdata);
114 /* grab an SHA1 transformation context
115 * - !!! if this tries to load the sha1.ko module, we will deadlock!!!
117 mvdata->digest = crypto_alloc_tfm2("sha1", 0, 1);
118 if (!mvdata->digest) {
119 printk("Couldn't load module - SHA1 transform unavailable\n");
123 crypto_digest_init(mvdata->digest);
129 /* load data from each relevant section into the digest */
130 for (i = 1; i < mvdata->nsects; i++) {
131 unsigned long sh_type = sechdrs[i].sh_type;
132 unsigned long sh_info = sechdrs[i].sh_info;
133 unsigned long sh_size = sechdrs[i].sh_size;
134 unsigned long sh_flags = sechdrs[i].sh_flags;
135 const char *sh_name = secstrings + sechdrs[i].sh_name;
136 const void *data = mvdata->buffer + sechdrs[i].sh_offset;
138 if (i == mvdata->sig_index)
145 /* it would be nice to include relocation sections, but the act
146 * of adding a signature to the module seems changes their
147 * contents, because the symtab gets changed when sections are
148 * added or removed */
149 if (sh_type == SHT_REL || sh_type == SHT_RELA) {
150 if (mvdata->canonlist[sh_info]) {
151 uint32_t xsh_info = mvdata->canonmap[sh_info];
153 crypto_digest_update_data(mvdata, sh_name, strlen(sh_name));
154 crypto_digest_update_val(mvdata, sechdrs[i].sh_type);
155 crypto_digest_update_val(mvdata, sechdrs[i].sh_flags);
156 crypto_digest_update_val(mvdata, sechdrs[i].sh_size);
157 crypto_digest_update_val(mvdata, sechdrs[i].sh_addralign);
158 crypto_digest_update_val(mvdata, xsh_info);
160 if (sh_type == SHT_RELA)
161 ret = extract_elf_rela(
164 sh_size / sizeof(Elf_Rela),
167 ret = extract_elf_rel(
170 sh_size / sizeof(Elf_Rel),
180 /* include allocatable loadable sections */
181 if (sh_type != SHT_NOBITS && sh_flags & SHF_ALLOC)
182 goto include_section;
187 crypto_digest_update_data(mvdata, sh_name, strlen(sh_name));
188 crypto_digest_update_val(mvdata, sechdrs[i].sh_type);
189 crypto_digest_update_val(mvdata, sechdrs[i].sh_flags);
190 crypto_digest_update_val(mvdata, sechdrs[i].sh_size);
191 crypto_digest_update_val(mvdata, sechdrs[i].sh_addralign);
192 crypto_digest_update_data(mvdata, data, sh_size);
194 _debug("%08zx %02x digested the %s section, size %ld\n",
195 mvdata->signed_size, mvdata->csum, sh_name, sh_size);
197 mvdata->canonlist[i] = 1;
200 _debug("Contributed %zu bytes to the digest (csum 0x%02x)\n",
201 mvdata->signed_size, mvdata->xcsum);
203 /* do the actual signature verification */
204 i = ksign_verify_signature(sig, sig_size, mvdata->digest);
206 _debug("verify-sig : %d\n", i);
213 crypto_free_tfm(mvdata->digest);
216 /* deal with the case of an unsigned module */
220 printk("An attempt to load unsigned module was rejected\n");
223 } /* end module_verify_signature() */
225 /*****************************************************************************/
227 * canonicalise the section table index numbers
229 static int module_verify_canonicalise(struct module_verify_data *mvdata)
231 int canon, loop, changed, tmp;
233 /* produce a list of index numbers of sections that contribute
234 * to the kernel's module image
237 kmalloc(sizeof(int) * mvdata->nsects * 2, GFP_KERNEL);
238 if (!mvdata->canonlist)
241 mvdata->canonmap = mvdata->canonlist + mvdata->nsects;
244 for (loop = 1; loop < mvdata->nsects; loop++) {
245 const Elf_Shdr *section = mvdata->sections + loop;
247 if (loop != mvdata->sig_index) {
248 /* we only need to canonicalise allocatable sections */
249 if (section->sh_flags & SHF_ALLOC)
250 mvdata->canonlist[canon++] = loop;
254 /* canonicalise the index numbers of the contributing section */
258 for (loop = 0; loop < canon - 1; loop++) {
261 x = mvdata->secstrings +
262 mvdata->sections[mvdata->canonlist[loop + 0]].sh_name;
263 y = mvdata->secstrings +
264 mvdata->sections[mvdata->canonlist[loop + 1]].sh_name;
266 if (strcmp(x, y) > 0) {
267 tmp = mvdata->canonlist[loop + 0];
268 mvdata->canonlist[loop + 0] =
269 mvdata->canonlist[loop + 1];
270 mvdata->canonlist[loop + 1] = tmp;
277 for (loop = 0; loop < canon; loop++)
278 mvdata->canonmap[mvdata->canonlist[loop]] = loop + 1;
282 } /* end module_verify_canonicalise() */
284 /*****************************************************************************/
286 * extract a RELA table
287 * - need to canonicalise the entries in case section addition/removal has
288 * rearranged the symbol table and the section table
290 static int extract_elf_rela(struct module_verify_data *mvdata,
292 const Elf_Rela *relatab, size_t nrels,
296 #if defined(MODULES_ARE_ELF32)
305 #elif defined(MODULES_ARE_ELF64)
315 #error unsupported module type
317 } __attribute__((packed)) relocation;
319 const Elf_Rela *reloc;
320 const Elf_Sym *symbol;
323 /* contribute the relevant bits from a join of { RELA, SYMBOL, SECTION } */
324 for (loop = 0; loop < nrels; loop++) {
327 reloc = &relatab[loop];
329 /* decode the relocation */
330 relocation.r_offset = reloc->r_offset;
331 relocation.r_addend = reloc->r_addend;
332 relocation.r_type = ELF_R_TYPE(reloc->r_info);
334 /* decode the symbol referenced by the relocation */
335 symbol = &mvdata->symbols[ELF_R_SYM(reloc->r_info)];
336 relocation.st_info = symbol->st_info;
337 relocation.st_other = symbol->st_other;
338 relocation.st_value = symbol->st_value;
339 relocation.st_size = symbol->st_size;
340 relocation.st_shndx = symbol->st_shndx;
341 st_shndx = symbol->st_shndx;
343 /* canonicalise the section used by the symbol */
344 if (st_shndx > SHN_UNDEF && st_shndx < mvdata->nsects)
345 relocation.st_shndx = mvdata->canonmap[st_shndx];
347 crypto_digest_update_val(mvdata, relocation);
349 /* undefined symbols must be named if referenced */
350 if (st_shndx == SHN_UNDEF) {
351 const char *name = mvdata->strings + symbol->st_name;
352 crypto_digest_update_data(mvdata,
353 name, strlen(name) + 1);
357 _debug("%08zx %02x digested the %s section, nrels %zu\n",
358 mvdata->signed_size, mvdata->csum, sh_name, nrels);
361 } /* end extract_elf_rela() */
363 /*****************************************************************************/
367 static int extract_elf_rel(struct module_verify_data *mvdata,
369 const Elf_Rel *reltab, size_t nrels,
373 #if defined(MODULES_ARE_ELF32)
381 #elif defined(MODULES_ARE_ELF64)
390 #error unsupported module type
392 } __attribute__((packed)) relocation;
394 const Elf_Rel *reloc;
395 const Elf_Sym *symbol;
398 /* contribute the relevant bits from a join of { RELA, SYMBOL, SECTION } */
399 for (loop = 0; loop < nrels; loop++) {
402 reloc = &reltab[loop];
404 /* decode the relocation */
405 relocation.r_offset = reloc->r_offset;
406 relocation.r_type = ELF_R_TYPE(reloc->r_info);
408 /* decode the symbol referenced by the relocation */
409 symbol = &mvdata->symbols[ELF_R_SYM(reloc->r_info)];
410 relocation.st_info = symbol->st_info;
411 relocation.st_other = symbol->st_other;
412 relocation.st_value = symbol->st_value;
413 relocation.st_size = symbol->st_size;
414 relocation.st_shndx = symbol->st_shndx;
415 st_shndx = symbol->st_shndx;
417 /* canonicalise the section used by the symbol */
418 if (st_shndx > SHN_UNDEF && st_shndx < mvdata->nsects)
419 relocation.st_shndx = mvdata->canonmap[st_shndx];
421 crypto_digest_update_val(mvdata, relocation);
423 /* undefined symbols must be named if referenced */
424 if (st_shndx == SHN_UNDEF) {
425 const char *name = mvdata->strings + symbol->st_name;
426 crypto_digest_update_data(mvdata,
427 name, strlen(name) + 1);
431 _debug("%08zx %02x digested the %s section, nrels %zu\n",
432 mvdata->signed_size, mvdata->csum, sh_name, nrels);
435 } /* end extract_elf_rel() */
437 static int __init sign_setup(char *str)
442 __setup("enforcemodulesig", sign_setup);