Commit da0acd7c authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'modules-for-v5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/jeyu/linux

Pull module updates from Jessica Yu:
 "Summary of modules changes for the 5.3 merge window:

   - Code fixes and cleanups

   - Fix bug where set_memory_x() wasn't being called when rodata=n

   - Fix bug where -EEXIST was being returned for going modules

   - Allow arches to override module_exit_section()"

* tag 'modules-for-v5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/jeyu/linux:
  modules: fix compile error if don't have strict module rwx
  ARM: module: recognize unwind exit sections
  module: allow arch overrides for .exit section names
  modules: fix BUG when load module with rodata=n
  kernel/module: Fix mem leak in module_add_modinfo_attrs
  kernel: module: Use struct_size() helper
  kernel/module.c: Only return -EEXIST for modules that have finished loading
parents 818e95c7 93651f80
...@@ -55,6 +55,13 @@ void *module_alloc(unsigned long size) ...@@ -55,6 +55,13 @@ void *module_alloc(unsigned long size)
} }
#endif #endif
bool module_exit_section(const char *name)
{
return strstarts(name, ".exit") ||
strstarts(name, ".ARM.extab.exit") ||
strstarts(name, ".ARM.exidx.exit");
}
int int
apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
unsigned int relindex, struct module *module) unsigned int relindex, struct module *module)
......
...@@ -29,6 +29,11 @@ void *module_alloc(unsigned long size); ...@@ -29,6 +29,11 @@ void *module_alloc(unsigned long size);
/* Free memory returned from module_alloc. */ /* Free memory returned from module_alloc. */
void module_memfree(void *module_region); void module_memfree(void *module_region);
/* Determines if the section name is an exit section (that is only used during
* module unloading)
*/
bool module_exit_section(const char *name);
/* /*
* Apply the given relocation to the (simplified) ELF. Return -error * Apply the given relocation to the (simplified) ELF. Return -error
* or 0. * or 0.
......
...@@ -1492,8 +1492,7 @@ static void add_sect_attrs(struct module *mod, const struct load_info *info) ...@@ -1492,8 +1492,7 @@ static void add_sect_attrs(struct module *mod, const struct load_info *info)
for (i = 0; i < info->hdr->e_shnum; i++) for (i = 0; i < info->hdr->e_shnum; i++)
if (!sect_empty(&info->sechdrs[i])) if (!sect_empty(&info->sechdrs[i]))
nloaded++; nloaded++;
size[0] = ALIGN(sizeof(*sect_attrs) size[0] = ALIGN(struct_size(sect_attrs, attrs, nloaded),
+ nloaded * sizeof(sect_attrs->attrs[0]),
sizeof(sect_attrs->grp.attrs[0])); sizeof(sect_attrs->grp.attrs[0]));
size[1] = (nloaded + 1) * sizeof(sect_attrs->grp.attrs[0]); size[1] = (nloaded + 1) * sizeof(sect_attrs->grp.attrs[0]);
sect_attrs = kzalloc(size[0] + size[1], GFP_KERNEL); sect_attrs = kzalloc(size[0] + size[1], GFP_KERNEL);
...@@ -1697,6 +1696,8 @@ static int add_usage_links(struct module *mod) ...@@ -1697,6 +1696,8 @@ static int add_usage_links(struct module *mod)
return ret; return ret;
} }
static void module_remove_modinfo_attrs(struct module *mod, int end);
static int module_add_modinfo_attrs(struct module *mod) static int module_add_modinfo_attrs(struct module *mod)
{ {
struct module_attribute *attr; struct module_attribute *attr;
...@@ -1711,24 +1712,34 @@ static int module_add_modinfo_attrs(struct module *mod) ...@@ -1711,24 +1712,34 @@ static int module_add_modinfo_attrs(struct module *mod)
return -ENOMEM; return -ENOMEM;
temp_attr = mod->modinfo_attrs; temp_attr = mod->modinfo_attrs;
for (i = 0; (attr = modinfo_attrs[i]) && !error; i++) { for (i = 0; (attr = modinfo_attrs[i]); i++) {
if (!attr->test || attr->test(mod)) { if (!attr->test || attr->test(mod)) {
memcpy(temp_attr, attr, sizeof(*temp_attr)); memcpy(temp_attr, attr, sizeof(*temp_attr));
sysfs_attr_init(&temp_attr->attr); sysfs_attr_init(&temp_attr->attr);
error = sysfs_create_file(&mod->mkobj.kobj, error = sysfs_create_file(&mod->mkobj.kobj,
&temp_attr->attr); &temp_attr->attr);
if (error)
goto error_out;
++temp_attr; ++temp_attr;
} }
} }
return 0;
error_out:
if (i > 0)
module_remove_modinfo_attrs(mod, --i);
return error; return error;
} }
static void module_remove_modinfo_attrs(struct module *mod) static void module_remove_modinfo_attrs(struct module *mod, int end)
{ {
struct module_attribute *attr; struct module_attribute *attr;
int i; int i;
for (i = 0; (attr = &mod->modinfo_attrs[i]); i++) { for (i = 0; (attr = &mod->modinfo_attrs[i]); i++) {
if (end >= 0 && i > end)
break;
/* pick a field to test for end of list */ /* pick a field to test for end of list */
if (!attr->attr.name) if (!attr->attr.name)
break; break;
...@@ -1816,7 +1827,7 @@ static int mod_sysfs_setup(struct module *mod, ...@@ -1816,7 +1827,7 @@ static int mod_sysfs_setup(struct module *mod,
return 0; return 0;
out_unreg_modinfo_attrs: out_unreg_modinfo_attrs:
module_remove_modinfo_attrs(mod); module_remove_modinfo_attrs(mod, -1);
out_unreg_param: out_unreg_param:
module_param_sysfs_remove(mod); module_param_sysfs_remove(mod);
out_unreg_holders: out_unreg_holders:
...@@ -1852,7 +1863,7 @@ static void mod_sysfs_fini(struct module *mod) ...@@ -1852,7 +1863,7 @@ static void mod_sysfs_fini(struct module *mod)
{ {
} }
static void module_remove_modinfo_attrs(struct module *mod) static void module_remove_modinfo_attrs(struct module *mod, int end)
{ {
} }
...@@ -1868,14 +1879,14 @@ static void init_param_lock(struct module *mod) ...@@ -1868,14 +1879,14 @@ static void init_param_lock(struct module *mod)
static void mod_sysfs_teardown(struct module *mod) static void mod_sysfs_teardown(struct module *mod)
{ {
del_usage_links(mod); del_usage_links(mod);
module_remove_modinfo_attrs(mod); module_remove_modinfo_attrs(mod, -1);
module_param_sysfs_remove(mod); module_param_sysfs_remove(mod);
kobject_put(mod->mkobj.drivers_dir); kobject_put(mod->mkobj.drivers_dir);
kobject_put(mod->holders_dir); kobject_put(mod->holders_dir);
mod_sysfs_fini(mod); mod_sysfs_fini(mod);
} }
#ifdef CONFIG_STRICT_MODULE_RWX #ifdef CONFIG_ARCH_HAS_STRICT_MODULE_RWX
/* /*
* LKM RO/NX protection: protect module's text/ro-data * LKM RO/NX protection: protect module's text/ro-data
* from modification and any data from execution. * from modification and any data from execution.
...@@ -1898,6 +1909,7 @@ static void frob_text(const struct module_layout *layout, ...@@ -1898,6 +1909,7 @@ static void frob_text(const struct module_layout *layout,
layout->text_size >> PAGE_SHIFT); layout->text_size >> PAGE_SHIFT);
} }
#ifdef CONFIG_STRICT_MODULE_RWX
static void frob_rodata(const struct module_layout *layout, static void frob_rodata(const struct module_layout *layout,
int (*set_memory)(unsigned long start, int num_pages)) int (*set_memory)(unsigned long start, int num_pages))
{ {
...@@ -1949,13 +1961,9 @@ void module_enable_ro(const struct module *mod, bool after_init) ...@@ -1949,13 +1961,9 @@ void module_enable_ro(const struct module *mod, bool after_init)
set_vm_flush_reset_perms(mod->core_layout.base); set_vm_flush_reset_perms(mod->core_layout.base);
set_vm_flush_reset_perms(mod->init_layout.base); set_vm_flush_reset_perms(mod->init_layout.base);
frob_text(&mod->core_layout, set_memory_ro); frob_text(&mod->core_layout, set_memory_ro);
frob_text(&mod->core_layout, set_memory_x);
frob_rodata(&mod->core_layout, set_memory_ro); frob_rodata(&mod->core_layout, set_memory_ro);
frob_text(&mod->init_layout, set_memory_ro); frob_text(&mod->init_layout, set_memory_ro);
frob_text(&mod->init_layout, set_memory_x);
frob_rodata(&mod->init_layout, set_memory_ro); frob_rodata(&mod->init_layout, set_memory_ro);
if (after_init) if (after_init)
...@@ -2014,9 +2022,19 @@ void set_all_modules_text_ro(void) ...@@ -2014,9 +2022,19 @@ void set_all_modules_text_ro(void)
} }
mutex_unlock(&module_mutex); mutex_unlock(&module_mutex);
} }
#else #else /* !CONFIG_STRICT_MODULE_RWX */
static void module_enable_nx(const struct module *mod) { } static void module_enable_nx(const struct module *mod) { }
#endif #endif /* CONFIG_STRICT_MODULE_RWX */
static void module_enable_x(const struct module *mod)
{
frob_text(&mod->core_layout, set_memory_x);
frob_text(&mod->init_layout, set_memory_x);
}
#else /* !CONFIG_ARCH_HAS_STRICT_MODULE_RWX */
static void module_enable_nx(const struct module *mod) { }
static void module_enable_x(const struct module *mod) { }
#endif /* CONFIG_ARCH_HAS_STRICT_MODULE_RWX */
#ifdef CONFIG_LIVEPATCH #ifdef CONFIG_LIVEPATCH
/* /*
...@@ -2723,6 +2741,11 @@ void * __weak module_alloc(unsigned long size) ...@@ -2723,6 +2741,11 @@ void * __weak module_alloc(unsigned long size)
return vmalloc_exec(size); return vmalloc_exec(size);
} }
bool __weak module_exit_section(const char *name)
{
return strstarts(name, ".exit");
}
#ifdef CONFIG_DEBUG_KMEMLEAK #ifdef CONFIG_DEBUG_KMEMLEAK
static void kmemleak_load_module(const struct module *mod, static void kmemleak_load_module(const struct module *mod,
const struct load_info *info) const struct load_info *info)
...@@ -2912,7 +2935,7 @@ static int rewrite_section_headers(struct load_info *info, int flags) ...@@ -2912,7 +2935,7 @@ static int rewrite_section_headers(struct load_info *info, int flags)
#ifndef CONFIG_MODULE_UNLOAD #ifndef CONFIG_MODULE_UNLOAD
/* Don't load .exit sections */ /* Don't load .exit sections */
if (strstarts(info->secstrings+shdr->sh_name, ".exit")) if (module_exit_section(info->secstrings+shdr->sh_name))
shdr->sh_flags &= ~(unsigned long)SHF_ALLOC; shdr->sh_flags &= ~(unsigned long)SHF_ALLOC;
#endif #endif
} }
...@@ -3390,8 +3413,7 @@ static bool finished_loading(const char *name) ...@@ -3390,8 +3413,7 @@ static bool finished_loading(const char *name)
sched_annotate_sleep(); sched_annotate_sleep();
mutex_lock(&module_mutex); mutex_lock(&module_mutex);
mod = find_module_all(name, strlen(name), true); mod = find_module_all(name, strlen(name), true);
ret = !mod || mod->state == MODULE_STATE_LIVE ret = !mod || mod->state == MODULE_STATE_LIVE;
|| mod->state == MODULE_STATE_GOING;
mutex_unlock(&module_mutex); mutex_unlock(&module_mutex);
return ret; return ret;
...@@ -3581,8 +3603,7 @@ static int add_unformed_module(struct module *mod) ...@@ -3581,8 +3603,7 @@ static int add_unformed_module(struct module *mod)
mutex_lock(&module_mutex); mutex_lock(&module_mutex);
old = find_module_all(mod->name, strlen(mod->name), true); old = find_module_all(mod->name, strlen(mod->name), true);
if (old != NULL) { if (old != NULL) {
if (old->state == MODULE_STATE_COMING if (old->state != MODULE_STATE_LIVE) {
|| old->state == MODULE_STATE_UNFORMED) {
/* Wait in case it fails to load. */ /* Wait in case it fails to load. */
mutex_unlock(&module_mutex); mutex_unlock(&module_mutex);
err = wait_event_interruptible(module_wq, err = wait_event_interruptible(module_wq,
...@@ -3621,6 +3642,7 @@ static int complete_formation(struct module *mod, struct load_info *info) ...@@ -3621,6 +3642,7 @@ static int complete_formation(struct module *mod, struct load_info *info)
module_enable_ro(mod, false); module_enable_ro(mod, false);
module_enable_nx(mod); module_enable_nx(mod);
module_enable_x(mod);
/* Mark state as coming so strong_try_module_get() ignores us, /* Mark state as coming so strong_try_module_get() ignores us,
* but kallsyms etc. can see us. */ * but kallsyms etc. can see us. */
......
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