1 /*
2 * Copyright (C) 2016 Citrix Systems R&D Ltd.
3 */
4
5 #include <xen/errno.h>
6 #include <xen/lib.h>
7 #include <xen/symbols.h>
8 #include <xen/livepatch_elf.h>
9 #include <xen/livepatch.h>
10
11 const struct livepatch_elf_sec *
livepatch_elf_sec_by_name(const struct livepatch_elf * elf,const char * name)12 livepatch_elf_sec_by_name(const struct livepatch_elf *elf,
13 const char *name)
14 {
15 unsigned int i;
16
17 for ( i = 1; i < elf->hdr->e_shnum; i++ )
18 {
19 if ( !strcmp(name, elf->sec[i].name) )
20 return &elf->sec[i];
21 }
22
23 return NULL;
24 }
25
elf_verify_strtab(const struct livepatch_elf_sec * sec)26 static int elf_verify_strtab(const struct livepatch_elf_sec *sec)
27 {
28 const Elf_Shdr *s;
29 const char *contents;
30
31 s = sec->sec;
32
33 if ( s->sh_type != SHT_STRTAB )
34 return -EINVAL;
35
36 if ( !s->sh_size )
37 return -EINVAL;
38
39 contents = sec->addr;
40
41 if ( contents[0] || contents[s->sh_size - 1] )
42 return -EINVAL;
43
44 return 0;
45 }
46
elf_resolve_sections(struct livepatch_elf * elf,void * data)47 static int elf_resolve_sections(struct livepatch_elf *elf, void *data)
48 {
49 struct livepatch_elf_sec *sec;
50 unsigned int i;
51 Elf_Off delta;
52 int rc;
53
54 /* livepatch_elf_load sanity checked e_shnum. */
55 sec = xzalloc_array(struct livepatch_elf_sec, elf->hdr->e_shnum);
56 if ( !sec )
57 {
58 printk(XENLOG_ERR LIVEPATCH"%s: Could not allocate memory for section table\n",
59 elf->name);
60 return -ENOMEM;
61 }
62
63 elf->sec = sec;
64
65 /* e_shoff and e_shnum overflow checks are done in livepatch_header_check. */
66 delta = elf->hdr->e_shoff + elf->hdr->e_shnum * elf->hdr->e_shentsize;
67 ASSERT(delta <= elf->len);
68
69 for ( i = 1; i < elf->hdr->e_shnum; i++ )
70 {
71 delta = elf->hdr->e_shoff + i * elf->hdr->e_shentsize;
72
73 sec[i].sec = data + delta;
74
75 delta = sec[i].sec->sh_offset;
76 /*
77 * N.B. elf_resolve_section_names, elf_get_sym skip this check as
78 * we do it here.
79 */
80 if ( delta < sizeof(Elf_Ehdr) ||
81 (sec[i].sec->sh_type != SHT_NOBITS && /* Skip SHT_NOBITS */
82 (delta > elf->len || (delta + sec[i].sec->sh_size > elf->len))) )
83 {
84 printk(XENLOG_ERR LIVEPATCH "%s: Section [%u] data %s of payload\n",
85 elf->name, i,
86 delta < sizeof(Elf_Ehdr) ? "at ELF header" : "is past end");
87 return -EINVAL;
88 }
89 else if ( sec[i].sec->sh_addralign & (sec[i].sec->sh_addralign - 1) )
90 {
91 printk(XENLOG_ERR LIVEPATCH "%s: Section [%u] alignment (%#"PRIxElfAddr") is not supported\n",
92 elf->name, i, sec[i].sec->sh_addralign);
93 return -EOPNOTSUPP;
94 }
95 else if ( sec[i].sec->sh_addralign &&
96 sec[i].sec->sh_addr % sec[i].sec->sh_addralign )
97 {
98 printk(XENLOG_ERR LIVEPATCH "%s: Section [%u] addr (%#"PRIxElfAddr") is not aligned properly (%#"PRIxElfAddr")\n",
99 elf->name, i, sec[i].sec->sh_addr, sec[i].sec->sh_addralign);
100 return -EINVAL;
101 }
102 else if ( (sec[i].sec->sh_flags & (SHF_WRITE | SHF_ALLOC)) &&
103 sec[i].sec->sh_type == SHT_NOBITS &&
104 sec[i].sec->sh_size > LIVEPATCH_MAX_SIZE )
105 return -EINVAL;
106
107 sec[i].addr = data + delta;
108 /* Name is populated in elf_resolve_section_names. */
109 sec[i].name = NULL;
110
111 if ( sec[i].sec->sh_type == SHT_SYMTAB )
112 {
113 if ( elf->symtab )
114 {
115 printk(XENLOG_ERR LIVEPATCH "%s: Unsupported multiple symbol tables\n",
116 elf->name);
117 return -EOPNOTSUPP;
118 }
119
120 elf->symtab = &sec[i];
121
122 elf->symtab_idx = i;
123 /*
124 * elf->symtab->sec->sh_link would point to the right section
125 * but we hadn't finished parsing all the sections.
126 */
127 if ( elf->symtab->sec->sh_link >= elf->hdr->e_shnum )
128 {
129 printk(XENLOG_ERR LIVEPATCH
130 "%s: Symbol table idx (%u) to strtab past end (%u)\n",
131 elf->name, elf->symtab->sec->sh_link,
132 elf->hdr->e_shnum);
133 return -EINVAL;
134 }
135 }
136 }
137
138 if ( !elf->symtab )
139 {
140 printk(XENLOG_ERR LIVEPATCH "%s: No symbol table found\n",
141 elf->name);
142 return -EINVAL;
143 }
144
145 if ( !elf->symtab->sec->sh_size ||
146 elf->symtab->sec->sh_entsize < sizeof(Elf_Sym) ||
147 elf->symtab->sec->sh_size % elf->symtab->sec->sh_entsize )
148 {
149 printk(XENLOG_ERR LIVEPATCH "%s: Symbol table header is corrupted\n",
150 elf->name);
151 return -EINVAL;
152 }
153
154 /*
155 * There can be multiple SHT_STRTAB (.shstrtab, .strtab) so pick the one
156 * associated with the symbol table.
157 */
158 elf->strtab = &sec[elf->symtab->sec->sh_link];
159
160 rc = elf_verify_strtab(elf->strtab);
161 if ( rc )
162 {
163 printk(XENLOG_ERR LIVEPATCH "%s: String table section is corrupted\n",
164 elf->name);
165 }
166
167 return rc;
168 }
169
elf_resolve_section_names(struct livepatch_elf * elf,const void * data)170 static int elf_resolve_section_names(struct livepatch_elf *elf, const void *data)
171 {
172 const char *shstrtab;
173 unsigned int i;
174 Elf_Off offset, delta;
175 struct livepatch_elf_sec *sec;
176 int rc;
177
178 /*
179 * The elf->sec[0 -> e_shnum] structures have been verified by
180 * elf_resolve_sections. Find file offset for section string table
181 * (normally called .shstrtab)
182 */
183 sec = &elf->sec[elf->hdr->e_shstrndx];
184
185 rc = elf_verify_strtab(sec);
186 if ( rc )
187 {
188 printk(XENLOG_ERR LIVEPATCH "%s: Section string table is corrupted\n",
189 elf->name);
190 return rc;
191 }
192
193 /* Verified in elf_resolve_sections but just in case. */
194 offset = sec->sec->sh_offset;
195 ASSERT(offset < elf->len && (offset + sec->sec->sh_size <= elf->len));
196
197 shstrtab = data + offset;
198
199 for ( i = 1; i < elf->hdr->e_shnum; i++ )
200 {
201 delta = elf->sec[i].sec->sh_name;
202
203 /* Boundary check on offset of name within the .shstrtab. */
204 if ( delta >= sec->sec->sh_size )
205 {
206 printk(XENLOG_ERR LIVEPATCH "%s: Section %u name is not within .shstrtab\n",
207 elf->name, i);
208 return -EINVAL;
209 }
210
211 elf->sec[i].name = shstrtab + delta;
212 }
213
214 return 0;
215 }
216
elf_get_sym(struct livepatch_elf * elf,const void * data)217 static int elf_get_sym(struct livepatch_elf *elf, const void *data)
218 {
219 const struct livepatch_elf_sec *symtab_sec, *strtab_sec;
220 struct livepatch_elf_sym *sym;
221 unsigned int i, nsym;
222 Elf_Off offset;
223 Elf_Word delta;
224
225 symtab_sec = elf->symtab;
226 strtab_sec = elf->strtab;
227
228 /* Pointers arithmetic to get file offset. */
229 offset = strtab_sec->addr - data;
230
231 /* Checked already in elf_resolve_sections, but just in case. */
232 ASSERT(offset == strtab_sec->sec->sh_offset);
233 ASSERT(offset < elf->len && (offset + strtab_sec->sec->sh_size <= elf->len));
234
235 /* symtab_sec->addr was computed in elf_resolve_sections. */
236 ASSERT((symtab_sec->sec->sh_offset + data) == symtab_sec->addr);
237
238 /* No need to check values as elf_resolve_sections did it. */
239 nsym = symtab_sec->sec->sh_size / symtab_sec->sec->sh_entsize;
240
241 sym = xzalloc_array(struct livepatch_elf_sym, nsym);
242 if ( !sym )
243 {
244 printk(XENLOG_ERR LIVEPATCH "%s: Could not allocate memory for symbols\n",
245 elf->name);
246 return -ENOMEM;
247 }
248
249 /* So we don't leak memory. */
250 elf->sym = sym;
251
252 for ( i = 1; i < nsym; i++ )
253 {
254 const Elf_Sym *s = symtab_sec->addr + symtab_sec->sec->sh_entsize * i;
255
256 delta = s->st_name;
257 /* Boundary check within the .strtab. */
258 if ( delta >= strtab_sec->sec->sh_size )
259 {
260 printk(XENLOG_ERR LIVEPATCH "%s: Symbol [%u] name is not within .strtab\n",
261 elf->name, i);
262 return -EINVAL;
263 }
264
265 sym[i].sym = s;
266 sym[i].name = strtab_sec->addr + delta;
267 if ( arch_livepatch_symbol_deny(elf, &sym[i]) )
268 {
269 printk(XENLOG_ERR LIVEPATCH "%s: Symbol '%s' should not be in payload\n",
270 elf->name, sym[i].name);
271 return -EINVAL;
272 }
273 }
274 elf->nsym = nsym;
275
276 return 0;
277 }
278
livepatch_elf_resolve_symbols(struct livepatch_elf * elf)279 int livepatch_elf_resolve_symbols(struct livepatch_elf *elf)
280 {
281 unsigned int i;
282 int rc = 0;
283
284 ASSERT(elf->sym);
285
286 for ( i = 1; i < elf->nsym; i++ )
287 {
288 unsigned int idx = elf->sym[i].sym->st_shndx;
289 const Elf_Sym *sym = elf->sym[i].sym;
290 Elf_Addr st_value = sym->st_value;
291
292 switch ( idx )
293 {
294 case SHN_COMMON:
295 printk(XENLOG_ERR LIVEPATCH "%s: Unexpected common symbol: %s\n",
296 elf->name, elf->sym[i].name);
297 rc = -EINVAL;
298 break;
299
300 case SHN_UNDEF:
301 st_value = symbols_lookup_by_name(elf->sym[i].name);
302 if ( !st_value )
303 {
304 st_value = livepatch_symbols_lookup_by_name(elf->sym[i].name);
305 if ( !st_value )
306 {
307 printk(XENLOG_ERR LIVEPATCH "%s: Unknown symbol: %s\n",
308 elf->name, elf->sym[i].name);
309 rc = -ENOENT;
310 break;
311 }
312 }
313 dprintk(XENLOG_DEBUG, LIVEPATCH "%s: Undefined symbol resolved: %s => %#"PRIxElfAddr"\n",
314 elf->name, elf->sym[i].name, st_value);
315 break;
316
317 case SHN_ABS:
318 dprintk(XENLOG_DEBUG, LIVEPATCH "%s: Absolute symbol: %s => %#"PRIxElfAddr"\n",
319 elf->name, elf->sym[i].name, sym->st_value);
320 break;
321
322 default:
323 /* SHN_COMMON and SHN_ABS are above. */
324 if ( idx >= SHN_LORESERVE )
325 rc = -EOPNOTSUPP;
326 else if ( idx >= elf->hdr->e_shnum )
327 rc = -EINVAL;
328
329 if ( rc )
330 {
331 printk(XENLOG_ERR LIVEPATCH "%s: Out of bounds symbol section %#x\n",
332 elf->name, idx);
333 break;
334 }
335
336 if ( livepatch_elf_ignore_section(elf->sec[idx].sec) )
337 {
338 dprintk(XENLOG_DEBUG, LIVEPATCH
339 "%s: Symbol %s from section %s ignored\n",
340 elf->name, elf->sym[i].name, elf->sec[idx].name);
341 elf->sym[i].ignored = true;
342 break;
343 }
344
345 st_value += (unsigned long)elf->sec[idx].addr;
346 if ( elf->sym[i].name )
347 dprintk(XENLOG_DEBUG, LIVEPATCH "%s: Symbol resolved: %s => %#"PRIxElfAddr" (%s)\n",
348 elf->name, elf->sym[i].name,
349 st_value, elf->sec[idx].name);
350 }
351
352 if ( rc )
353 break;
354
355 ((Elf_Sym *)sym)->st_value = st_value;
356 }
357
358 return rc;
359 }
360
livepatch_elf_perform_relocs(struct livepatch_elf * elf)361 int livepatch_elf_perform_relocs(struct livepatch_elf *elf)
362 {
363 struct livepatch_elf_sec *r, *base;
364 unsigned int i;
365 int rc = 0;
366 size_t sz;
367
368 ASSERT(elf->sym);
369
370 for ( i = 1; i < elf->hdr->e_shnum; i++ )
371 {
372 r = &elf->sec[i];
373
374 if ( (r->sec->sh_type != SHT_RELA) &&
375 (r->sec->sh_type != SHT_REL) )
376 continue;
377
378 /* Is it a valid relocation section? */
379 if ( r->sec->sh_info >= elf->hdr->e_shnum )
380 continue;
381
382 base = &elf->sec[r->sec->sh_info];
383
384 /* Don't relocate non-allocated sections. */
385 if ( !(base->sec->sh_flags & SHF_ALLOC) )
386 continue;
387
388 if ( r->sec->sh_link != elf->symtab_idx )
389 {
390 printk(XENLOG_ERR LIVEPATCH "%s: Relative link of %s is incorrect (%d, expected=%d)\n",
391 elf->name, r->name, r->sec->sh_link, elf->symtab_idx);
392 rc = -EINVAL;
393 break;
394 }
395
396 if ( r->sec->sh_type == SHT_RELA )
397 sz = sizeof(Elf_RelA);
398 else
399 sz = sizeof(Elf_Rel);
400
401 if ( !r->sec->sh_size )
402 continue;
403
404 if ( r->sec->sh_entsize < sz || r->sec->sh_size % r->sec->sh_entsize )
405 {
406 printk(XENLOG_ERR LIVEPATCH "%s: Section relative header is corrupted\n",
407 elf->name);
408 rc = -EINVAL;
409 break;
410 }
411
412 if ( r->sec->sh_type == SHT_RELA )
413 rc = arch_livepatch_perform_rela(elf, base, r);
414 else /* SHT_REL */
415 rc = arch_livepatch_perform_rel(elf, base, r);
416
417 if ( rc )
418 break;
419 }
420
421 return rc;
422 }
423
livepatch_header_check(const struct livepatch_elf * elf)424 static int livepatch_header_check(const struct livepatch_elf *elf)
425 {
426 const Elf_Ehdr *hdr = elf->hdr;
427 int rc;
428
429 if ( sizeof(*elf->hdr) > elf->len )
430 {
431 printk(XENLOG_ERR LIVEPATCH "%s: Section header is bigger than payload\n",
432 elf->name);
433 return -EINVAL;
434 }
435
436 if ( !IS_ELF(*hdr) )
437 {
438 printk(XENLOG_ERR LIVEPATCH "%s: Not an ELF payload\n", elf->name);
439 return -EINVAL;
440 }
441
442 /* EI_CLASS, EI_DATA, and e_flags are platform specific. */
443 if ( hdr->e_version != EV_CURRENT ||
444 hdr->e_ident[EI_VERSION] != EV_CURRENT ||
445 hdr->e_ident[EI_ABIVERSION] != 0 ||
446 (hdr->e_ident[EI_OSABI] != ELFOSABI_NONE &&
447 hdr->e_ident[EI_OSABI] != ELFOSABI_FREEBSD) ||
448 hdr->e_type != ET_REL ||
449 hdr->e_phnum != 0 )
450 {
451 printk(XENLOG_ERR LIVEPATCH "%s: Invalid ELF payload\n", elf->name);
452 return -EOPNOTSUPP;
453 }
454
455 rc = arch_livepatch_verify_elf(elf);
456 if ( rc )
457 return rc;
458
459 if ( elf->hdr->e_shstrndx == SHN_UNDEF )
460 {
461 printk(XENLOG_ERR LIVEPATCH "%s: Section name idx is undefined\n",
462 elf->name);
463 return -EINVAL;
464 }
465
466 /* Arbitrary boundary limit. */
467 if ( elf->hdr->e_shnum >= 1024 )
468 {
469 printk(XENLOG_ERR LIVEPATCH "%s: Too many (%u) sections\n",
470 elf->name, elf->hdr->e_shnum);
471 return -EOPNOTSUPP;
472 }
473
474 /* Check that section name index is within the sections. */
475 if ( elf->hdr->e_shstrndx >= elf->hdr->e_shnum )
476 {
477 printk(XENLOG_ERR LIVEPATCH "%s: Section name idx (%u) is past end of sections (%u)\n",
478 elf->name, elf->hdr->e_shstrndx, elf->hdr->e_shnum);
479 return -EINVAL;
480 }
481
482 if ( elf->hdr->e_shoff >= elf->len )
483 {
484 printk(XENLOG_ERR LIVEPATCH "%s: Bogus e_shoff\n", elf->name);
485 return -EINVAL;
486 }
487
488 if ( elf->hdr->e_shentsize < sizeof(Elf_Shdr) )
489 {
490 printk(XENLOG_ERR LIVEPATCH "%s: Section header size is %u! Expected %zu.\n",
491 elf->name, elf->hdr->e_shentsize, sizeof(Elf_Shdr));
492 return -EINVAL;
493 }
494
495 if ( ((elf->len - elf->hdr->e_shoff) / elf->hdr->e_shentsize) <
496 elf->hdr->e_shnum )
497 {
498 printk(XENLOG_ERR LIVEPATCH "%s: Section header size is corrupted\n",
499 elf->name);
500 return -EINVAL;
501 }
502
503 return 0;
504 }
505
livepatch_elf_load(struct livepatch_elf * elf,void * data)506 int livepatch_elf_load(struct livepatch_elf *elf, void *data)
507 {
508 int rc;
509
510 elf->hdr = data;
511
512 rc = livepatch_header_check(elf);
513 if ( rc )
514 return rc;
515
516 rc = elf_resolve_sections(elf, data);
517 if ( rc )
518 return rc;
519
520 rc = elf_resolve_section_names(elf, data);
521 if ( rc )
522 return rc;
523
524 rc = elf_get_sym(elf, data);
525 if ( rc )
526 return rc;
527
528 return 0;
529 }
530
livepatch_elf_free(struct livepatch_elf * elf)531 void livepatch_elf_free(struct livepatch_elf *elf)
532 {
533 xfree(elf->sec);
534 elf->sec = NULL;
535 xfree(elf->sym);
536 elf->sym = NULL;
537 elf->nsym = 0;
538 elf->name = NULL;
539 elf->len = 0;
540 }
541
542 /*
543 * Local variables:
544 * mode: C
545 * c-file-style: "BSD"
546 * c-basic-offset: 4
547 * tab-width: 4
548 * indent-tabs-mode: nil
549 * End:
550 */
551