mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] x86, mm: set NX across entire PMD at boot
@ 2014-11-14 19:47 Kees Cook
  2014-11-14 20:12 ` Thomas Gleixner
  2014-11-18 17:40 ` [tip:x86/urgent] x86, mm: Set " tip-bot for Kees Cook
  0 siblings, 2 replies; 4+ messages in thread
From: Kees Cook @ 2014-11-14 19:47 UTC (permalink / raw)
  To: linux-kernel
  Cc: Thomas Gleixner, Ingo Molnar, H. Peter Anvin, x86, Andrew Morton,
	Andy Lutomirski, Toshi Kani, Yasuaki Ishimatsu, David Vrabel,
	Wang Nan, Kees Cook, Yinghai Lu

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

Signed-off-by: Kees Cook <keescook@chromium.org>
---
 arch/x86/mm/init_64.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index 4cb8763868fc..7da7a4ab46f7 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -1123,7 +1123,9 @@ void mark_rodata_ro(void)
 	unsigned long end = (unsigned long) &__end_rodata_hpage_align;
 	unsigned long text_end = PFN_ALIGN(&__stop___ex_table);
 	unsigned long rodata_end = PFN_ALIGN(&__end_rodata);
-	unsigned long all_end = PFN_ALIGN(&_end);
+	/* End of kernel memory will span a PMD, so align to PMD. */
+	unsigned long all_end = (((unsigned long)(&_end) + (PMD_SIZE - 1))
+				 & PMD_MASK);
 
 	printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n",
 	       (end - start) >> 10);
-- 
1.9.1


-- 
Kees Cook
Chrome OS Security

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] x86, mm: set NX across entire PMD at boot
  2014-11-14 19:47 [PATCH] x86, mm: set NX across entire PMD at boot Kees Cook
@ 2014-11-14 20:12 ` Thomas Gleixner
  2014-11-18 17:40 ` [tip:x86/urgent] x86, mm: Set " tip-bot for Kees Cook
  1 sibling, 0 replies; 4+ messages in thread
From: Thomas Gleixner @ 2014-11-14 20:12 UTC (permalink / raw)
  To: Kees Cook
  Cc: linux-kernel, Ingo Molnar, H. Peter Anvin, x86, Andrew Morton,
	Andy Lutomirski, Toshi Kani, Yasuaki Ishimatsu, David Vrabel,
	Wang Nan, Yinghai Lu

On Fri, 14 Nov 2014, Kees Cook wrote:

> 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
> 
> Signed-off-by: Kees Cook <keescook@chromium.org>
> ---
>  arch/x86/mm/init_64.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
> index 4cb8763868fc..7da7a4ab46f7 100644
> --- a/arch/x86/mm/init_64.c
> +++ b/arch/x86/mm/init_64.c
> @@ -1123,7 +1123,9 @@ void mark_rodata_ro(void)
>  	unsigned long end = (unsigned long) &__end_rodata_hpage_align;
>  	unsigned long text_end = PFN_ALIGN(&__stop___ex_table);
>  	unsigned long rodata_end = PFN_ALIGN(&__end_rodata);
> -	unsigned long all_end = PFN_ALIGN(&_end);
> +	/* End of kernel memory will span a PMD, so align to PMD. */
> +	unsigned long all_end = (((unsigned long)(&_end) + (PMD_SIZE - 1))
> +				 & PMD_MASK);

I prefer to free the leftover pages like we do with the init
sections. In the above example it's only 44k, but it can be 2044k in
the worst case, which was enough to boot a embedded box 15 years ago :)

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [tip:x86/urgent] x86, mm: Set NX across entire PMD at boot
  2014-11-14 19:47 [PATCH] x86, mm: set NX across entire PMD at boot Kees Cook
  2014-11-14 20:12 ` Thomas Gleixner
@ 2014-11-18 17:40 ` tip-bot for Kees Cook
  2014-11-18 17:56   ` Yinghai Lu
  1 sibling, 1 reply; 4+ messages in thread
From: tip-bot for Kees Cook @ 2014-11-18 17:40 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: david.vrabel, keescook, linux-kernel, mingo, tglx, hpa, luto,
	isimatu.yasuaki, wangnan0, yinghai, toshi.kani

Commit-ID:  45e2a9d4701d8c624d4a4bcdd1084eae31e92f58
Gitweb:     http://git.kernel.org/tip/45e2a9d4701d8c624d4a4bcdd1084eae31e92f58
Author:     Kees Cook <keescook@chromium.org>
AuthorDate: Fri, 14 Nov 2014 11:47:37 -0800
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Tue, 18 Nov 2014 18:32:24 +0100

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: 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>
Cc: stable@vger.kernel.org
Link: http://lkml.kernel.org/r/20141114194737.GA3091@www.outflux.net
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/x86/mm/init_64.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index 4cb8763..4e5dfec 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -1123,7 +1123,7 @@ void mark_rodata_ro(void)
 	unsigned long end = (unsigned long) &__end_rodata_hpage_align;
 	unsigned long text_end = PFN_ALIGN(&__stop___ex_table);
 	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",
 	       (end - start) >> 10);
@@ -1134,7 +1134,16 @@ void mark_rodata_ro(void)
 	/*
 	 * The rodata/data/bss/brk section (but not the kernel text!)
 	 * 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);
 
 	rodata_test();

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [tip:x86/urgent] x86, mm: Set NX across entire PMD at boot
  2014-11-18 17:40 ` [tip:x86/urgent] x86, mm: Set " tip-bot for Kees Cook
@ 2014-11-18 17:56   ` Yinghai Lu
  0 siblings, 0 replies; 4+ messages in thread
From: Yinghai Lu @ 2014-11-18 17:56 UTC (permalink / raw)
  To: Thomas Gleixner, Ingo Molnar, Linux Kernel Mailing List,
	Kees Cook, David Vrabel, Yinghai Lu, Toshi Kani, Wang Nan,
	Yasuaki Ishimatsu, H. Peter Anvin, Andy Lutomirski
  Cc: linux-tip-commits

On Tue, Nov 18, 2014 at 9:40 AM, tip-bot for Kees Cook <tipbot@zytor.com> wrote:
> Commit-ID:  45e2a9d4701d8c624d4a4bcdd1084eae31e92f58
> Gitweb:     http://git.kernel.org/tip/45e2a9d4701d8c624d4a4bcdd1084eae31e92f58
> Author:     Kees Cook <keescook@chromium.org>
> AuthorDate: Fri, 14 Nov 2014 11:47:37 -0800
> Committer:  Thomas Gleixner <tglx@linutronix.de>
> CommitDate: Tue, 18 Nov 2014 18:32:24 +0100
>
> 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: 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>
> Cc: stable@vger.kernel.org
> Link: http://lkml.kernel.org/r/20141114194737.GA3091@www.outflux.net
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> ---
>  arch/x86/mm/init_64.c | 11 ++++++++++-
>  1 file changed, 10 insertions(+), 1 deletion(-)
>
> diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
> index 4cb8763..4e5dfec 100644
> --- a/arch/x86/mm/init_64.c
> +++ b/arch/x86/mm/init_64.c
> @@ -1123,7 +1123,7 @@ void mark_rodata_ro(void)
>         unsigned long end = (unsigned long) &__end_rodata_hpage_align;
>         unsigned long text_end = PFN_ALIGN(&__stop___ex_table);
>         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",
>                (end - start) >> 10);
> @@ -1134,7 +1134,16 @@ void mark_rodata_ro(void)
>         /*
>          * The rodata/data/bss/brk section (but not the kernel text!)
>          * 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().

should be cleanup_highmap()

>          */
> +       all_end = roundup((unsigned long)_brk_end, PMD_SIZE);

Why do you need cast here ?

>         set_memory_nx(rodata_start, (all_end - rodata_start) >> PAGE_SHIFT);
>
>         rodata_test();

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2014-11-18 17:56 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-11-14 19:47 [PATCH] x86, mm: set NX across entire PMD at boot Kees Cook
2014-11-14 20:12 ` Thomas Gleixner
2014-11-18 17:40 ` [tip:x86/urgent] x86, mm: Set " tip-bot for Kees Cook
2014-11-18 17:56   ` Yinghai Lu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

Powered by JetHome