aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/mm
diff options
context:
space:
mode:
authorJan Glauber <jang@linux.vnet.ibm.com>2011-03-15 12:08:22 -0400
committerMartin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com>2011-03-15 12:08:23 -0400
commit305b1523250faf9675919def94906775992ce52d (patch)
tree2dcbe253cf463eca3c0dfcc9ee8ac7b97cfa5021 /arch/s390/mm
parentd54cddb620fa493968111f479029dcd910fcb921 (diff)
[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')
-rw-r--r--arch/s390/mm/Makefile1
-rw-r--r--arch/s390/mm/pageattr.c55
2 files changed, 56 insertions, 0 deletions
diff --git a/arch/s390/mm/Makefile b/arch/s390/mm/Makefile
index 6fbc6f3fbdf..d98fe9004a5 100644
--- a/arch/s390/mm/Makefile
+++ b/arch/s390/mm/Makefile
@@ -6,3 +6,4 @@ obj-y := init.o fault.o extmem.o mmap.o vmem.o pgtable.o maccess.o \
6 page-states.o gup.o 6 page-states.o gup.o
7obj-$(CONFIG_CMM) += cmm.o 7obj-$(CONFIG_CMM) += cmm.o
8obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o 8obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
9obj-$(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
index 00000000000..122ffbd08ce
--- /dev/null
+++ b/arch/s390/mm/pageattr.c
@@ -0,0 +1,55 @@
1/*
2 * Copyright IBM Corp. 2011
3 * Author(s): Jan Glauber <jang@linux.vnet.ibm.com>
4 */
5#include <linux/module.h>
6#include <linux/mm.h>
7#include <linux/hugetlb.h>
8#include <asm/pgtable.h>
9
10static void change_page_attr(unsigned long addr, int numpages,
11 pte_t (*set) (pte_t))
12{
13 pte_t *ptep, pte;
14 pmd_t *pmdp;
15 pud_t *pudp;
16 pgd_t *pgdp;
17 int i;
18
19 for (i = 0; i < numpages; i++) {
20 pgdp = pgd_offset(&init_mm, addr);
21 pudp = pud_offset(pgdp, addr);
22 pmdp = pmd_offset(pudp, addr);
23 if (pmd_huge(*pmdp)) {
24 WARN_ON_ONCE(1);
25 continue;
26 }
27 ptep = pte_offset_kernel(pmdp, addr + i * PAGE_SIZE);
28
29 pte = *ptep;
30 pte = set(pte);
31 ptep_invalidate(&init_mm, addr + i * PAGE_SIZE, ptep);
32 *ptep = pte;
33 }
34}
35
36int set_memory_ro(unsigned long addr, int numpages)
37{
38 change_page_attr(addr, numpages, pte_wrprotect);
39 return 0;
40}
41EXPORT_SYMBOL_GPL(set_memory_ro);
42
43int set_memory_rw(unsigned long addr, int numpages)
44{
45 change_page_attr(addr, numpages, pte_mkwrite);
46 return 0;
47}
48EXPORT_SYMBOL_GPL(set_memory_rw);
49
50/* not possible */
51int set_memory_nx(unsigned long addr, int numpages)
52{
53 return 0;
54}
55EXPORT_SYMBOL_GPL(set_memory_nx);