summaryrefslogtreecommitdiff
path: root/kernel/module.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/module.c')
-rw-r--r--kernel/module.c18
1 files changed, 12 insertions, 6 deletions
diff --git a/kernel/module.c b/kernel/module.c
index 1d8410b0569f..f9ee37c95dbe 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -592,14 +592,17 @@ static void *copy_section(const char *name,
{
void *dest;
unsigned long *use;
+ unsigned long max;
/* Only copy to init section if there is one */
if (strstr(name, ".init") && mod->module_init) {
dest = mod->module_init;
use = &used->init_size;
+ max = mod->init_size;
} else {
dest = mod->module_core;
use = &used->core_size;
+ max = mod->core_size;
}
/* Align up */
@@ -607,6 +610,9 @@ static void *copy_section(const char *name,
dest += *use;
*use += sechdr->sh_size;
+ if (*use > max)
+ return ERR_PTR(-ENOEXEC);
+
/* May not actually be in the file (eg. bss). */
if (sechdr->sh_type != SHT_NOBITS)
memcpy(dest, base + sechdr->sh_offset, sechdr->sh_size);
@@ -773,9 +779,10 @@ static void simplify_symbols(Elf_Shdr *sechdrs,
/* Get the total allocation size of the init and non-init sections */
static struct sizes get_sizes(const Elf_Ehdr *hdr,
const Elf_Shdr *sechdrs,
- const char *secstrings)
+ const char *secstrings,
+ unsigned long common_length)
{
- struct sizes ret = { 0, 0 };
+ struct sizes ret = { 0, common_length };
unsigned i;
/* Everything marked ALLOC (this includes the exported
@@ -933,10 +940,9 @@ static struct module *load_module(void *umod,
mod->live = 0;
module_unload_init(mod);
- /* How much space will we need? (Common area in core) */
- sizes = get_sizes(hdr, sechdrs, secstrings);
+ /* How much space will we need? (Common area in first) */
common_length = read_commons(hdr, &sechdrs[symindex]);
- sizes.core_size += common_length;
+ sizes = get_sizes(hdr, sechdrs, secstrings, common_length);
/* Set these up, and allow archs to manipulate them. */
mod->core_size = sizes.core_size;
@@ -963,7 +969,7 @@ static struct module *load_module(void *umod,
mod->module_core = ptr;
ptr = module_alloc(mod->init_size);
- if (!ptr) {
+ if (!ptr && mod->init_size) {
err = -ENOMEM;
goto free_core;
}