From patchwork Wed Jun 27 13:33:42 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Kurinnoi X-Patchwork-Id: 10491695 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 18FDB60325 for ; Wed, 27 Jun 2018 13:33:49 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 06DA128FB6 for ; Wed, 27 Jun 2018 13:33:49 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id EF77728FC7; Wed, 27 Jun 2018 13:33:48 +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.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI, T_DKIM_INVALID 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 7815C28FB6 for ; Wed, 27 Jun 2018 13:33:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S965293AbeF0Nds (ORCPT ); Wed, 27 Jun 2018 09:33:48 -0400 Received: from mail-qk0-f195.google.com ([209.85.220.195]:37109 "EHLO mail-qk0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S964850AbeF0Ndr (ORCPT ); Wed, 27 Jun 2018 09:33:47 -0400 Received: by mail-qk0-f195.google.com with SMTP id t79-v6so1012144qke.4 for ; Wed, 27 Jun 2018 06:33:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:date:from:to:cc:subject:message-id:mime-version :content-transfer-encoding; bh=OsmoECsRJsZT+G2pW4Um9Fapq6jr91EuuXdrw//eN4c=; b=ZiarCWLthdEsRXsb6B1/AHmDusiwvK71/mOzQ2+r3CfCCTrKzy0h01QQ1t7zDWpA93 OPxLJl/r6oapCor/Qp1HAlOFZ62SXIloGtWvuvzJ0z4FDO5pqNC/M0ON3EWk6ReGmVIm mOIcRqYDpEKXG0oMkikDBuXDFLGiaoRYH4jED5N+YDfjoJtKOp4cXpGOcqlOaF7d5TV6 4ZSUGFyR27fRa+JjLIWD9aw8lJRSm1amZef6rOVgev7xswebsRHLBa4HktVvA8ZUwOUn Wb3O6UxY8asubyFXrT8HTgohCKCuLERfZ9gNcuP9cI3CUufknfyfK7FoR+zLd0inqWap 3uwQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:from:to:cc:subject:message-id :mime-version:content-transfer-encoding; bh=OsmoECsRJsZT+G2pW4Um9Fapq6jr91EuuXdrw//eN4c=; b=Woe5vWuY4zNEDCXQpaXag9+SwD0oWbzd/SMi0zKkl1YcKKHVhwto0FtLPNe0flGn8+ /JykeXCTkfItHAD4Ikzh51awRYMyGeKe2roTJLzbp+r/rJYDKEm338k3mNminbALIYdJ sV8iWoDelSQ1OuiQc38h+fWVgN7ypcNmZzeZplcwYlPwUTwdMr9KSPKfPqkEBAnl+pwV /5Np0/YhkepWH5tDaSf40B9LMwYBWvpxiK6NFw0V2aQx4eFzYPq2iLnYkpzVMfPYOtRM Cx09Nm5D6NvkOCGg8SKBHfRcNzjK2K4gsYC9c5YTQCROiEqJBj1J7V8zBKmSn17eGcUf pJmQ== X-Gm-Message-State: APt69E1a39mZ0RmVkDy+9f+hVHO7paBtsyRQedolClrjx0O897hzkj8J KmOLoxVa/8ZwsVX9cXEJEOhLkiV1 X-Google-Smtp-Source: AAOMgpfUBq4oHxVRTLAhdR9sm/RAMIdSU2xDQU1Ypda63eGxIPQBqC8ESOLisxuWDvRLKdtOgSOYBw== X-Received: by 2002:a37:82c7:: with SMTP id e190-v6mr4978324qkd.313.1530106426484; Wed, 27 Jun 2018 06:33:46 -0700 (PDT) Received: from totoro ([83.217.199.211]) by smtp.gmail.com with ESMTPSA id b40-v6sm3655343qtb.87.2018.06.27.06.33.44 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Wed, 27 Jun 2018 06:33:45 -0700 (PDT) Date: Wed, 27 Jun 2018 16:33:42 +0300 From: Mikhail Kurinnoi To: linux-integrity@vger.kernel.org Cc: Matthias Gerstner , Mimi Zohar Subject: [PATCH] integrity: prevent deadlock during digsig verification. Message-ID: <20180627163342.3e1d6333@totoro> MIME-Version: 1.0 Sender: linux-integrity-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch aimed to prevent deadlock during digsig verification.The point of issue - user space utility modprobe and/or it's dependencies (ld-*.so, libz.so.*, libc-*.so and /lib/modules/ files) that could be used for kernel modules load during digsig verification and could be signed by digsig in the same time. First at all, look at crypto_alloc_tfm() work algorithm: crypto_alloc_tfm() will first attempt to locate an already loaded algorithm. If that fails and the kernel supports dynamically loadable modules, it will then attempt to load a module of the same name or alias. If that fails it will send a query to any loaded crypto manager to construct an algorithm on the fly. We have situation, when public_key_verify_signature() in case of RSA algorithm use alg_name to store internal information in order to construct an algorithm on the fly, but crypto_larval_lookup() will try to use alg_name in order to load kernel module with same name. 1) we can't do anything with crypto module work, since it designed to work exactly in this way; 2) we can't globally filter module requests for modprobe, since it designed to work with any requests. In this patch, I propose add an exception for "crypto-pkcs1pad(rsa,*)" module requests only in case of enabled integrity asymmetric keys support. Since we don't have any real "crypto-pkcs1pad(rsa,*)" kernel modules for sure, we are safe to fail such module request from crypto_larval_lookup(). In this way we prevent modprobe execution during digsig verification and avoid possible deadlock if modprobe and/or it's dependencies also signed with digsig. Requested "crypto-pkcs1pad(rsa,*)" kernel module name formed by: 1) "pkcs1pad(rsa,%s)" in public_key_verify_signature(); 2) "crypto-%s" / "crypto-%s-all" in crypto_larval_lookup(). "crypto-pkcs1pad(rsa," part of request is a constant and unique and could be used as filter. Signed-off-by: Mikhail Kurinnoi include/linux/integrity.h | 13 +++++++++++++ security/integrity/digsig_asymmetric.c | 23 +++++++++++++++++++++++ security/security.c | 7 ++++++- 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/include/linux/integrity.h b/include/linux/integrity.h index c2d6082..8678e32 100644 --- a/include/linux/integrity.h +++ b/include/linux/integrity.h @@ -43,4 +43,17 @@ static inline void integrity_load_keys(void) } #endif /* CONFIG_INTEGRITY */ +#ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS + +extern int integrity_kernel_module_request(char *kmod_name); + +#else + +static inline int integrity_kernel_module_request(char *kmod_name) +{ + return 0; +} + +#endif /* CONFIG_INTEGRITY_ASYMMETRIC_KEYS */ + #endif /* _LINUX_INTEGRITY_H */ diff --git a/security/integrity/digsig_asymmetric.c b/security/integrity/digsig_asymmetric.c index 80052ed..f1ab90c 100644 --- a/security/integrity/digsig_asymmetric.c +++ b/security/integrity/digsig_asymmetric.c @@ -115,3 +115,26 @@ int asymmetric_verify(struct key *keyring, const char *sig, pr_debug("%s() = %d\n", __func__, ret); return ret; } + +/** + * integrity_kernel_module_request - prevent crypto-pkcs1pad(rsa,*) requests + * @kmod_name: kernel module name + * + * We have situation, when public_key_verify_signature() in case of RSA + * algorithm use alg_name to store internal information in order to + * construct an algorithm on the fly, but crypto_larval_lookup() will try + * to use alg_name in order to load kernel module with same name. + * Since we don't have any real "crypto-pkcs1pad(rsa,*)" kernel modules, + * we are safe to fail such module request from crypto_larval_lookup(). + * + * In this way we prevent modprobe execution during digsig verification + * and avoid possible deadlock if modprobe and/or it's dependencies + * also signed with digsig. + */ +int integrity_kernel_module_request(char *kmod_name) +{ + if (strncmp(kmod_name, "crypto-pkcs1pad(rsa,", 20) == 0) + return -EINVAL; + + return 0; +} diff --git a/security/security.c b/security/security.c index f825304..d53b4cb 100644 --- a/security/security.c +++ b/security/security.c @@ -929,7 +929,12 @@ int security_kernel_create_files_as(struct cred *new, struct inode *inode) int security_kernel_module_request(char *kmod_name) { - return call_int_hook(kernel_module_request, 0, kmod_name); + int ret; + + ret = call_int_hook(kernel_module_request, 0, kmod_name); + if (ret) + return ret; + return integrity_kernel_module_request(kmod_name); } int security_kernel_read_file(struct file *file, enum kernel_read_file_id id)