Merge to Fedora kernel-2.6.18-1.2224_FC5 patched with stable patch-2.6.18.1-vs2.0...
[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/kernel.h>
14 #include <linux/module.h>
15 #include <linux/slab.h>
16 #include <linux/elf.h>
17 #include <linux/crypto.h>
18 #include <linux/crypto/ksign.h>
19 #include "module-verify.h"
20
21 #undef MODSIGN_DEBUG
22
23 #ifdef MODSIGN_DEBUG
24 #define _debug(FMT, ...) printk(FMT, ##__VA_ARGS__)
25 #else
26 #define _debug(FMT, ...) do {} while (0)
27 #endif
28
29 #ifdef MODSIGN_DEBUG
30 #define count_and_csum(C, __p,__n)                      \
31 do {                                                    \
32         int __loop;                                     \
33         for (__loop = 0; __loop < __n; __loop++) {      \
34                 (C)->csum += __p[__loop];               \
35                 (C)->xcsum += __p[__loop];              \
36         }                                               \
37         (C)->signed_size += __n;                        \
38 } while(0)
39 #else
40 #define count_and_csum(C, __p,__n)              \
41 do {                                            \
42         (C)->signed_size += __n;                \
43 } while(0)
44 #endif
45
46 #define crypto_digest_update_data(C,PTR,N)                      \
47 do {                                                            \
48         size_t __n = (N);                                       \
49         uint8_t *__p = (uint8_t *)(PTR);                        \
50         count_and_csum((C), __p, __n);                          \
51         crypto_digest_update_kernel((C)->digest, __p, __n);     \
52 } while(0)
53
54 #define crypto_digest_update_val(C,VAL)                         \
55 do {                                                            \
56         size_t __n = sizeof(VAL);                               \
57         uint8_t *__p = (uint8_t *)&(VAL);                       \
58         count_and_csum((C), __p, __n);                          \
59         crypto_digest_update_kernel((C)->digest, __p, __n);     \
60 } while(0)
61
62 static int module_verify_canonicalise(struct module_verify_data *mvdata);
63
64 static int extract_elf_rela(struct module_verify_data *mvdata,
65                             int secix,
66                             const Elf_Rela *relatab, size_t nrels,
67                             const char *sh_name);
68
69 static int extract_elf_rel(struct module_verify_data *mvdata,
70                            int secix,
71                            const Elf_Rel *reltab, size_t nrels,
72                            const char *sh_name);
73
74 static int signedonly;
75
76 /*****************************************************************************/
77 /*
78  * verify a module's signature
79  */
80 int module_verify_signature(struct module_verify_data *mvdata)
81 {
82         const Elf_Shdr *sechdrs = mvdata->sections;
83         const char *secstrings = mvdata->secstrings;
84         const char *sig;
85         unsigned sig_size;
86         int i, ret;
87
88         for (i = 1; i < mvdata->nsects; i++) {
89                 switch (sechdrs[i].sh_type) {
90                 case SHT_PROGBITS:
91                         if (strcmp(mvdata->secstrings + sechdrs[i].sh_name,
92                                    ".module_sig") == 0) {
93                                 mvdata->sig_index = i;
94                         }
95                         break;
96                 }
97         }
98
99         if (mvdata->sig_index <= 0)
100                 goto no_signature;
101
102         sig = mvdata->buffer + sechdrs[mvdata->sig_index].sh_offset;
103         sig_size = sechdrs[mvdata->sig_index].sh_size;
104
105         _debug("sig in section %d (size %d)\n",
106                mvdata->sig_index, sig_size);
107
108         /* produce a canonicalisation map for the sections */
109         ret = module_verify_canonicalise(mvdata);
110         if (ret < 0)
111                 return ret;
112
113         /* grab an SHA1 transformation context
114          * - !!! if this tries to load the sha1.ko module, we will deadlock!!!
115          */
116         mvdata->digest = crypto_alloc_tfm2("sha1", 0, 1);
117         if (!mvdata->digest) {
118                 printk("Couldn't load module - SHA1 transform unavailable\n");
119                 return -EPERM;
120         }
121
122         crypto_digest_init(mvdata->digest);
123
124 #ifdef MODSIGN_DEBUG
125         mvdata->xcsum = 0;
126 #endif
127
128         /* load data from each relevant section into the digest */
129         for (i = 1; i < mvdata->nsects; i++) {
130                 unsigned long sh_type = sechdrs[i].sh_type;
131                 unsigned long sh_info = sechdrs[i].sh_info;
132                 unsigned long sh_size = sechdrs[i].sh_size;
133                 unsigned long sh_flags = sechdrs[i].sh_flags;
134                 const char *sh_name = secstrings + sechdrs[i].sh_name;
135                 const void *data = mvdata->buffer + sechdrs[i].sh_offset;
136
137                 if (i == mvdata->sig_index)
138                         continue;
139
140 #ifdef MODSIGN_DEBUG
141                 mvdata->csum = 0;
142 #endif
143
144                 /* it would be nice to include relocation sections, but the act
145                  * of adding a signature to the module seems changes their
146                  * contents, because the symtab gets changed when sections are
147                  * added or removed */
148                 if (sh_type == SHT_REL || sh_type == SHT_RELA) {
149                         if (mvdata->canonlist[sh_info]) {
150                                 uint32_t xsh_info = mvdata->canonmap[sh_info];
151
152                                 crypto_digest_update_data(mvdata, sh_name, strlen(sh_name));
153                                 crypto_digest_update_val(mvdata, sechdrs[i].sh_type);
154                                 crypto_digest_update_val(mvdata, sechdrs[i].sh_flags);
155                                 crypto_digest_update_val(mvdata, sechdrs[i].sh_size);
156                                 crypto_digest_update_val(mvdata, sechdrs[i].sh_addralign);
157                                 crypto_digest_update_val(mvdata, xsh_info);
158
159                                 if (sh_type == SHT_RELA)
160                                         ret = extract_elf_rela(
161                                                 mvdata, i,
162                                                 data,
163                                                 sh_size / sizeof(Elf_Rela),
164                                                 sh_name);
165                                 else
166                                         ret = extract_elf_rel(
167                                                 mvdata, i,
168                                                 data,
169                                                 sh_size / sizeof(Elf_Rel),
170                                                 sh_name);
171
172                                 if (ret < 0)
173                                         goto format_error;
174                         }
175
176                         continue;
177                 }
178
179                 /* include allocatable loadable sections */
180                 if (sh_type != SHT_NOBITS && sh_flags & SHF_ALLOC)
181                         goto include_section;
182
183                 continue;
184
185         include_section:
186                 crypto_digest_update_data(mvdata, sh_name, strlen(sh_name));
187                 crypto_digest_update_val(mvdata, sechdrs[i].sh_type);
188                 crypto_digest_update_val(mvdata, sechdrs[i].sh_flags);
189                 crypto_digest_update_val(mvdata, sechdrs[i].sh_size);
190                 crypto_digest_update_val(mvdata, sechdrs[i].sh_addralign);
191                 crypto_digest_update_data(mvdata, data, sh_size);
192
193                 _debug("%08zx %02x digested the %s section, size %ld\n",
194                        mvdata->signed_size, mvdata->csum, sh_name, sh_size);
195
196                 mvdata->canonlist[i] = 1;
197         }
198
199         _debug("Contributed %zu bytes to the digest (csum 0x%02x)\n",
200                mvdata->signed_size, mvdata->xcsum);
201
202         /* do the actual signature verification */
203         i = ksign_verify_signature(sig, sig_size, mvdata->digest);
204
205         _debug("verify-sig : %d\n", i);
206
207         if (i == 0)
208                 i = 1;
209         return i;
210
211  format_error:
212         crypto_free_tfm(mvdata->digest);
213         return -ELIBBAD;
214
215         /* deal with the case of an unsigned module */
216  no_signature:
217         if (!signedonly)
218                 return 0;
219         printk("An attempt to load unsigned module was rejected\n");
220         return -EPERM;
221
222 } /* end module_verify_signature() */
223
224 /*****************************************************************************/
225 /*
226  * canonicalise the section table index numbers
227  */
228 static int module_verify_canonicalise(struct module_verify_data *mvdata)
229 {
230         int canon, loop, changed, tmp;
231
232         /* produce a list of index numbers of sections that contribute
233          * to the kernel's module image
234          */
235         mvdata->canonlist =
236                 kmalloc(sizeof(int) * mvdata->nsects * 2, GFP_KERNEL);
237         if (!mvdata->canonlist)
238                 return -ENOMEM;
239
240         mvdata->canonmap = mvdata->canonlist + mvdata->nsects;
241         canon = 0;
242
243         for (loop = 1; loop < mvdata->nsects; loop++) {
244                 const Elf_Shdr *section = mvdata->sections + loop;
245
246                 if (loop != mvdata->sig_index) {
247                         /* we only need to canonicalise allocatable sections */
248                         if (section->sh_flags & SHF_ALLOC)
249                                 mvdata->canonlist[canon++] = loop;
250                 }
251         }
252
253         /* canonicalise the index numbers of the contributing section */
254         do {
255                 changed = 0;
256
257                 for (loop = 0; loop < canon - 1; loop++) {
258                         const char *x, *y;
259
260                         x = mvdata->secstrings +
261                                 mvdata->sections[mvdata->canonlist[loop + 0]].sh_name;
262                         y = mvdata->secstrings +
263                                 mvdata->sections[mvdata->canonlist[loop + 1]].sh_name;
264
265                         if (strcmp(x, y) > 0) {
266                                 tmp = mvdata->canonlist[loop + 0];
267                                 mvdata->canonlist[loop + 0] =
268                                         mvdata->canonlist[loop + 1];
269                                 mvdata->canonlist[loop + 1] = tmp;
270                                 changed = 1;
271                         }
272                 }
273
274         } while(changed);
275
276         for (loop = 0; loop < canon; loop++)
277                 mvdata->canonmap[mvdata->canonlist[loop]] = loop + 1;
278
279         return 0;
280
281 } /* end module_verify_canonicalise() */
282
283 /*****************************************************************************/
284 /*
285  * extract a RELA table
286  * - need to canonicalise the entries in case section addition/removal has
287  *   rearranged the symbol table and the section table
288  */
289 static int extract_elf_rela(struct module_verify_data *mvdata,
290                             int secix,
291                             const Elf_Rela *relatab, size_t nrels,
292                             const char *sh_name)
293 {
294         struct {
295 #if defined(MODULES_ARE_ELF32)
296                 uint32_t        r_offset;
297                 uint32_t        r_addend;
298                 uint32_t        st_value;
299                 uint32_t        st_size;
300                 uint16_t        st_shndx;
301                 uint8_t         r_type;
302                 uint8_t         st_info;
303                 uint8_t         st_other;
304 #elif defined(MODULES_ARE_ELF64)
305                 uint64_t        r_offset;
306                 uint64_t        r_addend;
307                 uint64_t        st_value;
308                 uint64_t        st_size;
309                 uint32_t        r_type;
310                 uint16_t        st_shndx;
311                 uint8_t         st_info;
312                 uint8_t         st_other;
313 #else
314 #error unsupported module type
315 #endif
316         } __attribute__((packed)) relocation;
317
318         const Elf_Rela *reloc;
319         const Elf_Sym *symbol;
320         size_t loop;
321
322         /* contribute the relevant bits from a join of { RELA, SYMBOL, SECTION } */
323         for (loop = 0; loop < nrels; loop++) {
324                 int st_shndx;
325
326                 reloc = &relatab[loop];
327
328                 /* decode the relocation */
329                 relocation.r_offset = reloc->r_offset;
330                 relocation.r_addend = reloc->r_addend;
331                 relocation.r_type = ELF_R_TYPE(reloc->r_info);
332
333                 /* decode the symbol referenced by the relocation */
334                 symbol = &mvdata->symbols[ELF_R_SYM(reloc->r_info)];
335                 relocation.st_info = symbol->st_info;
336                 relocation.st_other = symbol->st_other;
337                 relocation.st_value = symbol->st_value;
338                 relocation.st_size = symbol->st_size;
339                 relocation.st_shndx = symbol->st_shndx;
340                 st_shndx = symbol->st_shndx;
341
342                 /* canonicalise the section used by the symbol */
343                 if (st_shndx > SHN_UNDEF && st_shndx < mvdata->nsects)
344                         relocation.st_shndx = mvdata->canonmap[st_shndx];
345
346                 crypto_digest_update_val(mvdata, relocation);
347
348                 /* undefined symbols must be named if referenced */
349                 if (st_shndx == SHN_UNDEF) {
350                         const char *name = mvdata->strings + symbol->st_name;
351                         crypto_digest_update_data(mvdata,
352                                                   name, strlen(name) + 1);
353                 }
354         }
355
356         _debug("%08zx %02x digested the %s section, nrels %zu\n",
357                mvdata->signed_size, mvdata->csum, sh_name, nrels);
358
359         return 0;
360 } /* end extract_elf_rela() */
361
362 /*****************************************************************************/
363 /*
364  *
365  */
366 static int extract_elf_rel(struct module_verify_data *mvdata,
367                            int secix,
368                            const Elf_Rel *reltab, size_t nrels,
369                            const char *sh_name)
370 {
371         struct {
372 #if defined(MODULES_ARE_ELF32)
373                 uint32_t        r_offset;
374                 uint32_t        st_value;
375                 uint32_t        st_size;
376                 uint16_t        st_shndx;
377                 uint8_t         r_type;
378                 uint8_t         st_info;
379                 uint8_t         st_other;
380 #elif defined(MODULES_ARE_ELF64)
381                 uint64_t        r_offset;
382                 uint64_t        st_value;
383                 uint64_t        st_size;
384                 uint32_t        r_type;
385                 uint16_t        st_shndx;
386                 uint8_t         st_info;
387                 uint8_t         st_other;
388 #else
389 #error unsupported module type
390 #endif
391         } __attribute__((packed)) relocation;
392
393         const Elf_Rel *reloc;
394         const Elf_Sym *symbol;
395         size_t loop;
396
397         /* contribute the relevant bits from a join of { RELA, SYMBOL, SECTION } */
398         for (loop = 0; loop < nrels; loop++) {
399                 int st_shndx;
400
401                 reloc = &reltab[loop];
402
403                 /* decode the relocation */
404                 relocation.r_offset = reloc->r_offset;
405                 relocation.r_type = ELF_R_TYPE(reloc->r_info);
406
407                 /* decode the symbol referenced by the relocation */
408                 symbol = &mvdata->symbols[ELF_R_SYM(reloc->r_info)];
409                 relocation.st_info = symbol->st_info;
410                 relocation.st_other = symbol->st_other;
411                 relocation.st_value = symbol->st_value;
412                 relocation.st_size = symbol->st_size;
413                 relocation.st_shndx = symbol->st_shndx;
414                 st_shndx = symbol->st_shndx;
415
416                 /* canonicalise the section used by the symbol */
417                 if (st_shndx > SHN_UNDEF && st_shndx < mvdata->nsects)
418                         relocation.st_shndx = mvdata->canonmap[st_shndx];
419
420                 crypto_digest_update_val(mvdata, relocation);
421
422                 /* undefined symbols must be named if referenced */
423                 if (st_shndx == SHN_UNDEF) {
424                         const char *name = mvdata->strings + symbol->st_name;
425                         crypto_digest_update_data(mvdata,
426                                                   name, strlen(name) + 1);
427                 }
428         }
429
430         _debug("%08zx %02x digested the %s section, nrels %zu\n",
431                mvdata->signed_size, mvdata->csum, sh_name, nrels);
432
433         return 0;
434 } /* end extract_elf_rel() */
435
436 static int __init sign_setup(char *str)
437 {
438         signedonly = 1;
439         return 0;
440 }
441 __setup("enforcemodulesig", sign_setup);