This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / kernel / module-verify-sig.c
1 /* module-verify-sig.c: module signature checker
2  *
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
6  *
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.
11  */
12
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"
21
22 #undef MODSIGN_DEBUG
23
24 #ifdef MODSIGN_DEBUG
25 #define _debug(FMT, ...) printk(FMT, ##__VA_ARGS__)
26 #else
27 #define _debug(FMT, ...) do {} while (0)
28 #endif
29
30 #ifdef MODSIGN_DEBUG
31 #define count_and_csum(C, __p,__n)                      \
32 do {                                                    \
33         int __loop;                                     \
34         for (__loop = 0; __loop < __n; __loop++) {      \
35                 (C)->csum += __p[__loop];               \
36                 (C)->xcsum += __p[__loop];              \
37         }                                               \
38         (C)->signed_size += __n;                        \
39 } while(0)
40 #else
41 #define count_and_csum(C, __p,__n)              \
42 do {                                            \
43         (C)->signed_size += __n;                \
44 } while(0)
45 #endif
46
47 #define crypto_digest_update_data(C,PTR,N)                      \
48 do {                                                            \
49         size_t __n = (N);                                       \
50         uint8_t *__p = (uint8_t *)(PTR);                        \
51         count_and_csum((C), __p, __n);                          \
52         crypto_digest_update_kernel((C)->digest, __p, __n);     \
53 } while(0)
54
55 #define crypto_digest_update_val(C,VAL)                         \
56 do {                                                            \
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);     \
61 } while(0)
62
63 static int module_verify_canonicalise(struct module_verify_data *mvdata);
64
65 static int extract_elf_rela(struct module_verify_data *mvdata,
66                             int secix,
67                             const Elf_Rela *relatab, size_t nrels,
68                             const char *sh_name);
69
70 static int extract_elf_rel(struct module_verify_data *mvdata,
71                            int secix,
72                            const Elf_Rel *reltab, size_t nrels,
73                            const char *sh_name);
74
75 static int signedonly;
76
77 /*****************************************************************************/
78 /*
79  * verify a module's signature
80  */
81 int module_verify_signature(struct module_verify_data *mvdata)
82 {
83         const Elf_Shdr *sechdrs = mvdata->sections;
84         const char *secstrings = mvdata->secstrings;
85         const char *sig;
86         unsigned sig_size;
87         int i, ret;
88
89         for (i = 1; i < mvdata->nsects; i++) {
90                 switch (sechdrs[i].sh_type) {
91                 case SHT_PROGBITS:
92                         if (strcmp(mvdata->secstrings + sechdrs[i].sh_name,
93                                    ".module_sig") == 0) {
94                                 mvdata->sig_index = i;
95                         }
96                         break;
97                 }
98         }
99
100         if (mvdata->sig_index <= 0)
101                 goto no_signature;
102
103         sig = mvdata->buffer + sechdrs[mvdata->sig_index].sh_offset;
104         sig_size = sechdrs[mvdata->sig_index].sh_size;
105
106         _debug("sig in section %d (size %d)\n",
107                mvdata->sig_index, sig_size);
108
109         /* produce a canonicalisation map for the sections */
110         ret = module_verify_canonicalise(mvdata);
111         if (ret < 0)
112                 return ret;
113
114         /* grab an SHA1 transformation context
115          * - !!! if this tries to load the sha1.ko module, we will deadlock!!!
116          */
117         mvdata->digest = crypto_alloc_tfm2("sha1", 0, 1);
118         if (!mvdata->digest) {
119                 printk("Couldn't load module - SHA1 transform unavailable\n");
120                 return -EPERM;
121         }
122
123         crypto_digest_init(mvdata->digest);
124
125 #ifdef MODSIGN_DEBUG
126         mvdata->xcsum = 0;
127 #endif
128
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;
137
138                 if (i == mvdata->sig_index)
139                         continue;
140
141 #ifdef MODSIGN_DEBUG
142                 mvdata->csum = 0;
143 #endif
144
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];
152
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);
159
160                                 if (sh_type == SHT_RELA)
161                                         ret = extract_elf_rela(
162                                                 mvdata, i,
163                                                 data,
164                                                 sh_size / sizeof(Elf_Rela),
165                                                 sh_name);
166                                 else
167                                         ret = extract_elf_rel(
168                                                 mvdata, i,
169                                                 data,
170                                                 sh_size / sizeof(Elf_Rel),
171                                                 sh_name);
172
173                                 if (ret < 0)
174                                         goto format_error;
175                         }
176
177                         continue;
178                 }
179
180                 /* include allocatable loadable sections */
181                 if (sh_type != SHT_NOBITS && sh_flags & SHF_ALLOC)
182                         goto include_section;
183
184                 continue;
185
186         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);
193
194                 _debug("%08zx %02x digested the %s section, size %ld\n",
195                        mvdata->signed_size, mvdata->csum, sh_name, sh_size);
196
197                 mvdata->canonlist[i] = 1;
198         }
199
200         _debug("Contributed %zu bytes to the digest (csum 0x%02x)\n",
201                mvdata->signed_size, mvdata->xcsum);
202
203         /* do the actual signature verification */
204         i = ksign_verify_signature(sig, sig_size, mvdata->digest);
205
206         _debug("verify-sig : %d\n", i);
207
208         if (i == 0)
209                 i = 1;
210         return i;
211
212  format_error:
213         crypto_free_tfm(mvdata->digest);
214         return -ELIBBAD;
215
216         /* deal with the case of an unsigned module */
217  no_signature:
218         if (!signedonly)
219                 return 0;
220         printk("An attempt to load unsigned module was rejected\n");
221         return -EPERM;
222
223 } /* end module_verify_signature() */
224
225 /*****************************************************************************/
226 /*
227  * canonicalise the section table index numbers
228  */
229 static int module_verify_canonicalise(struct module_verify_data *mvdata)
230 {
231         int canon, loop, changed, tmp;
232
233         /* produce a list of index numbers of sections that contribute
234          * to the kernel's module image
235          */
236         mvdata->canonlist =
237                 kmalloc(sizeof(int) * mvdata->nsects * 2, GFP_KERNEL);
238         if (!mvdata->canonlist)
239                 return -ENOMEM;
240
241         mvdata->canonmap = mvdata->canonlist + mvdata->nsects;
242         canon = 0;
243
244         for (loop = 1; loop < mvdata->nsects; loop++) {
245                 const Elf_Shdr *section = mvdata->sections + loop;
246
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;
251                 }
252         }
253
254         /* canonicalise the index numbers of the contributing section */
255         do {
256                 changed = 0;
257
258                 for (loop = 0; loop < canon - 1; loop++) {
259                         const char *x, *y;
260
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;
265
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;
271                                 changed = 1;
272                         }
273                 }
274
275         } while(changed);
276
277         for (loop = 0; loop < canon; loop++)
278                 mvdata->canonmap[mvdata->canonlist[loop]] = loop + 1;
279
280         return 0;
281
282 } /* end module_verify_canonicalise() */
283
284 /*****************************************************************************/
285 /*
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
289  */
290 static int extract_elf_rela(struct module_verify_data *mvdata,
291                             int secix,
292                             const Elf_Rela *relatab, size_t nrels,
293                             const char *sh_name)
294 {
295         struct {
296 #if defined(MODULES_ARE_ELF32)
297                 uint32_t        r_offset;
298                 uint32_t        r_addend;
299                 uint32_t        st_value;
300                 uint32_t        st_size;
301                 uint16_t        st_shndx;
302                 uint8_t         r_type;
303                 uint8_t         st_info;
304                 uint8_t         st_other;
305 #elif defined(MODULES_ARE_ELF64)
306                 uint64_t        r_offset;
307                 uint64_t        r_addend;
308                 uint64_t        st_value;
309                 uint64_t        st_size;
310                 uint32_t        r_type;
311                 uint16_t        st_shndx;
312                 uint8_t         st_info;
313                 uint8_t         st_other;
314 #else
315 #error unsupported module type
316 #endif
317         } __attribute__((packed)) relocation;
318
319         const Elf_Rela *reloc;
320         const Elf_Sym *symbol;
321         size_t loop;
322
323         /* contribute the relevant bits from a join of { RELA, SYMBOL, SECTION } */
324         for (loop = 0; loop < nrels; loop++) {
325                 int st_shndx;
326
327                 reloc = &relatab[loop];
328
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);
333
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;
342
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];
346
347                 crypto_digest_update_val(mvdata, relocation);
348
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);
354                 }
355         }
356
357         _debug("%08zx %02x digested the %s section, nrels %zu\n",
358                mvdata->signed_size, mvdata->csum, sh_name, nrels);
359
360         return 0;
361 } /* end extract_elf_rela() */
362
363 /*****************************************************************************/
364 /*
365  *
366  */
367 static int extract_elf_rel(struct module_verify_data *mvdata,
368                            int secix,
369                            const Elf_Rel *reltab, size_t nrels,
370                            const char *sh_name)
371 {
372         struct {
373 #if defined(MODULES_ARE_ELF32)
374                 uint32_t        r_offset;
375                 uint32_t        st_value;
376                 uint32_t        st_size;
377                 uint16_t        st_shndx;
378                 uint8_t         r_type;
379                 uint8_t         st_info;
380                 uint8_t         st_other;
381 #elif defined(MODULES_ARE_ELF64)
382                 uint64_t        r_offset;
383                 uint64_t        st_value;
384                 uint64_t        st_size;
385                 uint32_t        r_type;
386                 uint16_t        st_shndx;
387                 uint8_t         st_info;
388                 uint8_t         st_other;
389 #else
390 #error unsupported module type
391 #endif
392         } __attribute__((packed)) relocation;
393
394         const Elf_Rel *reloc;
395         const Elf_Sym *symbol;
396         size_t loop;
397
398         /* contribute the relevant bits from a join of { RELA, SYMBOL, SECTION } */
399         for (loop = 0; loop < nrels; loop++) {
400                 int st_shndx;
401
402                 reloc = &reltab[loop];
403
404                 /* decode the relocation */
405                 relocation.r_offset = reloc->r_offset;
406                 relocation.r_type = ELF_R_TYPE(reloc->r_info);
407
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;
416
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];
420
421                 crypto_digest_update_val(mvdata, relocation);
422
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);
428                 }
429         }
430
431         _debug("%08zx %02x digested the %s section, nrels %zu\n",
432                mvdata->signed_size, mvdata->csum, sh_name, nrels);
433
434         return 0;
435 } /* end extract_elf_rel() */
436
437 static int __init sign_setup(char *str)
438 {
439         signedonly = 1;
440         return 0;
441 }
442 __setup("enforcemodulesig", sign_setup);