aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mm/init.c
diff options
context:
space:
mode:
authorKees Cook <keescook@chromium.org>2016-01-25 19:19:36 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2016-02-08 10:56:45 -0500
commit25362dc496edaf17f714c0fecd8b3eb79670207b (patch)
treed2d84f7e6ca5babcd66caf41fa5a6af87af31d38 /arch/arm/mm/init.c
parent4138323eac0b485316e54ad9ce241bac24ddd175 (diff)
ARM: 8501/1: mm: flip priority of CONFIG_DEBUG_RODATA
The use of CONFIG_DEBUG_RODATA is generally seen as an essential part of kernel self-protection: http://www.openwall.com/lists/kernel-hardening/2015/11/30/13 Additionally, its name has grown to mean things beyond just rodata. To get ARM closer to this, we ought to rearrange the names of the configs that control how the kernel protects its memory. What was called CONFIG_ARM_KERNMEM_PERMS is realy doing the work that other architectures call CONFIG_DEBUG_RODATA. This redefines CONFIG_DEBUG_RODATA to actually do the bulk of the ROing (and NXing). In the place of the old CONFIG_DEBUG_RODATA, use CONFIG_DEBUG_ALIGN_RODATA, since that's what the option does: adds section alignment for making rodata explicitly NX, as arm does not split the page tables like arm64 does without _ALIGN_RODATA. Also adds human readable names to the sections so I could more easily debug my typos, and makes CONFIG_DEBUG_RODATA default "y" for CPU_V7. Results in /sys/kernel/debug/kernel_page_tables for each config state: # CONFIG_DEBUG_RODATA is not set # CONFIG_DEBUG_ALIGN_RODATA is not set ---[ Kernel Mapping ]--- 0x80000000-0x80900000 9M RW x SHD 0x80900000-0xa0000000 503M RW NX SHD CONFIG_DEBUG_RODATA=y CONFIG_DEBUG_ALIGN_RODATA=y ---[ Kernel Mapping ]--- 0x80000000-0x80100000 1M RW NX SHD 0x80100000-0x80700000 6M ro x SHD 0x80700000-0x80a00000 3M ro NX SHD 0x80a00000-0xa0000000 502M RW NX SHD CONFIG_DEBUG_RODATA=y # CONFIG_DEBUG_ALIGN_RODATA is not set ---[ Kernel Mapping ]--- 0x80000000-0x80100000 1M RW NX SHD 0x80100000-0x80a00000 9M ro x SHD 0x80a00000-0xa0000000 502M RW NX SHD Signed-off-by: Kees Cook <keescook@chromium.org> Reviewed-by: Laura Abbott <labbott@fedoraproject.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mm/init.c')
-rw-r--r--arch/arm/mm/init.c19
1 files changed, 10 insertions, 9 deletions
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 49bd08178008..53f42508025b 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -572,8 +572,9 @@ void __init mem_init(void)
572 } 572 }
573} 573}
574 574
575#ifdef CONFIG_ARM_KERNMEM_PERMS 575#ifdef CONFIG_DEBUG_RODATA
576struct section_perm { 576struct section_perm {
577 const char *name;
577 unsigned long start; 578 unsigned long start;
578 unsigned long end; 579 unsigned long end;
579 pmdval_t mask; 580 pmdval_t mask;
@@ -584,6 +585,7 @@ struct section_perm {
584static struct section_perm nx_perms[] = { 585static struct section_perm nx_perms[] = {
585 /* Make pages tables, etc before _stext RW (set NX). */ 586 /* Make pages tables, etc before _stext RW (set NX). */
586 { 587 {
588 .name = "pre-text NX",
587 .start = PAGE_OFFSET, 589 .start = PAGE_OFFSET,
588 .end = (unsigned long)_stext, 590 .end = (unsigned long)_stext,
589 .mask = ~PMD_SECT_XN, 591 .mask = ~PMD_SECT_XN,
@@ -591,14 +593,16 @@ static struct section_perm nx_perms[] = {
591 }, 593 },
592 /* Make init RW (set NX). */ 594 /* Make init RW (set NX). */
593 { 595 {
596 .name = "init NX",
594 .start = (unsigned long)__init_begin, 597 .start = (unsigned long)__init_begin,
595 .end = (unsigned long)_sdata, 598 .end = (unsigned long)_sdata,
596 .mask = ~PMD_SECT_XN, 599 .mask = ~PMD_SECT_XN,
597 .prot = PMD_SECT_XN, 600 .prot = PMD_SECT_XN,
598 }, 601 },
599#ifdef CONFIG_DEBUG_RODATA 602#ifdef CONFIG_DEBUG_ALIGN_RODATA
600 /* Make rodata NX (set RO in ro_perms below). */ 603 /* Make rodata NX (set RO in ro_perms below). */
601 { 604 {
605 .name = "rodata NX",
602 .start = (unsigned long)__start_rodata, 606 .start = (unsigned long)__start_rodata,
603 .end = (unsigned long)__init_begin, 607 .end = (unsigned long)__init_begin,
604 .mask = ~PMD_SECT_XN, 608 .mask = ~PMD_SECT_XN,
@@ -607,10 +611,10 @@ static struct section_perm nx_perms[] = {
607#endif 611#endif
608}; 612};
609 613
610#ifdef CONFIG_DEBUG_RODATA
611static struct section_perm ro_perms[] = { 614static struct section_perm ro_perms[] = {
612 /* Make kernel code and rodata RX (set RO). */ 615 /* Make kernel code and rodata RX (set RO). */
613 { 616 {
617 .name = "text/rodata RO",
614 .start = (unsigned long)_stext, 618 .start = (unsigned long)_stext,
615 .end = (unsigned long)__init_begin, 619 .end = (unsigned long)__init_begin,
616#ifdef CONFIG_ARM_LPAE 620#ifdef CONFIG_ARM_LPAE
@@ -623,7 +627,6 @@ static struct section_perm ro_perms[] = {
623#endif 627#endif
624 }, 628 },
625}; 629};
626#endif
627 630
628/* 631/*
629 * Updates section permissions only for the current mm (sections are 632 * Updates section permissions only for the current mm (sections are
@@ -670,8 +673,8 @@ void set_section_perms(struct section_perm *perms, int n, bool set,
670 for (i = 0; i < n; i++) { 673 for (i = 0; i < n; i++) {
671 if (!IS_ALIGNED(perms[i].start, SECTION_SIZE) || 674 if (!IS_ALIGNED(perms[i].start, SECTION_SIZE) ||
672 !IS_ALIGNED(perms[i].end, SECTION_SIZE)) { 675 !IS_ALIGNED(perms[i].end, SECTION_SIZE)) {
673 pr_err("BUG: section %lx-%lx not aligned to %lx\n", 676 pr_err("BUG: %s section %lx-%lx not aligned to %lx\n",
674 perms[i].start, perms[i].end, 677 perms[i].name, perms[i].start, perms[i].end,
675 SECTION_SIZE); 678 SECTION_SIZE);
676 continue; 679 continue;
677 } 680 }
@@ -712,7 +715,6 @@ void fix_kernmem_perms(void)
712 stop_machine(__fix_kernmem_perms, NULL, NULL); 715 stop_machine(__fix_kernmem_perms, NULL, NULL);
713} 716}
714 717
715#ifdef CONFIG_DEBUG_RODATA
716int __mark_rodata_ro(void *unused) 718int __mark_rodata_ro(void *unused)
717{ 719{
718 update_sections_early(ro_perms, ARRAY_SIZE(ro_perms)); 720 update_sections_early(ro_perms, ARRAY_SIZE(ro_perms));
@@ -735,11 +737,10 @@ void set_kernel_text_ro(void)
735 set_section_perms(ro_perms, ARRAY_SIZE(ro_perms), true, 737 set_section_perms(ro_perms, ARRAY_SIZE(ro_perms), true,
736 current->active_mm); 738 current->active_mm);
737} 739}
738#endif /* CONFIG_DEBUG_RODATA */
739 740
740#else 741#else
741static inline void fix_kernmem_perms(void) { } 742static inline void fix_kernmem_perms(void) { }
742#endif /* CONFIG_ARM_KERNMEM_PERMS */ 743#endif /* CONFIG_DEBUG_RODATA */
743 744
744void free_tcmmem(void) 745void free_tcmmem(void)
745{ 746{