]> git.karo-electronics.de Git - mv-sheeva.git/commitdiff
[S390] Write protect module text and RO data
authorJan Glauber <jang@linux.vnet.ibm.com>
Tue, 15 Mar 2011 16:08:22 +0000 (17:08 +0100)
committerMartin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com>
Tue, 15 Mar 2011 16:08:23 +0000 (17:08 +0100)
Implement write protection for kernel modules text and read-only
data sections by implementing set_memory_[ro|rw] on s390.
Since s390 has no execute bit in the pte's NX is not supported.

set_memory_[ro|rw] will only work on normal pages and not on
large pages, so in case a large page should be modified bail
out with a warning.

Signed-off-by: Jan Glauber <jang@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/Kconfig.debug
arch/s390/include/asm/cacheflush.h
arch/s390/mm/Makefile
arch/s390/mm/pageattr.c [new file with mode: 0644]

index 2b380df95606f02a927b7566c41b6efedf3f4169..d76cef3fef37bac6f3df5ad6d336a30cdfc8233f 100644 (file)
@@ -31,4 +31,7 @@ config DEBUG_STRICT_USER_COPY_CHECKS
 
          If unsure, or if you run an older (pre 4.4) gcc, say N.
 
+config DEBUG_SET_MODULE_RONX
+       def_bool y
+       depends on MODULES
 endmenu
index 7e1f776206248033025a1bd50779acd5be1225c6..43a5c78046db6cd918939607ae1cd6f7db0ee4e9 100644 (file)
@@ -8,4 +8,8 @@
 void kernel_map_pages(struct page *page, int numpages, int enable);
 #endif
 
+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);
+
 #endif /* _S390_CACHEFLUSH_H */
index 6fbc6f3fbdf276f90b21cf9b15e200086171b737..d98fe9004a524b8e4f11a4de5e099e56103beddf 100644 (file)
@@ -6,3 +6,4 @@ obj-y    := init.o fault.o extmem.o mmap.o vmem.o pgtable.o maccess.o \
            page-states.o gup.o
 obj-$(CONFIG_CMM) += cmm.o
 obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
+obj-$(CONFIG_DEBUG_SET_MODULE_RONX) += pageattr.o
diff --git a/arch/s390/mm/pageattr.c b/arch/s390/mm/pageattr.c
new file mode 100644 (file)
index 0000000..122ffbd
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright IBM Corp. 2011
+ * Author(s): Jan Glauber <jang@linux.vnet.ibm.com>
+ */
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/hugetlb.h>
+#include <asm/pgtable.h>
+
+static void change_page_attr(unsigned long addr, int numpages,
+                            pte_t (*set) (pte_t))
+{
+       pte_t *ptep, pte;
+       pmd_t *pmdp;
+       pud_t *pudp;
+       pgd_t *pgdp;
+       int i;
+
+       for (i = 0; i < numpages; i++) {
+               pgdp = pgd_offset(&init_mm, addr);
+               pudp = pud_offset(pgdp, addr);
+               pmdp = pmd_offset(pudp, addr);
+               if (pmd_huge(*pmdp)) {
+                       WARN_ON_ONCE(1);
+                       continue;
+               }
+               ptep = pte_offset_kernel(pmdp, addr + i * PAGE_SIZE);
+
+               pte = *ptep;
+               pte = set(pte);
+               ptep_invalidate(&init_mm, addr + i * PAGE_SIZE, ptep);
+               *ptep = pte;
+       }
+}
+
+int set_memory_ro(unsigned long addr, int numpages)
+{
+       change_page_attr(addr, numpages, pte_wrprotect);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(set_memory_ro);
+
+int set_memory_rw(unsigned long addr, int numpages)
+{
+       change_page_attr(addr, numpages, pte_mkwrite);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(set_memory_rw);
+
+/* not possible */
+int set_memory_nx(unsigned long addr, int numpages)
+{
+       return 0;
+}
+EXPORT_SYMBOL_GPL(set_memory_nx);