From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1424037AbcFMWKy (ORCPT ); Mon, 13 Jun 2016 18:10:54 -0400 Received: from cloudserver094114.home.net.pl ([79.96.170.134]:54007 "HELO cloudserver094114.home.net.pl" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with SMTP id S1423760AbcFMWKx (ORCPT ); Mon, 13 Jun 2016 18:10:53 -0400 From: "Rafael J. Wysocki" To: Kees Cook Cc: Linux PM list , Linux Kernel Mailing List , Stephen Smalley , Ingo Molnar , Logan Gunthorpe , the arch/x86 maintainers , Andy Lutomirski , Borislav Petkov Subject: Re: [PATCH] x86 / hibernate: Fix 64-bit code passing control to image kernel Date: Tue, 14 Jun 2016 00:15 +0200 Message-ID: <1518490.AMlP2tjrQi@vostro.rjw.lan> User-Agent: KMail/4.11.5 (Linux/4.5.0-rc1+; KDE/4.11.5; x86_64; ; ) In-Reply-To: References: <3006711.q9ei2E2zzf@vostro.rjw.lan> MIME-Version: 1.0 Content-Transfer-Encoding: 7Bit Content-Type: text/plain; charset="utf-8" Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Monday, June 13, 2016 02:58:57 PM Kees Cook wrote: > On Mon, Jun 13, 2016 at 6:42 AM, Rafael J. Wysocki wrote: > > From: Rafael J. Wysocki > > > > Logan Gunthorpe reports that hibernation stopped working reliably for > > him after commit ab76f7b4ab23 (x86/mm: Set NX on gap between __ex_table > > and rodata). Most likely, what happens is that the page containing > > the image kernel's entry point is sometimes marked as non-executable > > in the page tables used at the time of the final jump to the image > > kernel. That at least is why commit ab76f7b4ab23 may matter. > > > > However, there is one more long-standing issue with the code in > > question, which is that the temporary page tables set up by it > > to avoid page tables corruption when the last bits of the image > > kernel's memory contents are copied into their original page frames > > re-use the boot kernel's text mapping, but that mapping may very > > well get corrupted just like any other part of the page tables. > > Of course, if that happens, the final jump to the image kernel's > > entry point will go to nowhere. > > > > As it turns out, those two issues may be addressed simultaneously. > > > > To that end, note that the code copying the last bits of the image > > kernel's memory contents to the page frames occupied by them > > previoulsy doesn't use the kernel text mapping, because it runs from > > a special page covered by the identity mapping set up for that code > > from scratch. Hence, the kernel text mapping is only needed before > > that code starts to run and then it will only be used just for the > > final jump to the image kernel's entry point. > > > > Accordingly, the temporary page tables set up in swsusp_arch_resume() > > on x86-64 can re-use the boot kernel's text mapping to start with, > > but after all of the image kernel's memory contents are in place, > > that mapping has to be replaced with a new one that will allow the > > final jump to the image kernel's entry point to succeed. Of course, > > since the first thing the image kernel does after getting control back > > is to switch over to its own original page tables, the new kernel text > > mapping only has to cover the image kernel's entry point (along with > > some following bytes). Moreover, it has to do that so the virtual > > address of the image kernel's entry point before the jump is the same > > as the one mapped by the image kernel's page tables. > > > > With that in mind, modify the x86-64's arch_hibernation_header_save() > > and arch_hibernation_header_restore() routines to pass the physical > > address of the image kernel's entry point (in addition to its virtual > > address) to the boot kernel (a small piece of assembly code involved > > in passing the entry point's virtual address to the image kernel is > > not necessary any more after that, so drop it). Update RESTORE_MAGIC > > too to reflect the image header format change. > > > > Next, in set_up_temporary_mappings(), use the physical and virtual > > addresses of the image kernel's entry point passed in the image > > header to set up a minimum kernel text mapping (using memory pages > > that won't be overwritten by the image kernel's memory contents) that > > will map those addresses to each other as appropriate. Do not use > > that mapping immediately, though. Instead, use the original boot > > kernel text mapping to start with and switch over to the new one > > after all of the image kernel's memory has been restored, right > > before the final jump to the image kernel's entry point. > > > > This makes the concern about the possible corruption of the original > > boot kernel text mapping go away and if the the minimum kernel text > > mapping used for the final jump marks the image kernel's entry point > > memory as executable, the jump to it is guaraneed to succeed. > > > > Fixes: ab76f7b4ab23 (x86/mm: Set NX on gap between __ex_table and rodata) > > Link: http://marc.info/?l=linux-pm&m=146372852823760&w=2 > > Reported-by: Logan Gunthorpe > > Signed-off-by: Rafael J. Wysocki > > Acked-by: Kees Cook > > And as an awesome added benefit: this fixes KASLR hibernation for me, > too! Interesting. :-) Is there documentation I can read about how the KASLR thing works exactly, wrt page tables in particular? > I will send a follow-up patch that removes all the KASLR vs > hibernation hacks. But that on x86-64 only? 32-bit still doesn't work I suppose? > Yay! I'm glad you like it. ;-) Cheers, Rafael