From patchwork Sat Jun 22 00:03:33 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matthew Garrett X-Patchwork-Id: 11010977 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 F024276 for ; Sat, 22 Jun 2019 00:04:14 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DE82A26E3D for ; Sat, 22 Jun 2019 00:04:14 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CF4CA28BB1; Sat, 22 Jun 2019 00:04:14 +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=-14.5 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,RCVD_IN_DNSWL_HI,USER_IN_DEF_DKIM_WL 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 55D3E26E3D for ; Sat, 22 Jun 2019 00:04:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726417AbfFVAEN (ORCPT ); Fri, 21 Jun 2019 20:04:13 -0400 Received: from mail-pf1-f201.google.com ([209.85.210.201]:56220 "EHLO mail-pf1-f201.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726412AbfFVAEM (ORCPT ); Fri, 21 Jun 2019 20:04:12 -0400 Received: by mail-pf1-f201.google.com with SMTP id i26so5284297pfo.22 for ; Fri, 21 Jun 2019 17:04:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=xWwvqoly0PlbH3oeDVETCqcyxNm+Yts9aIPiMy6JED0=; b=vLKG7NXbdP5iB0pGbeaWEB/S5uQntOo7aDNOTRJE5FTCqU5mqc1FLcJV5X9DTKhRUF skhH25su+evM+aesFmCqTJGHSxr9PAuHNaWTxTdOZu1cs13K5HlxqZ/Vsx3o/2bXx/No 0C5LtbZv0KOVW2DTNIKFUDaPPbPHV7ouuhcHm5Rb7VSKB58D+SncR0Xpw+xFUzQcV/+S DhX82dzykAkEOBveZ+dKP2HdwUYPf1a46nQNkwXxDMk2hns0a9BLiYEXeFOdphGJ+RWP iP95ZFn4U7U1cVFqsLm5QxNRF31uyeVhEntSAEbWBO/844S4nQR9bRUp4mGqvnPElkq1 tnuA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=xWwvqoly0PlbH3oeDVETCqcyxNm+Yts9aIPiMy6JED0=; b=LXH9Qb6y0i28fyaieOvtSrEhL8+aK+xqlynVtDCh3hO9NU13xaFaPznIZq2zSJm+qN UwnE3+gSuHPnAg/nmvgkYXI6UiYtm5mu6o3YVdIpaCclWjkciskI3lndbBtL/G/i3AC9 1rbCw2w2x0V5WlXCAuJukBsQhTBJ96TEcLye3jPJ9MqCsJSBLj8+2n24KCCpMQV+WBqB Lel7IdJ3+MQD1oQg/gKgMX2bANycplZ2R71lzPXQbTyuSrECHER0xSmHpJox07lRgNG5 uAavZOUvz+LNzY0qZ9nLuXXVIO7J4YySzvrA9LeS1YzsLtXq1npJWAf6I6j9+ZL1lHp+ QkfA== X-Gm-Message-State: APjAAAWUxfA/cp+zIb67h4obMkV/jwgBTnDHwVcacw5IKmUJ5tEZhAhC 8v5ncg18H4YEJCLD3u/8eL5Kn68XbEs1GpUA40qNsg== X-Google-Smtp-Source: APXvYqx0mEhlT0ooxRI6ZbcDWX5ttbbUK2UhpRjvoSoGikcOsjmlTxGeN/u7fJgSuhxSgvvZPRyqVv+YDyhrsCuMO0voxQ== X-Received: by 2002:a63:3042:: with SMTP id w63mr13863609pgw.21.1561161851464; Fri, 21 Jun 2019 17:04:11 -0700 (PDT) Date: Fri, 21 Jun 2019 17:03:33 -0700 In-Reply-To: <20190622000358.19895-1-matthewgarrett@google.com> Message-Id: <20190622000358.19895-5-matthewgarrett@google.com> Mime-Version: 1.0 References: <20190622000358.19895-1-matthewgarrett@google.com> X-Mailer: git-send-email 2.22.0.410.gd8fdbe21b5-goog Subject: [PATCH V34 04/29] Enforce module signatures if the kernel is locked down From: Matthew Garrett To: jmorris@namei.org Cc: linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org, linux-api@vger.kernel.org, David Howells , Matthew Garrett , Jessica Yu Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP From: David Howells If the kernel is locked down, require that all modules have valid signatures that we can verify. I have adjusted the errors generated: (1) If there's no signature (ENODATA) or we can't check it (ENOPKG, ENOKEY), then: (a) If signatures are enforced then EKEYREJECTED is returned. (b) If there's no signature or we can't check it, but the kernel is locked down then EPERM is returned (this is then consistent with other lockdown cases). (2) If the signature is unparseable (EBADMSG, EINVAL), the signature fails the check (EKEYREJECTED) or a system error occurs (eg. ENOMEM), we return the error we got. Note that the X.509 code doesn't check for key expiry as the RTC might not be valid or might not have been transferred to the kernel's clock yet. [Modified by Matthew Garrett to remove the IMA integration. This will be replaced with integration with the IMA architecture policy patchset.] Signed-off-by: David Howells Signed-off-by: Matthew Garrett Cc: Jessica Yu Reviewed-by: Kees Cook --- include/linux/security.h | 1 + kernel/module.c | 38 +++++++++++++++++++++++++++++------- security/lockdown/lockdown.c | 1 + 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/include/linux/security.h b/include/linux/security.h index c808d344ec75..46d85cd63b06 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -82,6 +82,7 @@ enum lsm_event { */ enum lockdown_reason { LOCKDOWN_NONE, + LOCKDOWN_MODULE_SIGNATURE, LOCKDOWN_INTEGRITY_MAX, LOCKDOWN_CONFIDENTIALITY_MAX, }; diff --git a/kernel/module.c b/kernel/module.c index 0b9aa8ab89f0..6aa681edd660 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -2763,8 +2763,9 @@ static inline void kmemleak_load_module(const struct module *mod, #ifdef CONFIG_MODULE_SIG static int module_sig_check(struct load_info *info, int flags) { - int err = -ENOKEY; + int ret, err = -ENODATA; const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1; + const char *reason; const void *mod = info->hdr; /* @@ -2779,16 +2780,39 @@ static int module_sig_check(struct load_info *info, int flags) err = mod_verify_sig(mod, info); } - if (!err) { + switch (err) { + case 0: info->sig_ok = true; return 0; - } - /* Not having a signature is only an error if we're strict. */ - if (err == -ENOKEY && !is_module_sig_enforced()) - err = 0; + /* We don't permit modules to be loaded into trusted kernels + * without a valid signature on them, but if we're not + * enforcing, certain errors are non-fatal. + */ + case -ENODATA: + reason = "Loading of unsigned module"; + goto decide; + case -ENOPKG: + reason = "Loading of module with unsupported crypto"; + goto decide; + case -ENOKEY: + reason = "Loading of module with unavailable key"; + decide: + if (is_module_sig_enforced()) { + pr_notice("%s is rejected\n", reason); + return -EKEYREJECTED; + } - return err; + ret = security_locked_down(LOCKDOWN_MODULE_SIGNATURE); + return ret; + + /* All other errors are fatal, including nomem, unparseable + * signatures and signature check failures - even if signatures + * aren't required. + */ + default: + return err; + } } #else /* !CONFIG_MODULE_SIG */ static int module_sig_check(struct load_info *info, int flags) diff --git a/security/lockdown/lockdown.c b/security/lockdown/lockdown.c index 8e39b36b8f33..25a3a5b0aa9c 100644 --- a/security/lockdown/lockdown.c +++ b/security/lockdown/lockdown.c @@ -18,6 +18,7 @@ static enum lockdown_reason kernel_locked_down; static char *lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1] = { [LOCKDOWN_NONE] = "none", + [LOCKDOWN_MODULE_SIGNATURE] = "unsigned module loading", [LOCKDOWN_INTEGRITY_MAX] = "integrity", [LOCKDOWN_CONFIDENTIALITY_MAX] = "confidentiality", };