Commit 1a829c59816e8c9f97a20b9f7967783591470bf2

Authored by Kees Cook
Committed by Greg Kroah-Hartman
1 parent dd0e988f1f

x86, mm: Set NX across entire PMD at boot

commit 45e2a9d4701d8c624d4a4bcdd1084eae31e92f58 upstream.

When setting up permissions on kernel memory at boot, the end of the
PMD that was split from bss remained executable. It should be NX like
the rest. This performs a PMD alignment instead of a PAGE alignment to
get the correct span of memory.

Before:
---[ High Kernel Mapping ]---
...
0xffffffff8202d000-0xffffffff82200000  1868K     RW       GLB NX pte
0xffffffff82200000-0xffffffff82c00000    10M     RW   PSE GLB NX pmd
0xffffffff82c00000-0xffffffff82df5000  2004K     RW       GLB NX pte
0xffffffff82df5000-0xffffffff82e00000    44K     RW       GLB x  pte
0xffffffff82e00000-0xffffffffc0000000   978M                     pmd

After:
---[ High Kernel Mapping ]---
...
0xffffffff8202d000-0xffffffff82200000  1868K     RW       GLB NX pte
0xffffffff82200000-0xffffffff82e00000    12M     RW   PSE GLB NX pmd
0xffffffff82e00000-0xffffffffc0000000   978M                     pmd

[ tglx: Changed it to roundup(_brk_end, PMD_SIZE) and added a comment.
        We really should unmap the reminder along with the holes
        caused by init,initdata etc. but thats a different issue ]

Signed-off-by: Kees Cook <keescook@chromium.org>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Toshi Kani <toshi.kani@hp.com>
Cc: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
Cc: David Vrabel <david.vrabel@citrix.com>
Cc: Wang Nan <wangnan0@huawei.com>
Cc: Yinghai Lu <yinghai@kernel.org>
Link: http://lkml.kernel.org/r/20141114194737.GA3091@www.outflux.net
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Showing 1 changed file with 10 additions and 1 deletions Side-by-side Diff

arch/x86/mm/init_64.c
... ... @@ -1110,7 +1110,7 @@
1110 1110 unsigned long end = (unsigned long) &__end_rodata_hpage_align;
1111 1111 unsigned long text_end = PFN_ALIGN(&__stop___ex_table);
1112 1112 unsigned long rodata_end = PFN_ALIGN(&__end_rodata);
1113   - unsigned long all_end = PFN_ALIGN(&_end);
  1113 + unsigned long all_end;
1114 1114  
1115 1115 printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n",
1116 1116 (end - start) >> 10);
1117 1117  
... ... @@ -1121,7 +1121,16 @@
1121 1121 /*
1122 1122 * The rodata/data/bss/brk section (but not the kernel text!)
1123 1123 * should also be not-executable.
  1124 + *
  1125 + * We align all_end to PMD_SIZE because the existing mapping
  1126 + * is a full PMD. If we would align _brk_end to PAGE_SIZE we
  1127 + * split the PMD and the reminder between _brk_end and the end
  1128 + * of the PMD will remain mapped executable.
  1129 + *
  1130 + * Any PMD which was setup after the one which covers _brk_end
  1131 + * has been zapped already via cleanup_highmem().
1124 1132 */
  1133 + all_end = roundup((unsigned long)_brk_end, PMD_SIZE);
1125 1134 set_memory_nx(rodata_start, (all_end - rodata_start) >> PAGE_SHIFT);
1126 1135  
1127 1136 rodata_test();