Check elf section fits into memory and fail elf2b() on elf handling errors

This commit is contained in:
Stefan Rueger 2022-12-02 18:28:19 +00:00
parent 3b30e5d424
commit 2e98ee3a1c
No known key found for this signature in database
GPG Key ID: B0B4F1FD86B1EC55
1 changed files with 22 additions and 13 deletions

View File

@ -772,7 +772,7 @@ static int elf2b(const char *infile, FILE *inf,
int bufsize, unsigned int fileoffset) int bufsize, unsigned int fileoffset)
{ {
Elf *e; Elf *e;
int rv = -1; int rv = 0, size = 0;
unsigned int low, high, foff; unsigned int low, high, foff;
if (elf_mem_limits(mem, p, &low, &high, &foff) != 0) { if (elf_mem_limits(mem, p, &low, &high, &foff) != 0) {
@ -897,6 +897,7 @@ static int elf2b(const char *infile, FILE *inf,
if (sh == NULL) { if (sh == NULL) {
pmsg_error("unable to read section #%u header: %s\n", (unsigned int) ndx, elf_errmsg(-1)); pmsg_error("unable to read section #%u header: %s\n", (unsigned int) ndx, elf_errmsg(-1));
rv = -1;
continue; continue;
} }
// Only interested in PROGBITS, ALLOC sections // Only interested in PROGBITS, ALLOC sections
@ -927,8 +928,9 @@ static int elf2b(const char *infile, FILE *inf,
* from it, using the "foff" offset obtained above. * from it, using the "foff" offset obtained above.
*/ */
if (mem->size != 1 && sh->sh_size > (unsigned) mem->size) { if (mem->size != 1 && sh->sh_size > (unsigned) mem->size) {
pmsg_error("section %s does not fit into %s memory:\n" pmsg_error("section %s of size %u does not fit into %s of size %d\n",
" 0x%x + %u > %u\n", sname, mem->desc, lma, sh->sh_size, mem->size); sname, sh->sh_size, mem->desc, mem->size);
rv = -1;
continue; continue;
} }
@ -939,31 +941,38 @@ static int elf2b(const char *infile, FILE *inf,
if (mem->size == 1) { if (mem->size == 1) {
if (d->d_off != 0) { if (d->d_off != 0) {
pmsg_error("unexpected data block at offset != 0\n"); pmsg_error("unexpected data block at offset != 0\n");
rv = -1;
} else if (foff >= d->d_size) { } else if (foff >= d->d_size) {
pmsg_error("ELF file section does not contain byte at offset %d\n", foff); pmsg_error("ELF file section does not contain byte at offset %d\n", foff);
rv = -1;
} else { } else {
msg_notice2(" Extracting one byte from file offset %d\n", foff); msg_notice2(" Extracting one byte from file offset %d\n", foff);
mem->buf[0] = ((unsigned char *)d->d_buf)[foff]; mem->buf[0] = ((unsigned char *)d->d_buf)[foff];
mem->tags[0] = TAG_ALLOCATED; mem->tags[0] = TAG_ALLOCATED;
rv = 1; size = 1;
} }
} else { } else {
unsigned int idx; int idx = lma-low + d->d_off;
int end = idx + d->d_size;
idx = lma - low + d->d_off; if(idx >= 0 && idx < mem->size && end >= 0 && end <= mem->size && end-idx >= 0) {
if ((int)(idx + d->d_size) > rv) if (end > size)
rv = idx + d->d_size; size = end;
msg_debug(" Writing %ld bytes to mem offset 0x%x\n", imsg_debug("writing %d bytes to mem offset 0x%x\n", end-idx, idx);
(long) d->d_size, idx); memcpy(mem->buf + idx, d->d_buf, end-idx);
memcpy(mem->buf + idx, d->d_buf, d->d_size); memset(mem->tags + idx, TAG_ALLOCATED, end-idx);
memset(mem->tags + idx, TAG_ALLOCATED, d->d_size); } else {
pmsg_error("section %s [0x%04x, 0x%04x] does not fit into %s [0, 0x%04x]\n",
sname, idx, (int) (idx + d->d_size-1), mem->desc, mem->size-1);
rv = -1;
}
} }
} }
} }
} }
done: done:
(void)elf_end(e); (void)elf_end(e);
return rv; return rv<0? rv: size;
} }
#endif /* HAVE_LIBELF */ #endif /* HAVE_LIBELF */