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->data;
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,const void * data)47 static int elf_resolve_sections(struct livepatch_elf *elf, const 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].data = 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->data - 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->data was computed in elf_resolve_sections. */
236 ASSERT((symtab_sec->sec->sh_offset + data) == symtab_sec->data);
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->data + 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->data + 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 break;
338
339 st_value += (unsigned long)elf->sec[idx].load_addr;
340 if ( elf->sym[i].name )
341 dprintk(XENLOG_DEBUG, LIVEPATCH "%s: Symbol resolved: %s => %#"PRIxElfAddr" (%s)\n",
342 elf->name, elf->sym[i].name,
343 st_value, elf->sec[idx].name);
344 }
345
346 if ( rc )
347 break;
348
349 ((Elf_Sym *)sym)->st_value = st_value;
350 }
351
352 return rc;
353 }
354
livepatch_elf_perform_relocs(struct livepatch_elf * elf)355 int livepatch_elf_perform_relocs(struct livepatch_elf *elf)
356 {
357 struct livepatch_elf_sec *r, *base;
358 unsigned int i;
359 int rc = 0;
360 size_t sz;
361
362 ASSERT(elf->sym);
363
364 for ( i = 1; i < elf->hdr->e_shnum; i++ )
365 {
366 r = &elf->sec[i];
367
368 if ( (r->sec->sh_type != SHT_RELA) &&
369 (r->sec->sh_type != SHT_REL) )
370 continue;
371
372 /* Is it a valid relocation section? */
373 if ( r->sec->sh_info >= elf->hdr->e_shnum )
374 continue;
375
376 base = &elf->sec[r->sec->sh_info];
377
378 /* Don't relocate non-allocated sections. */
379 if ( !(base->sec->sh_flags & SHF_ALLOC) )
380 continue;
381
382 if ( r->sec->sh_link != elf->symtab_idx )
383 {
384 printk(XENLOG_ERR LIVEPATCH "%s: Relative link of %s is incorrect (%d, expected=%d)\n",
385 elf->name, r->name, r->sec->sh_link, elf->symtab_idx);
386 rc = -EINVAL;
387 break;
388 }
389
390 if ( r->sec->sh_type == SHT_RELA )
391 sz = sizeof(Elf_RelA);
392 else
393 sz = sizeof(Elf_Rel);
394
395 if ( !r->sec->sh_size )
396 continue;
397
398 if ( r->sec->sh_entsize < sz || r->sec->sh_size % r->sec->sh_entsize )
399 {
400 printk(XENLOG_ERR LIVEPATCH "%s: Section relative header is corrupted\n",
401 elf->name);
402 rc = -EINVAL;
403 break;
404 }
405
406 if ( r->sec->sh_type == SHT_RELA )
407 rc = arch_livepatch_perform_rela(elf, base, r);
408 else /* SHT_REL */
409 rc = arch_livepatch_perform_rel(elf, base, r);
410
411 if ( rc )
412 break;
413 }
414
415 return rc;
416 }
417
livepatch_header_check(const struct livepatch_elf * elf)418 static int livepatch_header_check(const struct livepatch_elf *elf)
419 {
420 const Elf_Ehdr *hdr = elf->hdr;
421 int rc;
422
423 if ( sizeof(*elf->hdr) > elf->len )
424 {
425 printk(XENLOG_ERR LIVEPATCH "%s: Section header is bigger than payload\n",
426 elf->name);
427 return -EINVAL;
428 }
429
430 if ( !IS_ELF(*hdr) )
431 {
432 printk(XENLOG_ERR LIVEPATCH "%s: Not an ELF payload\n", elf->name);
433 return -EINVAL;
434 }
435
436 /* EI_CLASS, EI_DATA, and e_flags are platform specific. */
437 if ( hdr->e_version != EV_CURRENT ||
438 hdr->e_ident[EI_VERSION] != EV_CURRENT ||
439 hdr->e_ident[EI_ABIVERSION] != 0 ||
440 (hdr->e_ident[EI_OSABI] != ELFOSABI_NONE &&
441 hdr->e_ident[EI_OSABI] != ELFOSABI_FREEBSD) ||
442 hdr->e_type != ET_REL ||
443 hdr->e_phnum != 0 )
444 {
445 printk(XENLOG_ERR LIVEPATCH "%s: Invalid ELF payload\n", elf->name);
446 return -EOPNOTSUPP;
447 }
448
449 rc = arch_livepatch_verify_elf(elf);
450 if ( rc )
451 return rc;
452
453 if ( elf->hdr->e_shstrndx == SHN_UNDEF )
454 {
455 printk(XENLOG_ERR LIVEPATCH "%s: Section name idx is undefined\n",
456 elf->name);
457 return -EINVAL;
458 }
459
460 /* Arbitrary boundary limit. */
461 if ( elf->hdr->e_shnum >= 1024 )
462 {
463 printk(XENLOG_ERR LIVEPATCH "%s: Too many (%u) sections\n",
464 elf->name, elf->hdr->e_shnum);
465 return -EOPNOTSUPP;
466 }
467
468 /* Check that section name index is within the sections. */
469 if ( elf->hdr->e_shstrndx >= elf->hdr->e_shnum )
470 {
471 printk(XENLOG_ERR LIVEPATCH "%s: Section name idx (%u) is past end of sections (%u)\n",
472 elf->name, elf->hdr->e_shstrndx, elf->hdr->e_shnum);
473 return -EINVAL;
474 }
475
476 if ( elf->hdr->e_shoff >= elf->len )
477 {
478 printk(XENLOG_ERR LIVEPATCH "%s: Bogus e_shoff\n", elf->name);
479 return -EINVAL;
480 }
481
482 if ( elf->hdr->e_shentsize < sizeof(Elf_Shdr) )
483 {
484 printk(XENLOG_ERR LIVEPATCH "%s: Section header size is %u! Expected %zu.\n",
485 elf->name, elf->hdr->e_shentsize, sizeof(Elf_Shdr));
486 return -EINVAL;
487 }
488
489 if ( ((elf->len - elf->hdr->e_shoff) / elf->hdr->e_shentsize) <
490 elf->hdr->e_shnum )
491 {
492 printk(XENLOG_ERR LIVEPATCH "%s: Section header size is corrupted\n",
493 elf->name);
494 return -EINVAL;
495 }
496
497 return 0;
498 }
499
livepatch_elf_load(struct livepatch_elf * elf,const void * data)500 int livepatch_elf_load(struct livepatch_elf *elf, const void *data)
501 {
502 int rc;
503
504 elf->hdr = data;
505
506 rc = livepatch_header_check(elf);
507 if ( rc )
508 return rc;
509
510 rc = elf_resolve_sections(elf, data);
511 if ( rc )
512 return rc;
513
514 rc = elf_resolve_section_names(elf, data);
515 if ( rc )
516 return rc;
517
518 rc = elf_get_sym(elf, data);
519 if ( rc )
520 return rc;
521
522 return 0;
523 }
524
livepatch_elf_free(struct livepatch_elf * elf)525 void livepatch_elf_free(struct livepatch_elf *elf)
526 {
527 xfree(elf->sec);
528 elf->sec = NULL;
529 xfree(elf->sym);
530 elf->sym = NULL;
531 elf->nsym = 0;
532 elf->name = NULL;
533 elf->len = 0;
534 }
535
536 /*
537 * Local variables:
538 * mode: C
539 * c-file-style: "BSD"
540 * c-basic-offset: 4
541 * tab-width: 4
542 * indent-tabs-mode: nil
543 * End:
544 */
545