aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Robinson <andr345@gmail.com>2009-05-14 10:28:22 +0200
committerAndreas Robinson <andr345@gmail.com>2009-05-15 14:36:56 +0200
commit49724cc9c9ea30d802a45d88adbcefabf6059f08 (patch)
tree40aff86556d581bc3862dcaef2e8a34b4523e38a
parent7fb32e459c9f6d1c2e21713f9f024a03e31a93ed (diff)
downloadmodule-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.c15
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,