Received: by 10.223.185.116 with SMTP id b49csp1979996wrg; Thu, 22 Feb 2018 06:23:07 -0800 (PST) X-Google-Smtp-Source: AH8x225C1tw2K2mUkFD4zpraJuSk8ZWmXVRLlb1idDQaoQELSYvF2Dl3yW/od8Ep5FediacACkS0 X-Received: by 10.99.148.17 with SMTP id m17mr5776806pge.367.1519309387458; Thu, 22 Feb 2018 06:23:07 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1519309387; cv=none; d=google.com; s=arc-20160816; b=ILTQ9eOKaybnU5g+rAGxmjgMznliJKmnOn/YTqfZAn+oBgNDhJLtc1c60QkK4KzJJ/ gDS+JdJyZPIfvkcFO1CCRK6IMFyKI4zrxc/2jKaK4qfbykJWVf6kiVuRYKaLYm7lkyg+ +FhWmsrB6BqbF6uEk7uSmZ502QlIxzTbXGgva+W6bn1t0xNj5nj7MgWaZyt4m0sukVsr B77b/4LdkHH2e1rNHnopPjbHw39he39m0f22uxBfHotKibNSKw5kaMmUjjEShjzBEWsC 2ROkJqoxyBuWkQR/tkGsl5uyAPoFw+pqXvebPoleQihPcBN1nP9AehWj4zHM1LdN1fJA 4GFg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:content-transfer-encoding :content-id:mime-version:subject:cc:to:references:in-reply-to:from :organization:arc-authentication-results; bh=VsqFNtUhYlajKKeCRUgPrIUs6R1jEv9bqB3eoIlFcmk=; b=D2IrQM0d3A0+AO6n0uix4RFeaA+8SYqmjrq1pWkpe07Z0BYUHdqDmj/qST+17SaBv9 29r/YndVNnfMCQku46q3uDH7Q0S/MXnqXoMgLOBm+HECI/hAkNl7LmfoGbLlHYhFS3wx ChtvhLUXwUTehRDV5eEFugid4/Zw4oYBYOZsx7Jg5aoUV6IePfQ03pniD4UpSj8FJD07 2S8Wel7dFgKJwOW+tjCyDEFktEHh9MhT32jZITMhPoc5+9RGZyhrbw8I+DVsm9LaTC+/ /Seplh7UO+3HDTL02EtdEZZOyOoF9mjeL9Kc/jzcrtoNLdAV5qBcQXuehWzQX6EwJW23 3zfQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 33-v6si102175plk.576.2018.02.22.06.22.52; Thu, 22 Feb 2018 06:23:07 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932737AbeBVOUu convert rfc822-to-8bit (ORCPT + 99 others); Thu, 22 Feb 2018 09:20:50 -0500 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:35466 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S932607AbeBVOUs (ORCPT ); Thu, 22 Feb 2018 09:20:48 -0500 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4B2088163C52; Thu, 22 Feb 2018 14:20:47 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-120-250.rdu2.redhat.com [10.10.120.250]) by smtp.corp.redhat.com (Postfix) with ESMTP id 9C182AB592; Thu, 22 Feb 2018 14:20:43 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 From: David Howells In-Reply-To: <151024869793.28329.4817577607302613028.stgit@warthog.procyon.org.uk> References: <151024869793.28329.4817577607302613028.stgit@warthog.procyon.org.uk> <151024863544.28329.2436580122759221600.stgit@warthog.procyon.org.uk> To: linux-security-module@vger.kernel.org Cc: dhowells@redhat.com, gnomes@lxorguk.ukuu.org.uk, linux-efi@vger.kernel.org, linux-kernel@vger.kernel.org, jforbes@redhat.com Subject: Re: [PATCH 08/30] kexec_file: Restrict at runtime if the kernel is locked down MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-ID: <8845.1519309243.1@warthog.procyon.org.uk> Content-Transfer-Encoding: 8BIT Date: Thu, 22 Feb 2018 14:20:43 +0000 Message-ID: <8846.1519309243@warthog.procyon.org.uk> X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Thu, 22 Feb 2018 14:20:47 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Thu, 22 Feb 2018 14:20:47 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'dhowells@redhat.com' RCPT:'' Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org I'm intending on inserting the attached patch before this one. David --- commit 87a39b258eca2e15884ee90c3fcd5758d6057b17 Author: David Howells Date: Thu Feb 22 13:42:04 2018 +0000 kexec_file: split KEXEC_VERIFY_SIG into KEXEC_SIG and KEXEC_SIG_FORCE This is a preparatory patch for kexec_file_load() lockdown. A locked down kernel needs to prevent unsigned kernel images to be loaded with kexec_file_load(). Currently, the only way to force the signature verification is compiling with KEXEC_VERIFY_SIG. This prevents loading usigned images even when the kernel is not locked down at runtime. This patch splits KEXEC_VERIFY_SIG into KEXEC_SIG and KEXEC_SIG_FORCE. Analogous to the MODULE_SIG and MODULE_SIG_FORCE for modules, KEXEC_SIG turns on the signature verification but allows unsigned images to be loaded. KEXEC_SIG_FORCE disallows images without a valid signature. [Modified by David Howells such that: (1) verify_pefile_signature() differentiates between no-signature and sig-didn't-match in its returned errors. (2) kexec fails with EKEYREJECTED and logs an appropriate message if signature checking is enforced and an signature is not found, uses unsupported crypto or has no matching key. (3) kexec fails with EKEYREJECTED if there is a signature for which we have a key, but signature doesn't match - even if in non-forcing mode. (4) kexec fails with EBADMSG or some other error if there is a signature which cannot be parsed - even if in non-forcing mode. (5) kexec fails with ELIBBAD if the PE file cannot be parsed to extract the signature - even if in non-forcing mode. ] Signed-off-by: Jiri Bohac Signed-off-by: David Howells cc: Matthew Garrett cc: Chun-Yi Lee cc: kexec@lists.infradead.org diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index c1236b187824..cb6e67b7442d 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -2019,20 +2019,30 @@ config KEXEC_FILE for kernel and initramfs as opposed to list of segments as accepted by previous system call. -config KEXEC_VERIFY_SIG +config KEXEC_SIG bool "Verify kernel signature during kexec_file_load() syscall" depends on KEXEC_FILE ---help--- - This option makes kernel signature verification mandatory for - the kexec_file_load() syscall. - In addition to that option, you need to enable signature + This option makes the kexec_file_load() syscall check for a valid + signature of the kernel image. The image can still be loaded without + a valid signature unless you also enable KEXEC_SIG_FORCE, though if + there's a signature that we can check, then it must be valid. + + In addition to this option, you need to enable signature verification for the corresponding kernel image type being loaded in order for this to work. +config KEXEC_SIG_FORCE + bool "Require a valid signature in kexec_file_load() syscall" + depends on KEXEC_SIG + ---help--- + This option makes kernel signature verification mandatory for + the kexec_file_load() syscall. + config KEXEC_BZIMAGE_VERIFY_SIG bool "Enable bzImage signature verification support" - depends on KEXEC_VERIFY_SIG + depends on KEXEC_SIG depends on SIGNED_PE_FILE_VERIFICATION select SYSTEM_TRUSTED_KEYRING ---help--- diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c index 1f790cf9d38f..3fbe35b923ef 100644 --- a/arch/x86/kernel/machine_kexec_64.c +++ b/arch/x86/kernel/machine_kexec_64.c @@ -406,7 +406,7 @@ int arch_kimage_file_post_load_cleanup(struct kimage *image) return image->fops->cleanup(image->image_loader_data); } -#ifdef CONFIG_KEXEC_VERIFY_SIG +#ifdef CONFIG_KEXEC_SIG int arch_kexec_kernel_verify_sig(struct kimage *image, void *kernel, unsigned long kernel_len) { diff --git a/crypto/asymmetric_keys/verify_pefile.c b/crypto/asymmetric_keys/verify_pefile.c index d178650fd524..4473cea1e877 100644 --- a/crypto/asymmetric_keys/verify_pefile.c +++ b/crypto/asymmetric_keys/verify_pefile.c @@ -100,7 +100,7 @@ static int pefile_parse_binary(const void *pebuf, unsigned int pelen, if (!ddir->certs.virtual_address || !ddir->certs.size) { pr_debug("Unsigned PE binary\n"); - return -EKEYREJECTED; + return -ENODATA; } chkaddr(ctx->header_size, ddir->certs.virtual_address, @@ -408,6 +408,8 @@ static int pefile_digest_pe(const void *pebuf, unsigned int pelen, * (*) 0 if at least one signature chain intersects with the keys in the trust * keyring, or: * + * (*) -ENODATA if there is no signature present. + * * (*) -ENOPKG if a suitable crypto module couldn't be found for a check on a * chain. * diff --git a/include/linux/kexec.h b/include/linux/kexec.h index f16f6ceb3875..19652372f3ee 100644 --- a/include/linux/kexec.h +++ b/include/linux/kexec.h @@ -121,7 +121,7 @@ typedef void *(kexec_load_t)(struct kimage *image, char *kernel_buf, unsigned long cmdline_len); typedef int (kexec_cleanup_t)(void *loader_data); -#ifdef CONFIG_KEXEC_VERIFY_SIG +#ifdef CONFIG_KEXEC_SIG typedef int (kexec_verify_sig_t)(const char *kernel_buf, unsigned long kernel_len); #endif @@ -130,7 +130,7 @@ struct kexec_file_ops { kexec_probe_t *probe; kexec_load_t *load; kexec_cleanup_t *cleanup; -#ifdef CONFIG_KEXEC_VERIFY_SIG +#ifdef CONFIG_KEXEC_SIG kexec_verify_sig_t *verify_sig; #endif }; diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c index e5bcd94c1efb..d5931e392050 100644 --- a/kernel/kexec_file.c +++ b/kernel/kexec_file.c @@ -45,7 +45,7 @@ int __weak arch_kimage_file_post_load_cleanup(struct kimage *image) return -EINVAL; } -#ifdef CONFIG_KEXEC_VERIFY_SIG +#ifdef CONFIG_KEXEC_SIG int __weak arch_kexec_kernel_verify_sig(struct kimage *image, void *buf, unsigned long buf_len) { @@ -116,7 +116,8 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd, const char __user *cmdline_ptr, unsigned long cmdline_len, unsigned flags) { - int ret = 0; + const char *reason; + int ret; void *ldata; loff_t size; @@ -135,15 +136,48 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd, if (ret) goto out; -#ifdef CONFIG_KEXEC_VERIFY_SIG +#ifdef CONFIG_KEXEC_SIG ret = arch_kexec_kernel_verify_sig(image, image->kernel_buf, image->kernel_buf_len); - if (ret) { - pr_debug("kernel signature verification failed.\n"); +#else + ret = -ENODATA; +#endif + + switch (ret) { + case 0: + break; + + /* Certain verification errors are non-fatal if we're not + * checking errors, provided we aren't mandating that there + * must be a valid signature. + */ + case -ENODATA: + reason = "kexec of unsigned image"; + goto decide; + case -ENOPKG: + reason = "kexec of image with unsupported crypto"; + goto decide; + case -ENOKEY: + reason = "kexec of image with unavailable key"; + decide: + if (IS_ENABLED(CONFIG_KEXEC_SIG_FORCE)) { + pr_notice("%s rejected\n", reason); + ret = -EKEYREJECTED; + goto out; + } + + ret = 0; + break; + + /* All other errors are fatal, including nomem, unparseable + * signatures and signature check failures - even if signatures + * aren't required. + */ + default: + pr_notice("kernel signature verification failed (%d).\n", ret); goto out; } - pr_debug("kernel signature verification successful.\n"); -#endif + /* It is possible that there no initramfs is being loaded */ if (!(flags & KEXEC_FILE_NO_INITRAMFS)) { ret = kernel_read_file_from_fd(initrd_fd, &image->initrd_buf,