From patchwork Thu Feb 14 14:48:51 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: David Woodhouse X-Patchwork-Id: 10812847 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 70F2C922 for ; Thu, 14 Feb 2019 14:48:58 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 583F02D791 for ; Thu, 14 Feb 2019 14:48:58 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 499C92D68D; Thu, 14 Feb 2019 14:48:58 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.7 required=2.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A0FE52D68D for ; Thu, 14 Feb 2019 14:48:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2392313AbfBNOs4 (ORCPT ); Thu, 14 Feb 2019 09:48:56 -0500 Received: from merlin.infradead.org ([205.233.59.134]:57358 "EHLO merlin.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2390743AbfBNOsz (ORCPT ); Thu, 14 Feb 2019 09:48:55 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=merlin.20170209; h=Mime-Version:Content-Type:Date:To:From: Subject:Message-ID:Sender:Reply-To:Cc:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=Cx9une/2vzhTWgdATxeK6CnnlbK5ivkNhO626fCPSxg=; b=cNO5luutOym9pkEUfrxau2D0QW xfZQQYHU7bY8yFgQZOaCpIS3qbpxIIgZwx0NOflcTF3t3oNHzzOGhQDgLpYZsFs7KwZ4Z/WRZjtfV elNzGvupMadBBRHoYOEB5fYDKbBdLKYl+Bwms2+16tIgK/93W277BFfQ8jB/YDnLSqIYgDFQgfrB2 kuHsMeuFkIjyeXu0UBQPEPr+a7jiqoUdth1w7+IVTIAlUNFluddMytZ/ZYnibOtp/wNvxQiDVYlSm YOJ9Nbfec4RAB/rFl+1CAJfUOa9dhk6nGF2xOoq6+oPFm3rvi6riIMmPfVt1P8d898uMuofO3Rw8b nBPLo1zg==; Received: from [54.239.6.185] (helo=vpn-10-85-98-54.fra54.corp.amazon.com) by merlin.infradead.org with esmtpsa (Exim 4.90_1 #2 (Red Hat Linux)) id 1guIJp-0005uC-8u for linux-pm@vger.kernel.org; Thu, 14 Feb 2019 14:48:53 +0000 Message-ID: Subject: [RFC PATCH] Honour ACPI hardware signature to prevent hibernation resume From: David Woodhouse To: linux-pm Date: Thu, 14 Feb 2019 15:48:51 +0100 X-Mailer: Evolution 3.28.5-0ubuntu0.18.04.1 Mime-Version: 1.0 X-SRS-Rewrite: SMTP reverse-path rewritten from by merlin.infradead.org. See http://www.infradead.org/rpr.html Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP When the hardware_signature changes, we're supposed to gracefully decline to attempt the resume: "If the signature has changed, OSPM will not restore the system context and can boot from scratch" Linux originally ignored the hardware signature completely. Starting from commit bdfe6b7c681 in July 2008, Linux changed behaviour to resume into the original image anyway, and then panic as soon as it got there. That was changed again in commit 5c551e624ab in 2014, to just print a warning and "success doubtful!" after resume instead of panicking, with a note that Windows 8 doesn't refuse to resume when the signature changes. We actually do have a use case where we want the behaviour that the spec requires — when resuming a hibernated guest on a hypervisor which has become sufficiently incompatible that we don't expect it to work, we'd really like to be able to tell it to boot cleanly, not resume. This untested proof-of-concept patch does precisely that, putting the hardware signature into the swsusp header and checking it in the boot kernel before deciding to resume at all. Before I clean it up and actually test it, I'd welcome some opinions: • Do we want to pretend the signature in the swsusp_header will ever be used for anything other than ACPI signatures, and make it larger than a u32? • Do we make it opt-in based on the platforms where this behaviour is particularly desired, or opt-out based on... DMI matches of the laptops which are known to change the signature gratuitously? • In the case where we don't refuse to resume based on a signature mismatch, should we still print the warning? Unless someone feels strongly, I'll probably go with "no" and "opt-in" as my answers to the first two of those questions, and make the third up as I go along. Signed-off-by: David Woodhouse diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 403c4ff15349..844e737c24eb 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -1248,8 +1248,10 @@ static void acpi_sleep_hibernate_setup(void) return; acpi_get_table(ACPI_SIG_FACS, 1, (struct acpi_table_header **)&facs); - if (facs) + if (facs) { s4_hardware_signature = facs->hardware_signature; + swsusp_hardware_signature = facs->hardware_signature; + } } #else /* !CONFIG_HIBERNATION */ static inline void acpi_sleep_hibernate_setup(void) {} diff --git a/include/linux/suspend.h b/include/linux/suspend.h index 3f529ad9a9d2..0e830ccd67dc 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h @@ -389,6 +389,7 @@ extern unsigned long get_safe_page(gfp_t gfp_mask); extern asmlinkage int swsusp_arch_suspend(void); extern asmlinkage int swsusp_arch_resume(void); +extern u32 swsusp_hardware_signature; extern void hibernation_set_ops(const struct platform_hibernation_ops *ops); extern int hibernate(void); extern bool system_entering_hibernation(void); diff --git a/kernel/power/power.h b/kernel/power/power.h index 9e58bdc8a562..d447571484e9 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h @@ -170,6 +170,7 @@ extern int swsusp_swap_in_use(void); #define SF_PLATFORM_MODE 1 #define SF_NOCOMPRESS_MODE 2 #define SF_CRC32_MODE 4 +#define SF_HW_SIG 8 /* kernel/power/hibernate.c */ extern int swsusp_check(void); diff --git a/kernel/power/swap.c b/kernel/power/swap.c index d7f6c1a288d3..bd37784b522f 100644 --- a/kernel/power/swap.c +++ b/kernel/power/swap.c @@ -38,6 +38,8 @@ #define HIBERNATE_SIG "S1SUSPEND" +u32 swsusp_hardware_signature; + /* * When reading an {un,}compressed image, we may restore pages in place, * in which case some architectures need these pages cleaning before they @@ -106,7 +108,8 @@ struct swap_map_handle { struct swsusp_header { char reserved[PAGE_SIZE - 20 - sizeof(sector_t) - sizeof(int) - - sizeof(u32)]; + sizeof(u32) - sizeof(u32)]; + u32 hw_sig; u32 crc32; sector_t image; unsigned int flags; /* Flags to pass to the "boot" kernel */ @@ -315,6 +317,10 @@ static int mark_swapfiles(struct swap_map_handle *handle, unsigned int flags) memcpy(swsusp_header->orig_sig,swsusp_header->sig, 10); memcpy(swsusp_header->sig, HIBERNATE_SIG, 10); swsusp_header->image = handle->first_sector; + if (swsusp_hardware_signature) { + swsusp_header->hw_sig = swsusp_hardware_signature; + flags |= SF_HW_SIG; + } swsusp_header->flags = flags; if (flags & SF_CRC32_MODE) swsusp_header->crc32 = handle->crc32; @@ -1533,6 +1539,12 @@ int swsusp_check(void) } else { error = -EINVAL; } + if (!error && swsusp_header->flags & SF_HW_SIG && + swsusp_header->hw_sig != swsusp_hardware_signature) { + pr_info("Suspend image hardware signature mismatch (%08x now %08x); aborting resume.\n", + swsusp_header->hw_sig, swsusp_hardware_signature); + error = -EINVAL; + } put: if (error)