summaryrefslogtreecommitdiff
path: root/arch/s390/mm/pageattr.c
diff options
context:
space:
mode:
authorJan Glauber <jang@linux.vnet.ibm.com>2011-03-15 16:08:22 (GMT)
committerMartin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com>2011-03-15 16:08:23 (GMT)
commit305b1523250faf9675919def94906775992ce52d (patch)
tree2dcbe253cf463eca3c0dfcc9ee8ac7b97cfa5021 /arch/s390/mm/pageattr.c
parentd54cddb620fa493968111f479029dcd910fcb921 (diff)
downloadlinux-305b1523250faf9675919def94906775992ce52d.tar.xz
[S390] Write protect module text and RO data
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>
Diffstat (limited to 'arch/s390/mm/pageattr.c')
-rw-r--r--arch/s390/mm/pageattr.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/arch/s390/mm/pageattr.c b/arch/s390/mm/pageattr.c
new file mode 100644
index 0000000..122ffbd
--- /dev/null
+++ b/arch/s390/mm/pageattr.c
@@ -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);