1
2
3
4
5
6
7
8
9
10
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) \
32do { \
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) \
42do { \
43 (C)->signed_size += __n; \
44} while(0)
45#endif
46
47#define crypto_digest_update_data(C,PTR,N) \
48do { \
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) \
56do { \
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
63static int module_verify_canonicalise(struct module_verify_data *mvdata);
64
65static 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
70static 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
75static int signedonly;
76
77
78
79
80
81int 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
110 ret = module_verify_canonicalise(mvdata);
111 if (ret < 0) {
112 if (signedonly)
113 return ret;
114 return 0;
115 }
116
117
118
119
120 mvdata->digest = crypto_alloc_tfm2("sha1", 0, 1);
121 if (!mvdata->digest) {
122 printk("Couldn't load module - SHA1 transform unavailable\n");
123 if (!signedonly)
124 return 0;
125 return -EPERM;
126 }
127
128 crypto_digest_init(mvdata->digest);
129
130#ifdef MODSIGN_DEBUG
131 mvdata->xcsum = 0;
132#endif
133
134
135 for (i = 1; i < mvdata->nsects; i++) {
136 unsigned long sh_type = sechdrs[i].sh_type;
137 unsigned long sh_info = sechdrs[i].sh_info;
138 unsigned long sh_size = sechdrs[i].sh_size;
139 unsigned long sh_flags = sechdrs[i].sh_flags;
140 const char *sh_name = secstrings + sechdrs[i].sh_name;
141 const void *data = mvdata->buffer + sechdrs[i].sh_offset;
142
143 if (i == mvdata->sig_index)
144 continue;
145
146#ifdef MODSIGN_DEBUG
147 mvdata->csum = 0;
148#endif
149
150
151
152
153
154 if (sh_type == SHT_REL || sh_type == SHT_RELA) {
155 if (mvdata->canonlist[sh_info]) {
156 uint32_t xsh_info = mvdata->canonmap[sh_info];
157
158 crypto_digest_update_data(mvdata, sh_name, strlen(sh_name));
159 crypto_digest_update_val(mvdata, sechdrs[i].sh_type);
160 crypto_digest_update_val(mvdata, sechdrs[i].sh_flags);
161 crypto_digest_update_val(mvdata, sechdrs[i].sh_size);
162 crypto_digest_update_val(mvdata, sechdrs[i].sh_addralign);
163 crypto_digest_update_val(mvdata, xsh_info);
164
165 if (sh_type == SHT_RELA)
166 ret = extract_elf_rela(
167 mvdata, i,
168 data,
169 sh_size / sizeof(Elf_Rela),
170 sh_name);
171 else
172 ret = extract_elf_rel(
173 mvdata, i,
174 data,
175 sh_size / sizeof(Elf_Rel),
176 sh_name);
177
178 if (ret < 0)
179 goto format_error;
180 }
181
182 continue;
183 }
184
185
186 if (sh_type != SHT_NOBITS && sh_flags & SHF_ALLOC)
187 goto include_section;
188
189 continue;
190
191 include_section:
192 crypto_digest_update_data(mvdata, sh_name, strlen(sh_name));
193 crypto_digest_update_val(mvdata, sechdrs[i].sh_type);
194 crypto_digest_update_val(mvdata, sechdrs[i].sh_flags);
195 crypto_digest_update_val(mvdata, sechdrs[i].sh_size);
196 crypto_digest_update_val(mvdata, sechdrs[i].sh_addralign);
197 crypto_digest_update_data(mvdata, data, sh_size);
198
199 _debug("%08zx %02x digested the %s section, size %ld\n",
200 mvdata->signed_size, mvdata->csum, sh_name, sh_size);
201
202 mvdata->canonlist[i] = 1;
203 }
204
205 _debug("Contributed %zu bytes to the digest (csum 0x%02x)\n",
206 mvdata->signed_size, mvdata->xcsum);
207
208
209 i = ksign_verify_signature(sig, sig_size, mvdata->digest);
210
211 _debug("verify-sig : %d\n", i);
212
213 if (i == 0)
214 i = 1;
215 else if (!signedonly)
216 i = 0;
217 return i;
218
219 format_error:
220 crypto_free_tfm(mvdata->digest);
221 if (!signedonly)
222 return 0;
223 return -ELIBBAD;
224
225
226 no_signature:
227 if (!signedonly)
228 return 0;
229 printk("An attempt to load unsigned module was rejected\n");
230 return -EPERM;
231
232}
233
234
235
236
237
238static int module_verify_canonicalise(struct module_verify_data *mvdata)
239{
240 int canon, loop, changed, tmp;
241
242
243
244
245 mvdata->canonlist =
246 kmalloc(sizeof(int) * mvdata->nsects * 2, GFP_KERNEL);
247 if (!mvdata->canonlist)
248 return -ENOMEM;
249
250 mvdata->canonmap = mvdata->canonlist + mvdata->nsects;
251 canon = 0;
252
253 for (loop = 1; loop < mvdata->nsects; loop++) {
254 const Elf_Shdr *section = mvdata->sections + loop;
255
256 if (loop != mvdata->sig_index) {
257
258 if (section->sh_flags & SHF_ALLOC)
259 mvdata->canonlist[canon++] = loop;
260 }
261 }
262
263
264 do {
265 changed = 0;
266
267 for (loop = 0; loop < canon - 1; loop++) {
268 const char *x, *y;
269
270 x = mvdata->secstrings +
271 mvdata->sections[mvdata->canonlist[loop + 0]].sh_name;
272 y = mvdata->secstrings +
273 mvdata->sections[mvdata->canonlist[loop + 1]].sh_name;
274
275 if (strcmp(x, y) > 0) {
276 tmp = mvdata->canonlist[loop + 0];
277 mvdata->canonlist[loop + 0] =
278 mvdata->canonlist[loop + 1];
279 mvdata->canonlist[loop + 1] = tmp;
280 changed = 1;
281 }
282 }
283
284 } while(changed);
285
286 for (loop = 0; loop < canon; loop++)
287 mvdata->canonmap[mvdata->canonlist[loop]] = loop + 1;
288
289 return 0;
290
291}
292
293
294
295
296
297
298
299static int extract_elf_rela(struct module_verify_data *mvdata,
300 int secix,
301 const Elf_Rela *relatab, size_t nrels,
302 const char *sh_name)
303{
304 struct {
305#if defined(MODULES_ARE_ELF32)
306 uint32_t r_offset;
307 uint32_t r_addend;
308 uint32_t st_value;
309 uint32_t st_size;
310 uint16_t st_shndx;
311 uint8_t r_type;
312 uint8_t st_info;
313 uint8_t st_other;
314#elif defined(MODULES_ARE_ELF64)
315 uint64_t r_offset;
316 uint64_t r_addend;
317 uint64_t st_value;
318 uint64_t st_size;
319 uint32_t r_type;
320 uint16_t st_shndx;
321 uint8_t st_info;
322 uint8_t st_other;
323#else
324#error unsupported module type
325#endif
326 } __attribute__((packed)) relocation;
327
328 const Elf_Rela *reloc;
329 const Elf_Sym *symbol;
330 size_t loop;
331
332
333 for (loop = 0; loop < nrels; loop++) {
334 int st_shndx;
335
336 reloc = &relatab[loop];
337
338
339 relocation.r_offset = reloc->r_offset;
340 relocation.r_addend = reloc->r_addend;
341 relocation.r_type = ELF_R_TYPE(reloc->r_info);
342
343
344 symbol = &mvdata->symbols[ELF_R_SYM(reloc->r_info)];
345 relocation.st_info = symbol->st_info;
346 relocation.st_other = symbol->st_other;
347 relocation.st_value = symbol->st_value;
348 relocation.st_size = symbol->st_size;
349 relocation.st_shndx = symbol->st_shndx;
350 st_shndx = symbol->st_shndx;
351
352
353 if (st_shndx > SHN_UNDEF && st_shndx < mvdata->nsects)
354 relocation.st_shndx = mvdata->canonmap[st_shndx];
355
356 crypto_digest_update_val(mvdata, relocation);
357
358
359 if (st_shndx == SHN_UNDEF) {
360 const char *name = mvdata->strings + symbol->st_name;
361 crypto_digest_update_data(mvdata,
362 name, strlen(name) + 1);
363 }
364 }
365
366 _debug("%08zx %02x digested the %s section, nrels %zu\n",
367 mvdata->signed_size, mvdata->csum, sh_name, nrels);
368
369 return 0;
370}
371
372
373
374
375
376static int extract_elf_rel(struct module_verify_data *mvdata,
377 int secix,
378 const Elf_Rel *reltab, size_t nrels,
379 const char *sh_name)
380{
381 struct {
382#if defined(MODULES_ARE_ELF32)
383 uint32_t r_offset;
384 uint32_t st_value;
385 uint32_t st_size;
386 uint16_t st_shndx;
387 uint8_t r_type;
388 uint8_t st_info;
389 uint8_t st_other;
390#elif defined(MODULES_ARE_ELF64)
391 uint64_t r_offset;
392 uint64_t st_value;
393 uint64_t st_size;
394 uint32_t r_type;
395 uint16_t st_shndx;
396 uint8_t st_info;
397 uint8_t st_other;
398#else
399#error unsupported module type
400#endif
401 } __attribute__((packed)) relocation;
402
403 const Elf_Rel *reloc;
404 const Elf_Sym *symbol;
405 size_t loop;
406
407
408 for (loop = 0; loop < nrels; loop++) {
409 int st_shndx;
410
411 reloc = &reltab[loop];
412
413
414 relocation.r_offset = reloc->r_offset;
415 relocation.r_type = ELF_R_TYPE(reloc->r_info);
416
417
418 symbol = &mvdata->symbols[ELF_R_SYM(reloc->r_info)];
419 relocation.st_info = symbol->st_info;
420 relocation.st_other = symbol->st_other;
421 relocation.st_value = symbol->st_value;
422 relocation.st_size = symbol->st_size;
423 relocation.st_shndx = symbol->st_shndx;
424 st_shndx = symbol->st_shndx;
425
426
427 if (st_shndx > SHN_UNDEF && st_shndx < mvdata->nsects)
428 relocation.st_shndx = mvdata->canonmap[st_shndx];
429
430 crypto_digest_update_val(mvdata, relocation);
431
432
433 if (st_shndx == SHN_UNDEF) {
434 const char *name = mvdata->strings + symbol->st_name;
435 crypto_digest_update_data(mvdata,
436 name, strlen(name) + 1);
437 }
438 }
439
440 _debug("%08zx %02x digested the %s section, nrels %zu\n",
441 mvdata->signed_size, mvdata->csum, sh_name, nrels);
442
443 return 0;
444}
445
446static int __init sign_setup(char *str)
447{
448 signedonly = 1;
449 return 0;
450}
451__setup("enforcemodulesig", sign_setup);
452