diff options
author | Andreas Robinson <andr345@gmail.com> | 2009-05-14 10:28:22 +0200 |
---|---|---|
committer | Andreas Robinson <andr345@gmail.com> | 2009-05-15 14:36:56 +0200 |
commit | 49724cc9c9ea30d802a45d88adbcefabf6059f08 (patch) | |
tree | 40aff86556d581bc3862dcaef2e8a34b4523e38a | |
parent | 7fb32e459c9f6d1c2e21713f9f024a03e31a93ed (diff) | |
download | module-init-tools-49724cc9c9ea30d802a45d88adbcefabf6059f08.tar.gz |
elfops: add strict bounds checking to get/load_section()
get_section() and load_section() now return NULL if a section header
is corrupt and points to a block that lies partially or entirely
outside the file data buffer.
Signed-off-by: Andreas Robinson <andr345@gmail.com>
-rw-r--r-- | elfops_core.c | 15 |
1 files changed, 10 insertions, 5 deletions
diff --git a/elfops_core.c b/elfops_core.c index 0b6596a..ec314df 100644 --- a/elfops_core.c +++ b/elfops_core.c @@ -24,11 +24,12 @@ void *PERBIT(get_section)(void *file, ElfPERBIT(Shdr) *sechdrs; ElfPERBIT(Off) e_shoff; ElfPERBIT(Half) e_shnum, e_shstrndx; + ElfPERBIT(Off) secoffset; const char *secnames; unsigned int i; - if (fsize > 0 && fsize < sizeof(*hdr)) + if (fsize <= 0 || fsize < sizeof(*hdr)) return NULL; hdr = file; @@ -36,12 +37,12 @@ void *PERBIT(get_section)(void *file, e_shnum = END(hdr->e_shnum, conv); e_shstrndx = END(hdr->e_shstrndx, conv); - if (fsize > 0 && fsize < e_shoff + e_shnum * sizeof(sechdrs[0])) + if (fsize < e_shoff + e_shnum * sizeof(sechdrs[0])) return NULL; sechdrs = file + e_shoff; - if (fsize > 0 && fsize < END(sechdrs[e_shstrndx].sh_offset, conv)) + if (fsize < END(sechdrs[e_shstrndx].sh_offset, conv)) return NULL; /* Find section by name, return pointer and size. */ @@ -50,7 +51,10 @@ void *PERBIT(get_section)(void *file, for (i = 1; i < e_shnum; i++) { if (streq(secnames + END(sechdrs[i].sh_name, conv), secname)) { *secsize = END(sechdrs[i].sh_size, conv); - return file + END(sechdrs[i].sh_offset, conv); + secoffset = END(sechdrs[i].sh_offset, conv); + if (fsize < secoffset + *secsize) + return NULL; + return file + secoffset; } } *secsize = 0; @@ -62,7 +66,8 @@ static void *PERBIT(load_section)(struct elf_file *module, const char *secname, unsigned long *secsize) { - return PERBIT(get_section)(module->data, 0, secname, secsize, module->conv); + return PERBIT(get_section)(module->data, module->len, + secname, secsize, module->conv); } static struct string_table *PERBIT(load_strings)(struct elf_file *module, |