From patchwork Sat Aug 13 03:18:22 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thiago Jung Bauermann X-Patchwork-Id: 9278307 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 4C16C60231 for ; Sat, 13 Aug 2016 03:19:39 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3F12228AD6 for ; Sat, 13 Aug 2016 03:19:39 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2BB2528B4B; Sat, 13 Aug 2016 03:19:39 +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=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=unavailable 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 7C46D28B46 for ; Sat, 13 Aug 2016 03:19:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753106AbcHMDTQ (ORCPT ); Fri, 12 Aug 2016 23:19:16 -0400 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:45185 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753103AbcHMDTP (ORCPT ); Fri, 12 Aug 2016 23:19:15 -0400 Received: from pps.filterd (m0098393.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.11/8.16.0.11) with SMTP id u7D3Iq4V141276 for ; Fri, 12 Aug 2016 23:19:09 -0400 Received: from e24smtp03.br.ibm.com (e24smtp03.br.ibm.com [32.104.18.24]) by mx0a-001b2d01.pphosted.com with ESMTP id 24s2v8yx40-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Fri, 12 Aug 2016 23:19:09 -0400 Received: from localhost by e24smtp03.br.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Sat, 13 Aug 2016 00:19:06 -0300 Received: from d24dlp01.br.ibm.com (9.18.248.204) by e24smtp03.br.ibm.com (10.172.0.139) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Sat, 13 Aug 2016 00:19:04 -0300 X-IBM-Helo: d24dlp01.br.ibm.com X-IBM-MailFrom: bauerman@linux.vnet.ibm.com X-IBM-RcptTo: linux-kernel@vger.kernel.org; linux-security-module@vger.kernel.org Received: from d24relay02.br.ibm.com (d24relay02.br.ibm.com [9.13.184.26]) by d24dlp01.br.ibm.com (Postfix) with ESMTP id 2E47B352006E; Fri, 12 Aug 2016 23:18:43 -0400 (EDT) Received: from d24av05.br.ibm.com (d24av05.br.ibm.com [9.18.232.44]) by d24relay02.br.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id u7D3J3Tu27263322; Sat, 13 Aug 2016 00:19:03 -0300 Received: from d24av05.br.ibm.com (localhost [127.0.0.1]) by d24av05.br.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id u7D3J1L4013995; Sat, 13 Aug 2016 00:19:03 -0300 Received: from hactar.ibm.com ([9.78.148.164]) by d24av05.br.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id u7D3ImfW013761; Sat, 13 Aug 2016 00:18:55 -0300 From: Thiago Jung Bauermann To: kexec@lists.infradead.org Cc: linux-security-module@vger.kernel.org, linux-ima-devel@lists.sourceforge.net, linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org, x86@kernel.org, Eric Biederman , Dave Young , Vivek Goyal , Baoquan He , Michael Ellerman , Benjamin Herrenschmidt , Paul Mackerras , Stewart Smith , Samuel Mendoza-Jonas , Mimi Zohar , Eric Richter , Thomas Gleixner , Ingo Molnar , "H. Peter Anvin" , Andrew Morton , Petko Manolov , David Laight , Balbir Singh , Thiago Jung Bauermann Subject: [PATCH v2 3/6] kexec_file: Allow skipping checksum calculation for some segments. Date: Sat, 13 Aug 2016 00:18:22 -0300 X-Mailer: git-send-email 1.9.1 In-Reply-To: <1471058305-30198-1-git-send-email-bauerman@linux.vnet.ibm.com> References: <1471058305-30198-1-git-send-email-bauerman@linux.vnet.ibm.com> X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 16081303-0024-0000-0000-000000F19771 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 16081303-0025-0000-0000-0000157C9E65 Message-Id: <1471058305-30198-4-git-send-email-bauerman@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2016-08-12_10:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=3 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1604210000 definitions=main-1608130039 Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP Adds checksum argument to kexec_add_buffer specifying whether the given segment should be part of the checksum calculation. The next patch will add a way to update segments after a kimage is loaded. Segments that will be updated in this way should not be checksummed, otherwise they will cause the purgatory checksum verification to fail when the machine is rebooted. As a bonus, we don't need to special-case the purgatory segment anymore to avoid checksumming it. Adjust call sites for the new argument. Signed-off-by: Thiago Jung Bauermann --- arch/powerpc/kernel/kexec_elf_64.c | 6 +++--- arch/x86/kernel/crash.c | 4 ++-- arch/x86/kernel/kexec-bzimage64.c | 6 +++--- include/linux/kexec.h | 10 +++++++--- kernel/kexec_file.c | 23 ++++++++++++----------- 5 files changed, 27 insertions(+), 22 deletions(-) diff --git a/arch/powerpc/kernel/kexec_elf_64.c b/arch/powerpc/kernel/kexec_elf_64.c index 22afc7b5ee73..4c528c81b076 100644 --- a/arch/powerpc/kernel/kexec_elf_64.c +++ b/arch/powerpc/kernel/kexec_elf_64.c @@ -128,7 +128,7 @@ static int elf_exec_load(struct kimage *image, struct elfhdr *ehdr, kbuf.memsz = phdr->p_memsz; kbuf.buf_align = phdr->p_align; kbuf.buf_min = phdr->p_paddr + base; - ret = kexec_add_buffer(&kbuf); + ret = kexec_add_buffer(&kbuf, true); if (ret) goto out; load_addr = kbuf.mem; @@ -188,7 +188,7 @@ void *elf64_load(struct kimage *image, char *kernel_buf, kbuf.bufsz = kbuf.memsz = initrd_len; kbuf.buf_align = PAGE_SIZE; kbuf.top_down = false; - ret = kexec_add_buffer(&kbuf); + ret = kexec_add_buffer(&kbuf, true); if (ret) goto out; initrd_load_addr = kbuf.mem; @@ -245,7 +245,7 @@ void *elf64_load(struct kimage *image, char *kernel_buf, kbuf.bufsz = kbuf.memsz = fdt_size; kbuf.buf_align = PAGE_SIZE; kbuf.top_down = true; - ret = kexec_add_buffer(&kbuf); + ret = kexec_add_buffer(&kbuf, true); if (ret) goto out; fdt_load_addr = kbuf.mem; diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c index 38a1cdf6aa05..634ab16377b1 100644 --- a/arch/x86/kernel/crash.c +++ b/arch/x86/kernel/crash.c @@ -642,7 +642,7 @@ int crash_load_segments(struct kimage *image) * copied in purgatory after crash. Just add a zero filled * segment for now to make sure checksum logic works fine. */ - ret = kexec_add_buffer(&kbuf); + ret = kexec_add_buffer(&kbuf, true); if (ret) return ret; image->arch.backup_load_addr = kbuf.mem; @@ -661,7 +661,7 @@ int crash_load_segments(struct kimage *image) kbuf.memsz = kbuf.bufsz; kbuf.buf_align = ELF_CORE_HEADER_ALIGN; - ret = kexec_add_buffer(&kbuf); + ret = kexec_add_buffer(&kbuf, true); if (ret) { vfree((void *)image->arch.elf_headers); return ret; diff --git a/arch/x86/kernel/kexec-bzimage64.c b/arch/x86/kernel/kexec-bzimage64.c index 4b3a75329fb6..a46e3fbb0639 100644 --- a/arch/x86/kernel/kexec-bzimage64.c +++ b/arch/x86/kernel/kexec-bzimage64.c @@ -422,7 +422,7 @@ static void *bzImage64_load(struct kimage *image, char *kernel, kbuf.memsz = kbuf.bufsz; kbuf.buf_align = 16; kbuf.buf_min = MIN_BOOTPARAM_ADDR; - ret = kexec_add_buffer(&kbuf); + ret = kexec_add_buffer(&kbuf, true); if (ret) goto out_free_params; bootparam_load_addr = kbuf.mem; @@ -435,7 +435,7 @@ static void *bzImage64_load(struct kimage *image, char *kernel, kbuf.memsz = PAGE_ALIGN(header->init_size); kbuf.buf_align = header->kernel_alignment; kbuf.buf_min = MIN_KERNEL_LOAD_ADDR; - ret = kexec_add_buffer(&kbuf); + ret = kexec_add_buffer(&kbuf, true); if (ret) goto out_free_params; kernel_load_addr = kbuf.mem; @@ -449,7 +449,7 @@ static void *bzImage64_load(struct kimage *image, char *kernel, kbuf.bufsz = kbuf.memsz = initrd_len; kbuf.buf_align = PAGE_SIZE; kbuf.buf_min = MIN_INITRD_LOAD_ADDR; - ret = kexec_add_buffer(&kbuf); + ret = kexec_add_buffer(&kbuf, true); if (ret) goto out_free_params; initrd_load_addr = kbuf.mem; diff --git a/include/linux/kexec.h b/include/linux/kexec.h index 4559a1a01b0a..37eea32fdff1 100644 --- a/include/linux/kexec.h +++ b/include/linux/kexec.h @@ -100,6 +100,9 @@ struct kexec_segment { size_t bufsz; unsigned long mem; size_t memsz; + + /* Whether this segment is part of the checksum calculation. */ + bool do_checksum; }; #ifdef CONFIG_COMPAT @@ -175,7 +178,7 @@ struct kexec_buf { int __weak arch_kexec_walk_mem(struct kexec_buf *kbuf, int (*func)(u64, u64, void *)); -extern int kexec_add_buffer(struct kexec_buf *kbuf); +extern int kexec_add_buffer(struct kexec_buf *kbuf, bool checksum); int kexec_locate_mem_hole(struct kexec_buf *kbuf); int __weak arch_kexec_verify_buffer(enum kexec_file_type type, const void *buf, unsigned long size); @@ -393,7 +396,7 @@ bool __weak kexec_can_hand_over_buffer(void); int __weak arch_kexec_add_handover_buffer(struct kimage *image, unsigned long load_addr, unsigned long size); -int kexec_add_handover_buffer(struct kexec_buf *kbuf); +int kexec_add_handover_buffer(struct kexec_buf *kbuf, bool checksum); int __weak kexec_get_handover_buffer(void **addr, unsigned long *size); int __weak kexec_free_handover_buffer(void); #else @@ -402,7 +405,8 @@ static inline bool kexec_can_hand_over_buffer(void) return false; } -static inline int kexec_add_handover_buffer(struct kexec_buf *kbuf) +static inline int kexec_add_handover_buffer(struct kexec_buf *kbuf, + bool checksum) { return -ENOTSUPP; } diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c index c8418d62e2fc..aed51175915f 100644 --- a/kernel/kexec_file.c +++ b/kernel/kexec_file.c @@ -161,6 +161,7 @@ int __weak arch_kexec_add_handover_buffer(struct kimage *image, /** * kexec_add_handover_buffer - add buffer to be used by the next kernel * @kbuf: Buffer contents and memory parameters. + * @checksum: Should the segment checksum be verified by the purgatory? * * This function assumes that kexec_mutex is held. * On successful return, @kbuf->mem will have the physical address of @@ -168,14 +169,14 @@ int __weak arch_kexec_add_handover_buffer(struct kimage *image, * * Return: 0 on success, negative errno on error. */ -int kexec_add_handover_buffer(struct kexec_buf *kbuf) +int kexec_add_handover_buffer(struct kexec_buf *kbuf, bool checksum) { int ret; if (!kexec_can_hand_over_buffer()) return -ENOTSUPP; - ret = kexec_add_buffer(kbuf); + ret = kexec_add_buffer(kbuf, checksum); if (ret) return ret; @@ -611,6 +612,7 @@ int kexec_locate_mem_hole(struct kexec_buf *kbuf) /** * kexec_add_buffer - place a buffer in a kexec segment * @kbuf: Buffer contents and memory parameters. + * @checksum: Should the segment checksum be verified by the purgatory? * * This function assumes that kexec_mutex is held. * On successful return, @kbuf->mem will have the physical address of @@ -618,7 +620,7 @@ int kexec_locate_mem_hole(struct kexec_buf *kbuf) * * Return: 0 on success, negative errno on error. */ -int kexec_add_buffer(struct kexec_buf *kbuf) +int kexec_add_buffer(struct kexec_buf *kbuf, bool checksum) { struct kexec_segment *ksegment; @@ -658,6 +660,7 @@ int kexec_add_buffer(struct kexec_buf *kbuf) ksegment->bufsz = kbuf->bufsz; ksegment->mem = kbuf->mem; ksegment->memsz = kbuf->memsz; + ksegment->do_checksum = checksum; kbuf->image->nr_segments++; return 0; } @@ -672,7 +675,6 @@ static int kexec_calculate_store_digests(struct kimage *image) char *digest; void *zero_buf; struct kexec_sha_region *sha_regions; - struct purgatory_info *pi = &image->purgatory_info; zero_buf = __va(page_to_pfn(ZERO_PAGE(0)) << PAGE_SHIFT); zero_buf_sz = PAGE_SIZE; @@ -712,11 +714,7 @@ static int kexec_calculate_store_digests(struct kimage *image) struct kexec_segment *ksegment; ksegment = &image->segment[i]; - /* - * Skip purgatory as it will be modified once we put digest - * info in purgatory. - */ - if (ksegment->kbuf == pi->purgatory_buf) + if (!ksegment->do_checksum) continue; ret = crypto_shash_update(desc, ksegment->kbuf, @@ -893,8 +891,11 @@ static int __kexec_load_purgatory(struct kimage *image, unsigned long min, if (kbuf.buf_align < bss_align) kbuf.buf_align = bss_align; - /* Add buffer to segment list */ - ret = kexec_add_buffer(&kbuf); + /* + * Add buffer to segment list. Don't checksum the segment as + * it will be modified once we put digest info in purgatory. + */ + ret = kexec_add_buffer(&kbuf, false); if (ret) goto out; pi->purgatory_load_addr = kbuf.mem;