Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Jan Glauber and committed by
Martin Schwidefsky
305b1523 d54cddb6

+63
+3
arch/s390/Kconfig.debug
··· 31 31 32 32 If unsure, or if you run an older (pre 4.4) gcc, say N. 33 33 34 + config DEBUG_SET_MODULE_RONX 35 + def_bool y 36 + depends on MODULES 34 37 endmenu
+4
arch/s390/include/asm/cacheflush.h
··· 8 8 void kernel_map_pages(struct page *page, int numpages, int enable); 9 9 #endif 10 10 11 + int set_memory_ro(unsigned long addr, int numpages); 12 + int set_memory_rw(unsigned long addr, int numpages); 13 + int set_memory_nx(unsigned long addr, int numpages); 14 + 11 15 #endif /* _S390_CACHEFLUSH_H */
+1
arch/s390/mm/Makefile
··· 6 6 page-states.o gup.o 7 7 obj-$(CONFIG_CMM) += cmm.o 8 8 obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o 9 + obj-$(CONFIG_DEBUG_SET_MODULE_RONX) += pageattr.o
+55
arch/s390/mm/pageattr.c
··· 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 + 10 + static 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 + 36 + int set_memory_ro(unsigned long addr, int numpages) 37 + { 38 + change_page_attr(addr, numpages, pte_wrprotect); 39 + return 0; 40 + } 41 + EXPORT_SYMBOL_GPL(set_memory_ro); 42 + 43 + int set_memory_rw(unsigned long addr, int numpages) 44 + { 45 + change_page_attr(addr, numpages, pte_mkwrite); 46 + return 0; 47 + } 48 + EXPORT_SYMBOL_GPL(set_memory_rw); 49 + 50 + /* not possible */ 51 + int set_memory_nx(unsigned long addr, int numpages) 52 + { 53 + return 0; 54 + } 55 + EXPORT_SYMBOL_GPL(set_memory_nx);