module: undo module RONX protection correctly.
authorJan Glauber <jang@linux.vnet.ibm.com>
Thu, 19 May 2011 22:55:26 +0000 (16:55 -0600)
committerRusty Russell <rusty@rustcorp.com.au>
Thu, 19 May 2011 07:25:26 +0000 (16:55 +0930)
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>
arch/s390/include/asm/cacheflush.h
arch/s390/mm/pageattr.c
kernel/module.c

index 43a5c78046db6cd918939607ae1cd6f7db0ee4e9..3e20383d09219f8bbbe26ddd731e362870e9676a 100644 (file)
@@ -11,5 +11,6 @@ void kernel_map_pages(struct page *page, int numpages, int enable);
 int set_memory_ro(unsigned long addr, int numpages);
 int set_memory_rw(unsigned long addr, int numpages);
 int set_memory_nx(unsigned long addr, int numpages);
+int set_memory_x(unsigned long addr, int numpages);
 
 #endif /* _S390_CACHEFLUSH_H */
index 0607e4b14b2742798e36b957c7f17e1451bc0bf0..f05edcc3beff42c53cae96eb1850001915ff5bbc 100644 (file)
@@ -54,3 +54,8 @@ int set_memory_nx(unsigned long addr, int numpages)
        return 0;
 }
 EXPORT_SYMBOL_GPL(set_memory_nx);
+
+int set_memory_x(unsigned long addr, int numpages)
+{
+       return 0;
+}
index 92112c91b7e90b35d527dbacfd261c9ed61944f6..b99dcebc980d035d97e354f967500cbe2f905107 100644 (file)
@@ -1607,22 +1607,23 @@ static void set_section_ro_nx(void *base,
        }
 }
 
-/* Setting memory back to RW+NX before releasing it */
+/* Setting memory back to W+X before releasing it */
 void unset_section_ro_nx(struct module *mod, void *module_region)
 {
-       unsigned long total_pages;
-
        if (mod->module_core == module_region) {
-               /* Set core as NX+RW */
-               total_pages = MOD_NUMBER_OF_PAGES(mod->module_core, mod->core_size);
-               set_memory_nx((unsigned long)mod->module_core, total_pages);
-               set_memory_rw((unsigned long)mod->module_core, total_pages);
-
+               set_page_attributes(mod->module_core + mod->core_text_size,
+                       mod->module_core + mod->core_size,
+                       set_memory_x);
+               set_page_attributes(mod->module_core,
+                       mod->module_core + mod->core_ro_size,
+                       set_memory_rw);
        } else if (mod->module_init == module_region) {
-               /* Set init as NX+RW */
-               total_pages = MOD_NUMBER_OF_PAGES(mod->module_init, mod->init_size);
-               set_memory_nx((unsigned long)mod->module_init, total_pages);
-               set_memory_rw((unsigned long)mod->module_init, total_pages);
+               set_page_attributes(mod->module_init + mod->init_text_size,
+                       mod->module_init + mod->init_size,
+                       set_memory_x);
+               set_page_attributes(mod->module_init,
+                       mod->module_init + mod->init_ro_size,
+                       set_memory_rw);
        }
 }