aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mm/init.c
diff options
context:
space:
mode:
authorKees Cook <keescook@chromium.org>2014-04-03 16:29:50 -0400
committerKees Cook <keescook@chromium.org>2014-10-16 17:38:54 -0400
commit80d6b0c2eed2a504f6740cd1f5ea76dc50abfc4d (patch)
tree32f6d8a1c5a2250cc3f303df545dfbf52da62d19 /arch/arm/mm/init.c
parent1e6b48116a95046ec51f3d40f83aff8b006674d7 (diff)
ARM: mm: allow text and rodata sections to be read-only
This introduces CONFIG_DEBUG_RODATA, making kernel text and rodata read-only. Additionally, this splits rodata from text so that rodata can also be NX, which may lead to wasted memory when aligning to SECTION_SIZE. The read-only areas are made writable during ftrace updates and kexec. Signed-off-by: Kees Cook <keescook@chromium.org> Tested-by: Laura Abbott <lauraa@codeaurora.org> Acked-by: Nicolas Pitre <nico@linaro.org>
Diffstat (limited to 'arch/arm/mm/init.c')
-rw-r--r--arch/arm/mm/init.c48
1 files changed, 47 insertions, 1 deletions
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index e6bfe76b2f59..dc2db779cdf4 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -622,9 +622,10 @@ struct section_perm {
622 unsigned long end; 622 unsigned long end;
623 pmdval_t mask; 623 pmdval_t mask;
624 pmdval_t prot; 624 pmdval_t prot;
625 pmdval_t clear;
625}; 626};
626 627
627struct section_perm nx_perms[] = { 628static struct section_perm nx_perms[] = {
628 /* Make pages tables, etc before _stext RW (set NX). */ 629 /* Make pages tables, etc before _stext RW (set NX). */
629 { 630 {
630 .start = PAGE_OFFSET, 631 .start = PAGE_OFFSET,
@@ -639,8 +640,35 @@ struct section_perm nx_perms[] = {
639 .mask = ~PMD_SECT_XN, 640 .mask = ~PMD_SECT_XN,
640 .prot = PMD_SECT_XN, 641 .prot = PMD_SECT_XN,
641 }, 642 },
643#ifdef CONFIG_DEBUG_RODATA
644 /* Make rodata NX (set RO in ro_perms below). */
645 {
646 .start = (unsigned long)__start_rodata,
647 .end = (unsigned long)__init_begin,
648 .mask = ~PMD_SECT_XN,
649 .prot = PMD_SECT_XN,
650 },
651#endif
642}; 652};
643 653
654#ifdef CONFIG_DEBUG_RODATA
655static struct section_perm ro_perms[] = {
656 /* Make kernel code and rodata RX (set RO). */
657 {
658 .start = (unsigned long)_stext,
659 .end = (unsigned long)__init_begin,
660#ifdef CONFIG_ARM_LPAE
661 .mask = ~PMD_SECT_RDONLY,
662 .prot = PMD_SECT_RDONLY,
663#else
664 .mask = ~(PMD_SECT_APX | PMD_SECT_AP_WRITE),
665 .prot = PMD_SECT_APX | PMD_SECT_AP_WRITE,
666 .clear = PMD_SECT_AP_WRITE,
667#endif
668 },
669};
670#endif
671
644/* 672/*
645 * Updates section permissions only for the current mm (sections are 673 * Updates section permissions only for the current mm (sections are
646 * copied into each mm). During startup, this is the init_mm. Is only 674 * copied into each mm). During startup, this is the init_mm. Is only
@@ -704,6 +732,24 @@ static inline void fix_kernmem_perms(void)
704{ 732{
705 set_section_perms(nx_perms, prot); 733 set_section_perms(nx_perms, prot);
706} 734}
735
736#ifdef CONFIG_DEBUG_RODATA
737void mark_rodata_ro(void)
738{
739 set_section_perms(ro_perms, prot);
740}
741
742void set_kernel_text_rw(void)
743{
744 set_section_perms(ro_perms, clear);
745}
746
747void set_kernel_text_ro(void)
748{
749 set_section_perms(ro_perms, prot);
750}
751#endif /* CONFIG_DEBUG_RODATA */
752
707#else 753#else
708static inline void fix_kernmem_perms(void) { } 754static inline void fix_kernmem_perms(void) { }
709#endif /* CONFIG_ARM_KERNMEM_PERMS */ 755#endif /* CONFIG_ARM_KERNMEM_PERMS */