Check for overflow when getting symbol name.
If there is a malformed elf with a particularly large st_name value,
then an overflow can occur. Check for this condition and ignore the
symbols that would cause an overflow.
Bug: 21162746
(cherry picked from commit 14de40d95372863fff4f460fb7e128404d87f8f4)
Change-Id: Icf44695b83b8371e176b9f303e43a182bd7bed4e
diff --git a/src/elfxx.c b/src/elfxx.c
index 8f185a8..ec30239 100644
--- a/src/elfxx.c
+++ b/src/elfxx.c
@@ -208,24 +208,27 @@
if (ip >= val && (Elf_W(Addr)) (ip - val) < sym.st_size) {
GET_SYM_FIELD(ei, sym_offset, &sym, st_name);
uintptr_t size = ei->u.memory.map->end - ei->u.memory.map->start;
- if (strtab_offset + sym.st_name > size) {
+ Elf_W(Off) strname_offset = strtab_offset + sym.st_name;
+ if (strname_offset > size || strname_offset < strtab_offset) {
// Malformed elf symbol table.
break;
}
size_t bytes_read = elf_w (memory_read) (
- ei, ei->u.memory.map->start + strtab_offset + sym.st_name,
+ ei, ei->u.memory.map->start + strname_offset,
(uint8_t*) buf, buf_len, true);
if (bytes_read == 0) {
// Empty name, so keep checking the other symbol tables
// for a possible match.
break;
}
+ // Ensure the string is nul terminated, it is assumed that
+ // sizeof(buf) >= buf_len + 1.
+ buf[buf_len] = '\0';
+
if (offp != NULL) {
*offp = ip - val;
}
- // Ensure the string is nul terminated.
- buf[buf_len] = '\0';
return true;
}
}
@@ -343,19 +346,23 @@
}
Debug (16, "0x%016lx info=0x%02x\n", (long) val, sym->st_info);
if (ip >= val && (Elf_W(Addr)) (ip - val) < sym->st_size) {
- if (strtab + sym->st_name > (char*) ei->u.mapped.image + ei->u.mapped.size) {
+ char* str_name = strtab + sym->st_name;
+ if (str_name > (char*) ei->u.mapped.image + ei->u.mapped.size ||
+ str_name < strtab) {
// Malformed elf symbol table.
break;
}
// Make sure we don't try and read past the end of the image.
- uintptr_t max_size = (uintptr_t) (strtab + sym->st_name)
- - (uintptr_t) ei->u.mapped.image;
+ uintptr_t max_size = (uintptr_t) str_name - (uintptr_t) ei->u.mapped.image;
if (buf_len > max_size) {
buf_len = max_size;
}
- strncpy (buf, strtab + sym->st_name, buf_len);
+ strncpy (buf, str_name, buf_len);
+ // Ensure the string is nul terminated, it is assumed that
+ // sizeof(buf) >= buf_len + 1.
+ buf[buf_len] = '\0';
if (buf[0] == '\0') {
// Empty name, so keep checking the other symbol tables
// for a possible match.
@@ -364,8 +371,6 @@
if (offp != NULL) {
*offp = ip - val;
}
- // Ensure the string is nul terminated.
- buf[buf_len] = '\0';
return true;
}
}