Commit 45e2a9d4 authored by Kees Cook's avatar Kees Cook Committed by Thomas Gleixner

x86, mm: Set NX across entire PMD at boot

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: default avatarKees 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>
Cc: stable@vger.kernel.org
Link: http://lkml.kernel.org/r/20141114194737.GA3091@www.outflux.netSigned-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent fb86b973
...@@ -1123,7 +1123,7 @@ void mark_rodata_ro(void) ...@@ -1123,7 +1123,7 @@ void mark_rodata_ro(void)
unsigned long end = (unsigned long) &__end_rodata_hpage_align; unsigned long end = (unsigned long) &__end_rodata_hpage_align;
unsigned long text_end = PFN_ALIGN(&__stop___ex_table); unsigned long text_end = PFN_ALIGN(&__stop___ex_table);
unsigned long rodata_end = PFN_ALIGN(&__end_rodata); unsigned long rodata_end = PFN_ALIGN(&__end_rodata);
unsigned long all_end = PFN_ALIGN(&_end); unsigned long all_end;
printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n", printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n",
(end - start) >> 10); (end - start) >> 10);
...@@ -1134,7 +1134,16 @@ void mark_rodata_ro(void) ...@@ -1134,7 +1134,16 @@ void mark_rodata_ro(void)
/* /*
* The rodata/data/bss/brk section (but not the kernel text!) * The rodata/data/bss/brk section (but not the kernel text!)
* should also be not-executable. * should also be not-executable.
*
* We align all_end to PMD_SIZE because the existing mapping
* is a full PMD. If we would align _brk_end to PAGE_SIZE we
* split the PMD and the reminder between _brk_end and the end
* of the PMD will remain mapped executable.
*
* Any PMD which was setup after the one which covers _brk_end
* has been zapped already via cleanup_highmem().
*/ */
all_end = roundup((unsigned long)_brk_end, PMD_SIZE);
set_memory_nx(rodata_start, (all_end - rodata_start) >> PAGE_SHIFT); set_memory_nx(rodata_start, (all_end - rodata_start) >> PAGE_SHIFT);
rodata_test(); rodata_test();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment