aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/module.c
diff options
context:
space:
mode:
authorJan Glauber <jang@linux.vnet.ibm.com>2011-05-19 18:55:26 -0400
committerRusty Russell <rusty@rustcorp.com.au>2011-05-19 03:25:26 -0400
commit448694a1d50432be63aafccb42d6f54d8cf3d02c (patch)
treebd066b7cdb04e8bdc61efdeaa0e358269f185f7e /kernel/module.c
parent4d10380e720a3ce19dbe88d0133f66ded07b6a8f (diff)
module: undo module RONX protection correctly.
While debugging I stumbled over two problems in the code that protects module pages. First issue is that disabling the protection before freeing init or unload of a module is not symmetric with the enablement. For instance, if pages are set to RO the page range from module_core to module_core + core_ro_size is protected. If a module is unloaded the page range from module_core to module_core + core_size is set back to RW. So pages that were not set to RO are also changed to RW. This is not critical but IMHO it should be symmetric. Second issue is that while set_memory_rw & set_memory_ro are used for RO/RW changes only set_memory_nx is involved for NX/X. One would await that the inverse function is called when the NX protection should be removed, which is not the case here, unless I'm missing something. Signed-off-by: Jan Glauber <jang@linux.vnet.ibm.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'kernel/module.c')
-rw-r--r--kernel/module.c25
1 files changed, 13 insertions, 12 deletions
diff --git a/kernel/module.c b/kernel/module.c
index 92112c91b7e..b99dcebc980 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -1607,22 +1607,23 @@ static void set_section_ro_nx(void *base,
1607 } 1607 }
1608} 1608}
1609 1609
1610/* Setting memory back to RW+NX before releasing it */ 1610/* Setting memory back to W+X before releasing it */
1611void unset_section_ro_nx(struct module *mod, void *module_region) 1611void unset_section_ro_nx(struct module *mod, void *module_region)
1612{ 1612{
1613 unsigned long total_pages;
1614
1615 if (mod->module_core == module_region) { 1613 if (mod->module_core == module_region) {
1616 /* Set core as NX+RW */ 1614 set_page_attributes(mod->module_core + mod->core_text_size,
1617 total_pages = MOD_NUMBER_OF_PAGES(mod->module_core, mod->core_size); 1615 mod->module_core + mod->core_size,
1618 set_memory_nx((unsigned long)mod->module_core, total_pages); 1616 set_memory_x);
1619 set_memory_rw((unsigned long)mod->module_core, total_pages); 1617 set_page_attributes(mod->module_core,
1620 1618 mod->module_core + mod->core_ro_size,
1619 set_memory_rw);
1621 } else if (mod->module_init == module_region) { 1620 } else if (mod->module_init == module_region) {
1622 /* Set init as NX+RW */ 1621 set_page_attributes(mod->module_init + mod->init_text_size,
1623 total_pages = MOD_NUMBER_OF_PAGES(mod->module_init, mod->init_size); 1622 mod->module_init + mod->init_size,
1624 set_memory_nx((unsigned long)mod->module_init, total_pages); 1623 set_memory_x);
1625 set_memory_rw((unsigned long)mod->module_init, total_pages); 1624 set_page_attributes(mod->module_init,
1625 mod->module_init + mod->init_ro_size,
1626 set_memory_rw);
1626 } 1627 }
1627} 1628}
1628 1629