Commit 055f23b7 authored by Jessica Yu's avatar Jessica Yu

module: check for exit sections in layout_sections() instead of module_init_section()

Previously, when CONFIG_MODULE_UNLOAD=n, the module loader just does not
attempt to load exit sections since it never expects that any code in those
sections will ever execute. However, dynamic code patching (alternatives,
jump_label and static_call) can have sites in __exit code, even if __exit is
never executed. Therefore __exit must be present at runtime, at least for as
long as __init code is.

Commit 33121347 ("module: treat exit sections the same as init
sections when !CONFIG_MODULE_UNLOAD") solves the requirements of
jump_labels and static_calls by putting the exit sections in the init
region of the module so that they are at least present at init, and
discarded afterwards. It does this by including a check for exit
sections in module_init_section(), so that it also returns true for exit
sections, and the module loader will automatically sort them in the init
region of the module.

However, the solution there was not completely arch-independent. ARM is
a special case where it supplies its own module_{init, exit}_section()
functions. Instead of pushing the exit section checks into
module_init_section(), just implement the exit section check in
layout_sections(), so that we don't have to touch arch-dependent code.

Fixes: 33121347 ("module: treat exit sections the same as init sections when !CONFIG_MODULE_UNLOAD")
Reviewed-by: default avatarRussell King (Oracle) <rmk+kernel@armlinux.org.uk>
Signed-off-by: default avatarJessica Yu <jeyu@kernel.org>
parent 6efb943b
...@@ -2401,6 +2401,15 @@ static long get_offset(struct module *mod, unsigned int *size, ...@@ -2401,6 +2401,15 @@ static long get_offset(struct module *mod, unsigned int *size,
return ret; return ret;
} }
static bool module_init_layout_section(const char *sname)
{
#ifndef CONFIG_MODULE_UNLOAD
if (module_exit_section(sname))
return true;
#endif
return module_init_section(sname);
}
/* /*
* Lay out the SHF_ALLOC sections in a way not dissimilar to how ld * Lay out the SHF_ALLOC sections in a way not dissimilar to how ld
* might -- code, read-only data, read-write data, small data. Tally * might -- code, read-only data, read-write data, small data. Tally
...@@ -2435,7 +2444,7 @@ static void layout_sections(struct module *mod, struct load_info *info) ...@@ -2435,7 +2444,7 @@ static void layout_sections(struct module *mod, struct load_info *info)
if ((s->sh_flags & masks[m][0]) != masks[m][0] if ((s->sh_flags & masks[m][0]) != masks[m][0]
|| (s->sh_flags & masks[m][1]) || (s->sh_flags & masks[m][1])
|| s->sh_entsize != ~0UL || s->sh_entsize != ~0UL
|| module_init_section(sname)) || module_init_layout_section(sname))
continue; continue;
s->sh_entsize = get_offset(mod, &mod->core_layout.size, s, i); s->sh_entsize = get_offset(mod, &mod->core_layout.size, s, i);
pr_debug("\t%s\n", sname); pr_debug("\t%s\n", sname);
...@@ -2468,7 +2477,7 @@ static void layout_sections(struct module *mod, struct load_info *info) ...@@ -2468,7 +2477,7 @@ static void layout_sections(struct module *mod, struct load_info *info)
if ((s->sh_flags & masks[m][0]) != masks[m][0] if ((s->sh_flags & masks[m][0]) != masks[m][0]
|| (s->sh_flags & masks[m][1]) || (s->sh_flags & masks[m][1])
|| s->sh_entsize != ~0UL || s->sh_entsize != ~0UL
|| !module_init_section(sname)) || !module_init_layout_section(sname))
continue; continue;
s->sh_entsize = (get_offset(mod, &mod->init_layout.size, s, i) s->sh_entsize = (get_offset(mod, &mod->init_layout.size, s, i)
| INIT_OFFSET_MASK); | INIT_OFFSET_MASK);
...@@ -2807,11 +2816,7 @@ void * __weak module_alloc(unsigned long size) ...@@ -2807,11 +2816,7 @@ void * __weak module_alloc(unsigned long size)
bool __weak module_init_section(const char *name) bool __weak module_init_section(const char *name)
{ {
#ifndef CONFIG_MODULE_UNLOAD
return strstarts(name, ".init") || module_exit_section(name);
#else
return strstarts(name, ".init"); return strstarts(name, ".init");
#endif
} }
bool __weak module_exit_section(const char *name) bool __weak module_exit_section(const char *name)
......
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