1 /* module-verify-elf.c: module ELF verifier
3 * Written by David Howells (dhowells@redhat.com)
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version
8 * 2 of the License, or (at your option) any later version.
11 #include <linux/kernel.h>
12 #include <linux/module.h>
13 #include <linux/slab.h>
14 #include <linux/elf.h>
15 #include "module-verify.h"
18 #define _debug(FMT, ...) printk(FMT, ##__VA_ARGS__)
20 #define _debug(FMT, ...) do {} while (0)
24 * verify the ELF structure of a module
26 int module_verify_elf(struct module_verify_data *mvdata)
28 const Elf_Ehdr *hdr = mvdata->hdr;
29 const Elf_Shdr *section, *section2, *secstop;
30 const Elf_Rela *relas, *rela, *relastop;
31 const Elf_Rel *rels, *rel, *relstop;
32 const Elf_Sym *symbol, *symstop;
33 size_t size, sssize, *secsize, tmp, tmp2;
38 mvdata->nsects = hdr->e_shnum;
41 do { if (unlikely(!(X))) { line = __LINE__; goto elfcheck_error; } } while(0)
44 do { if (unlikely(!(X))) { line = __LINE__; goto seccheck_error; } } while(0)
47 do { if (unlikely(!(X))) { line = __LINE__; goto symcheck_error; } } while(0)
50 do { if (unlikely(!(X))) { line = __LINE__; goto relcheck_error; } } while(0)
52 #define relacheck(X) \
53 do { if (unlikely(!(X))) { line = __LINE__; goto relacheck_error; } } while(0)
55 /* validate the ELF header */
56 elfcheck(hdr->e_ehsize < size);
57 elfcheck(hdr->e_entry == 0);
58 elfcheck(hdr->e_phoff == 0);
59 elfcheck(hdr->e_phnum == 0);
61 elfcheck(hdr->e_shnum < SHN_LORESERVE);
62 elfcheck(hdr->e_shoff < size);
63 elfcheck(hdr->e_shoff >= hdr->e_ehsize);
64 elfcheck((hdr->e_shoff & (sizeof(long) - 1)) == 0);
65 elfcheck(hdr->e_shstrndx > 0);
66 elfcheck(hdr->e_shstrndx < hdr->e_shnum);
67 elfcheck(hdr->e_shentsize == sizeof(Elf_Shdr));
69 tmp = (size_t) hdr->e_shentsize * (size_t) hdr->e_shnum;
70 elfcheck(tmp <= size - hdr->e_shoff);
72 /* allocate a table to hold in-file section sizes */
73 mvdata->secsizes = kcalloc(hdr->e_shnum, sizeof(size_t), GFP_KERNEL);
74 if (!mvdata->secsizes)
77 /* validate the ELF section headers */
78 mvdata->sections = mvdata->buffer + hdr->e_shoff;
79 secstop = mvdata->sections + mvdata->nsects;
81 sssize = mvdata->sections[hdr->e_shstrndx].sh_size;
84 section = mvdata->sections;
85 seccheck(section->sh_type == SHT_NULL);
86 seccheck(section->sh_size == 0);
87 seccheck(section->sh_offset == 0);
89 secsize = mvdata->secsizes + 1;
90 for (section++; section < secstop; secsize++, section++) {
91 seccheck(section->sh_name < sssize);
92 seccheck(section->sh_link < hdr->e_shnum);
94 if (section->sh_entsize > 0)
95 seccheck(section->sh_size % section->sh_entsize == 0);
97 seccheck(section->sh_offset >= hdr->e_ehsize);
98 seccheck(section->sh_offset < size);
100 /* determine the section's in-file size */
101 tmp = size - section->sh_offset;
102 if (section->sh_offset < hdr->e_shoff)
103 tmp = hdr->e_shoff - section->sh_offset;
105 for (section2 = mvdata->sections + 1;
108 if (section->sh_offset < section2->sh_offset) {
109 tmp2 = section2->sh_offset -
117 _debug("Section %ld: %zx bytes at %lx\n",
118 section - mvdata->sections,
120 (unsigned long) section->sh_offset);
122 /* perform section type specific checks */
123 switch (section->sh_type) {
128 seccheck(section->sh_entsize == sizeof(Elf_Rel));
129 goto more_rel_checks;
132 seccheck(section->sh_entsize == sizeof(Elf_Rela));
134 seccheck(section->sh_info > 0);
135 seccheck(section->sh_info < hdr->e_shnum);
136 goto more_sec_checks;
139 seccheck(section->sh_entsize == sizeof(Elf_Sym));
140 goto more_sec_checks;
144 /* most types of section must be contained entirely
146 seccheck(section->sh_size <= *secsize);
151 /* validate the ELF section names */
152 section = &mvdata->sections[hdr->e_shstrndx];
154 seccheck(section->sh_offset != hdr->e_shoff);
156 mvdata->secstrings = mvdata->buffer + section->sh_offset;
159 for (section = mvdata->sections + 1; section < secstop; section++) {
161 tmp = sssize - section->sh_name;
162 secname = mvdata->secstrings + section->sh_name;
163 seccheck(secname[0] != 0);
164 if (section->sh_name > last)
165 last = section->sh_name;
170 elfcheck(memchr(mvdata->secstrings + last, 0, tmp) != NULL);
173 /* look for various sections in the module */
174 for (section = mvdata->sections + 1; section < secstop; section++) {
175 switch (section->sh_type) {
177 if (strcmp(mvdata->secstrings + section->sh_name,
180 seccheck(mvdata->symbols == NULL);
182 mvdata->buffer + section->sh_offset;
184 section->sh_size / sizeof(Elf_Sym);
185 seccheck(section->sh_size > 0);
190 if (strcmp(mvdata->secstrings + section->sh_name,
193 seccheck(mvdata->strings == NULL);
195 mvdata->buffer + section->sh_offset;
196 sssize = mvdata->nstrings = section->sh_size;
197 seccheck(section->sh_size > 0);
203 if (!mvdata->symbols) {
204 printk("Couldn't locate module symbol table\n");
208 if (!mvdata->strings) {
209 printk("Couldn't locate module strings table\n");
213 /* validate the symbol table */
214 symstop = mvdata->symbols + mvdata->nsyms;
216 symbol = mvdata->symbols;
217 symcheck(ELF_ST_TYPE(symbol[0].st_info) == STT_NOTYPE);
218 symcheck(symbol[0].st_shndx == SHN_UNDEF);
219 symcheck(symbol[0].st_value == 0);
220 symcheck(symbol[0].st_size == 0);
223 for (symbol++; symbol < symstop; symbol++) {
224 symcheck(symbol->st_name < sssize);
225 if (symbol->st_name > last)
226 last = symbol->st_name;
227 symcheck(symbol->st_shndx < mvdata->nsects ||
228 symbol->st_shndx >= SHN_LORESERVE);
233 elfcheck(memchr(mvdata->strings + last, 0, tmp) != NULL);
236 /* validate each relocation table as best we can */
237 for (section = mvdata->sections + 1; section < secstop; section++) {
238 section2 = mvdata->sections + section->sh_info;
240 switch (section->sh_type) {
242 rels = mvdata->buffer + section->sh_offset;
243 relstop = mvdata->buffer +
244 section->sh_offset + section->sh_size;
246 for (rel = rels; rel < relstop; rel++) {
247 relcheck(rel->r_offset < section2->sh_size);
248 relcheck(ELF_R_SYM(rel->r_info) <
255 relas = mvdata->buffer + section->sh_offset;
256 relastop = mvdata->buffer +
257 section->sh_offset + section->sh_size;
259 for (rela = relas; rela < relastop; rela++) {
260 relacheck(rela->r_offset < section2->sh_size);
261 relacheck(ELF_R_SYM(rela->r_info) <
273 _debug("ELF okay\n");
277 printk("Verify ELF error (assertion %d)\n", line);
281 printk("Verify ELF error [sec %ld] (assertion %d)\n",
282 (long)(section - mvdata->sections), line);
286 printk("Verify ELF error [sym %ld] (assertion %d)\n",
287 (long)(symbol - mvdata->symbols), line);
291 printk("Verify ELF error [sec %ld rel %ld] (assertion %d)\n",
292 (long)(section - mvdata->sections),
293 (long)(rel - rels), line);
297 printk("Verify ELF error [sec %ld rela %ld] (assertion %d)\n",
298 (long)(section - mvdata->sections),
299 (long)(rela - relas), line);