Commit 82fab442 authored by Rusty Russell's avatar Rusty Russell

modules: don't hand 0 to vmalloc.

In commit d0a21265 David Rientjes unified various archs'
module_alloc implementation (including x86) and removed the graduitous
shortcut for size == 0.

Then, in commit de7d2b56, Joe Perches added a warning for
zero-length vmallocs, which can happen without kallsyms on modules
with no init sections (eg. zlib_deflate).

Fix this once and for all; the module code has to handle zero length
anyway, so get it right at the caller and remove the now-gratuitous
checks within the arch-specific module_alloc implementations.

Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=42608Reported-by: default avatarConrad Kostecki <ConiKost@gmx.de>
Cc: David Rientjes <rientjes@google.com>
Cc: Joe Perches <joe@perches.com>
Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent 54523ec7
...@@ -32,8 +32,6 @@ ...@@ -32,8 +32,6 @@
#ifdef CONFIG_ETRAX_KMALLOCED_MODULES #ifdef CONFIG_ETRAX_KMALLOCED_MODULES
void *module_alloc(unsigned long size) void *module_alloc(unsigned long size)
{ {
if (size == 0)
return NULL;
return kmalloc(size, GFP_KERNEL); return kmalloc(size, GFP_KERNEL);
} }
......
...@@ -214,8 +214,6 @@ static inline int reassemble_22(int as22) ...@@ -214,8 +214,6 @@ static inline int reassemble_22(int as22)
void *module_alloc(unsigned long size) void *module_alloc(unsigned long size)
{ {
if (size == 0)
return NULL;
/* using RWX means less protection for modules, but it's /* using RWX means less protection for modules, but it's
* easier than trying to map the text, data, init_text and * easier than trying to map the text, data, init_text and
* init_data correctly */ * init_data correctly */
......
...@@ -43,10 +43,6 @@ void *module_alloc(unsigned long size) ...@@ -43,10 +43,6 @@ void *module_alloc(unsigned long size)
{ {
void *ret; void *ret;
/* We handle the zero case fine, unlike vmalloc */
if (size == 0)
return NULL;
ret = module_map(size); ret = module_map(size);
if (ret) if (ret)
memset(ret, 0, size); memset(ret, 0, size);
......
...@@ -42,8 +42,6 @@ void *module_alloc(unsigned long size) ...@@ -42,8 +42,6 @@ void *module_alloc(unsigned long size)
int i = 0; int i = 0;
int npages; int npages;
if (size == 0)
return NULL;
npages = (size + PAGE_SIZE - 1) / PAGE_SIZE; npages = (size + PAGE_SIZE - 1) / PAGE_SIZE;
pages = kmalloc(npages * sizeof(struct page *), GFP_KERNEL); pages = kmalloc(npages * sizeof(struct page *), GFP_KERNEL);
if (pages == NULL) if (pages == NULL)
......
...@@ -27,9 +27,6 @@ void *module_alloc(unsigned long size) ...@@ -27,9 +27,6 @@ void *module_alloc(unsigned long size)
struct vm_struct *area; struct vm_struct *area;
size = PAGE_ALIGN(size); size = PAGE_ALIGN(size);
if (!size)
return NULL;
area = __get_vm_area(size, VM_ALLOC, MODULES_VADDR, MODULES_END); area = __get_vm_area(size, VM_ALLOC, MODULES_VADDR, MODULES_END);
if (!area) if (!area)
return NULL; return NULL;
......
...@@ -2377,7 +2377,7 @@ static void dynamic_debug_remove(struct _ddebug *debug) ...@@ -2377,7 +2377,7 @@ static void dynamic_debug_remove(struct _ddebug *debug)
void * __weak module_alloc(unsigned long size) void * __weak module_alloc(unsigned long size)
{ {
return size == 0 ? NULL : vmalloc_exec(size); return vmalloc_exec(size);
} }
static void *module_alloc_update_bounds(unsigned long size) static void *module_alloc_update_bounds(unsigned long size)
...@@ -2793,20 +2793,23 @@ static int move_module(struct module *mod, struct load_info *info) ...@@ -2793,20 +2793,23 @@ static int move_module(struct module *mod, struct load_info *info)
memset(ptr, 0, mod->core_size); memset(ptr, 0, mod->core_size);
mod->module_core = ptr; mod->module_core = ptr;
ptr = module_alloc_update_bounds(mod->init_size); if (mod->init_size) {
/* ptr = module_alloc_update_bounds(mod->init_size);
* The pointer to this block is stored in the module structure /*
* which is inside the block. This block doesn't need to be * The pointer to this block is stored in the module structure
* scanned as it contains data and code that will be freed * which is inside the block. This block doesn't need to be
* after the module is initialized. * scanned as it contains data and code that will be freed
*/ * after the module is initialized.
kmemleak_ignore(ptr); */
if (!ptr && mod->init_size) { kmemleak_ignore(ptr);
module_free(mod, mod->module_core); if (!ptr) {
return -ENOMEM; module_free(mod, mod->module_core);
} return -ENOMEM;
memset(ptr, 0, mod->init_size); }
mod->module_init = ptr; memset(ptr, 0, mod->init_size);
mod->module_init = ptr;
} else
mod->module_init = NULL;
/* Transfer each section which specifies SHF_ALLOC */ /* Transfer each section which specifies SHF_ALLOC */
pr_debug("final section addresses:\n"); pr_debug("final section addresses:\n");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment