Prefer kASLR over Hibernation
diff mbox series

Message ID 20160406194404.GA11150@www.outflux.net
State New, archived
Headers show
Series
  • Prefer kASLR over Hibernation
Related show

Commit Message

Kees Cook April 6, 2016, 7:44 p.m. UTC
When building with both CONFIG_HIBERNATION and CONFIG_RANDOMIZE_BASE,
one or the other must be chosen at boot-time. Until now, hibernation
was selected when no choice was made on the command line.

To make the security benefits of kASLR more widely available to end
users (since the use of hibernation is becoming more rare and kASLR,
already available on x86, will be available on arm64 and MIPS soon),
this changes the default to preferring kASLR over hibernation. Users
wanting hibernation can turn off kASLR by adding "nokaslr" to the kernel
command line.

Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 Documentation/kernel-parameters.txt |  7 +++++--
 arch/x86/boot/compressed/aslr.c     |  7 -------
 kernel/power/hibernate.c            | 13 +++++++++++++
 3 files changed, 18 insertions(+), 9 deletions(-)

Comments

Pavel Machek April 6, 2016, 8:17 p.m. UTC | #1
Hi!

> When building with both CONFIG_HIBERNATION and CONFIG_RANDOMIZE_BASE,
> one or the other must be chosen at boot-time. Until now, hibernation
> was selected when no choice was made on the command line.
> 
> To make the security benefits of kASLR more widely available to end
> users (since the use of hibernation is becoming more rare and kASLR,
> already available on x86, will be available on arm64 and MIPS soon),
> this changes the default to preferring kASLR over hibernation. Users
> wanting hibernation can turn off kASLR by adding "nokaslr" to the kernel
> command line.

I must say I don't exactly like this patch.

Why is kASLR incompatible with hibernation? We can hibernate have 
4.3 kernel resume hibernation image of 4.2 kernel (on x86-64, and I
have patches for x86). Resuming kernel with different randomization
does not look that much different...

Best regards,
								Pavel
Linus Torvalds April 6, 2016, 8:56 p.m. UTC | #2
On Wed, Apr 6, 2016 at 1:17 PM, Pavel Machek <pavel@denx.de> wrote:
>
> Why is kASLR incompatible with hibernation? We can hibernate have
> 4.3 kernel resume hibernation image of 4.2 kernel (on x86-64, and I
> have patches for x86). Resuming kernel with different randomization
> does not look that much different...

Oh, I'd absolutely prefer to just allow kaslr together with
hibernation if it actually works.

Could the people who piped up to say that they actually use
hibernation just try passing in the "kaslr" command line option on
their machine, and see if it works for them? We could just remove the
"no kaslr with hibername" code - or at least limit it to 32-bit for
now..

Because that would be lovely.

            Linus
Kees Cook April 6, 2016, 9:25 p.m. UTC | #3
On Wed, Apr 6, 2016 at 1:56 PM, Linus Torvalds
<torvalds@linux-foundation.org> wrote:
> On Wed, Apr 6, 2016 at 1:17 PM, Pavel Machek <pavel@denx.de> wrote:
>>
>> Why is kASLR incompatible with hibernation? We can hibernate have
>> 4.3 kernel resume hibernation image of 4.2 kernel (on x86-64, and I
>> have patches for x86). Resuming kernel with different randomization
>> does not look that much different...
>
> Oh, I'd absolutely prefer to just allow kaslr together with
> hibernation if it actually works.
>
> Could the people who piped up to say that they actually use
> hibernation just try passing in the "kaslr" command line option on
> their machine, and see if it works for them? We could just remove the
> "no kaslr with hibername" code - or at least limit it to 32-bit for
> now..
>
> Because that would be lovely.

This is where our original investigation of having them coexist ended:
https://lkml.org/lkml/2014/6/15/180

To quote Rafael Wysocki:
> We're jumping from the boot kernel into the image kernel.  The virtual address
> comes from the image kernel, but the boot kernel has to use it.  The only way
> we can ensure that we'll jump to the right place is to pass the physical address
> in the header (otherwise we de facto assume that the virtual address of the
> target page frame will be the same in both the boot and the image kernels).
>
> The missing piece is that the code in swsusp_arch_resume() sets up temporary
> page tables to ensure that they won't be overwritten while copying the last
> remaining image kernel pages to the right page frames (those page tables
> have to be stored in page frames that are free from the kernel image perspective).
>
> But if the kernel address space is randomized, set_up_temporary_mappings()
> really should duplicate the existing layout instead of creating a new one from
> scratch.  Otherwise, virtual addresses before set_up_temporary_mappings() may
> be different from the ones after it.

-Kees
Ingo Molnar April 6, 2016, 9:48 p.m. UTC | #4
* Kees Cook <keescook@chromium.org> wrote:

> On Wed, Apr 6, 2016 at 1:56 PM, Linus Torvalds
> <torvalds@linux-foundation.org> wrote:
> > On Wed, Apr 6, 2016 at 1:17 PM, Pavel Machek <pavel@denx.de> wrote:
> >>
> >> Why is kASLR incompatible with hibernation? We can hibernate have
> >> 4.3 kernel resume hibernation image of 4.2 kernel (on x86-64, and I
> >> have patches for x86). Resuming kernel with different randomization
> >> does not look that much different...
> >
> > Oh, I'd absolutely prefer to just allow kaslr together with
> > hibernation if it actually works.
> >
> > Could the people who piped up to say that they actually use
> > hibernation just try passing in the "kaslr" command line option on
> > their machine, and see if it works for them? We could just remove the
> > "no kaslr with hibername" code - or at least limit it to 32-bit for
> > now..
> >
> > Because that would be lovely.
> 
> This is where our original investigation of having them coexist ended:
> https://lkml.org/lkml/2014/6/15/180
> 
> To quote Rafael Wysocki:
> > We're jumping from the boot kernel into the image kernel.  The virtual address
> > comes from the image kernel, but the boot kernel has to use it.  The only way
> > we can ensure that we'll jump to the right place is to pass the physical address
> > in the header (otherwise we de facto assume that the virtual address of the
> > target page frame will be the same in both the boot and the image kernels).
> >
> > The missing piece is that the code in swsusp_arch_resume() sets up temporary
> > page tables to ensure that they won't be overwritten while copying the last
> > remaining image kernel pages to the right page frames (those page tables
> > have to be stored in page frames that are free from the kernel image perspective).
> >
> > But if the kernel address space is randomized, set_up_temporary_mappings()
> > really should duplicate the existing layout instead of creating a new one from
> > scratch.  Otherwise, virtual addresses before set_up_temporary_mappings() may
> > be different from the ones after it.

So as I suggested it in the previous mail, the right solution would be to pass in 
the randomization seed via a new kasl_seed=xyz boot option, and thus have the same 
addresses as prior hibernation.

That should make hibernation work as-is, with very little effort.

Two details I can think of:

1) the new option has to be hidden from /proc/cmdline, due to:

  triton:~/tip> ll /proc/cmdline
  -r--r--r-- 1 root root 0 Apr  6 23:45 /proc/cmdline

2)

another detail is that the new boot option has to be checked in 
choose_kernel_location(), to make sure it's done at the right point during bootup. 
That's a good place to remove it from the boot options string as well.

Thanks,

	Ingo
Rafael J. Wysocki April 6, 2016, 9:49 p.m. UTC | #5
On Wed, Apr 6, 2016 at 9:44 PM, Kees Cook <keescook@chromium.org> wrote:
> When building with both CONFIG_HIBERNATION and CONFIG_RANDOMIZE_BASE,
> one or the other must be chosen at boot-time. Until now, hibernation
> was selected when no choice was made on the command line.
>
> To make the security benefits of kASLR more widely available to end
> users (since the use of hibernation is becoming more rare and kASLR,
> already available on x86, will be available on arm64 and MIPS soon),
> this changes the default to preferring kASLR over hibernation. Users
> wanting hibernation can turn off kASLR by adding "nokaslr" to the kernel
> command line.
>
> Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
> Signed-off-by: Kees Cook <keescook@chromium.org>

Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Or do you want me to apply it?
Ingo Molnar April 6, 2016, 9:52 p.m. UTC | #6
* Ingo Molnar <mingo@kernel.org> wrote:

> 
> * Kees Cook <keescook@chromium.org> wrote:
> 
> > On Wed, Apr 6, 2016 at 1:56 PM, Linus Torvalds
> > <torvalds@linux-foundation.org> wrote:
> > > On Wed, Apr 6, 2016 at 1:17 PM, Pavel Machek <pavel@denx.de> wrote:
> > >>
> > >> Why is kASLR incompatible with hibernation? We can hibernate have
> > >> 4.3 kernel resume hibernation image of 4.2 kernel (on x86-64, and I
> > >> have patches for x86). Resuming kernel with different randomization
> > >> does not look that much different...
> > >
> > > Oh, I'd absolutely prefer to just allow kaslr together with
> > > hibernation if it actually works.
> > >
> > > Could the people who piped up to say that they actually use
> > > hibernation just try passing in the "kaslr" command line option on
> > > their machine, and see if it works for them? We could just remove the
> > > "no kaslr with hibername" code - or at least limit it to 32-bit for
> > > now..
> > >
> > > Because that would be lovely.
> > 
> > This is where our original investigation of having them coexist ended:
> > https://lkml.org/lkml/2014/6/15/180
> > 
> > To quote Rafael Wysocki:
> > > We're jumping from the boot kernel into the image kernel.  The virtual address
> > > comes from the image kernel, but the boot kernel has to use it.  The only way
> > > we can ensure that we'll jump to the right place is to pass the physical address
> > > in the header (otherwise we de facto assume that the virtual address of the
> > > target page frame will be the same in both the boot and the image kernels).
> > >
> > > The missing piece is that the code in swsusp_arch_resume() sets up temporary
> > > page tables to ensure that they won't be overwritten while copying the last
> > > remaining image kernel pages to the right page frames (those page tables
> > > have to be stored in page frames that are free from the kernel image perspective).
> > >
> > > But if the kernel address space is randomized, set_up_temporary_mappings()
> > > really should duplicate the existing layout instead of creating a new one from
> > > scratch.  Otherwise, virtual addresses before set_up_temporary_mappings() may
> > > be different from the ones after it.
> 
> So as I suggested it in the previous mail, the right solution would be to pass in 
> the randomization seed via a new kasl_seed=xyz boot option, and thus have the same 
> addresses as prior hibernation.
> 
> That should make hibernation work as-is, with very little effort.
> 
> Two details I can think of:
> 
> 1) the new option has to be hidden from /proc/cmdline, due to:
> 
>   triton:~/tip> ll /proc/cmdline
>   -r--r--r-- 1 root root 0 Apr  6 23:45 /proc/cmdline
> 
> 2)
> 
> another detail is that the new boot option has to be checked in 
> choose_kernel_location(), to make sure it's done at the right point during bootup. 
> That's a good place to remove it from the boot options string as well.

... and I missed the biggest complication: to solve the chicken and egg problem 
with software_resume() running very late during bootup, software_resume() should 
probably kexec() the original kernel image, this time with the kaslr seed set in 
the boot parameters.

So it's two bootups...

Thanks,

	Ingo
Ingo Molnar April 6, 2016, 9:56 p.m. UTC | #7
* Rafael J. Wysocki <rafael@kernel.org> wrote:

> On Wed, Apr 6, 2016 at 9:44 PM, Kees Cook <keescook@chromium.org> wrote:
> > When building with both CONFIG_HIBERNATION and CONFIG_RANDOMIZE_BASE,
> > one or the other must be chosen at boot-time. Until now, hibernation
> > was selected when no choice was made on the command line.
> >
> > To make the security benefits of kASLR more widely available to end
> > users (since the use of hibernation is becoming more rare and kASLR,
> > already available on x86, will be available on arm64 and MIPS soon),
> > this changes the default to preferring kASLR over hibernation. Users
> > wanting hibernation can turn off kASLR by adding "nokaslr" to the kernel
> > command line.
> >
> > Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
> > Signed-off-by: Kees Cook <keescook@chromium.org>
> 
> Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> 
> Or do you want me to apply it?

I don't think this is a good idea, as it turns off emergency hibernation of 
laptops - many desktop distros support it by default.

Thanks,

	Ingo
Rafael J. Wysocki April 6, 2016, 10:04 p.m. UTC | #8
On Wed, Apr 6, 2016 at 11:56 PM, Ingo Molnar <mingo@kernel.org> wrote:
>
> * Rafael J. Wysocki <rafael@kernel.org> wrote:
>
>> On Wed, Apr 6, 2016 at 9:44 PM, Kees Cook <keescook@chromium.org> wrote:
>> > When building with both CONFIG_HIBERNATION and CONFIG_RANDOMIZE_BASE,
>> > one or the other must be chosen at boot-time. Until now, hibernation
>> > was selected when no choice was made on the command line.
>> >
>> > To make the security benefits of kASLR more widely available to end
>> > users (since the use of hibernation is becoming more rare and kASLR,
>> > already available on x86, will be available on arm64 and MIPS soon),
>> > this changes the default to preferring kASLR over hibernation. Users
>> > wanting hibernation can turn off kASLR by adding "nokaslr" to the kernel
>> > command line.
>> >
>> > Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
>> > Signed-off-by: Kees Cook <keescook@chromium.org>
>>
>> Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>>
>> Or do you want me to apply it?
>
> I don't think this is a good idea, as it turns off emergency hibernation of
> laptops - many desktop distros support it by default.

Right, I forgot about this one.

Thanks,
Rafael
Kees Cook April 6, 2016, 10:16 p.m. UTC | #9
On Wed, Apr 6, 2016 at 3:04 PM, Rafael J. Wysocki <rafael@kernel.org> wrote:
> On Wed, Apr 6, 2016 at 11:56 PM, Ingo Molnar <mingo@kernel.org> wrote:
>>
>> * Rafael J. Wysocki <rafael@kernel.org> wrote:
>>
>>> On Wed, Apr 6, 2016 at 9:44 PM, Kees Cook <keescook@chromium.org> wrote:
>>> > When building with both CONFIG_HIBERNATION and CONFIG_RANDOMIZE_BASE,
>>> > one or the other must be chosen at boot-time. Until now, hibernation
>>> > was selected when no choice was made on the command line.
>>> >
>>> > To make the security benefits of kASLR more widely available to end
>>> > users (since the use of hibernation is becoming more rare and kASLR,
>>> > already available on x86, will be available on arm64 and MIPS soon),
>>> > this changes the default to preferring kASLR over hibernation. Users
>>> > wanting hibernation can turn off kASLR by adding "nokaslr" to the kernel
>>> > command line.
>>> >
>>> > Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
>>> > Signed-off-by: Kees Cook <keescook@chromium.org>
>>>
>>> Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>>>
>>> Or do you want me to apply it?
>>
>> I don't think this is a good idea, as it turns off emergency hibernation of
>> laptops - many desktop distros support it by default.
>
> Right, I forgot about this one.

When I last checked Ubuntu doesn't enable hibernation by default any more:
https://help.ubuntu.com/16.04/ubuntu-help/power-hibernate.html

And it seems like Fedora either doesn't either, or has a lot of people
for whom it doesn't work:
https://bugzilla.redhat.com/show_bug.cgi?id=1206936
https://bugzilla.redhat.com/show_bug.cgi?id=1224151
http://blog.kriptonium.com/2015/12/fedora-23-hibernate.html

-Kees
Rafael J. Wysocki April 6, 2016, 10:32 p.m. UTC | #10
On Wed, Apr 6, 2016 at 11:52 PM, Ingo Molnar <mingo@kernel.org> wrote:
>
> * Ingo Molnar <mingo@kernel.org> wrote:
>
>>
>> * Kees Cook <keescook@chromium.org> wrote:
>>
>> > On Wed, Apr 6, 2016 at 1:56 PM, Linus Torvalds
>> > <torvalds@linux-foundation.org> wrote:
>> > > On Wed, Apr 6, 2016 at 1:17 PM, Pavel Machek <pavel@denx.de> wrote:
>> > >>
>> > >> Why is kASLR incompatible with hibernation? We can hibernate have
>> > >> 4.3 kernel resume hibernation image of 4.2 kernel (on x86-64, and I
>> > >> have patches for x86). Resuming kernel with different randomization
>> > >> does not look that much different...
>> > >
>> > > Oh, I'd absolutely prefer to just allow kaslr together with
>> > > hibernation if it actually works.
>> > >
>> > > Could the people who piped up to say that they actually use
>> > > hibernation just try passing in the "kaslr" command line option on
>> > > their machine, and see if it works for them? We could just remove the
>> > > "no kaslr with hibername" code - or at least limit it to 32-bit for
>> > > now..
>> > >
>> > > Because that would be lovely.
>> >
>> > This is where our original investigation of having them coexist ended:
>> > https://lkml.org/lkml/2014/6/15/180
>> >
>> > To quote Rafael Wysocki:
>> > > We're jumping from the boot kernel into the image kernel.  The virtual address
>> > > comes from the image kernel, but the boot kernel has to use it.  The only way
>> > > we can ensure that we'll jump to the right place is to pass the physical address
>> > > in the header (otherwise we de facto assume that the virtual address of the
>> > > target page frame will be the same in both the boot and the image kernels).
>> > >
>> > > The missing piece is that the code in swsusp_arch_resume() sets up temporary
>> > > page tables to ensure that they won't be overwritten while copying the last
>> > > remaining image kernel pages to the right page frames (those page tables
>> > > have to be stored in page frames that are free from the kernel image perspective).
>> > >
>> > > But if the kernel address space is randomized, set_up_temporary_mappings()
>> > > really should duplicate the existing layout instead of creating a new one from
>> > > scratch.  Otherwise, virtual addresses before set_up_temporary_mappings() may
>> > > be different from the ones after it.
>>
>> So as I suggested it in the previous mail, the right solution would be to pass in
>> the randomization seed via a new kasl_seed=xyz boot option, and thus have the same
>> addresses as prior hibernation.
>>
>> That should make hibernation work as-is, with very little effort.
>>
>> Two details I can think of:
>>
>> 1) the new option has to be hidden from /proc/cmdline, due to:
>>
>>   triton:~/tip> ll /proc/cmdline
>>   -r--r--r-- 1 root root 0 Apr  6 23:45 /proc/cmdline
>>
>> 2)
>>
>> another detail is that the new boot option has to be checked in
>> choose_kernel_location(), to make sure it's done at the right point during bootup.
>> That's a good place to remove it from the boot options string as well.
>
> ... and I missed the biggest complication: to solve the chicken and egg problem
> with software_resume() running very late during bootup, software_resume() should
> probably kexec() the original kernel image, this time with the kaslr seed set in
> the boot parameters.
>
> So it's two bootups...

I'm not sure I get this part to be honest.

The image kernel will use its own page tables with the original
address space layout no matter what, so I'm not sure why it needs the
seed.

Also the loading of the image is based on PFNs and not on virtual
addresses, so during resume all of the page frames used before
hibernation will be populated with the same data regardless of the
randomization.

One of the weak points is the final jump, because it has to be done to
the physical location of the image kernel's entry point even though
the virtual addresses of it may differ between the boot and the image
kernels.  The seed is not needed for that, only the physical address
of the entry point.  The boot kernel doesn't have it today, though,
because the virtual address of that is passed in the image header.
That should not be too difficult to change, however.

The second weak point is the temporary page tables setup in
swsusp_arch_resume(), but as I said in the quoted message, that can be
addressed by copying the existing page tables (of the boot kernel)
instead of creating new ones from scratch - or by ensuring that the
new ones will be laid out in exactly the same way.  Again, the seed is
not necessary here, because all of that is confined to the boot kernel
only.

Thanks,
Rafael
Paul Bolle April 6, 2016, 10:41 p.m. UTC | #11
On wo, 2016-04-06 at 15:16 -0700, Kees Cook wrote:
> And it seems like Fedora either doesn't either, or has a lot of people
> for whom it doesn't work:
> https://bugzilla.redhat.com/show_bug.cgi?id=1206936
> https://bugzilla.redhat.com/show_bug.cgi?id=1224151
> http://blog.kriptonium.com/2015/12/fedora-23-hibernate.html

Which are all variations on a theme: add "resume=$SWAP" to your kernel
commandline, aren't they?

(No idea why that's needed since Fedora 22, but it cost me quite a bit
of head scratching to find out.)

Once that parameter was set hibernate functioned again on the few
laptops I, well, manage that run Fedora 22.

Thanks,


Paul Bolle
Ingo Molnar April 7, 2016, 12:05 a.m. UTC | #12
* Kees Cook <keescook@chromium.org> wrote:

> >> I don't think this is a good idea, as it turns off emergency hibernation of 
> >> laptops - many desktop distros support it by default.
> >
> > Right, I forgot about this one.
> 
> When I last checked Ubuntu doesn't enable hibernation by default any more: 
> https://help.ubuntu.com/16.04/ubuntu-help/power-hibernate.html
> 
> And it seems like Fedora either doesn't either, or has a lot of people
> for whom it doesn't work:
> https://bugzilla.redhat.com/show_bug.cgi?id=1206936
> https://bugzilla.redhat.com/show_bug.cgi?id=1224151
> http://blog.kriptonium.com/2015/12/fedora-23-hibernate.html

Ok, that's a relatively recent development, I distinctly remember my laptop being 
hibernated in such a fashion fairly recently.

That makes it easier to hack around the kASLR incompatibility by making 
hibernation less useful. Personally I think that conceptually user space 
persistency (CRIU et al) is superior to kernel level hibernation - but
user-space save/restore is nowhere near as complete as kernel hibernation,
so it's still somewhat sad that it doesn't work ...

Thanks,

	Ingo
Ingo Molnar April 7, 2016, 12:49 a.m. UTC | #13
* Rafael J. Wysocki <rafael@kernel.org> wrote:

> [...]
> 
> One of the weak points is the final jump, because it has to be done to the 
> physical location of the image kernel's entry point even though the virtual 
> addresses of it may differ between the boot and the image kernels.  The seed is 
> not needed for that, only the physical address of the entry point.  The boot 
> kernel doesn't have it today, though, because the virtual address of that is 
> passed in the image header. That should not be too difficult to change, however.

I didn't realize we jumped to the image kernel as well - I (wrongly) assumed we 
kept the bootup kernel. That should indeed make hibernation mostly 
kASLR-invariant.

Thanks,

	Ingo
James Morse April 11, 2016, 8 a.m. UTC | #14
Hi Kees,

On 06/04/16 20:44, Kees Cook wrote:
> When building with both CONFIG_HIBERNATION and CONFIG_RANDOMIZE_BASE,
> one or the other must be chosen at boot-time. Until now, hibernation
> was selected when no choice was made on the command line.
> 
> To make the security benefits of kASLR more widely available to end
> users (since the use of hibernation is becoming more rare and kASLR,
> already available on x86, will be available on arm64 and MIPS soon),
> this changes the default to preferring kASLR over hibernation. Users
> wanting hibernation can turn off kASLR by adding "nokaslr" to the kernel
> command line.

While hibernate isn't yet merged for arm64, it does work with kASLR in v4.6-rc*,
it would be a shame to have to choose at boot time, (but that's my problem to
fix if/when its merged).


> diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
> index fca9254280ee..be5041354b1e 100644
> --- a/kernel/power/hibernate.c
> +++ b/kernel/power/hibernate.c
> @@ -1159,6 +1164,13 @@ static int __init kaslr_nohibernate_setup(char *str)
>  	return nohibernate_setup(str);
>  }
>  
> +static int __init nokaslr_hibernate_setup(char *str)
> +{
> +	noresume = 0;
> +	nohibernate = 0;
> +	return 1;
> +}
> +
>  static int __init page_poison_nohibernate_setup(char *str)
>  {
>  #ifdef CONFIG_PAGE_POISONING_ZERO
> @@ -1183,4 +1195,5 @@ __setup("resumewait", resumewait_setup);
>  __setup("resumedelay=", resumedelay_setup);
>  __setup("nohibernate", nohibernate_setup);
>  __setup("kaslr", kaslr_nohibernate_setup);
> +__setup("nokaslr", nokaslr_hibernate_setup);

So one or the other option has to be specified at boot?

The kASLR patches for arm64 in v4.6-rc1 enable kASLR at boot if you chose to
select it at compile time. I guess this patch is preparation for doing the same
on x86?

I didn't hit this kaslr_nohibernate_setup() call during testing because of the
on by default behaviour. Is it worth exposing this via Kconfig? Something like:
ARCH_RANDOMIZE_BASE_DEFAULT_ON ?


Thanks,

James
Kees Cook April 11, 2016, 6:03 p.m. UTC | #15
On Mon, Apr 11, 2016 at 1:00 AM, James Morse <james.morse@arm.com> wrote:
> Hi Kees,
>
> On 06/04/16 20:44, Kees Cook wrote:
>> When building with both CONFIG_HIBERNATION and CONFIG_RANDOMIZE_BASE,
>> one or the other must be chosen at boot-time. Until now, hibernation
>> was selected when no choice was made on the command line.
>>
>> To make the security benefits of kASLR more widely available to end
>> users (since the use of hibernation is becoming more rare and kASLR,
>> already available on x86, will be available on arm64 and MIPS soon),
>> this changes the default to preferring kASLR over hibernation. Users
>> wanting hibernation can turn off kASLR by adding "nokaslr" to the kernel
>> command line.
>
> While hibernate isn't yet merged for arm64, it does work with kASLR in v4.6-rc*,
> it would be a shame to have to choose at boot time, (but that's my problem to
> fix if/when its merged).

Ah, interesting, so they work together on arm64? (i.e. you've actually
tested a boot loader that provides the seed for kASLR to operate?)

>> diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
>> index fca9254280ee..be5041354b1e 100644
>> --- a/kernel/power/hibernate.c
>> +++ b/kernel/power/hibernate.c
>> @@ -1159,6 +1164,13 @@ static int __init kaslr_nohibernate_setup(char *str)
>>       return nohibernate_setup(str);
>>  }
>>
>> +static int __init nokaslr_hibernate_setup(char *str)
>> +{
>> +     noresume = 0;
>> +     nohibernate = 0;
>> +     return 1;
>> +}
>> +
>>  static int __init page_poison_nohibernate_setup(char *str)
>>  {
>>  #ifdef CONFIG_PAGE_POISONING_ZERO
>> @@ -1183,4 +1195,5 @@ __setup("resumewait", resumewait_setup);
>>  __setup("resumedelay=", resumedelay_setup);
>>  __setup("nohibernate", nohibernate_setup);
>>  __setup("kaslr", kaslr_nohibernate_setup);
>> +__setup("nokaslr", nokaslr_hibernate_setup);
>
> So one or the other option has to be specified at boot?

No, this patch was just flipping the default from hibernate to kASLR
if "kaslr" wasn't on the command line.

> The kASLR patches for arm64 in v4.6-rc1 enable kASLR at boot if you chose to
> select it at compile time. I guess this patch is preparation for doing the same
> on x86?

That was the goal, yes. A better approach would be to have hibernate
on x86 work with kASLR, but I likely won't have time to learn the
details on hibernation and debug it for a while.

> I didn't hit this kaslr_nohibernate_setup() call during testing because of the
> on by default behaviour. Is it worth exposing this via Kconfig? Something like:
> ARCH_RANDOMIZE_BASE_DEFAULT_ON ?

Maybe RANDOMIZE_BASE_DEFAULT (default to y) and if x86 && hibernation,
select =n. and use that for selecting it?

-Kees
Geert Uytterhoeven April 11, 2016, 6:21 p.m. UTC | #16
On Mon, Apr 11, 2016 at 8:03 PM, Kees Cook <keescook@chromium.org> wrote:
> On Mon, Apr 11, 2016 at 1:00 AM, James Morse <james.morse@arm.com> wrote:
>> On 06/04/16 20:44, Kees Cook wrote:
>>> When building with both CONFIG_HIBERNATION and CONFIG_RANDOMIZE_BASE,
>>> one or the other must be chosen at boot-time. Until now, hibernation
>>> was selected when no choice was made on the command line.
>>>
>>> To make the security benefits of kASLR more widely available to end
>>> users (since the use of hibernation is becoming more rare and kASLR,
>>> already available on x86, will be available on arm64 and MIPS soon),
>>> this changes the default to preferring kASLR over hibernation. Users
>>> wanting hibernation can turn off kASLR by adding "nokaslr" to the kernel
>>> command line.
>>
>> While hibernate isn't yet merged for arm64, it does work with kASLR in v4.6-rc*,
>> it would be a shame to have to choose at boot time, (but that's my problem to
>> fix if/when its merged).
>
> Ah, interesting, so they work together on arm64? (i.e. you've actually
> tested a boot loader that provides the seed for kASLR to operate?)

Probably the PS3 people can provide us with a good tool to generate a
seed that makes hibernation work all the time ;-)

https://xkcd.com/221/

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds
Kees Cook April 11, 2016, 6:47 p.m. UTC | #17
On Mon, Apr 11, 2016 at 11:21 AM, Geert Uytterhoeven
<geert@linux-m68k.org> wrote:
> On Mon, Apr 11, 2016 at 8:03 PM, Kees Cook <keescook@chromium.org> wrote:
>> On Mon, Apr 11, 2016 at 1:00 AM, James Morse <james.morse@arm.com> wrote:
>>> On 06/04/16 20:44, Kees Cook wrote:
>>>> When building with both CONFIG_HIBERNATION and CONFIG_RANDOMIZE_BASE,
>>>> one or the other must be chosen at boot-time. Until now, hibernation
>>>> was selected when no choice was made on the command line.
>>>>
>>>> To make the security benefits of kASLR more widely available to end
>>>> users (since the use of hibernation is becoming more rare and kASLR,
>>>> already available on x86, will be available on arm64 and MIPS soon),
>>>> this changes the default to preferring kASLR over hibernation. Users
>>>> wanting hibernation can turn off kASLR by adding "nokaslr" to the kernel
>>>> command line.
>>>
>>> While hibernate isn't yet merged for arm64, it does work with kASLR in v4.6-rc*,
>>> it would be a shame to have to choose at boot time, (but that's my problem to
>>> fix if/when its merged).
>>
>> Ah, interesting, so they work together on arm64? (i.e. you've actually
>> tested a boot loader that provides the seed for kASLR to operate?)
>
> Probably the PS3 people can provide us with a good tool to generate a
> seed that makes hibernation work all the time ;-)
>
> https://xkcd.com/221/

:)

http://assets.amuniversal.com/321a39e06d6401301d80001dd8b71c47

-Kees
James Morse April 12, 2016, 5:51 p.m. UTC | #18
On 11/04/16 19:03, Kees Cook wrote:
> On Mon, Apr 11, 2016 at 1:00 AM, James Morse <james.morse@arm.com> wrote:
>> On 06/04/16 20:44, Kees Cook wrote:
>>> When building with both CONFIG_HIBERNATION and CONFIG_RANDOMIZE_BASE,
>>> one or the other must be chosen at boot-time. Until now, hibernation
>>> was selected when no choice was made on the command line.
>>>
>>> To make the security benefits of kASLR more widely available to end
>>> users (since the use of hibernation is becoming more rare and kASLR,
>>> already available on x86, will be available on arm64 and MIPS soon),
>>> this changes the default to preferring kASLR over hibernation. Users
>>> wanting hibernation can turn off kASLR by adding "nokaslr" to the kernel
>>> command line.
>>
>> While hibernate isn't yet merged for arm64, it does work with kASLR in v4.6-rc*,
>> it would be a shame to have to choose at boot time, (but that's my problem to
>> fix if/when its merged).
> 
> Ah, interesting, so they work together on arm64? (i.e. you've actually
> tested a boot loader that provides the seed for kASLR to operate?)

Almost: due to a lack of firmware support I hacked the efi stub to read a 'seed'
from a system counter.

To check it works I printed the address of 'panic' out during boot:
> [    0.353712] DEBUG: &panic == ffffff960819a4e8

Then hibernated, and powered the board back on, the resume kernel gives:
> [    0.353528] DEBUG: &panic == ffffff840819a4e8

But after it has restored the hibernate image, I can dig in /proc/kallsyms to
see the original value:
> root@localhost:~# cat /proc/kallsyms  | grep "T panic"
> ffffff960819a4e8 T panic


> Maybe RANDOMIZE_BASE_DEFAULT (default to y) and if x86 && hibernation,
> select =n. and use that for selecting it?

Looks good to me.


Thanks,

James

Patch
diff mbox series

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index ecc74fa4bfde..71393ec89295 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1774,8 +1774,8 @@  bytes respectively. Such letter suffixes can also be entirely omitted.
 			Enable/disable kernel and module base offset ASLR
 			(Address Space Layout Randomization) if built into
 			the kernel. When CONFIG_HIBERNATION is selected,
-			kASLR is disabled by default. When kASLR is enabled,
-			hibernation will be disabled.
+			kASLR must be disabled for hibernation to be
+			available.
 
 	keepinitrd	[HW,ARM]
 
@@ -3513,6 +3513,9 @@  bytes respectively. Such letter suffixes can also be entirely omitted.
 			(e.g. USB and MMC devices).
 
 	hibernate=	[HIBERNATION]
+			When CONFIG_RANDOMIZE_BASE is defined, hibernation
+			is disabled by default. Hibernation can be enabled
+			by passing "nokaslr" on the kernel command line.
 		noresume	Don't check if there's a hibernation image
 				present during boot.
 		nocompress	Don't compress/decompress hibernation images.
diff --git a/arch/x86/boot/compressed/aslr.c b/arch/x86/boot/compressed/aslr.c
index 6a9b96b4624d..81e2835c0dfb 100644
--- a/arch/x86/boot/compressed/aslr.c
+++ b/arch/x86/boot/compressed/aslr.c
@@ -304,17 +304,10 @@  unsigned char *choose_kernel_location(struct boot_params *boot_params,
 	unsigned long choice = (unsigned long)output;
 	unsigned long random;
 
-#ifdef CONFIG_HIBERNATION
-	if (!cmdline_find_option_bool("kaslr")) {
-		debug_putstr("KASLR disabled by default...\n");
-		goto out;
-	}
-#else
 	if (cmdline_find_option_bool("nokaslr")) {
 		debug_putstr("KASLR disabled by cmdline...\n");
 		goto out;
 	}
-#endif
 
 	boot_params->hdr.loadflags |= KASLR_FLAG;
 
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index fca9254280ee..be5041354b1e 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -35,8 +35,13 @@ 
 
 
 static int nocompress;
+#ifdef CONFIG_RANDOMIZE_BASE
+static int noresume = 1;
+static int nohibernate = 1;
+#else
 static int noresume;
 static int nohibernate;
+#endif
 static int resume_wait;
 static unsigned int resume_delay;
 static char resume_file[256] = CONFIG_PM_STD_PARTITION;
@@ -1159,6 +1164,13 @@  static int __init kaslr_nohibernate_setup(char *str)
 	return nohibernate_setup(str);
 }
 
+static int __init nokaslr_hibernate_setup(char *str)
+{
+	noresume = 0;
+	nohibernate = 0;
+	return 1;
+}
+
 static int __init page_poison_nohibernate_setup(char *str)
 {
 #ifdef CONFIG_PAGE_POISONING_ZERO
@@ -1183,4 +1195,5 @@  __setup("resumewait", resumewait_setup);
 __setup("resumedelay=", resumedelay_setup);
 __setup("nohibernate", nohibernate_setup);
 __setup("kaslr", kaslr_nohibernate_setup);
+__setup("nokaslr", nokaslr_hibernate_setup);
 __setup("page_poison=", page_poison_nohibernate_setup);