blob: 8c33deb1295897b57182daa9fc0aae9be5c0c231 [file] [log] [blame]
This patch get the symbol table size by visiting the ELF section header.
Previous it figures the symbol table size by assuming string table always
directly follows the symbol table, but this assumption does not hold for
LLD.
--- a/libsandbox/wrapper-funcs/__wrapper_exec.c
+++ b/libsandbox/wrapper-funcs/__wrapper_exec.c
@@ -83,11 +83,12 @@ static bool sb_check_exec(const char *fi
({ \
Elf##n##_Ehdr *ehdr = (void *)elf; \
Elf##n##_Phdr *phdr = (void *)(elf + ehdr->e_phoff); \
+ Elf##n##_Shdr *shdr = (void *)(elf + ehdr->e_shoff); \
Elf##n##_Addr vaddr, filesz, vsym = 0, vstr = 0, vhash = 0; \
Elf##n##_Off offset, symoff = 0, stroff = 0, hashoff = 0; \
Elf##n##_Dyn *dyn; \
Elf##n##_Sym *sym, *symend; \
- uint##n##_t ent_size = 0, str_size = 0; \
+ uint##n##_t ent_size = 0, str_size = 0, sym_table_size = 0; \
bool dynamic = false; \
size_t i; \
\
@@ -114,6 +115,13 @@ static bool sb_check_exec(const char *fi
} \
} \
\
+ for (i = 0; i < ehdr->e_shnum; ++i) { \
+ if (shdr[i].sh_type == SHT_DYNSYM) { \
+ sym_table_size = shdr[i].sh_size; \
+ break; \
+ } \
+ }\
+ \
if (dynamic && vsym && ent_size && vstr && str_size) { \
/* Figure out where in the file these tables live. */ \
for (i = 0; i < ehdr->e_phnum; ++i) { \
@@ -136,16 +144,13 @@ static bool sb_check_exec(const char *fi
/* Hash entries are always 32-bits. */ \
uint32_t *hashes = (void *)(elf + hashoff); \
/* Nowhere is the # of symbols recorded, or the size of the symbol \
- * table. Instead, we do what glibc does: use the sysv hash table \
- * if it exists, else assume that the string table always directly \
- * follows the symbol table. This seems like a poor assumption to \
- * make, but glibc has gotten by this long. \
+ * table. Get the symbol table size by accessing the section headers. \
* \
* We don't sanity check the ranges here as you aren't executing \
* corrupt programs in the sandbox. \
*/ \
sym = (void *)(elf + symoff); \
- symend = vhash ? (sym + hashes[1]) : (void *)(elf + stroff); \
+ symend = vhash ? (sym + hashes[1]) : (void *)(elf + symoff + sym_table_size); \
while (sym < symend) { \
char *symname = (void *)(elf + stroff + sym->st_name); \
if (ELF##n##_ST_VISIBILITY(sym->st_other) == STV_DEFAULT && \