From patchwork Mon Apr 15 16:10:36 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 13630273 Received: from frasgout12.his.huawei.com (frasgout12.his.huawei.com [14.137.139.154]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6740380BF7; Mon, 15 Apr 2024 16:11:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=14.137.139.154 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713197511; cv=none; b=Yc9582Q8N6/0fk/BoPMlFanQUz/UqHQV7k4Rn0op0v5Fo7ZEUJiQKHJAisUytfbfmaa1wB5+fbupVrhdd07jeXSfv+iKScL/hBHK0zvUU4vYLwh2rEzrchpf5GcrWpF9p9GIxthqLImMf/zipYQzuSZyo4/k5kA4ebIn1VoFs7I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713197511; c=relaxed/simple; bh=fzNhu5+L37tz+f9+SsSu8RCO8zKco+WeH9wCYtepQbk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=SDq6VxddsXvty6pq3D6n+y8WGHAtW3FCV50DJmioyrruCBwD6AgKyWWfPiu5OKyJNnntsh0gRsuk/+SDRKaUlSkJxEju+wCUaIJHK5sJynz1XXQY1/WVjfH6O+g+b0rOCRjJ+jhTUGIfA1JsTbsCWVx43DCOeUkv8ugCUr53o84= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=14.137.139.154 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.18.186.29]) by frasgout12.his.huawei.com (SkyGuard) with ESMTP id 4VJBTm52Kcz9xGYK; Mon, 15 Apr 2024 23:50:52 +0800 (CST) Received: from mail02.huawei.com (unknown [7.182.16.27]) by mail.maildlp.com (Postfix) with ESMTP id E29AE1405E1; Tue, 16 Apr 2024 00:11:35 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP2 (Coremail) with SMTP id GxC2BwDn0iaZUR1m4n9HBg--.16529S3; Mon, 15 Apr 2024 17:11:35 +0100 (CET) From: Roberto Sassu To: corbet@lwn.net, zohar@linux.ibm.com, dmitry.kasatkin@gmail.com, eric.snowberg@oracle.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com Cc: linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, wufan@linux.microsoft.com, pbrobinson@gmail.com, zbyszek@in.waw.pl, hch@lst.de, mjg59@srcf.ucam.org, pmatilai@redhat.com, jannh@google.com, dhowells@redhat.com, jikos@kernel.org, mkoutny@suse.com, ppavlu@suse.com, petr.vorel@gmail.com, mzerqung@0pointer.de, kgold@linux.ibm.com, Roberto Sassu Subject: [RFC][PATCH v2 1/9] ima: Introduce hook DIGEST_LIST_CHECK Date: Mon, 15 Apr 2024 18:10:36 +0200 Message-Id: <20240415161044.2572438-2-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240415161044.2572438-1-roberto.sassu@huaweicloud.com> References: <20240415161044.2572438-1-roberto.sassu@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: GxC2BwDn0iaZUR1m4n9HBg--.16529S3 X-Coremail-Antispam: 1UD129KBjvJXoWxAw47Ar1rXF47XFy8Cw1rWFg_yoW5Cw4xpa 1qga40kryYqFy2gFZ3C3W29FWkKrWSgF4UG39093WvkFnxAF18Xryayr9F9FyfGryFyFn7 trs0gr47Aa1jyw7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUPab4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUGw A2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxS w2x7M28EF7xvwVC0I7IYx2IY67AKxVW8JVW5JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxV W8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_Cr0_Gr1UM28EF7xvwVC2z280aVCY1x0267AK xVW0oVCq3wAS0I0E0xvYzxvE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG6I80ew Av7VC0I7IYx2IY67AKxVWUGVWUXwAv7VC2z280aVAFwI0_Jr0_Gr1lOx8S6xCaFVCjc4AY 6r1j6r4UM4x0Y48IcxkI7VAKI48JM4IIrI8v6xkF7I0E8cxan2IY04v7MxkF7I0En4kS14 v26r4a6rW5MxAIw28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY6r1j6r4UMI8I3I0E5I8C rVAFwI0_Jr0_Jr4lx2IqxVCjr7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVW8ZVWrXw CIc40Y0x0EwIxGrwCI42IY6xIIjxv20xvE14v26r4j6ryUMIIF0xvE2Ix0cI8IcVCY1x02 67AKxVW8Jr0_Cr1UMIIF0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxV W8JVWxJwCI42IY6I8E87Iv6xkF7I0E14v26F4UJVW0obIYCTnIWIevJa73UjIFyTuYvjxU xU73DUUUU X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAgAOBF1jj5h14AAAs0 From: Roberto Sassu Introduce a new hook to check the integrity of digest lists. The new hook is invoked during a kernel read with file type READING_DIGEST LIST, which is done by the digest_cache LSM when it is populating a digest cache with a digest list. Signed-off-by: Roberto Sassu --- Documentation/ABI/testing/ima_policy | 1 + security/integrity/ima/ima.h | 1 + security/integrity/ima/ima_main.c | 3 ++- security/integrity/ima/ima_policy.c | 3 +++ 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy index c2385183826c..22237fec5532 100644 --- a/Documentation/ABI/testing/ima_policy +++ b/Documentation/ABI/testing/ima_policy @@ -36,6 +36,7 @@ Description: [KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK] [KEXEC_CMDLINE] [KEY_CHECK] [CRITICAL_DATA] [SETXATTR_CHECK][MMAP_CHECK_REQPROT] + [DIGEST_LIST_CHECK] mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND] [[^]MAY_EXEC] fsmagic:= hex value diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 11d7c0332207..cea4517e73ab 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -310,6 +310,7 @@ static inline unsigned int ima_hash_key(u8 *digest) hook(KEY_CHECK, key) \ hook(CRITICAL_DATA, critical_data) \ hook(SETXATTR_CHECK, setxattr_check) \ + hook(DIGEST_LIST_CHECK, digest_list_check) \ hook(MAX_CHECK, none) #define __ima_hook_enumify(ENUM, str) ENUM, diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index c84e8c55333d..780627b0cde7 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -785,7 +785,8 @@ const int read_idmap[READING_MAX_ID] = { [READING_MODULE] = MODULE_CHECK, [READING_KEXEC_IMAGE] = KEXEC_KERNEL_CHECK, [READING_KEXEC_INITRAMFS] = KEXEC_INITRAMFS_CHECK, - [READING_POLICY] = POLICY_CHECK + [READING_POLICY] = POLICY_CHECK, + [READING_DIGEST_LIST] = DIGEST_LIST_CHECK, }; /** diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index c0556907c2e6..7cfd1860791f 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -1287,6 +1287,7 @@ static bool ima_validate_rule(struct ima_rule_entry *entry) case MODULE_CHECK: case KEXEC_KERNEL_CHECK: case KEXEC_INITRAMFS_CHECK: + case DIGEST_LIST_CHECK: if (entry->flags & ~(IMA_FUNC | IMA_MASK | IMA_FSMAGIC | IMA_UID | IMA_FOWNER | IMA_FSUUID | IMA_INMASK | IMA_EUID | IMA_PCR | @@ -1530,6 +1531,8 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) entry->func = CRITICAL_DATA; else if (strcmp(args[0].from, "SETXATTR_CHECK") == 0) entry->func = SETXATTR_CHECK; + else if (strcmp(args[0].from, "DIGEST_LIST_CHECK") == 0) + entry->func = DIGEST_LIST_CHECK; else result = -EINVAL; if (!result) From patchwork Mon Apr 15 16:10:37 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 13630274 Received: from frasgout12.his.huawei.com (frasgout12.his.huawei.com [14.137.139.154]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4520C8175E; Mon, 15 Apr 2024 16:11:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=14.137.139.154 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713197514; cv=none; b=GqgFATNJ30Xw6T1GPO0u6vYOgVMuJSIqZndE7vmFgvAmQShI4NNfQmB54WpQJ2DEYRN92mkaXVZ/XOrMzDBR9h+UI2tyZPv4SGa/iAcYzH70dCF85Crb+BMWGqKcwYw+XlPW8Sdwd31xo9PRGUaEbiqoBxUNUet2lp2Oc3jxDpQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713197514; c=relaxed/simple; bh=Qmnl4eIUFNBIMJkcZ6lG8jyypOm/wejoN+kXBSHxVZU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=r/Q+RXURF7LE6D+TX4XN5ly/pTYQx/6aeoJtwO0sPM+ZQE3LJMGHOtqLASTgZrp3cKeMcfxF+oMzMGe7FZQEc55+Qy7qDPN9NZhDqk4AisSMIgjAbJoQ9q7qcbvEtpLrFkp/OkLLvxvdz+WZsPGTXOmYU6YXy6bQpvXSX3Wg2MQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=14.137.139.154 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.18.186.51]) by frasgout12.his.huawei.com (SkyGuard) with ESMTP id 4VJBTr1t71z9xrnb; Mon, 15 Apr 2024 23:50:56 +0800 (CST) Received: from mail02.huawei.com (unknown [7.182.16.27]) by mail.maildlp.com (Postfix) with ESMTP id 5C7FE1402A5; Tue, 16 Apr 2024 00:11:49 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP2 (Coremail) with SMTP id GxC2BwDn0iaZUR1m4n9HBg--.16529S4; Mon, 15 Apr 2024 17:11:48 +0100 (CET) From: Roberto Sassu To: corbet@lwn.net, zohar@linux.ibm.com, dmitry.kasatkin@gmail.com, eric.snowberg@oracle.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com Cc: linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, wufan@linux.microsoft.com, pbrobinson@gmail.com, zbyszek@in.waw.pl, hch@lst.de, mjg59@srcf.ucam.org, pmatilai@redhat.com, jannh@google.com, dhowells@redhat.com, jikos@kernel.org, mkoutny@suse.com, ppavlu@suse.com, petr.vorel@gmail.com, mzerqung@0pointer.de, kgold@linux.ibm.com, Roberto Sassu Subject: [RFC][PATCH v2 2/9] ima: Nest iint mutex for DIGEST_LIST_CHECK hook Date: Mon, 15 Apr 2024 18:10:37 +0200 Message-Id: <20240415161044.2572438-3-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240415161044.2572438-1-roberto.sassu@huaweicloud.com> References: <20240415161044.2572438-1-roberto.sassu@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: GxC2BwDn0iaZUR1m4n9HBg--.16529S4 X-Coremail-Antispam: 1UD129KBjvJXoW3Ary8AFW5Wr1rGF4DKF1UGFg_yoW7Cr48pa 9rta4DJ3s8XFZ7ur4rta9rZryfKFykWFW8Gw45A3WvyFn8Xr1FqF18try29Fy5CrWFv3WI vr4jgws8Z3Wjyr7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUPIb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUXw A2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxS w2x7M28EF7xvwVC0I7IYx2IY67AKxVW8JVW5JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxV W8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_Cr0_Gr1UM28EF7xvwVC2z280aVCY1x0267AK xVW0oVCq3wAS0I0E0xvYzxvE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG6I80ew Av7VC0I7IYx2IY67AKxVWUGVWUXwAv7VC2z280aVAFwI0_Jr0_Gr1lOx8S6xCaFVCjc4AY 6r1j6r4UM4x0Y48IcxkI7VAKI48JM4IIrI8v6xkF7I0E8cxan2IY04v7MxkF7I0En4kS14 v26r4a6rW5MxAIw28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY6r1j6r4UMI8I3I0E5I8C rVAFwI0_Jr0_Jr4lx2IqxVCjr7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVW8ZVWrXw CIc40Y0x0EwIxGrwCI42IY6xIIjxv20xvE14v26r4j6ryUMIIF0xvE2Ix0cI8IcVCY1x02 67AKxVW8Jr0_Cr1UMIIF0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxV W8JVWxJwCI42IY6I8E87Iv6xkF7I0E14v26rxl6s0DYxBIdaVFxhVjvjDU0xZFpf9x07j7 hLnUUUUU= X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAgAOBF1jj5h14AABs1 From: Roberto Sassu Invoking digest_cache_get() inside the iint->mutex critical region can cause deadlocks due to the fact that IMA can be recursively invoked for reading the digest list. The deadlock would occur if the digest_cache LSM attempts to read the same inode that is already locked by IMA. However, since the digest_cache LSM makes sure that the above situation never happens, as it checks the inodes, it is safe to call digest_cache_get() inside the critical region and nest the iint->mutex when the DIGEST_LIST_CHECK hook is executed. Add a lockdep subclass to the iint->mutex, that is 0 if the IMA hook executed is not DIGEST_LIST_CHECK, and 1 when it is. Since lockdep allows nesting with higher classes and subclasses, that effectively eliminates the warning about the unsafe lock. Pass the new lockdep subclass (nested variable) from ima_inode_get() to ima_iint_init_always() and ima_iint_lockdep_annotate(). Signed-off-by: Roberto Sassu --- security/integrity/ima/ima.h | 2 +- security/integrity/ima/ima_iint.c | 17 +++++++++++------ security/integrity/ima/ima_main.c | 6 +++--- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index cea4517e73ab..c9140a57b591 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -216,7 +216,7 @@ static inline void ima_inode_set_iint(const struct inode *inode, } struct ima_iint_cache *ima_iint_find(struct inode *inode); -struct ima_iint_cache *ima_inode_get(struct inode *inode); +struct ima_iint_cache *ima_inode_get(struct inode *inode, bool nested); void ima_inode_free(struct inode *inode); void __init ima_iintcache_init(void); diff --git a/security/integrity/ima/ima_iint.c b/security/integrity/ima/ima_iint.c index e7c9c216c1c6..c98a30815c8a 100644 --- a/security/integrity/ima/ima_iint.c +++ b/security/integrity/ima/ima_iint.c @@ -39,9 +39,12 @@ struct ima_iint_cache *ima_iint_find(struct inode *inode) * files both on overlayfs and on underlying fs, we need to annotate the iint * mutex to avoid lockdep false positives related to IMA + overlayfs. * See ovl_lockdep_annotate_inode_mutex_key() for more details. + * + * In addition to that, safely ignored nested locks for digest lists, since + * the digest_cache LSM prevents circular dependencies. */ static inline void ima_iint_lockdep_annotate(struct ima_iint_cache *iint, - struct inode *inode) + struct inode *inode, bool nested) { #ifdef CONFIG_LOCKDEP static struct lock_class_key ima_iint_mutex_key[IMA_MAX_NESTING]; @@ -51,12 +54,13 @@ static inline void ima_iint_lockdep_annotate(struct ima_iint_cache *iint, if (WARN_ON_ONCE(depth < 0 || depth >= IMA_MAX_NESTING)) depth = 0; - lockdep_set_class(&iint->mutex, &ima_iint_mutex_key[depth]); + lockdep_set_class_and_subclass(&iint->mutex, &ima_iint_mutex_key[depth], + nested); #endif } static void ima_iint_init_always(struct ima_iint_cache *iint, - struct inode *inode) + struct inode *inode, bool nested) { iint->ima_hash = NULL; iint->version = 0; @@ -69,7 +73,7 @@ static void ima_iint_init_always(struct ima_iint_cache *iint, iint->ima_creds_status = INTEGRITY_UNKNOWN; iint->measured_pcrs = 0; mutex_init(&iint->mutex); - ima_iint_lockdep_annotate(iint, inode); + ima_iint_lockdep_annotate(iint, inode, nested); } static void ima_iint_free(struct ima_iint_cache *iint) @@ -82,13 +86,14 @@ static void ima_iint_free(struct ima_iint_cache *iint) /** * ima_inode_get - Find or allocate an iint associated with an inode * @inode: Pointer to the inode + * @nested: Whether or not the iint->mutex lock can be nested * * Find an iint associated with an inode, and allocate a new one if not found. * Caller must lock i_mutex. * * Return: An iint on success, NULL on error. */ -struct ima_iint_cache *ima_inode_get(struct inode *inode) +struct ima_iint_cache *ima_inode_get(struct inode *inode, bool nested) { struct ima_iint_cache *iint; @@ -100,7 +105,7 @@ struct ima_iint_cache *ima_inode_get(struct inode *inode) if (!iint) return NULL; - ima_iint_init_always(iint, inode); + ima_iint_init_always(iint, inode, nested); inode->i_flags |= S_IMA; ima_inode_set_iint(inode, iint); diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 780627b0cde7..18285fc8ac07 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -248,7 +248,7 @@ static int process_measurement(struct file *file, const struct cred *cred, inode_lock(inode); if (action) { - iint = ima_inode_get(inode); + iint = ima_inode_get(inode, func == DIGEST_LIST_CHECK); if (!iint) rc = -ENOMEM; } @@ -699,7 +699,7 @@ static void ima_post_create_tmpfile(struct mnt_idmap *idmap, return; /* Nothing to do if we can't allocate memory */ - iint = ima_inode_get(inode); + iint = ima_inode_get(inode, false); if (!iint) return; @@ -731,7 +731,7 @@ static void ima_post_path_mknod(struct mnt_idmap *idmap, struct dentry *dentry) return; /* Nothing to do if we can't allocate memory */ - iint = ima_inode_get(inode); + iint = ima_inode_get(inode, false); if (!iint) return; From patchwork Mon Apr 15 16:10:38 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 13630275 Received: from frasgout11.his.huawei.com (frasgout11.his.huawei.com [14.137.139.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4266B7FBA4; Mon, 15 Apr 2024 16:12:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=14.137.139.23 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713197538; cv=none; b=mty1yRby/HozNOWZL89yCQcTUKANeU0yZuC6szmLGmcaRB2NPEvJ6u1BvVxX8c2FAHkWUVVlfowU0d+JrZ4MXXTFbPcTlNHDD2Z/RrMA7WKgkQzNftPw3iWVszG5pwIe1wJ4uRKCsb6SYURuQzhhQTFt3buedJAPqhG9ecR6UIg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713197538; c=relaxed/simple; bh=0tDFC0Rzwu0TnZ9tH4wkji+B1IUHRT8OEVZwyh0x3is=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Vaqm1O70rLEsrnliK5Lde4Wz0R5qLzqKHm4JICDCSgnbo7tVmx/lriM1Yl+R0u+5GjP8HUonOUUX3WpaN8OICVF6eX3ctQhDXH6ICYQZK3Tm5TnD4j+h0cYB+/tc2HFdvRtOEVDKCbFp7CP8YulOuBThm1To344bC3EvmqFneRs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=14.137.139.23 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.18.186.29]) by frasgout11.his.huawei.com (SkyGuard) with ESMTP id 4VJBbM3gdzz9v7Nb; Mon, 15 Apr 2024 23:55:43 +0800 (CST) Received: from mail02.huawei.com (unknown [7.182.16.27]) by mail.maildlp.com (Postfix) with ESMTP id AD9271405E1; Tue, 16 Apr 2024 00:12:02 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP2 (Coremail) with SMTP id GxC2BwDn0iaZUR1m4n9HBg--.16529S5; Mon, 15 Apr 2024 17:12:02 +0100 (CET) From: Roberto Sassu To: corbet@lwn.net, zohar@linux.ibm.com, dmitry.kasatkin@gmail.com, eric.snowberg@oracle.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com Cc: linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, wufan@linux.microsoft.com, pbrobinson@gmail.com, zbyszek@in.waw.pl, hch@lst.de, mjg59@srcf.ucam.org, pmatilai@redhat.com, jannh@google.com, dhowells@redhat.com, jikos@kernel.org, mkoutny@suse.com, ppavlu@suse.com, petr.vorel@gmail.com, mzerqung@0pointer.de, kgold@linux.ibm.com, Roberto Sassu Subject: [RFC][PATCH v2 3/9] ima: Add digest_cache policy keyword Date: Mon, 15 Apr 2024 18:10:38 +0200 Message-Id: <20240415161044.2572438-4-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240415161044.2572438-1-roberto.sassu@huaweicloud.com> References: <20240415161044.2572438-1-roberto.sassu@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: GxC2BwDn0iaZUR1m4n9HBg--.16529S5 X-Coremail-Antispam: 1UD129KBjvAXoW3Aw1xtFyxKr15WryktryUGFg_yoW8Jw1kAo Z3K39rJF48GFy3CayUCFnIyay8W3yrGwn7JFnYgr98Z3Z2vryUGasrWr1UZFW3ZF45Xa90 kw1xX3y8tFW8Jas3n29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjp_UUUO07kC6x804xWl14x267AKxVWrJVCq3wAFc2x0x2IEx4CE42xK 8VAvwI8IcIk0rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2048vs2IY020E87I2jVAFwI0_Jr Wl82xGYIkIc2x26xkF7I0E14v26ryj6s0DM28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48v e4kI8wA2z4x0Y4vE2Ix0cI8IcVAFwI0_Gr0_Xr1l84ACjcxK6xIIjxv20xvEc7CjxVAFwI 0_Gr1j6F4UJwA2z4x0Y4vEx4A2jsIE14v26F4j6r4UJwA2z4x0Y4vEx4A2jsIEc7CjxVAF wI0_GcCE3s1le2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrVC2j2 WlYx0E2Ix0cI8IcVAFwI0_JrI_JrylYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE7xkE bVWUJVW8JwACjcxG0xvY0x0EwIxGrwACI402YVCY1x02628vn2kIc2xKxwCY1x0262kKe7 AKxVW8ZVWrXwCF04k20xvY0x0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02 F40E14v26r1j6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_GFv_Wr ylIxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVW8JVW5JwCI42IY6xIIjxv20xvEc7Cj xVAFwI0_Gr1j6F4UJwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI 0_Gr0_Cr1lIxAIcVC2z280aVCY1x0267AKxVW0oVCq3bIYCTnIWIevJa73UjIFyTuYvjxU 4R6zUUUUU X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAgAOBF1jj5h14AACs2 From: Roberto Sassu Add the 'digest_cache=' policy keyword, to enable the usage of digest caches for specific IMA actions and purpose. At the moment, it accepts only 'data' as value, as digest caches can be used only for measurement and appraisal of file data. In the future, it might be possible to use them for file metadata too. The 'digest_cache=' keyword can be specified for the subset of IMA hooks listed in ima_digest_cache_func_allowed(). In case the function is not specified in the policy, digest caches might not be available. POLICY_CHECK has been excluded for measurement, because policy changes must be visible in the IMA measurement list. For appraisal, instead, it might be useful to load custom policies in the initial ram disk (no security.ima xattr). Add the digest_cache_usage member to the ima_rule_entry structure, and set the flag IMA_DIGEST_CACHE_MEASURE_DATA if 'digest_cache=data' was specified for a measure rule, IMA_DIGEST_CACHE_APPRAISE_DATA for an appraise rule. Propagate the usage down to ima_match_policy() and ima_get_action(), so that process_measurement() can make the final decision on whether or not digest caches should be used to measure/appraise the file being evaluated. Since using digest caches changes the meaning of the IMA measurement list, which will include only digest lists and unknown files, enforce specifying 'pcr=' with a non-standard value, when 'digest_cache=data' is specified in a measure rule. This removes the ambiguity on the meaning of the IMA measurement list. Signed-off-by: Roberto Sassu --- Documentation/ABI/testing/ima_policy | 5 +- security/integrity/ima/ima.h | 10 +++- security/integrity/ima/ima_api.c | 6 ++- security/integrity/ima/ima_appraise.c | 2 +- security/integrity/ima/ima_main.c | 8 +-- security/integrity/ima/ima_policy.c | 70 ++++++++++++++++++++++++++- 6 files changed, 89 insertions(+), 12 deletions(-) diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy index 22237fec5532..887ac79f66eb 100644 --- a/Documentation/ABI/testing/ima_policy +++ b/Documentation/ABI/testing/ima_policy @@ -29,7 +29,7 @@ Description: [obj_user=] [obj_role=] [obj_type=]] option: [digest_type=] [template=] [permit_directio] [appraise_type=] [appraise_flag=] - [appraise_algos=] [keyrings=] + [appraise_algos=] [keyrings=] [digest_cache=] base: func:= [BPRM_CHECK][MMAP_CHECK][CREDS_CHECK][FILE_CHECK][MODULE_CHECK] [FIRMWARE_CHECK] @@ -77,6 +77,9 @@ Description: For example, "sha256,sha512" to only accept to appraise files where the security.ima xattr was hashed with one of these two algorithms. + digest_cache:= [data] + "data" means that the digest cache is used only + for file data measurement and/or appraisal. default policy: # PROC_SUPER_MAGIC diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index c9140a57b591..337b3b76b28d 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -43,6 +43,10 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8, TPM_PCR10 = 10 }; #define NR_BANKS(chip) ((chip != NULL) ? chip->nr_allocated_banks : 0) +/* Digest cache usage flags. */ +#define IMA_DIGEST_CACHE_MEASURE_DATA 0x0000000000000001 +#define IMA_DIGEST_CACHE_APPRAISE_DATA 0x0000000000000002 + /* current content of the policy */ extern int ima_policy_flag; @@ -367,7 +371,8 @@ int ima_get_action(struct mnt_idmap *idmap, struct inode *inode, const struct cred *cred, u32 secid, int mask, enum ima_hooks func, int *pcr, struct ima_template_desc **template_desc, - const char *func_data, unsigned int *allowed_algos); + const char *func_data, unsigned int *allowed_algos, + u64 *digest_cache_usage); int ima_must_measure(struct inode *inode, int mask, enum ima_hooks func); int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file, void *buf, loff_t size, enum hash_algo algo, @@ -398,7 +403,8 @@ int ima_match_policy(struct mnt_idmap *idmap, struct inode *inode, const struct cred *cred, u32 secid, enum ima_hooks func, int mask, int flags, int *pcr, struct ima_template_desc **template_desc, - const char *func_data, unsigned int *allowed_algos); + const char *func_data, unsigned int *allowed_algos, + u64 *digest_cache_usage); void ima_init_policy(void); void ima_update_policy(void); void ima_update_policy_flags(void); diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index b37d043d5748..f0a1ce10afe8 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c @@ -173,6 +173,7 @@ void ima_add_violation(struct file *file, const unsigned char *filename, * @template_desc: pointer filled in if matched measure policy sets template= * @func_data: func specific data, may be NULL * @allowed_algos: allowlist of hash algorithms for the IMA xattr + * @digest_cache_usage: Actions and purpose for which digest cache is allowed * * The policy is defined in terms of keypairs: * subj=, obj=, type=, func=, mask=, fsmagic= @@ -190,7 +191,8 @@ int ima_get_action(struct mnt_idmap *idmap, struct inode *inode, const struct cred *cred, u32 secid, int mask, enum ima_hooks func, int *pcr, struct ima_template_desc **template_desc, - const char *func_data, unsigned int *allowed_algos) + const char *func_data, unsigned int *allowed_algos, + u64 *digest_cache_usage) { int flags = IMA_MEASURE | IMA_AUDIT | IMA_APPRAISE | IMA_HASH; @@ -198,7 +200,7 @@ int ima_get_action(struct mnt_idmap *idmap, struct inode *inode, return ima_match_policy(idmap, inode, cred, secid, func, mask, flags, pcr, template_desc, func_data, - allowed_algos); + allowed_algos, digest_cache_usage); } static bool ima_get_verity_digest(struct ima_iint_cache *iint, diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index 3497741caea9..27ccc9a2c09f 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -81,7 +81,7 @@ int ima_must_appraise(struct mnt_idmap *idmap, struct inode *inode, security_current_getsecid_subj(&secid); return ima_match_policy(idmap, inode, current_cred(), secid, func, mask, IMA_APPRAISE | IMA_HASH, NULL, - NULL, NULL, NULL); + NULL, NULL, NULL, NULL); } static int ima_fix_xattr(struct dentry *dentry, struct ima_iint_cache *iint) diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 18285fc8ac07..e3ca80098c4c 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -232,7 +232,7 @@ static int process_measurement(struct file *file, const struct cred *cred, */ action = ima_get_action(file_mnt_idmap(file), inode, cred, secid, mask, func, &pcr, &template_desc, NULL, - &allowed_algos); + &allowed_algos, NULL); violation_check = ((func == FILE_CHECK || func == MMAP_CHECK || func == MMAP_CHECK_REQPROT) && (ima_policy_flag & IMA_MEASURE)); @@ -489,11 +489,11 @@ static int ima_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, inode = file_inode(vma->vm_file); action = ima_get_action(file_mnt_idmap(vma->vm_file), inode, current_cred(), secid, MAY_EXEC, MMAP_CHECK, - &pcr, &template, NULL, NULL); + &pcr, &template, NULL, NULL, NULL); action |= ima_get_action(file_mnt_idmap(vma->vm_file), inode, current_cred(), secid, MAY_EXEC, MMAP_CHECK_REQPROT, &pcr, &template, NULL, - NULL); + NULL, NULL); /* Is the mmap'ed file in policy? */ if (!(action & (IMA_MEASURE | IMA_APPRAISE_SUBMASK))) @@ -972,7 +972,7 @@ int process_buffer_measurement(struct mnt_idmap *idmap, security_current_getsecid_subj(&secid); action = ima_get_action(idmap, inode, current_cred(), secid, 0, func, &pcr, &template, - func_data, NULL); + func_data, NULL, NULL); if (!(action & IMA_MEASURE) && !digest) return -ENOENT; } diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 7cfd1860791f..9e13b88b0ed5 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -122,6 +122,7 @@ struct ima_rule_entry { struct ima_rule_opt_list *keyrings; /* Measure keys added to these keyrings */ struct ima_rule_opt_list *label; /* Measure data grouped under this label */ struct ima_template_desc *template; + u64 digest_cache_usage; /* Actions and purpose for which digest cache is allowed */ }; /* @@ -726,6 +727,7 @@ static int get_subaction(struct ima_rule_entry *rule, enum ima_hooks func) * @template_desc: the template that should be used for this rule * @func_data: func specific data, may be NULL * @allowed_algos: allowlist of hash algorithms for the IMA xattr + * @digest_cache_usage: Actions and purpose for which digest cache is allowed * * Measure decision based on func/mask/fsmagic and LSM(subj/obj/type) * conditions. @@ -738,7 +740,8 @@ int ima_match_policy(struct mnt_idmap *idmap, struct inode *inode, const struct cred *cred, u32 secid, enum ima_hooks func, int mask, int flags, int *pcr, struct ima_template_desc **template_desc, - const char *func_data, unsigned int *allowed_algos) + const char *func_data, unsigned int *allowed_algos, + u64 *digest_cache_usage) { struct ima_rule_entry *entry; int action = 0, actmask = flags | (flags << 1); @@ -783,6 +786,9 @@ int ima_match_policy(struct mnt_idmap *idmap, struct inode *inode, if (template_desc && entry->template) *template_desc = entry->template; + if (digest_cache_usage) + *digest_cache_usage |= entry->digest_cache_usage; + if (!actmask) break; } @@ -859,6 +865,30 @@ static int ima_appraise_flag(enum ima_hooks func) return 0; } +static bool ima_digest_cache_func_allowed(struct ima_rule_entry *entry) +{ + switch (entry->func) { + case NONE: + case FILE_CHECK: + case MMAP_CHECK: + case MMAP_CHECK_REQPROT: + case BPRM_CHECK: + case CREDS_CHECK: + case FIRMWARE_CHECK: + case POLICY_CHECK: + case MODULE_CHECK: + case KEXEC_KERNEL_CHECK: + case KEXEC_INITRAMFS_CHECK: + /* Exception: always add policy updates to measurement list! */ + if (entry->action == MEASURE && entry->func == POLICY_CHECK) + return false; + + return true; + default: + return false; + } +} + static void add_rules(struct ima_rule_entry *entries, int count, enum policy_rule_list policy_rule) { @@ -1073,7 +1103,7 @@ enum policy_opt { Opt_digest_type, Opt_appraise_type, Opt_appraise_flag, Opt_appraise_algos, Opt_permit_directio, Opt_pcr, Opt_template, Opt_keyrings, - Opt_label, Opt_err + Opt_label, Opt_digest_cache, Opt_err }; static const match_table_t policy_tokens = { @@ -1122,6 +1152,7 @@ static const match_table_t policy_tokens = { {Opt_template, "template=%s"}, {Opt_keyrings, "keyrings=%s"}, {Opt_label, "label=%s"}, + {Opt_digest_cache, "digest_cache=%s"}, {Opt_err, NULL} }; @@ -1245,6 +1276,18 @@ static bool ima_validate_rule(struct ima_rule_entry *entry) if (entry->action != MEASURE && entry->flags & IMA_PCR) return false; + /* New-style measurements with digest cache cannot be on default PCR. */ + if (entry->action == MEASURE && + (entry->digest_cache_usage & IMA_DIGEST_CACHE_MEASURE_DATA)) { + if (!(entry->flags & IMA_PCR) || + entry->pcr == CONFIG_IMA_MEASURE_PCR_IDX) + return false; + } + + /* Digest caches can be used only for a subset of the IMA hooks. */ + if (entry->digest_cache_usage && !ima_digest_cache_func_allowed(entry)) + return false; + if (entry->action != APPRAISE && entry->flags & (IMA_DIGSIG_REQUIRED | IMA_MODSIG_ALLOWED | IMA_CHECK_BLACKLIST | IMA_VALIDATE_ALGOS)) @@ -1881,6 +1924,26 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) &(template_desc->num_fields)); entry->template = template_desc; break; + case Opt_digest_cache: + ima_log_string(ab, "digest_cache", args[0].from); + + result = -EINVAL; + + if (!strcmp(args[0].from, "data")) { + switch (entry->action) { + case MEASURE: + entry->digest_cache_usage |= IMA_DIGEST_CACHE_MEASURE_DATA; + result = 0; + break; + case APPRAISE: + entry->digest_cache_usage |= IMA_DIGEST_CACHE_APPRAISE_DATA; + result = 0; + break; + default: + break; + } + } + break; case Opt_err: ima_log_string(ab, "UNKNOWN", p); result = -EINVAL; @@ -2271,6 +2334,9 @@ int ima_policy_show(struct seq_file *m, void *v) seq_puts(m, "digest_type=verity "); if (entry->flags & IMA_PERMIT_DIRECTIO) seq_puts(m, "permit_directio "); + if ((entry->digest_cache_usage & IMA_DIGEST_CACHE_MEASURE_DATA) || + (entry->digest_cache_usage & IMA_DIGEST_CACHE_APPRAISE_DATA)) + seq_puts(m, "digest_cache=data "); rcu_read_unlock(); seq_puts(m, "\n"); return 0; From patchwork Mon Apr 15 16:10:39 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 13630276 Received: from frasgout13.his.huawei.com (frasgout13.his.huawei.com [14.137.139.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2B9B980C14; Mon, 15 Apr 2024 16:12:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=14.137.139.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713197541; cv=none; b=c8DGv7RrZbYc8Czt01AgwO7q4q/xZAPIeFA1EYjaULGDS0QoSMHcCkXQQxNLHvOrJD9sAlUhPD0q/nQL2WB56wsYGsz5EPfTpCbShGjr9KliZVRtg+3L/PgTE1yun5lKDxeLDCXKe/RKfqV6LF/3fS7mG9O2mDQNMr8XvUkWknA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713197541; c=relaxed/simple; bh=Lq03hBo9irT2FumkWfUnQv9n2u2+4mLpxr7sOeBCN+g=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=CCmjowkns5C6Htbg7NYTPO8SEVvKG7HIY046oY2EyffvL1UaQ5mq7NsKLCNoojONYh8+9Uaxs07IUtcNlgIKSIvswvAZpy8CG4ty1A7tNJsgVTX0ZRFk9pHuwm41fWd1CcYHRw40ynHiBxIZqvDKb0ji91OkfB909G/yGx9QDsA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=14.137.139.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.18.186.29]) by frasgout13.his.huawei.com (SkyGuard) with ESMTP id 4VJBbT27rKz9xHvT; Mon, 15 Apr 2024 23:55:49 +0800 (CST) Received: from mail02.huawei.com (unknown [7.182.16.27]) by mail.maildlp.com (Postfix) with ESMTP id 1B7F4140627; Tue, 16 Apr 2024 00:12:16 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP2 (Coremail) with SMTP id GxC2BwDn0iaZUR1m4n9HBg--.16529S6; Mon, 15 Apr 2024 17:12:15 +0100 (CET) From: Roberto Sassu To: corbet@lwn.net, zohar@linux.ibm.com, dmitry.kasatkin@gmail.com, eric.snowberg@oracle.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com Cc: linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, wufan@linux.microsoft.com, pbrobinson@gmail.com, zbyszek@in.waw.pl, hch@lst.de, mjg59@srcf.ucam.org, pmatilai@redhat.com, jannh@google.com, dhowells@redhat.com, jikos@kernel.org, mkoutny@suse.com, ppavlu@suse.com, petr.vorel@gmail.com, mzerqung@0pointer.de, kgold@linux.ibm.com, Roberto Sassu Subject: [RFC][PATCH v2 4/9] ima: Add digest_cache_measure/appraise boot-time built-in policies Date: Mon, 15 Apr 2024 18:10:39 +0200 Message-Id: <20240415161044.2572438-5-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240415161044.2572438-1-roberto.sassu@huaweicloud.com> References: <20240415161044.2572438-1-roberto.sassu@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: GxC2BwDn0iaZUR1m4n9HBg--.16529S6 X-Coremail-Antispam: 1UD129KBjvJXoWxtF1kKr1UWF13Zr1DWw48Zwb_yoW7CrWfpa 9rWFy5trZ8XF9xCw47Ca4xuF4Fy3s2ga17Wws8Ga4jy3Z8Zr1q9w1Fy3W3ZrZ8Ar1jq3Wx JFs09r4jkw1qqaDanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUPqb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVW8JVW5JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_Cr0_Gr1UM28EF7xvwVC2z280aVCY1x02 67AKxVW0oVCq3wAS0I0E0xvYzxvE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG6I 80ewAv7VC0I7IYx2IY67AKxVWUGVWUXwAv7VC2z280aVAFwI0_Jr0_Gr1lOx8S6xCaFVCj c4AY6r1j6r4UM4x0Y48IcxkI7VAKI48JM4IIrI8v6xkF7I0E8cxan2IY04v7MxkF7I0En4 kS14v26r4a6rW5MxAIw28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY6r1j6r4UMI8I3I0E 5I8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVW8ZV WrXwCIc40Y0x0EwIxGrwCI42IY6xIIjxv20xvE14v26r4j6ryUMIIF0xvE2Ix0cI8IcVCY 1x0267AKxVW8Jr0_Cr1UMIIF0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67 AKxVW8JVWxJwCI42IY6I8E87Iv6xkF7I0E14v26rxl6s0DYxBIdaVFxhVjvjDU0xZFpf9x 07j7GYLUUUUU= X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAgAOBF1jj5h14AAEsw From: Roberto Sassu Specify the 'digest_cache_measure' boot-time policy with 'ima_policy=' in the kernel command line to add the following rule at the beginning of the IMA policy, before other rules: measure func=DIGEST_LIST_CHECK pcr=12 which will measure digest lists into PCR 12 (or the value in CONFIG_IMA_DIGEST_CACHE_MEASURE_PCR_IDX). Specify 'digest_cache_appraise' to add the following rule at the beginning, before other rules: appraise func=DIGEST_LIST_CHECK appraise_type=imasig|modsig which will appraise digest lists with IMA signatures or module-style appended signatures. Adding those rule at the beginning rather than at the end is necessary to ensure that digest lists are measured and appraised in the initial ram disk, which would be otherwise prevented by the dont_ rules. Signed-off-by: Roberto Sassu --- .../admin-guide/kernel-parameters.txt | 10 +++++- security/integrity/ima/Kconfig | 10 ++++++ security/integrity/ima/ima_policy.c | 35 +++++++++++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 902ecd92a29f..df877588decc 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -2050,7 +2050,8 @@ ima_policy= [IMA] The builtin policies to load during IMA setup. Format: "tcb | appraise_tcb | secure_boot | - fail_securely | critical_data" + fail_securely | critical_data | + digest_cache_measure | digest_cache_appraise" The "tcb" policy measures all programs exec'd, files mmap'd for exec, and all files opened with the read @@ -2072,6 +2073,13 @@ The "critical_data" policy measures kernel integrity critical data. + The "digest_cache_measure" policy measures digest lists + into PCR 12 (can be changed with kernel config). + + The "digest_cache_appraise" policy appraises digest + lists with IMA signatures or module-style appended + signatures. + ima_tcb [IMA] Deprecated. Use ima_policy= instead. Load a policy which meets the needs of the Trusted Computing Base. This means IMA will measure all diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig index 475c32615006..6a481019fb6e 100644 --- a/security/integrity/ima/Kconfig +++ b/security/integrity/ima/Kconfig @@ -321,4 +321,14 @@ config IMA_DISABLE_HTABLE help This option disables htable to allow measurement of duplicate records. +config IMA_DIGEST_CACHE_MEASURE_PCR_IDX + int + range 8 14 + default 12 + help + This option determines the TPM PCR register index that IMA uses to + maintain the integrity aggregate of the measurement list, when the + digest_cache LSM is used (different measurement style). If unsure, + use the default 12. + endif diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 9e13b88b0ed5..f049543f6b64 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -254,6 +254,21 @@ static struct ima_rule_entry critical_data_rules[] __ro_after_init = { {.action = MEASURE, .func = CRITICAL_DATA, .flags = IMA_FUNC}, }; +static struct ima_rule_entry measure_digest_cache_rule __ro_after_init = { +#ifdef CONFIG_SECURITY_DIGEST_CACHE + .action = MEASURE, .func = DIGEST_LIST_CHECK, + .pcr = CONFIG_IMA_DIGEST_CACHE_MEASURE_PCR_IDX, + .flags = IMA_FUNC | IMA_PCR +#endif +}; + +static struct ima_rule_entry appraise_digest_cache_rule __ro_after_init = { +#ifdef CONFIG_SECURITY_DIGEST_CACHE + .action = APPRAISE, .func = DIGEST_LIST_CHECK, + .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED | IMA_MODSIG_ALLOWED, +#endif +}; + /* An array of architecture specific rules */ static struct ima_rule_entry *arch_policy_entry __ro_after_init; @@ -278,6 +293,8 @@ static bool ima_use_appraise_tcb __initdata; static bool ima_use_secure_boot __initdata; static bool ima_use_critical_data __initdata; static bool ima_fail_unverifiable_sigs __ro_after_init; +static bool ima_digest_cache_measure __ro_after_init; +static bool ima_digest_cache_appraise __ro_after_init; static int __init policy_setup(char *str) { char *p; @@ -295,6 +312,10 @@ static int __init policy_setup(char *str) ima_use_critical_data = true; else if (strcmp(p, "fail_securely") == 0) ima_fail_unverifiable_sigs = true; + else if (strcmp(p, "digest_cache_measure") == 0) + ima_digest_cache_measure = true; + else if (strcmp(p, "digest_cache_appraise") == 0) + ima_digest_cache_appraise = true; else pr_err("policy \"%s\" not found", p); } @@ -971,6 +992,20 @@ void __init ima_init_policy(void) { int build_appraise_entries, arch_entries; + /* + * We need to load digest cache rules at the beginning, to avoid dont_ + * rules causing ours to not be reached. + */ + if (IS_ENABLED(CONFIG_SECURITY_DIGEST_CACHE)) { + if (ima_digest_cache_measure) + add_rules(&measure_digest_cache_rule, 1, + IMA_DEFAULT_POLICY); + + if (ima_digest_cache_appraise) + add_rules(&appraise_digest_cache_rule, 1, + IMA_DEFAULT_POLICY); + } + /* if !ima_policy, we load NO default rules */ if (ima_policy) add_rules(dont_measure_rules, ARRAY_SIZE(dont_measure_rules), From patchwork Mon Apr 15 16:10:40 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 13630277 Received: from frasgout12.his.huawei.com (frasgout12.his.huawei.com [14.137.139.154]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9E1C080635; Mon, 15 Apr 2024 16:12:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=14.137.139.154 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713197561; cv=none; b=qJr/fK+lUE5dcvHHKR65L/zoXbKbARJF3ftN/j2ajZE4912AX+7fcrAyrAoehPtrG/2wMcsMjlJZuZimZAuMnQEX+VV4RYFHX12dEqWKCgVWXxHXMDrx4LY8pbj6IgCUrnWXZvNVT7Ne0ypU6vy1D7dTZdPefSDyyE/BDLfYLjU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713197561; c=relaxed/simple; bh=JHPuKB2cACTEpt/cnPDWe+nSC05Prn8YFIRzP5Ua1qw=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=YDjPpsxc7GXPb1vxgDr01w4fceutG9OpJz2tVjQzOHDcFYBcn0DnMcA9adHgFO3qdUXjfjrjHBuPHMszT5DVU8HDVZXgFtvv2Aoz7/7kkMPOflPyvzmx8s//qA95F0EvWh+gYAaMHQRFE+LHxVuvcVytNxH3QX7O/qrba96deKk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=14.137.139.154 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.18.186.29]) by frasgout12.his.huawei.com (SkyGuard) with ESMTP id 4VJBVl4PwCz9xqv8; Mon, 15 Apr 2024 23:51:43 +0800 (CST) Received: from mail02.huawei.com (unknown [7.182.16.27]) by mail.maildlp.com (Postfix) with ESMTP id 7A7DB140B20; Tue, 16 Apr 2024 00:12:29 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP2 (Coremail) with SMTP id GxC2BwDn0iaZUR1m4n9HBg--.16529S7; Mon, 15 Apr 2024 17:12:28 +0100 (CET) From: Roberto Sassu To: corbet@lwn.net, zohar@linux.ibm.com, dmitry.kasatkin@gmail.com, eric.snowberg@oracle.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com Cc: linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, wufan@linux.microsoft.com, pbrobinson@gmail.com, zbyszek@in.waw.pl, hch@lst.de, mjg59@srcf.ucam.org, pmatilai@redhat.com, jannh@google.com, dhowells@redhat.com, jikos@kernel.org, mkoutny@suse.com, ppavlu@suse.com, petr.vorel@gmail.com, mzerqung@0pointer.de, kgold@linux.ibm.com, Roberto Sassu Subject: [RFC][PATCH v2 5/9] ima: Modify existing boot-time built-in policies with digest cache policies Date: Mon, 15 Apr 2024 18:10:40 +0200 Message-Id: <20240415161044.2572438-6-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240415161044.2572438-1-roberto.sassu@huaweicloud.com> References: <20240415161044.2572438-1-roberto.sassu@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: GxC2BwDn0iaZUR1m4n9HBg--.16529S7 X-Coremail-Antispam: 1UD129KBjvJXoWxXry7Jw1fZFyfWFW3Cw4kJFb_yoW5ur15pa 9rWryFkrZxXF97Cw1fA3W29F4rK3ykta1UGa1qg345Aa15GF1qv3W0yr43ZFyUGr10qFW7 AF45Kw4jk3WqvaUanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUPqb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVW8JVW5JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_Cr0_Gr1UM28EF7xvwVC2z280aVCY1x02 67AKxVW0oVCq3wAS0I0E0xvYzxvE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG6I 80ewAv7VC0I7IYx2IY67AKxVWUGVWUXwAv7VC2z280aVAFwI0_Jr0_Gr1lOx8S6xCaFVCj c4AY6r1j6r4UM4x0Y48IcxkI7VAKI48JM4IIrI8v6xkF7I0E8cxan2IY04v7MxkF7I0En4 kS14v26r4a6rW5MxAIw28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY6r1j6r4UMI8I3I0E 5I8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVW8ZV WrXwCIc40Y0x0EwIxGrwCI42IY6xIIjxv20xvE14v26r4j6ryUMIIF0xvE2Ix0cI8IcVCY 1x0267AKxVW8Jr0_Cr1UMIIF0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67 AKxVW8JVWxJwCI42IY6I8E87Iv6xkF7I0E14v26rxl6s0DYxBIdaVFxhVjvjDU0xZFpf9x 07j7GYLUUUUU= X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAgAOBF1jj5h14AAGsy From: Roberto Sassu Setting the boot-time built-in policies 'digest_cache_measure' and 'digest_cache_appraise' is not sufficient to use the digest_cache LSM to measure and appraise files, since their effect is only to measure and appraise digest lists. Modify existing measurement rules if the 'digest_cache_measure' built-in policy is specified by adding to them: digest_cache=data pcr=12 Other than enabling the usage of the digest_cache LSM for measurement, the additional keywords also store measurements in the PCR 12, to not confuse new style measurements with the original ones still stored on PCR 10. Modify existing appraisal rules if the 'digest_cache_appraise' built-in policy is specified by adding to them: digest_cache=data The additional keyword enables the usage of digest_cache LSM for appraisal. Signed-off-by: Roberto Sassu --- Documentation/admin-guide/kernel-parameters.txt | 9 +++++++-- security/integrity/ima/ima_policy.c | 14 ++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index df877588decc..dc96e6f4eb40 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -2074,11 +2074,16 @@ critical data. The "digest_cache_measure" policy measures digest lists - into PCR 12 (can be changed with kernel config). + into PCR 12 (can be changed with kernel config), enables + the digest cache to be used for the other selected + measure rules (if compatible), and measures the files + with digest not found in the digest list into PCR 12 + (changeable). The "digest_cache_appraise" policy appraises digest lists with IMA signatures or module-style appended - signatures. + signatures, and enables the digest cache to be used for + the other selected appraise rules (if compatible). ima_tcb [IMA] Deprecated. Use ima_policy= instead. Load a policy which meets the needs of the Trusted diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index f049543f6b64..21bd7a123548 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -918,6 +918,20 @@ static void add_rules(struct ima_rule_entry *entries, int count, for (i = 0; i < count; i++) { struct ima_rule_entry *entry; + if (IS_ENABLED(CONFIG_SECURITY_DIGEST_CACHE) && + entries[i].action == MEASURE && ima_digest_cache_measure && + ima_digest_cache_func_allowed(&entries[i])) { + entries[i].digest_cache_usage |= IMA_DIGEST_CACHE_MEASURE_DATA; + entries[i].pcr = CONFIG_IMA_DIGEST_CACHE_MEASURE_PCR_IDX; + entries[i].flags |= IMA_PCR; + } + + if (IS_ENABLED(CONFIG_SECURITY_DIGEST_CACHE) && + entries[i].action == APPRAISE && + ima_digest_cache_appraise && + ima_digest_cache_func_allowed(&entries[i])) + entries[i].digest_cache_usage |= IMA_DIGEST_CACHE_APPRAISE_DATA; + if (policy_rule & IMA_DEFAULT_POLICY) list_add_tail(&entries[i].list, &ima_default_rules); From patchwork Mon Apr 15 16:10:41 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 13630278 Received: from frasgout12.his.huawei.com (frasgout12.his.huawei.com [14.137.139.154]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3F72982494; Mon, 15 Apr 2024 16:12:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=14.137.139.154 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713197577; cv=none; b=ipLsvXl8l4GUtaVgJY5qZ6es7+bCi5bbWAYA5zNSSOrguPs4YtMD/v28P8Uy6gDXskN2a4bMwwt4wN5fg0vEPRCcpKBGJ5QCOpL4JOkoanmfoVEe82VZ6H7ZzEkSxEJFTglCs2YX5L/kdVhH0MVriFhVLwOUH3Sg1FMo3AVWD0g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713197577; c=relaxed/simple; bh=LwSw9uoE6uVD+zxxnCEZ4oH8uTTzcvhlas/3ik0KdLE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=HJtkMZUGL4ovxX8H/iZTO0OLNbeN4Id08+RZtFz999ePoOaC0t5URyEjrUjR9LKcm0DnmX4Vt+iJPpUKZyymsfHA/0Cj6vH6eD0EtXyE22uH6QmLjIj3Hz7GRNEpazFGfhMDr2YZvDRGtsoXRStrxKfP5MjuYFXblEVTL9qTxn0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=14.137.139.154 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.18.186.29]) by frasgout12.his.huawei.com (SkyGuard) with ESMTP id 4VJBW34rZYz9xqv8; Mon, 15 Apr 2024 23:51:59 +0800 (CST) Received: from mail02.huawei.com (unknown [7.182.16.27]) by mail.maildlp.com (Postfix) with ESMTP id DC18C1405E3; Tue, 16 Apr 2024 00:12:42 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP2 (Coremail) with SMTP id GxC2BwDn0iaZUR1m4n9HBg--.16529S8; Mon, 15 Apr 2024 17:12:42 +0100 (CET) From: Roberto Sassu To: corbet@lwn.net, zohar@linux.ibm.com, dmitry.kasatkin@gmail.com, eric.snowberg@oracle.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com Cc: linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, wufan@linux.microsoft.com, pbrobinson@gmail.com, zbyszek@in.waw.pl, hch@lst.de, mjg59@srcf.ucam.org, pmatilai@redhat.com, jannh@google.com, dhowells@redhat.com, jikos@kernel.org, mkoutny@suse.com, ppavlu@suse.com, petr.vorel@gmail.com, mzerqung@0pointer.de, kgold@linux.ibm.com, Roberto Sassu Subject: [RFC][PATCH v2 6/9] ima: Store allowed usage in digest cache based on integrity metadata flags Date: Mon, 15 Apr 2024 18:10:41 +0200 Message-Id: <20240415161044.2572438-7-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240415161044.2572438-1-roberto.sassu@huaweicloud.com> References: <20240415161044.2572438-1-roberto.sassu@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: GxC2BwDn0iaZUR1m4n9HBg--.16529S8 X-Coremail-Antispam: 1UD129KBjvJXoW3Jr1rtF4xJw47uw15JFy7ZFb_yoW7Kr1rpa 93KF15Kr18Zry7Crn3A3W2ka1rK39YvF4UWws8XrnayFW5Xr1jvw4kAry7ZFy3Jr4qya1x tr43Kr13Aw1DtaDanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUPqb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVW8JVW5JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_Cr0_Gr1UM28EF7xvwVC2z280aVCY1x02 67AKxVW0oVCq3wAS0I0E0xvYzxvE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG6I 80ewAv7VC0I7IYx2IY67AKxVWUGVWUXwAv7VC2z280aVAFwI0_Jr0_Gr1lOx8S6xCaFVCj c4AY6r1j6r4UM4x0Y48IcxkI7VAKI48JM4IIrI8v6xkF7I0E8cxan2IY04v7MxkF7I0En4 kS14v26r4a6rW5MxAIw28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY6r1j6r4UMI8I3I0E 5I8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVW8ZV WrXwCIc40Y0x0EwIxGrwCI42IY6xIIjxv20xvE14v26r4j6ryUMIIF0xvE2Ix0cI8IcVCY 1x0267AKxVW8Jr0_Cr1UMIIF0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67 AKxVW8JVWxJwCI42IY6I8E87Iv6xkF7I0E14v26rxl6s0DYxBIdaVFxhVjvjDU0xZFpf9x 07j7GYLUUUUU= X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAgAOBF1jj5h14gAAs2 From: Roberto Sassu The digest_cache LSM allows integrity providers to record how the digest list being used to populate the digest cache was verified. Integrity providers can register a kernel_post_read_file LSM hook implementation, and call digest_cache_verif_set() providing the result of the digest list verification, together with the digest list file descriptor. IMA implements ima_digest_cache_store_allowed_usage(), storing allowed usage of the digest cache based on whether or not the digest list the digest cache is being populated from was measured/appraised. If the digest list was measured (IMA_MEASURED set in iint->flags), ima_digest_cache_store_allowed_usage() sets the IMA_DIGEST_CACHE_MEASURE_DATA in the allowed usage. If the digest list was appraised (IMA_APPRAISED_SUBMASK), ima_digest_cache_store_allowed_usage() sets the IMA_DIGEST_CACHE_APPRAISE_DATA in the allowed usage. Allowed usage based on integrity metadata will be ANDed with the allowed usage from the IMA policy. Then, the final decision will ultimately depend on whether or not the calculated digest of the accessed file was found in the digest cache. ANDing the usage prevents remote verifiers from receiving an incomplete IMA measurement list, where measurements are skipped, but there isn't the digest list the calculated file digest was searched into. It also prevents successful appraisal without appraising the digest list itself. Signed-off-by: Roberto Sassu --- security/integrity/ima/Makefile | 1 + security/integrity/ima/ima_digest_cache.c | 45 +++++++++++++++++++++++ security/integrity/ima/ima_digest_cache.h | 21 +++++++++++ security/integrity/ima/ima_main.c | 3 ++ 4 files changed, 70 insertions(+) create mode 100644 security/integrity/ima/ima_digest_cache.c create mode 100644 security/integrity/ima/ima_digest_cache.h diff --git a/security/integrity/ima/Makefile b/security/integrity/ima/Makefile index b376d38b4ee6..edd74a7374de 100644 --- a/security/integrity/ima/Makefile +++ b/security/integrity/ima/Makefile @@ -14,6 +14,7 @@ ima-$(CONFIG_HAVE_IMA_KEXEC) += ima_kexec.o ima-$(CONFIG_IMA_BLACKLIST_KEYRING) += ima_mok.o ima-$(CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS) += ima_asymmetric_keys.o ima-$(CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS) += ima_queue_keys.o +ima-$(CONFIG_SECURITY_DIGEST_CACHE) += ima_digest_cache.o ifeq ($(CONFIG_EFI),y) ima-$(CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT) += ima_efi.o diff --git a/security/integrity/ima/ima_digest_cache.c b/security/integrity/ima/ima_digest_cache.c new file mode 100644 index 000000000000..0b0fd26cc0d7 --- /dev/null +++ b/security/integrity/ima/ima_digest_cache.c @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2024 Huawei Technologies Duesseldorf GmbH + * + * Author: Roberto Sassu + * + * Integrate with the digest_cache LSM. + */ + +#include + +#include "ima_digest_cache.h" + +/** + * ima_digest_cache_store_allowed_usage - Store allowed usage in digest cache + * @file: Digest list file descriptor + * @iint: Inode integrity metadata + * + * Set digest cache allowed usage in the digest cache associated to the + * digest list file descriptor. Allowed usage is based on whether or not the + * digest list was measured/appraised. + */ +void ima_digest_cache_store_allowed_usage(struct file *file, + struct ima_iint_cache *iint) +{ + u64 allowed_usage = 0; + int rc; + + if (iint->flags & IMA_MEASURED) + allowed_usage |= IMA_DIGEST_CACHE_MEASURE_DATA; + if (iint->flags & IMA_APPRAISED_SUBMASK) + allowed_usage |= IMA_DIGEST_CACHE_APPRAISE_DATA; + + /* + * Set digest cache allowed usage from integrity metadata flags for + * later use. + */ + rc = digest_cache_verif_set(file, "ima", &allowed_usage, + sizeof(allowed_usage)); + + /* Ignore if fd doesn't have digest cache set (prefetching). */ + if (rc && rc != -ENOENT) + pr_debug("Cannot set verification mask for %s, ret: %d, ignoring\n", + file_dentry(file)->d_name.name, rc); +} diff --git a/security/integrity/ima/ima_digest_cache.h b/security/integrity/ima/ima_digest_cache.h new file mode 100644 index 000000000000..f2534a01bb18 --- /dev/null +++ b/security/integrity/ima/ima_digest_cache.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2024 Huawei Technologies Duesseldorf GmbH + * + * Author: Roberto Sassu + * + * Header file of ima_digest_cache.c. + */ + +#include "ima.h" + +#ifdef CONFIG_SECURITY_DIGEST_CACHE +void ima_digest_cache_store_allowed_usage(struct file *file, + struct ima_iint_cache *iint); +#else +static inline void +ima_digest_cache_store_allowed_usage(struct file *file, + struct ima_iint_cache *iint) +{ } + +#endif /* CONFIG_SECURITY_DIGEST_CACHE */ diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index e3ca80098c4c..7c968cdb5678 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -28,6 +28,7 @@ #include #include "ima.h" +#include "ima_digest_cache.h" #ifdef CONFIG_IMA_APPRAISE int ima_appraise = IMA_APPRAISE_ENFORCE; @@ -399,6 +400,8 @@ static int process_measurement(struct file *file, const struct cred *cred, if ((mask & MAY_WRITE) && test_bit(IMA_DIGSIG, &iint->atomic_flags) && !(iint->flags & IMA_NEW_FILE)) rc = -EACCES; + if (!rc && func == DIGEST_LIST_CHECK) + ima_digest_cache_store_allowed_usage(file, iint); mutex_unlock(&iint->mutex); kfree(xattr_value); ima_free_modsig(modsig); From patchwork Mon Apr 15 16:10:42 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 13630279 Received: from frasgout13.his.huawei.com (frasgout13.his.huawei.com [14.137.139.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 27A308062E; Mon, 15 Apr 2024 16:13:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=14.137.139.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713197591; cv=none; b=M37w2uPz+K431nxDFbFDSDBAq4a0rllXbNBcipYR+r1woNESKyfXZAAB/OWeiOSuuZGb9uWn9ayJtaC9Mp1qkheqRe0jLDtMARGcoMyJ9XwePj4Gn1+i1fWMCWF05YFluVft18LlzGz8TVMU+5fQi2BYgNQD3Y2qRLIAVP14bis= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713197591; c=relaxed/simple; bh=pEmknL2/6lnmt81ftfpClFRTiK0Me9ZoDCWCf4uH/Yg=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=bYNShQvQha3MCGd2McF3XO4Q1tfQscwQuOvS+5JOf4OHjM2fV06hU3n7LvsEUnJi/4PboLxFTlEy786AsVJiu69xMZ5q7Rv+moXSRUHXD9qeD1dtpMdAmp8JoNPrA/SRC5vd5odSaC0OPTNyudz7eMj2A70on7Govvp6UiuSEYw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=14.137.139.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.18.186.29]) by frasgout13.his.huawei.com (SkyGuard) with ESMTP id 4VJBcR3Q1qz9xGnS; Mon, 15 Apr 2024 23:56:39 +0800 (CST) Received: from mail02.huawei.com (unknown [7.182.16.27]) by mail.maildlp.com (Postfix) with ESMTP id 57CCE1405E3; Tue, 16 Apr 2024 00:12:56 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP2 (Coremail) with SMTP id GxC2BwDn0iaZUR1m4n9HBg--.16529S9; Mon, 15 Apr 2024 17:12:55 +0100 (CET) From: Roberto Sassu To: corbet@lwn.net, zohar@linux.ibm.com, dmitry.kasatkin@gmail.com, eric.snowberg@oracle.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com Cc: linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, wufan@linux.microsoft.com, pbrobinson@gmail.com, zbyszek@in.waw.pl, hch@lst.de, mjg59@srcf.ucam.org, pmatilai@redhat.com, jannh@google.com, dhowells@redhat.com, jikos@kernel.org, mkoutny@suse.com, ppavlu@suse.com, petr.vorel@gmail.com, mzerqung@0pointer.de, kgold@linux.ibm.com, Roberto Sassu Subject: [RFC][PATCH v2 7/9] ima: Use digest caches for measurement Date: Mon, 15 Apr 2024 18:10:42 +0200 Message-Id: <20240415161044.2572438-8-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240415161044.2572438-1-roberto.sassu@huaweicloud.com> References: <20240415161044.2572438-1-roberto.sassu@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: GxC2BwDn0iaZUR1m4n9HBg--.16529S9 X-Coremail-Antispam: 1UD129KBjvJXoW3ZrWxuw1fArW3ArWxWr4xXrb_yoWDZF1fpa 9IgF1UKr1kZFy7Cr1fA3ZruF4Fk3yktF4UJ398Xw1akFs8Xr1jywnYkr1UZFy3JrWjva4x ta1jgw1UAw1qyaDanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUPqb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVW8JVW5JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_Cr0_Gr1UM28EF7xvwVC2z280aVCY1x02 67AKxVW0oVCq3wAS0I0E0xvYzxvE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG6I 80ewAv7VC0I7IYx2IY67AKxVWUGVWUXwAv7VC2z280aVAFwI0_Jr0_Gr1lOx8S6xCaFVCj c4AY6r1j6r4UM4x0Y48IcxkI7VAKI48JM4IIrI8v6xkF7I0E8cxan2IY04v7MxkF7I0En4 kS14v26r4a6rW5MxAIw28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY6r1j6r4UMI8I3I0E 5I8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVW8ZV WrXwCIc40Y0x0EwIxGrwCI42IY6xIIjxv20xvE14v26r4j6ryUMIIF0xvE2Ix0cI8IcVCY 1x0267AKxVW8Jr0_Cr1UMIIF0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67 AKxVW8JVWxJwCI42IY6I8E87Iv6xkF7I0E14v26rxl6s0DYxBIdaVFxhVjvjDU0xZFpf9x 07j7GYLUUUUU= X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAgAOBF1jj5h14wAAs3 From: Roberto Sassu Introduce a new measurement style using digest caches, which can be performed exclusively on non-standard PCRs, to avoid ambiguity. While a measurement on the standard PCR means that a file was accessed and had the measured data, a measurement with the digest cache means only that the calculated file digest was not found in any of the measured digest lists (any digest list used for the search must be measured, otherwise IMA wouldn't use it). The new measurement style does not tell: whether or not the file was actually accessed (since its measurement is skipped even if it was); in which sequence files were accessed. So, one has to guess that the system might have possibly accessed any of the files whose digest is in the measured digest lists, in any order. However, it has the following benefits: the IMA measurement list can be much shorter, system performance can be much better due to less PCR extend operations (see the performance evaluation in the digest_cache LSM documentation); the PCR can be predictable as long as the set of measured digest lists does not change (which obviously happens during software updates). The PCR can be predictable because the digest_cache LSM has a prefetching mechanism that reads digest lists in a deterministic order, until it finds the digest list containing the digest calculated by IMA from an accessed file. If IMA measures digest lists, the PCR is extended in a deterministic order too. Predictable PCR means that a TPM key can be made dependent on specific PCR values (or a OR of them, depending on the key policy). Accessing a file with an unknown digest immediately makes that TPM key unusable, requiring a reboot to use it again. This mechanism can be used for the so called implicit remote attestation, where the ability of a system to respond to challenges based on the private part of the TPM key means that the system has the expected PCR values (which would mean that the integrity of the system is ok). This is opposed to the explicit remote attestation, where a system has to send all its measurements, to prove to a remote party about its integrity. If the IMA policy allows the usage of digest caches for the current file access (except for DIGEST_LIST_CHECK hook, not supported), call the newly introduced function ima_digest_cache_update_allowed_usage(), to make a final decision on whether or not a digest cache can be used for measurement and/or appraisal. First, call digest_cache_get() to get a digest cache from the file being accessed. Second, perform a lookup of the calculated file digest in the digest cache. Third, retrieve the allowed usage from the integrity metadata flags of the digest list and AND it with the allowed usage from the policy. If any of the previous step fails, set the allowed usage to zero. Finally, pass the allowed usage to ima_store_measurement() and, if it has the IMA_DIGEST_CACHE_MEASURE_DATA flag set, behave as if the file was successfully added to the IMA measurement list (i.e. set the IMA_MEASURED flag and the PCR flag from the value specified in the matching policy rule), but actually don't do it. Finally, release the digest cache reference acquired with digest_cache_get(), by calling digest_cache_put(). Signed-off-by: Roberto Sassu --- security/integrity/ima/ima.h | 3 +- security/integrity/ima/ima_api.c | 15 +++++++- security/integrity/ima/ima_digest_cache.c | 47 +++++++++++++++++++++++ security/integrity/ima/ima_digest_cache.h | 9 +++++ security/integrity/ima/ima_main.c | 14 ++++++- 5 files changed, 84 insertions(+), 4 deletions(-) diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 337b3b76b28d..865137dfcf22 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -381,7 +381,8 @@ void ima_store_measurement(struct ima_iint_cache *iint, struct file *file, const unsigned char *filename, struct evm_ima_xattr_data *xattr_value, int xattr_len, const struct modsig *modsig, int pcr, - struct ima_template_desc *template_desc); + struct ima_template_desc *template_desc, + u64 allowed_usage); int process_buffer_measurement(struct mnt_idmap *idmap, struct inode *inode, const void *buf, int size, const char *eventname, enum ima_hooks func, diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index f0a1ce10afe8..0bbe19e33584 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c @@ -345,7 +345,8 @@ void ima_store_measurement(struct ima_iint_cache *iint, struct file *file, const unsigned char *filename, struct evm_ima_xattr_data *xattr_value, int xattr_len, const struct modsig *modsig, int pcr, - struct ima_template_desc *template_desc) + struct ima_template_desc *template_desc, + u64 allowed_usage) { static const char op[] = "add_template_measure"; static const char audit_cause[] = "ENOMEM"; @@ -369,6 +370,18 @@ void ima_store_measurement(struct ima_iint_cache *iint, struct file *file, if (iint->measured_pcrs & (0x1 << pcr) && !modsig) return; + /* + * If digest cache usage was authorized with the IMA policy, the digest + * list the digest cache was populated from was measured, and the file + * digest was found in the digest cache, mark the file as successfully + * measured. + */ + if (allowed_usage & IMA_DIGEST_CACHE_MEASURE_DATA) { + iint->flags |= IMA_MEASURED; + iint->measured_pcrs |= (0x1 << pcr); + return; + } + result = ima_alloc_init_template(&event_data, &entry, template_desc); if (result < 0) { integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename, diff --git a/security/integrity/ima/ima_digest_cache.c b/security/integrity/ima/ima_digest_cache.c index 0b0fd26cc0d7..013c69f265d8 100644 --- a/security/integrity/ima/ima_digest_cache.c +++ b/security/integrity/ima/ima_digest_cache.c @@ -43,3 +43,50 @@ void ima_digest_cache_store_allowed_usage(struct file *file, pr_debug("Cannot set verification mask for %s, ret: %d, ignoring\n", file_dentry(file)->d_name.name, rc); } + +/** + * ima_digest_cache_update_allowed_usage - Update digest cache allowed usage + * @file: Digest list file descriptor + * @iint: Inode integrity metadata + * @allowed_usage: Digest cache allowed usage to update + * + * Update the digest cache allowed usage obtained from the IMA policy. First, + * retrieve the digest cache for the passed inode, and do a lookup of the + * calculated digest. If the digest is found, update the digest cache allowed + * usage with the allowed usage from integrity metadata flags, previously stored + * in the digest cache itself with ima_digest_cache_store_allowed_usage(). + */ +void ima_digest_cache_update_allowed_usage(struct file *file, + struct ima_iint_cache *iint, + u64 *allowed_usage) +{ + struct digest_cache *digest_cache, *found_cache; + u64 *iint_allowed_usage; + digest_cache_found_t found; + + digest_cache = digest_cache_get(file_dentry(file)); + if (!digest_cache) { + *allowed_usage = 0; + return; + } + + found = digest_cache_lookup(file_dentry(file), digest_cache, + iint->ima_hash->digest, + iint->ima_hash->algo); + if (!found) { + *allowed_usage = 0; + goto out; + } + + /* AND what is allowed by the policy, and what IMA verified. */ + found_cache = digest_cache_from_found_t(found); + iint_allowed_usage = digest_cache_verif_get(found_cache, "ima"); + if (!iint_allowed_usage) { + *allowed_usage = 0; + goto out; + } + + *allowed_usage &= *iint_allowed_usage; +out: + digest_cache_put(digest_cache); +} diff --git a/security/integrity/ima/ima_digest_cache.h b/security/integrity/ima/ima_digest_cache.h index f2534a01bb18..cb47c15e975d 100644 --- a/security/integrity/ima/ima_digest_cache.h +++ b/security/integrity/ima/ima_digest_cache.h @@ -12,10 +12,19 @@ #ifdef CONFIG_SECURITY_DIGEST_CACHE void ima_digest_cache_store_allowed_usage(struct file *file, struct ima_iint_cache *iint); +void ima_digest_cache_update_allowed_usage(struct file *file, + struct ima_iint_cache *iint, + u64 *allowed_usage); #else static inline void ima_digest_cache_store_allowed_usage(struct file *file, struct ima_iint_cache *iint) { } +static inline void +ima_digest_cache_update_allowed_usage(struct file *file, + struct ima_iint_cache *iint, + u64 *allowed_usage) +{ } + #endif /* CONFIG_SECURITY_DIGEST_CACHE */ diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 7c968cdb5678..0ff5de9bef70 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -223,6 +223,7 @@ static int process_measurement(struct file *file, const struct cred *cred, bool violation_check; enum hash_algo hash_algo; unsigned int allowed_algos = 0; + u64 digest_cache_usage = 0; if (!ima_policy_flag || !S_ISREG(inode->i_mode)) return 0; @@ -233,7 +234,7 @@ static int process_measurement(struct file *file, const struct cred *cred, */ action = ima_get_action(file_mnt_idmap(file), inode, cred, secid, mask, func, &pcr, &template_desc, NULL, - &allowed_algos, NULL); + &allowed_algos, &digest_cache_usage); violation_check = ((func == FILE_CHECK || func == MMAP_CHECK || func == MMAP_CHECK_REQPROT) && (ima_policy_flag & IMA_MEASURE)); @@ -364,10 +365,19 @@ static int process_measurement(struct file *file, const struct cred *cred, if (!pathbuf) /* ima_rdwr_violation possibly pre-fetched */ pathname = ima_d_path(&file->f_path, &pathbuf, filename); + /* + * For now we don't support nested verification with digest caches. + * Since we allow IMA policy rules without func=, we have to enforce + * this restriction here. + */ + if (rc == 0 && digest_cache_usage && func != DIGEST_LIST_CHECK) + ima_digest_cache_update_allowed_usage(file, iint, + &digest_cache_usage); + if (action & IMA_MEASURE) ima_store_measurement(iint, file, pathname, xattr_value, xattr_len, modsig, pcr, - template_desc); + template_desc, digest_cache_usage); if (rc == 0 && (action & IMA_APPRAISE_SUBMASK)) { rc = ima_check_blacklist(iint, modsig, pcr); if (rc != -EPERM) { From patchwork Mon Apr 15 16:10:43 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 13630280 Received: from frasgout11.his.huawei.com (frasgout11.his.huawei.com [14.137.139.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9FDB984D0F; Mon, 15 Apr 2024 16:13:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=14.137.139.23 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713197594; cv=none; b=PMmjLiA5VKM7yhLwGmL6/ci5jpEVIDsLMQ+GA5682rQ2mSq/EB41NhBQ6RmITGxR16iLt6eMuWKAonYeJ0Htr+5/kx7SZ2msdVQRvasghoun61eORxkFUo1KyBE1n32pcj8/m/szLeV1aNSt7OgIO/bU/D/peMAEsDU1zWcbIas= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713197594; c=relaxed/simple; bh=PoVu1zT5xkQsZ4kp0hfNGuar5mykAljYwYgLbKEw6OE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=li3+otRapvQGQBo2cz4kJLS4rucPglYr6BbbGV8s8fx1qaWP3qmgGQr2l7PVZisma3MYylJlugrVUgWdgx9XtlPifNDM2YJgFS1MMdf4aDczK2XsZcGq46OZ5Y30NU12FiyHQOw62Yr+5a/pbY6YD9vbwD51zKFtfOPScHI+RTo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=14.137.139.23 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.18.186.51]) by frasgout11.his.huawei.com (SkyGuard) with ESMTP id 4VJBcS4DNQz9xGhS; Mon, 15 Apr 2024 23:56:40 +0800 (CST) Received: from mail02.huawei.com (unknown [7.182.16.27]) by mail.maildlp.com (Postfix) with ESMTP id A7F63140159; Tue, 16 Apr 2024 00:13:09 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP2 (Coremail) with SMTP id GxC2BwDn0iaZUR1m4n9HBg--.16529S10; Mon, 15 Apr 2024 17:13:09 +0100 (CET) From: Roberto Sassu To: corbet@lwn.net, zohar@linux.ibm.com, dmitry.kasatkin@gmail.com, eric.snowberg@oracle.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com Cc: linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, wufan@linux.microsoft.com, pbrobinson@gmail.com, zbyszek@in.waw.pl, hch@lst.de, mjg59@srcf.ucam.org, pmatilai@redhat.com, jannh@google.com, dhowells@redhat.com, jikos@kernel.org, mkoutny@suse.com, ppavlu@suse.com, petr.vorel@gmail.com, mzerqung@0pointer.de, kgold@linux.ibm.com, Roberto Sassu Subject: [RFC][PATCH v2 8/9] ima: Use digest caches for appraisal Date: Mon, 15 Apr 2024 18:10:43 +0200 Message-Id: <20240415161044.2572438-9-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240415161044.2572438-1-roberto.sassu@huaweicloud.com> References: <20240415161044.2572438-1-roberto.sassu@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: GxC2BwDn0iaZUR1m4n9HBg--.16529S10 X-Coremail-Antispam: 1UD129KBjvJXoW3XFWDAFW8CF45CFyxXr4fXwb_yoW7Zr15pa 9xKF1UKry8WFW29rZ3A39xua1Sk340gFWUWws8X3429FnxXr10vryrtw129Fy5Gr18trn7 tw4qgw1UAan5K3DanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUPqb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVW5JVW7JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_Cr0_Gr1UM28EF7xvwVC2z280aVCY1x02 67AKxVW0oVCq3wAS0I0E0xvYzxvE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG6I 80ewAv7VC0I7IYx2IY67AKxVWUGVWUXwAv7VC2z280aVAFwI0_Jr0_Gr1lOx8S6xCaFVCj c4AY6r1j6r4UM4x0Y48IcxkI7VAKI48JM4IIrI8v6xkF7I0E8cxan2IY04v7MxkF7I0En4 kS14v26r4a6rW5MxAIw28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY6r1j6r4UMI8I3I0E 5I8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVW8ZV WrXwCIc40Y0x0EwIxGrwCI42IY6xIIjxv20xvE14v26r4j6ryUMIIF0xvE2Ix0cI8IcVCY 1x0267AKxVW8Jr0_Cr1UMIIF0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67 AKxVW8JVWxJwCI42IY6I8E87Iv6xkF7I0E14v26rxl6s0DYxBIdaVFxhVjvjDU0xZFpf9x 07j7GYLUUUUU= X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAQAOBF1jj5x3GgAAsL From: Roberto Sassu Similarly to measurement, enable the new appraisal style too using digest caches. Instead of verifying individual file signatures, verify the signature of lists of digests and search calculated file digests in those lists. The benefits are that signed lists of digests already exist (e.g. RPM package headers), although their format needs to be supported by the digest_cache LSM, and appraisal with digest lists is computationally much less expensive than with individual file signatures (see the performance evaluation of the digest_cache LSM). Take the allowed usage after the call to ima_digest_cache_update_allowed_usage(), and pass it to ima_appraise_measurement(). If EVM is disabled or the file does not have any protected xattr (evm_verifyxattr() returns INTEGRITY_UNKNOWN or INTEGRITY_NOXATTRS) and the allowed usage has the IMA_DIGEST_CACHE_APPRAISE_DATA flag set, mark the file as successfully appraised (i.e. set the integrity status to INTEGRITY_PASS and return zero). The digest cache method is tried first, for performance reasons, in the event there are for example IMA signatures in the system (which are computationally more expensive to verify). The usage of the digest_cache LSM has anyway to be authorized in the IMA policy. Signed-off-by: Roberto Sassu --- security/integrity/ima/ima.h | 6 ++++-- security/integrity/ima/ima_appraise.c | 30 ++++++++++++++++++++------- security/integrity/ima/ima_main.c | 3 ++- 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 865137dfcf22..1f0810be9f8a 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -432,7 +432,8 @@ int ima_check_blacklist(struct ima_iint_cache *iint, int ima_appraise_measurement(enum ima_hooks func, struct ima_iint_cache *iint, struct file *file, const unsigned char *filename, struct evm_ima_xattr_data *xattr_value, - int xattr_len, const struct modsig *modsig); + int xattr_len, const struct modsig *modsig, + u64 allowed_usage); int ima_must_appraise(struct mnt_idmap *idmap, struct inode *inode, int mask, enum ima_hooks func); void ima_update_xattr(struct ima_iint_cache *iint, struct file *file); @@ -457,7 +458,8 @@ static inline int ima_appraise_measurement(enum ima_hooks func, const unsigned char *filename, struct evm_ima_xattr_data *xattr_value, int xattr_len, - const struct modsig *modsig) + const struct modsig *modsig, + u64 allowed_usage) { return INTEGRITY_UNKNOWN; } diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index 27ccc9a2c09f..3b4d6491e69e 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -478,7 +478,8 @@ int ima_check_blacklist(struct ima_iint_cache *iint, int ima_appraise_measurement(enum ima_hooks func, struct ima_iint_cache *iint, struct file *file, const unsigned char *filename, struct evm_ima_xattr_data *xattr_value, - int xattr_len, const struct modsig *modsig) + int xattr_len, const struct modsig *modsig, + u64 allowed_usage) { static const char op[] = "appraise_data"; const char *cause = "unknown"; @@ -488,12 +489,18 @@ int ima_appraise_measurement(enum ima_hooks func, struct ima_iint_cache *iint, int rc = xattr_len; bool try_modsig = iint->flags & IMA_MODSIG_ALLOWED && modsig; - /* If not appraising a modsig, we need an xattr. */ - if (!(inode->i_opflags & IOP_XATTR) && !try_modsig) + /* + * If not appraising a modsig/there is no digest cache match, we need + * an xattr. + */ + if (!(inode->i_opflags & IOP_XATTR) && !try_modsig && !allowed_usage) return INTEGRITY_UNKNOWN; - /* If reading the xattr failed and there's no modsig, error out. */ - if (rc <= 0 && !try_modsig) { + /* + * If reading the xattr failed and there's no modsig/digest cache match, + * error out. + */ + if (rc <= 0 && !try_modsig && !allowed_usage) { if (rc && rc != -ENODATA) goto out; @@ -524,8 +531,11 @@ int ima_appraise_measurement(enum ima_hooks func, struct ima_iint_cache *iint, case INTEGRITY_UNKNOWN: break; case INTEGRITY_NOXATTRS: /* No EVM protected xattrs. */ - /* It's fine not to have xattrs when using a modsig. */ - if (try_modsig) + /* + * It's fine not to have xattrs when using a modsig or the + * digest cache. + */ + if (try_modsig || allowed_usage) break; fallthrough; case INTEGRITY_NOLABEL: /* No security.evm xattr. */ @@ -542,6 +552,12 @@ int ima_appraise_measurement(enum ima_hooks func, struct ima_iint_cache *iint, WARN_ONCE(true, "Unexpected integrity status %d\n", status); } + if (allowed_usage & IMA_DIGEST_CACHE_APPRAISE_DATA) { + status = INTEGRITY_PASS; + rc = 0; + goto out; + } + if (xattr_value) rc = xattr_verify(func, iint, xattr_value, xattr_len, &status, &cause); diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 0ff5de9bef70..7ae2bd888d41 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -384,7 +384,8 @@ static int process_measurement(struct file *file, const struct cred *cred, inode_lock(inode); rc = ima_appraise_measurement(func, iint, file, pathname, xattr_value, - xattr_len, modsig); + xattr_len, modsig, + digest_cache_usage); inode_unlock(inode); } if (!rc) From patchwork Mon Apr 15 16:10:44 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 13630281 Received: from frasgout11.his.huawei.com (frasgout11.his.huawei.com [14.137.139.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E394B82862; Mon, 15 Apr 2024 16:13:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=14.137.139.23 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713197613; cv=none; b=Fk33ZLvthvRUIsD5NeA3SjlEvXvMhg6uqOh0937PIHAmRaq9F0iaDXvt7mktnexI9gpgslLeQ1mx01VlkZHyjFXTRGInXwDGDPLFtOryDkZYOHbTD0jkg5mM4WqPhWT1fOTszCTDqmX2PLx3IqOX6HyyFwvgTGM04mZj/vBIhag= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713197613; c=relaxed/simple; bh=OstlfuSyRFOTycwkFPIRoGHthbADv/RkObuMjJltxto=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=qBD6yVTZtH4Bp19r7NML1qrP1XIuSS5MbFMSXCqIJ7oKDqd0XyTjUBKcPmRofpdjLb2Nv+H38RWvPa5C5+9nDGJRpY6mhJTRkrlfHq77K+vhbAbKpHf+TiwqRGQo9aPN+EaNjtSku8x1C/yKcuDIopet+jMCyu2t+OAdwwupYbs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=14.137.139.23 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.18.186.51]) by frasgout11.his.huawei.com (SkyGuard) with ESMTP id 4VJBcp5D7Cz9xHvk; Mon, 15 Apr 2024 23:56:58 +0800 (CST) Received: from mail02.huawei.com (unknown [7.182.16.27]) by mail.maildlp.com (Postfix) with ESMTP id 120C41408C5; Tue, 16 Apr 2024 00:13:23 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP2 (Coremail) with SMTP id GxC2BwDn0iaZUR1m4n9HBg--.16529S11; Mon, 15 Apr 2024 17:13:22 +0100 (CET) From: Roberto Sassu To: corbet@lwn.net, zohar@linux.ibm.com, dmitry.kasatkin@gmail.com, eric.snowberg@oracle.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com Cc: linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, wufan@linux.microsoft.com, pbrobinson@gmail.com, zbyszek@in.waw.pl, hch@lst.de, mjg59@srcf.ucam.org, pmatilai@redhat.com, jannh@google.com, dhowells@redhat.com, jikos@kernel.org, mkoutny@suse.com, ppavlu@suse.com, petr.vorel@gmail.com, mzerqung@0pointer.de, kgold@linux.ibm.com, Roberto Sassu Subject: [RFC][PATCH v2 9/9] ima: Register to the digest_cache LSM notifier and process events Date: Mon, 15 Apr 2024 18:10:44 +0200 Message-Id: <20240415161044.2572438-10-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240415161044.2572438-1-roberto.sassu@huaweicloud.com> References: <20240415161044.2572438-1-roberto.sassu@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: GxC2BwDn0iaZUR1m4n9HBg--.16529S11 X-Coremail-Antispam: 1UD129KBjvJXoWxZr47Gr1xXw47ZFy8ArW7twb_yoWrXF1fpa 9rG3WrKrW8Zry7ur4fAFnFyayrK3yktayxW395X3sIyF4DXr1jy395Jr1UuFyrJr4Yqw4x tw45Kry5uw1jyaDanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUPvb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVW5JVW7JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_Cr0_Gr1UM28EF7xvwVC2z280aVCY1x02 67AKxVW0oVCq3wAS0I0E0xvYzxvE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG6I 80ewAv7VC0I7IYx2IY67AKxVWUGVWUXwAv7VC2z280aVAFwI0_Jr0_Gr1lOx8S6xCaFVCj c4AY6r1j6r4UM4x0Y48IcxkI7VAKI48JM4IIrI8v6xkF7I0E8cxan2IY04v7MxkF7I0En4 kS14v26r4a6rW5MxAIw28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY6r1j6r4UMI8I3I0E 5I8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVW8ZV WrXwCIc40Y0x0EwIxGrwCI42IY6xIIjxv20xvE14v26r4j6ryUMIIF0xvE2Ix0cI8IcVCY 1x0267AKxVW8Jr0_Cr1UMIIF0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67 AKxVWxJVW8Jr1lIxAIcVC2z280aVCY1x0267AKxVW0oVCq3bIYCTnIWIevJa73UjIFyTuY vjxUxrcTDUUUU X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAQAOBF1jj5x3HAAAsN From: Roberto Sassu A digest cache used for measurement/appraisal might change over the time (due to file modification, directory changes). When that happens, IMA should invalidate the cached integrity result for affected inodes and evaluate those inodes again. Implement ima_digest_cache_change(), to be invoked at every notification by the digest_cache LSM, and register it as a callback with digest_cache_register_notifier(). For every notification, and if the type of event is DIGEST_CACHE_RESET, retrieve the inode integrity metadata (if any), and set the IMA_CHANGE_XATTR atomic flag, so that IMA fully reevaluates the inode in process_measurement(). Signed-off-by: Roberto Sassu --- security/integrity/ima/ima_digest_cache.c | 31 +++++++++++++++++++++++ security/integrity/ima/ima_digest_cache.h | 6 +++++ security/integrity/ima/ima_main.c | 11 +++++++- 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/security/integrity/ima/ima_digest_cache.c b/security/integrity/ima/ima_digest_cache.c index 013c69f265d8..0ab35575ff7c 100644 --- a/security/integrity/ima/ima_digest_cache.c +++ b/security/integrity/ima/ima_digest_cache.c @@ -90,3 +90,34 @@ void ima_digest_cache_update_allowed_usage(struct file *file, out: digest_cache_put(digest_cache); } + +static int ima_digest_cache_change(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct ima_iint_cache *iint; + struct digest_cache_event_data *event_data = data; + + if (event != DIGEST_CACHE_RESET) + return NOTIFY_DONE; + + iint = ima_iint_find(event_data->inode); + if (!iint) { + pr_debug("Integrity metadata not found for inode %lu\n", + event_data->inode->i_ino); + return NOTIFY_OK; + } + + set_bit(IMA_CHANGE_XATTR, &iint->atomic_flags); + pr_debug("Integrity metadata of inode %lu successfully reset\n", + event_data->inode->i_ino); + return NOTIFY_OK; +} + +static struct notifier_block digest_cache_notifier = { + .notifier_call = ima_digest_cache_change, +}; + +int ima_digest_cache_register_notifier(void) +{ + return digest_cache_register_notifier(&digest_cache_notifier); +} diff --git a/security/integrity/ima/ima_digest_cache.h b/security/integrity/ima/ima_digest_cache.h index cb47c15e975d..44c188c2fb93 100644 --- a/security/integrity/ima/ima_digest_cache.h +++ b/security/integrity/ima/ima_digest_cache.h @@ -15,6 +15,7 @@ void ima_digest_cache_store_allowed_usage(struct file *file, void ima_digest_cache_update_allowed_usage(struct file *file, struct ima_iint_cache *iint, u64 *allowed_usage); +int ima_digest_cache_register_notifier(void); #else static inline void ima_digest_cache_store_allowed_usage(struct file *file, @@ -27,4 +28,9 @@ ima_digest_cache_update_allowed_usage(struct file *file, u64 *allowed_usage) { } +static inline int ima_digest_cache_register_notifier(void) +{ + return 0; +} + #endif /* CONFIG_SECURITY_DIGEST_CACHE */ diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 7ae2bd888d41..fe826755acd1 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -1159,8 +1159,17 @@ static int __init init_ima(void) return error; error = register_blocking_lsm_notifier(&ima_lsm_policy_notifier); - if (error) + if (error) { pr_warn("Couldn't register LSM notifier, error %d\n", error); + return error; + } + + error = ima_digest_cache_register_notifier(); + if (error) { + pr_warn("Couldn't register digest cache notifier, error %d\n", + error); + unregister_blocking_lsm_notifier(&ima_lsm_policy_notifier); + } if (!error) ima_update_policy_flags();