Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752948AbdCQDm4 (ORCPT ); Thu, 16 Mar 2017 23:42:56 -0400 Received: from mx1.redhat.com ([209.132.183.28]:50518 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751389AbdCQDmz (ORCPT ); Thu, 16 Mar 2017 23:42:55 -0400 DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com F0D9581F01 Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=xlpang@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com F0D9581F01 From: Xunlei Pang To: linux-kernel@vger.kernel.org, kexec@lists.infradead.org Cc: akpm@linux-foundation.org, Eric Biederman , Dave Young , Baoquan He , Xunlei Pang Subject: [PATCH v2] kexec: Introduce vmcoreinfo signature verification Date: Fri, 17 Mar 2017 11:45:18 +0800 Message-Id: <1489722318-13695-1-git-send-email-xlpang@redhat.com> X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Fri, 17 Mar 2017 03:42:55 +0000 (UTC) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3446 Lines: 124 Currently vmcoreinfo data is updated at boot time subsys_initcall(), it has the risk of being modified by some wrong code during system is running. As a result, vmcore dumped may contain the wrong vmcoreinfo. Later on, when using "crash" or "makedumpfile"(etc) utility to parse this vmcore, we probably will get "Segmentation fault" or other unexpected/confusing errors. As vmcoreinfo is the most fundamental information for vmcore, we better double check its correctness. Here we generate a signature(using crc32) after it is saved, then verify it in crash_save_vmcoreinfo() to see if the signature was broken, if so we have to re-save the vmcoreinfo data to get the correct vmcoreinfo for kdump as possible as we can. Signed-off-by: Xunlei Pang --- v1->v2: - Keep crash_save_vmcoreinfo_init() because "makedumpfile --mem-usage" uses the information. - Add crc32 verification for vmcoreinfo, re-save when failure. arch/Kconfig | 1 + kernel/kexec_core.c | 43 +++++++++++++++++++++++++++++++++++-------- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/arch/Kconfig b/arch/Kconfig index c4d6833..66eb296 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -4,6 +4,7 @@ config KEXEC_CORE bool + select CRC32 config HAVE_IMA_KEXEC bool diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c index bfe62d5..012acbe 100644 --- a/kernel/kexec_core.c +++ b/kernel/kexec_core.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -53,9 +54,10 @@ /* vmcoreinfo stuff */ static unsigned char vmcoreinfo_data[VMCOREINFO_BYTES]; -u32 vmcoreinfo_note[VMCOREINFO_NOTE_SIZE/4]; +static u32 vmcoreinfo_sig; size_t vmcoreinfo_size; size_t vmcoreinfo_max_size = sizeof(vmcoreinfo_data); +u32 vmcoreinfo_note[VMCOREINFO_NOTE_SIZE/4]; /* Flag to indicate we are going to kexec a new kernel */ bool kexec_in_progress = false; @@ -1367,12 +1369,6 @@ static void update_vmcoreinfo_note(void) final_note(buf); } -void crash_save_vmcoreinfo(void) -{ - vmcoreinfo_append_str("CRASHTIME=%ld\n", get_seconds()); - update_vmcoreinfo_note(); -} - void vmcoreinfo_append_str(const char *fmt, ...) { va_list args; @@ -1402,7 +1398,7 @@ phys_addr_t __weak paddr_vmcoreinfo_note(void) return __pa_symbol((unsigned long)(char *)&vmcoreinfo_note); } -static int __init crash_save_vmcoreinfo_init(void) +static void do_crash_save_vmcoreinfo_init(void) { VMCOREINFO_OSRELEASE(init_uts_ns.name.release); VMCOREINFO_PAGESIZE(PAGE_SIZE); @@ -1474,6 +1470,37 @@ static int __init crash_save_vmcoreinfo_init(void) #endif arch_crash_save_vmcoreinfo(); +} + +static u32 crash_calc_vmcoreinfo_sig(void) +{ + return crc32(~0, vmcoreinfo_data, vmcoreinfo_size); +} + +static bool crash_verify_vmcoreinfo(void) +{ + if (crash_calc_vmcoreinfo_sig() == vmcoreinfo_sig) + return true; + + return false; +} + +void crash_save_vmcoreinfo(void) +{ + /* Re-save if verification fails */ + if (!crash_verify_vmcoreinfo()) { + vmcoreinfo_size = 0; + do_crash_save_vmcoreinfo_init(); + } + + vmcoreinfo_append_str("CRASHTIME=%ld\n", get_seconds()); + update_vmcoreinfo_note(); +} + +static int __init crash_save_vmcoreinfo_init(void) +{ + do_crash_save_vmcoreinfo_init(); + vmcoreinfo_sig = crash_calc_vmcoreinfo_sig(); update_vmcoreinfo_note(); return 0; -- 1.8.3.1