Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1404187 > unrolled thread

Re: PROBLEM: Resume form hibernate broken by setting NX on gap

Started byIngo Molnar <mingo@kernel.org>
First post2016-05-20 09:20 +0200
Last post2016-05-21 18:50 +0200
Articles 7 — 4 participants

Back to article view | Back to linux.kernel

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: PROBLEM: Resume form hibernate broken by setting NX on gap Ingo Molnar <mingo@kernel.org> - 2016-05-20 09:20 +0200
    Re: PROBLEM: Resume form hibernate broken by setting NX on gap "Rafael J. Wysocki" <rafael@kernel.org> - 2016-05-20 13:40 +0200
      Re: PROBLEM: Resume form hibernate broken by setting NX on gap Stephen Smalley <sds@tycho.nsa.gov> - 2016-05-20 16:10 +0200
        Re: PROBLEM: Resume form hibernate broken by setting NX on gap "Rafael J. Wysocki" <rafael@kernel.org> - 2016-05-20 23:50 +0200
          Re: PROBLEM: Resume form hibernate broken by setting NX on gap Kees Cook <keescook@chromium.org> - 2016-05-21 00:00 +0200
            Re: PROBLEM: Resume form hibernate broken by setting NX on gap Kees Cook <keescook@chromium.org> - 2016-05-21 00:20 +0200
              Re: PROBLEM: Resume form hibernate broken by setting NX on gap Kees Cook <keescook@chromium.org> - 2016-05-21 18:50 +0200

#1404187 — Re: PROBLEM: Resume form hibernate broken by setting NX on gap

FromIngo Molnar <mingo@kernel.org>
Date2016-05-20 09:20 +0200
SubjectRe: PROBLEM: Resume form hibernate broken by setting NX on gap
Message-ID<rAMSZ-2uP-3@gated-at.bofh.it>
* Logan Gunthorpe <logang@deltatee.com> wrote:

> Hi,
> 
> I have been working on a bug that causes my laptop to freeze during
> resume from hibernation. I did a bisect to find the offending commit:
> 
> [ab76f7b4ab] x86/mm: Set NX on gap between __ex_table and rodata
> 
> There is more information in the bugzilla report [1] that
> I've been working on but I will summarize things below.
> 
> I've experienced intermittent but reproducible freezes when resuming
> from hibernation since about kernel version 3.19. The freeze was
> significantly more reproducible when a few applications were loaded
> before hibernation and would largely not happen if hibernated
> immediately after booting to a desktop. I did some tracing work to find
> that the kernel gets as far as the resume_image call in
> swsusp_arch_resume and I could not find any response from the image
> kernel when I hit the bug. I also did testing that seemed to rule out
> this being caused by a problematic driver.
> 
> I did a successful bisect between 3.18 and 3.19 which found a bug in
> commit f5b2831d6 that was then later fixed by commit 55696b1f66 in 4.4.
> Then, I did a second bisect with a ported version of the fix to the
> first bug and found commit ab76f7b4ab in 4.3 to also break hibernation
> with what appears to be the exact same symptoms. Reverting that commit
> in recent kernels up to and including 4.6 fixes the issue and restores
> reliable hibernation. However, it's not at all clear to me why that
> commit would cause this issue or how to fix the issue without reverting.

I've attached that commit below and also Cc:-ed a few more people who might have 
an idea about why this regressed. Worst-case we'll have to revert it.

Thanks,

	Ingo

=================>
From ab76f7b4ab2397ffdd2f1eb07c55697d19991d10 Mon Sep 17 00:00:00 2001
From: Stephen Smalley <sds@tycho.nsa.gov>
Date: Thu, 1 Oct 2015 09:04:22 -0400
Subject: [PATCH] x86/mm: Set NX on gap between __ex_table and rodata

Unused space between the end of __ex_table and the start of
rodata can be left W+x in the kernel page tables.  Extend the
setting of the NX bit to cover this gap by starting from
text_end rather than rodata_start.

  Before:
  ---[ High Kernel Mapping ]---
  0xffffffff80000000-0xffffffff81000000          16M                               pmd
  0xffffffff81000000-0xffffffff81600000           6M     ro         PSE     GLB x  pmd
  0xffffffff81600000-0xffffffff81754000        1360K     ro                 GLB x  pte
  0xffffffff81754000-0xffffffff81800000         688K     RW                 GLB x  pte
  0xffffffff81800000-0xffffffff81a00000           2M     ro         PSE     GLB NX pmd
  0xffffffff81a00000-0xffffffff81b3b000        1260K     ro                 GLB NX pte
  0xffffffff81b3b000-0xffffffff82000000        4884K     RW                 GLB NX pte
  0xffffffff82000000-0xffffffff82200000           2M     RW         PSE     GLB NX pmd
  0xffffffff82200000-0xffffffffa0000000         478M                               pmd

  After:
  ---[ High Kernel Mapping ]---
  0xffffffff80000000-0xffffffff81000000          16M                               pmd
  0xffffffff81000000-0xffffffff81600000           6M     ro         PSE     GLB x  pmd
  0xffffffff81600000-0xffffffff81754000        1360K     ro                 GLB x  pte
  0xffffffff81754000-0xffffffff81800000         688K     RW                 GLB NX pte
  0xffffffff81800000-0xffffffff81a00000           2M     ro         PSE     GLB NX pmd
  0xffffffff81a00000-0xffffffff81b3b000        1260K     ro                 GLB NX pte
  0xffffffff81b3b000-0xffffffff82000000        4884K     RW                 GLB NX pte
  0xffffffff82000000-0xffffffff82200000           2M     RW         PSE     GLB NX pmd
  0xffffffff82200000-0xffffffffa0000000         478M                               pmd

Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
Acked-by: Kees Cook <keescook@chromium.org>
Cc: <stable@vger.kernel.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-kernel@vger.kernel.org
Link: http://lkml.kernel.org/r/1443704662-3138-1-git-send-email-sds@tycho.nsa.gov
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 arch/x86/mm/init_64.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index 30564e2752d3..df48430c279b 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -1132,7 +1132,7 @@ void mark_rodata_ro(void)
 	 * 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(text_end, (all_end - text_end) >> PAGE_SHIFT);
 
 	rodata_test();
 

[toc] | [next] | [standalone]


#1404356

From"Rafael J. Wysocki" <rafael@kernel.org>
Date2016-05-20 13:40 +0200
Message-ID<rAQWC-4Vm-27@gated-at.bofh.it>
In reply to#1404187
On Fri, May 20, 2016 at 9:15 AM, Ingo Molnar <mingo@kernel.org> wrote:
>
> * Logan Gunthorpe <logang@deltatee.com> wrote:
>
>> Hi,
>>
>> I have been working on a bug that causes my laptop to freeze during
>> resume from hibernation. I did a bisect to find the offending commit:
>>
>> [ab76f7b4ab] x86/mm: Set NX on gap between __ex_table and rodata
>>
>> There is more information in the bugzilla report [1] that
>> I've been working on but I will summarize things below.
>>
>> I've experienced intermittent but reproducible freezes when resuming
>> from hibernation since about kernel version 3.19. The freeze was
>> significantly more reproducible when a few applications were loaded
>> before hibernation and would largely not happen if hibernated
>> immediately after booting to a desktop. I did some tracing work to find
>> that the kernel gets as far as the resume_image call in
>> swsusp_arch_resume and I could not find any response from the image
>> kernel when I hit the bug. I also did testing that seemed to rule out
>> this being caused by a problematic driver.
>>
>> I did a successful bisect between 3.18 and 3.19 which found a bug in
>> commit f5b2831d6 that was then later fixed by commit 55696b1f66 in 4.4.
>> Then, I did a second bisect with a ported version of the fix to the
>> first bug and found commit ab76f7b4ab in 4.3 to also break hibernation
>> with what appears to be the exact same symptoms. Reverting that commit
>> in recent kernels up to and including 4.6 fixes the issue and restores
>> reliable hibernation. However, it's not at all clear to me why that
>> commit would cause this issue or how to fix the issue without reverting.
>
> I've attached that commit below and also Cc:-ed a few more people who might have
> an idea about why this regressed. Worst-case we'll have to revert it.

Without looking deep into mm, my theory would be that after this patch
the final jump from the boot kernel to the image kernel's trampoline
code during resume may crash the kernel if the trampoline page turns
out to be NX in the boot kernel (it has to be executable in both the
boot and the image kernels).

Thanks,
Rafael

[toc] | [prev] | [next] | [standalone]


#1404482

FromStephen Smalley <sds@tycho.nsa.gov>
Date2016-05-20 16:10 +0200
Message-ID<rAThM-6uH-35@gated-at.bofh.it>
In reply to#1404356
On 05/20/2016 07:34 AM, Rafael J. Wysocki wrote:
> On Fri, May 20, 2016 at 9:15 AM, Ingo Molnar <mingo@kernel.org> wrote:
>>
>> * Logan Gunthorpe <logang@deltatee.com> wrote:
>>
>>> Hi,
>>>
>>> I have been working on a bug that causes my laptop to freeze during
>>> resume from hibernation. I did a bisect to find the offending commit:
>>>
>>> [ab76f7b4ab] x86/mm: Set NX on gap between __ex_table and rodata
>>>
>>> There is more information in the bugzilla report [1] that
>>> I've been working on but I will summarize things below.
>>>
>>> I've experienced intermittent but reproducible freezes when resuming
>>> from hibernation since about kernel version 3.19. The freeze was
>>> significantly more reproducible when a few applications were loaded
>>> before hibernation and would largely not happen if hibernated
>>> immediately after booting to a desktop. I did some tracing work to find
>>> that the kernel gets as far as the resume_image call in
>>> swsusp_arch_resume and I could not find any response from the image
>>> kernel when I hit the bug. I also did testing that seemed to rule out
>>> this being caused by a problematic driver.
>>>
>>> I did a successful bisect between 3.18 and 3.19 which found a bug in
>>> commit f5b2831d6 that was then later fixed by commit 55696b1f66 in 4.4.
>>> Then, I did a second bisect with a ported version of the fix to the
>>> first bug and found commit ab76f7b4ab in 4.3 to also break hibernation
>>> with what appears to be the exact same symptoms. Reverting that commit
>>> in recent kernels up to and including 4.6 fixes the issue and restores
>>> reliable hibernation. However, it's not at all clear to me why that
>>> commit would cause this issue or how to fix the issue without reverting.
>>
>> I've attached that commit below and also Cc:-ed a few more people who might have
>> an idea about why this regressed. Worst-case we'll have to revert it.
> 
> Without looking deep into mm, my theory would be that after this patch
> the final jump from the boot kernel to the image kernel's trampoline
> code during resume may crash the kernel if the trampoline page turns
> out to be NX in the boot kernel (it has to be executable in both the
> boot and the image kernels).

So, pardon my ignorance, but where is this trampoline page placed in
kernel memory?

[toc] | [prev] | [next] | [standalone]


#1404742

From"Rafael J. Wysocki" <rafael@kernel.org>
Date2016-05-20 23:50 +0200
Message-ID<rB0sV-2Vx-11@gated-at.bofh.it>
In reply to#1404482
On Fri, May 20, 2016 at 3:56 PM, Stephen Smalley <sds@tycho.nsa.gov> wrote:
> On 05/20/2016 07:34 AM, Rafael J. Wysocki wrote:
>> On Fri, May 20, 2016 at 9:15 AM, Ingo Molnar <mingo@kernel.org> wrote:
>>>
>>> * Logan Gunthorpe <logang@deltatee.com> wrote:
>>>
>>>> Hi,
>>>>
>>>> I have been working on a bug that causes my laptop to freeze during
>>>> resume from hibernation. I did a bisect to find the offending commit:
>>>>
>>>> [ab76f7b4ab] x86/mm: Set NX on gap between __ex_table and rodata
>>>>
>>>> There is more information in the bugzilla report [1] that
>>>> I've been working on but I will summarize things below.
>>>>
>>>> I've experienced intermittent but reproducible freezes when resuming
>>>> from hibernation since about kernel version 3.19. The freeze was
>>>> significantly more reproducible when a few applications were loaded
>>>> before hibernation and would largely not happen if hibernated
>>>> immediately after booting to a desktop. I did some tracing work to find
>>>> that the kernel gets as far as the resume_image call in
>>>> swsusp_arch_resume and I could not find any response from the image
>>>> kernel when I hit the bug. I also did testing that seemed to rule out
>>>> this being caused by a problematic driver.
>>>>
>>>> I did a successful bisect between 3.18 and 3.19 which found a bug in
>>>> commit f5b2831d6 that was then later fixed by commit 55696b1f66 in 4.4.
>>>> Then, I did a second bisect with a ported version of the fix to the
>>>> first bug and found commit ab76f7b4ab in 4.3 to also break hibernation
>>>> with what appears to be the exact same symptoms. Reverting that commit
>>>> in recent kernels up to and including 4.6 fixes the issue and restores
>>>> reliable hibernation. However, it's not at all clear to me why that
>>>> commit would cause this issue or how to fix the issue without reverting.
>>>
>>> I've attached that commit below and also Cc:-ed a few more people who might have
>>> an idea about why this regressed. Worst-case we'll have to revert it.
>>
>> Without looking deep into mm, my theory would be that after this patch
>> the final jump from the boot kernel to the image kernel's trampoline
>> code during resume may crash the kernel if the trampoline page turns
>> out to be NX in the boot kernel (it has to be executable in both the
>> boot and the image kernels).
>
> So, pardon my ignorance, but where is this trampoline page placed in
> kernel memory?

On 32-bit its location has to be the same in both the boot and the
image kernels and that's within kernel text in both cases, so that
shouldn't be a problem.

On 64-bit its location depends on the image kernel and specifically on
the location of the restore_registers routine in it.  The (virtual)
address of that routine is stored in the restore_jump_address
variable, so the page containing it (the trampoline page) can be found
with the help of that.

swsusp_arch_resume() sets up a temporary kernel mapping to finalize
the image restoration and that page must not be NX in that mapping for
things to work.

[toc] | [prev] | [next] | [standalone]


#1404743

FromKees Cook <keescook@chromium.org>
Date2016-05-21 00:00 +0200
Message-ID<rB0CC-31A-7@gated-at.bofh.it>
In reply to#1404742
On Fri, May 20, 2016 at 2:46 PM, Rafael J. Wysocki <rafael@kernel.org> wrote:
> On Fri, May 20, 2016 at 3:56 PM, Stephen Smalley <sds@tycho.nsa.gov> wrote:
>> On 05/20/2016 07:34 AM, Rafael J. Wysocki wrote:
>>> On Fri, May 20, 2016 at 9:15 AM, Ingo Molnar <mingo@kernel.org> wrote:
>>>>
>>>> * Logan Gunthorpe <logang@deltatee.com> wrote:
>>>>
>>>>> Hi,
>>>>>
>>>>> I have been working on a bug that causes my laptop to freeze during
>>>>> resume from hibernation. I did a bisect to find the offending commit:
>>>>>
>>>>> [ab76f7b4ab] x86/mm: Set NX on gap between __ex_table and rodata
>>>>>
>>>>> There is more information in the bugzilla report [1] that
>>>>> I've been working on but I will summarize things below.
>>>>>
>>>>> I've experienced intermittent but reproducible freezes when resuming
>>>>> from hibernation since about kernel version 3.19. The freeze was
>>>>> significantly more reproducible when a few applications were loaded
>>>>> before hibernation and would largely not happen if hibernated
>>>>> immediately after booting to a desktop. I did some tracing work to find
>>>>> that the kernel gets as far as the resume_image call in
>>>>> swsusp_arch_resume and I could not find any response from the image
>>>>> kernel when I hit the bug. I also did testing that seemed to rule out
>>>>> this being caused by a problematic driver.
>>>>>
>>>>> I did a successful bisect between 3.18 and 3.19 which found a bug in
>>>>> commit f5b2831d6 that was then later fixed by commit 55696b1f66 in 4.4.
>>>>> Then, I did a second bisect with a ported version of the fix to the
>>>>> first bug and found commit ab76f7b4ab in 4.3 to also break hibernation
>>>>> with what appears to be the exact same symptoms. Reverting that commit
>>>>> in recent kernels up to and including 4.6 fixes the issue and restores
>>>>> reliable hibernation. However, it's not at all clear to me why that
>>>>> commit would cause this issue or how to fix the issue without reverting.
>>>>
>>>> I've attached that commit below and also Cc:-ed a few more people who might have
>>>> an idea about why this regressed. Worst-case we'll have to revert it.
>>>
>>> Without looking deep into mm, my theory would be that after this patch
>>> the final jump from the boot kernel to the image kernel's trampoline
>>> code during resume may crash the kernel if the trampoline page turns
>>> out to be NX in the boot kernel (it has to be executable in both the
>>> boot and the image kernels).
>>
>> So, pardon my ignorance, but where is this trampoline page placed in
>> kernel memory?
>
> On 32-bit its location has to be the same in both the boot and the
> image kernels and that's within kernel text in both cases, so that
> shouldn't be a problem.
>
> On 64-bit its location depends on the image kernel and specifically on
> the location of the restore_registers routine in it.  The (virtual)
> address of that routine is stored in the restore_jump_address
> variable, so the page containing it (the trampoline page) can be found
> with the help of that.
>
> swsusp_arch_resume() sets up a temporary kernel mapping to finalize
> the image restoration and that page must not be NX in that mapping for
> things to work.

It looks like nothing in the swsusp_arch_resume() -> get_safe_page()
-> get_image_page() path sets the page executable...

Untested, but I wonder if this work work in swsusp_arch_resume()
before the memcpy?

(apologies for any gmail-based whitespace mangling...)

diff --git a/arch/x86/power/hibernate_64.c b/arch/x86/power/hibernate_64.c
index 009947d419a6..c2f3ecc45bd4 100644
--- a/arch/x86/power/hibernate_64.c
+++ b/arch/x86/power/hibernate_64.c
@@ -12,6 +12,7 @@
 #include <linux/smp.h>
 #include <linux/suspend.h>

+#include <asm/cacheflush.h>
 #include <asm/init.h>
 #include <asm/proto.h>
 #include <asm/page.h>
@@ -89,6 +90,7 @@ int swsusp_arch_resume(void)
        relocated_restore_code = (void *)get_safe_page(GFP_ATOMIC);
        if (!relocated_restore_code)
                return -ENOMEM;
+       set_memory_x((unsigned long)relocated_restore_code, 1);
        memcpy(relocated_restore_code, &core_restore_code,
               &restore_registers - &core_restore_code);


-Kees

-- 
Kees Cook
Chrome OS & Brillo Security

[toc] | [prev] | [next] | [standalone]


#1404749

FromKees Cook <keescook@chromium.org>
Date2016-05-21 00:20 +0200
Message-ID<rB0VY-3pl-13@gated-at.bofh.it>
In reply to#1404743
On Fri, May 20, 2016 at 2:59 PM, Kees Cook <keescook@chromium.org> wrote:
> On Fri, May 20, 2016 at 2:46 PM, Rafael J. Wysocki <rafael@kernel.org> wrote:
>> On Fri, May 20, 2016 at 3:56 PM, Stephen Smalley <sds@tycho.nsa.gov> wrote:
>>> On 05/20/2016 07:34 AM, Rafael J. Wysocki wrote:
>>>> On Fri, May 20, 2016 at 9:15 AM, Ingo Molnar <mingo@kernel.org> wrote:
>>>>>
>>>>> * Logan Gunthorpe <logang@deltatee.com> wrote:
>>>>>
>>>>>> Hi,
>>>>>>
>>>>>> I have been working on a bug that causes my laptop to freeze during
>>>>>> resume from hibernation. I did a bisect to find the offending commit:
>>>>>>
>>>>>> [ab76f7b4ab] x86/mm: Set NX on gap between __ex_table and rodata
>>>>>>
>>>>>> There is more information in the bugzilla report [1] that
>>>>>> I've been working on but I will summarize things below.
>>>>>>
>>>>>> I've experienced intermittent but reproducible freezes when resuming
>>>>>> from hibernation since about kernel version 3.19. The freeze was
>>>>>> significantly more reproducible when a few applications were loaded
>>>>>> before hibernation and would largely not happen if hibernated
>>>>>> immediately after booting to a desktop. I did some tracing work to find
>>>>>> that the kernel gets as far as the resume_image call in
>>>>>> swsusp_arch_resume and I could not find any response from the image
>>>>>> kernel when I hit the bug. I also did testing that seemed to rule out
>>>>>> this being caused by a problematic driver.
>>>>>>
>>>>>> I did a successful bisect between 3.18 and 3.19 which found a bug in
>>>>>> commit f5b2831d6 that was then later fixed by commit 55696b1f66 in 4.4.
>>>>>> Then, I did a second bisect with a ported version of the fix to the
>>>>>> first bug and found commit ab76f7b4ab in 4.3 to also break hibernation
>>>>>> with what appears to be the exact same symptoms. Reverting that commit
>>>>>> in recent kernels up to and including 4.6 fixes the issue and restores
>>>>>> reliable hibernation. However, it's not at all clear to me why that
>>>>>> commit would cause this issue or how to fix the issue without reverting.
>>>>>
>>>>> I've attached that commit below and also Cc:-ed a few more people who might have
>>>>> an idea about why this regressed. Worst-case we'll have to revert it.
>>>>
>>>> Without looking deep into mm, my theory would be that after this patch
>>>> the final jump from the boot kernel to the image kernel's trampoline
>>>> code during resume may crash the kernel if the trampoline page turns
>>>> out to be NX in the boot kernel (it has to be executable in both the
>>>> boot and the image kernels).
>>>
>>> So, pardon my ignorance, but where is this trampoline page placed in
>>> kernel memory?
>>
>> On 32-bit its location has to be the same in both the boot and the
>> image kernels and that's within kernel text in both cases, so that
>> shouldn't be a problem.
>>
>> On 64-bit its location depends on the image kernel and specifically on
>> the location of the restore_registers routine in it.  The (virtual)
>> address of that routine is stored in the restore_jump_address
>> variable, so the page containing it (the trampoline page) can be found
>> with the help of that.
>>
>> swsusp_arch_resume() sets up a temporary kernel mapping to finalize
>> the image restoration and that page must not be NX in that mapping for
>> things to work.
>
> It looks like nothing in the swsusp_arch_resume() -> get_safe_page()
> -> get_image_page() path sets the page executable...
>
> Untested, but I wonder if this work work in swsusp_arch_resume()
> before the memcpy?

I can't type today, it seems. It should read "... if this would work ..."

If you can test this and it works for you, I'll send a proper patch... :P

-Kees

>
> (apologies for any gmail-based whitespace mangling...)
>
> diff --git a/arch/x86/power/hibernate_64.c b/arch/x86/power/hibernate_64.c
> index 009947d419a6..c2f3ecc45bd4 100644
> --- a/arch/x86/power/hibernate_64.c
> +++ b/arch/x86/power/hibernate_64.c
> @@ -12,6 +12,7 @@
>  #include <linux/smp.h>
>  #include <linux/suspend.h>
>
> +#include <asm/cacheflush.h>
>  #include <asm/init.h>
>  #include <asm/proto.h>
>  #include <asm/page.h>
> @@ -89,6 +90,7 @@ int swsusp_arch_resume(void)
>         relocated_restore_code = (void *)get_safe_page(GFP_ATOMIC);
>         if (!relocated_restore_code)
>                 return -ENOMEM;
> +       set_memory_x((unsigned long)relocated_restore_code, 1);
>         memcpy(relocated_restore_code, &core_restore_code,
>                &restore_registers - &core_restore_code);
>
>
> -Kees
>
> --
> Kees Cook
> Chrome OS & Brillo Security



-- 
Kees Cook
Chrome OS & Brillo Security

[toc] | [prev] | [next] | [standalone]


#1404869

FromKees Cook <keescook@chromium.org>
Date2016-05-21 18:50 +0200
Message-ID<rBig9-5UY-1@gated-at.bofh.it>
In reply to#1404749
On Fri, May 20, 2016 at 6:57 PM, Logan Gunthorpe <logang@deltatee.com> wrote:
> On 20/05/16 04:16 PM, Kees Cook wrote:
>>
>> On Fri, May 20, 2016 at 2:59 PM, Kees Cook <keescook@chromium.org> wrote:
>>>
>>> On Fri, May 20, 2016 at 2:46 PM, Rafael J. Wysocki <rafael@kernel.org>
>>> wrote:
>>>>
>>>> On Fri, May 20, 2016 at 3:56 PM, Stephen Smalley <sds@tycho.nsa.gov>
>>>> wrote:
>>>>>
>>>>> On 05/20/2016 07:34 AM, Rafael J. Wysocki wrote:
>>>>>>
>>>>>> On Fri, May 20, 2016 at 9:15 AM, Ingo Molnar <mingo@kernel.org> wrote:
>>>>>>>
>>>>>>>
>>>>>>> * Logan Gunthorpe <logang@deltatee.com> wrote:
>>>>>>>
>>>>>>>> Hi,
>>>>>>>>
>>>>>>>> I have been working on a bug that causes my laptop to freeze during
>>>>>>>> resume from hibernation. I did a bisect to find the offending
>>>>>>>> commit:
>>>>>>>>
>>>>>>>> [ab76f7b4ab] x86/mm: Set NX on gap between __ex_table and rodata
>>>>>>>>
>>>>>>>> There is more information in the bugzilla report [1] that
>>>>>>>> I've been working on but I will summarize things below.
>>>>>>>>
>>>>>>>> I've experienced intermittent but reproducible freezes when resuming
>>>>>>>> from hibernation since about kernel version 3.19. The freeze was
>>>>>>>> significantly more reproducible when a few applications were loaded
>>>>>>>> before hibernation and would largely not happen if hibernated
>>>>>>>> immediately after booting to a desktop. I did some tracing work to
>>>>>>>> find
>>>>>>>> that the kernel gets as far as the resume_image call in
>>>>>>>> swsusp_arch_resume and I could not find any response from the image
>>>>>>>> kernel when I hit the bug. I also did testing that seemed to rule
>>>>>>>> out
>>>>>>>> this being caused by a problematic driver.
>>>>>>>>
>>>>>>>> I did a successful bisect between 3.18 and 3.19 which found a bug in
>>>>>>>> commit f5b2831d6 that was then later fixed by commit 55696b1f66 in
>>>>>>>> 4.4.
>>>>>>>> Then, I did a second bisect with a ported version of the fix to the
>>>>>>>> first bug and found commit ab76f7b4ab in 4.3 to also break
>>>>>>>> hibernation
>>>>>>>> with what appears to be the exact same symptoms. Reverting that
>>>>>>>> commit
>>>>>>>> in recent kernels up to and including 4.6 fixes the issue and
>>>>>>>> restores
>>>>>>>> reliable hibernation. However, it's not at all clear to me why that
>>>>>>>> commit would cause this issue or how to fix the issue without
>>>>>>>> reverting.
>>>>>>>
>>>>>>>
>>>>>>> I've attached that commit below and also Cc:-ed a few more people who
>>>>>>> might have
>>>>>>> an idea about why this regressed. Worst-case we'll have to revert it.
>>>>>>
>>>>>>
>>>>>> Without looking deep into mm, my theory would be that after this patch
>>>>>> the final jump from the boot kernel to the image kernel's trampoline
>>>>>> code during resume may crash the kernel if the trampoline page turns
>>>>>> out to be NX in the boot kernel (it has to be executable in both the
>>>>>> boot and the image kernels).
>>>>>
>>>>>
>>>>> So, pardon my ignorance, but where is this trampoline page placed in
>>>>> kernel memory?
>>>>
>>>>
>>>> On 32-bit its location has to be the same in both the boot and the
>>>> image kernels and that's within kernel text in both cases, so that
>>>> shouldn't be a problem.
>>>>
>>>> On 64-bit its location depends on the image kernel and specifically on
>>>> the location of the restore_registers routine in it.  The (virtual)
>>>> address of that routine is stored in the restore_jump_address
>>>> variable, so the page containing it (the trampoline page) can be found
>>>> with the help of that.
>>>>
>>>> swsusp_arch_resume() sets up a temporary kernel mapping to finalize
>>>> the image restoration and that page must not be NX in that mapping for
>>>> things to work.
>>>
>>>
>>> It looks like nothing in the swsusp_arch_resume() -> get_safe_page()
>>> -> get_image_page() path sets the page executable...
>>>
>>> Untested, but I wonder if this work work in swsusp_arch_resume()
>>> before the memcpy?
>>
>>
>> I can't type today, it seems. It should read "... if this would work ..."
>>
>> If you can test this and it works for you, I'll send a proper patch... :P
>>
>> -Kees
>>
>
> Hi Kees,
>
> Thanks. I tried the patch but it only resulted in a kernel warning and
> freeze. I've attached a photo showing as much of the messages as I could
> get.
>
> Logan

Ah, dang, ok, thanks for trying it. I'll let Rafael try to figure this one out.

-Kees

-- 
Kees Cook
Chrome OS & Brillo Security

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web