From nobody Sat Jun 13 04:53:58 2026 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 74E4340F8F4; Wed, 29 Apr 2026 16:20:12 +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=1777479618; cv=none; b=FGQlHzYn3A0RuuLiDemgmRoL0va8sWxQAT+zOvpoWKAnMC+o81cPIUbvTFz7yFnNRMuS0w+SfGXBpSy1r9rUPsvJIi6U32xtRPtgxTFniy3ehMflpKSKVBRYWbZLhIvWIebViRb+SxS3vHmHA0600eAElNtnLK2zyrF2+rBUQA4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777479618; c=relaxed/simple; bh=MP9+scg3dwoUSuqETp6ePAjChlt97Y7yrh+Xbl1cumQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=nIIGw8yZV9Zwl5aYK+2kgcWvphL7AmNjuWhfv8kK4G+ViXd5AOitUVMYcNvdqThPC97HK1Vx46OltmwBIN0uGpM44jq6IkxbQe7V+RTdOao/h5/jxZwMLBZVeZ7a9K/LVrC5PQdVpOrHf49O1Okz0Yg73XZRNRjTmcdWNJ6a3dM= 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.224.235]) by frasgout13.his.huawei.com (SkyGuard) with ESMTPS id 4g5MSD2wKbzpTvM; Wed, 29 Apr 2026 23:59:24 +0800 (CST) Received: from mail02.huawei.com (unknown [7.182.16.27]) by mail.maildlp.com (Postfix) with ESMTP id 989D44056A; Thu, 30 Apr 2026 00:03:54 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP2 (Coremail) with SMTP id GxC2BwBHPmrYK_JpRQ1BAA--.12298S3; Wed, 29 Apr 2026 17:03:54 +0100 (CET) From: Roberto Sassu To: corbet@lwn.net, skhan@linuxfoundation.org, zohar@linux.ibm.com, dmitry.kasatkin@gmail.com, eric.snowberg@oracle.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com Cc: linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, gregorylumen@linux.microsoft.com, chenste@linux.microsoft.com, nramas@linux.microsoft.com, Roberto Sassu Subject: [PATCH v5 01/13] ima: Remove ima_h_table structure Date: Wed, 29 Apr 2026 18:03:07 +0200 Message-ID: <20260429160319.4162918-2-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260429160319.4162918-1-roberto.sassu@huaweicloud.com> References: <20260429160319.4162918-1-roberto.sassu@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: GxC2BwBHPmrYK_JpRQ1BAA--.12298S3 X-Coremail-Antispam: 1UD129KBjvJXoWxtw4rXFW5Zw1fXFWUuw17Jrb_yoWxtw1kpa nFga42kF48XFyI9ryDAayqkrWrW3yUKr17Wws8Gw1Fk3ZrXr12gF15AFy2kFyfGrZYyF1I qrs0qrn0kwsYyrJanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUPYb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUGw A2048vs2IY020Ec7CjxVAFwI0_Gr0_Xr1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxS w2x7M28EF7xvwVC0I7IYx2IY67AKxVWUJVWUCwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxV W8JVWxJwA2z4x0Y4vEx4A2jsIE14v26r1j6r4UM28EF7xvwVC2z280aVCY1x0267AKxVW8 JVW8Jr1le2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrVC2j2WlYx 0E2Ix0cI8IcVAFwI0_Jr0_Jr4lYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE7xkEbVWU JVW8JwACjcxG0xvY0x0EwIxGrwACI402YVCY1x02628vn2kIc2xKxwCY1x0262kKe7AKxV WUtVW8ZwCF04k20xvY0x0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02F40E 14v26r1j6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_GFv_WrylIx kGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVWUJVWUCwCI42IY6xIIjxv20xvEc7CjxVAF wI0_Gr0_Cr1lIxAIcVCF04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26r1j6r 4UMIIF0xvEx4A2jsIEc7CjxVAFwI0_Gr0_Gr1UYxBIdaVFxhVjvjDU0xZFpf9x07jnpnQU UUUU= X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAQASBGnx6jgGGgAAsB Content-Type: text/plain; charset="utf-8" From: Roberto Sassu With the upcoming change of dynamically allocating and replacing the hash table, the ima_h_table structure would have been replaced with a new one. However, since the ima_h_table structure contains also the counters for number of measurements entries and violations, we would have needed to preserve their values in the new ima_h_table structure. Instead, separate those counters from the hash table, remove the ima_h_table structure, and just replace the hash table pointer. Finally, rename ima_show_htable_value(), ima_show_htable_violations() and ima_htable_violations_ops respectively to ima_show_counter(), ima_show_num_violations() and ima_num_violations_ops. Link: https://github.com/linux-integrity/linux/issues/1 Signed-off-by: Roberto Sassu Tested-by: Stefan Berger --- security/integrity/ima/ima.h | 9 +++------ security/integrity/ima/ima_api.c | 2 +- security/integrity/ima/ima_fs.c | 19 +++++++++---------- security/integrity/ima/ima_kexec.c | 2 +- security/integrity/ima/ima_queue.c | 17 ++++++++++------- 5 files changed, 24 insertions(+), 25 deletions(-) diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 69e9bf0b82c6..51a8a582df56 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -324,12 +324,9 @@ int ima_lsm_policy_change(struct notifier_block *nb, u= nsigned long event, */ extern spinlock_t ima_queue_lock; =20 -struct ima_h_table { - atomic_long_t len; /* number of stored measurements in the list */ - atomic_long_t violations; - struct hlist_head queue[IMA_MEASURE_HTABLE_SIZE]; -}; -extern struct ima_h_table ima_htable; +extern atomic_long_t ima_num_entries; +extern atomic_long_t ima_num_violations; +extern struct hlist_head ima_htable[IMA_MEASURE_HTABLE_SIZE]; =20 static inline unsigned int ima_hash_key(u8 *digest) { diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_= api.c index 0916f24f005f..122d127e108d 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c @@ -146,7 +146,7 @@ void ima_add_violation(struct file *file, const unsigne= d char *filename, int result; =20 /* can overflow, only indicator */ - atomic_long_inc(&ima_htable.violations); + atomic_long_inc(&ima_num_violations); =20 result =3D ima_alloc_init_template(&event_data, &entry, NULL); if (result < 0) { diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_f= s.c index ca4931a95098..aaa460d70ff7 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -38,8 +38,8 @@ __setup("ima_canonical_fmt", default_canonical_fmt_setup); =20 static int valid_policy =3D 1; =20 -static ssize_t ima_show_htable_value(char __user *buf, size_t count, - loff_t *ppos, atomic_long_t *val) +static ssize_t ima_show_counter(char __user *buf, size_t count, loff_t *pp= os, + atomic_long_t *val) { char tmpbuf[32]; /* greater than largest 'long' string value */ ssize_t len; @@ -48,15 +48,14 @@ static ssize_t ima_show_htable_value(char __user *buf, = size_t count, return simple_read_from_buffer(buf, count, ppos, tmpbuf, len); } =20 -static ssize_t ima_show_htable_violations(struct file *filp, - char __user *buf, - size_t count, loff_t *ppos) +static ssize_t ima_show_num_violations(struct file *filp, char __user *buf, + size_t count, loff_t *ppos) { - return ima_show_htable_value(buf, count, ppos, &ima_htable.violations); + return ima_show_counter(buf, count, ppos, &ima_num_violations); } =20 -static const struct file_operations ima_htable_violations_ops =3D { - .read =3D ima_show_htable_violations, +static const struct file_operations ima_num_violations_ops =3D { + .read =3D ima_show_num_violations, .llseek =3D generic_file_llseek, }; =20 @@ -64,7 +63,7 @@ static ssize_t ima_show_measurements_count(struct file *f= ilp, char __user *buf, size_t count, loff_t *ppos) { - return ima_show_htable_value(buf, count, ppos, &ima_htable.len); + return ima_show_counter(buf, count, ppos, &ima_num_entries); =20 } =20 @@ -545,7 +544,7 @@ int __init ima_fs_init(void) } =20 dentry =3D securityfs_create_file("violations", S_IRUSR | S_IRGRP, - ima_dir, NULL, &ima_htable_violations_ops); + ima_dir, NULL, &ima_num_violations_ops); if (IS_ERR(dentry)) { ret =3D PTR_ERR(dentry); goto out; diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/im= a_kexec.c index 36a34c54de58..5801649fbbef 100644 --- a/security/integrity/ima/ima_kexec.c +++ b/security/integrity/ima/ima_kexec.c @@ -43,7 +43,7 @@ void ima_measure_kexec_event(const char *event_name) int n; =20 buf_size =3D ima_get_binary_runtime_size(); - len =3D atomic_long_read(&ima_htable.len); + len =3D atomic_long_read(&ima_num_entries); =20 n =3D scnprintf(ima_kexec_event, IMA_KEXEC_EVENT_LEN, "kexec_segment_size=3D%lu;ima_binary_runtime_size=3D%lu;" diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/im= a_queue.c index 319522450854..1f6515f7d015 100644 --- a/security/integrity/ima/ima_queue.c +++ b/security/integrity/ima/ima_queue.c @@ -32,11 +32,14 @@ static unsigned long binary_runtime_size; static unsigned long binary_runtime_size =3D ULONG_MAX; #endif =20 +/* num of stored measurements in the list */ +atomic_long_t ima_num_entries =3D ATOMIC_LONG_INIT(0); +/* num of violations in the list */ +atomic_long_t ima_num_violations =3D ATOMIC_LONG_INIT(0); + /* key: inode (before secure-hashing a file) */ -struct ima_h_table ima_htable =3D { - .len =3D ATOMIC_LONG_INIT(0), - .violations =3D ATOMIC_LONG_INIT(0), - .queue[0 ... IMA_MEASURE_HTABLE_SIZE - 1] =3D HLIST_HEAD_INIT +struct hlist_head ima_htable[IMA_MEASURE_HTABLE_SIZE] =3D { + [0 ... IMA_MEASURE_HTABLE_SIZE - 1] =3D HLIST_HEAD_INIT }; =20 /* mutex protects atomicity of extending measurement list @@ -61,7 +64,7 @@ static struct ima_queue_entry *ima_lookup_digest_entry(u8= *digest_value, =20 key =3D ima_hash_key(digest_value); rcu_read_lock(); - hlist_for_each_entry_rcu(qe, &ima_htable.queue[key], hnext) { + hlist_for_each_entry_rcu(qe, &ima_htable[key], hnext) { rc =3D memcmp(qe->entry->digests[ima_hash_algo_idx].digest, digest_value, hash_digest_size[ima_hash_algo]); if ((rc =3D=3D 0) && (qe->entry->pcr =3D=3D pcr)) { @@ -113,10 +116,10 @@ static int ima_add_digest_entry(struct ima_template_e= ntry *entry, INIT_LIST_HEAD(&qe->later); list_add_tail_rcu(&qe->later, &ima_measurements); =20 - atomic_long_inc(&ima_htable.len); + atomic_long_inc(&ima_num_entries); if (update_htable) { key =3D ima_hash_key(entry->digests[ima_hash_algo_idx].digest); - hlist_add_head_rcu(&qe->hnext, &ima_htable.queue[key]); + hlist_add_head_rcu(&qe->hnext, &ima_htable[key]); } =20 if (binary_runtime_size !=3D ULONG_MAX) { --=20 2.43.0 From nobody Sat Jun 13 04:53:58 2026 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 325DD35F16B; Wed, 29 Apr 2026 16:04:05 +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=1777478648; cv=none; b=UmQ4BlWA49IfNX5KrGba+wCfkNrMXvzxm4vg3NNIazXcxBbq0f3Kkdf3jvMlUARZ+buYL6l8LO/VBoTkz3vt9QWLp8cRb+eMYUa8ZDoGU/HI9qlkeHJOK4IbBfsEZ+qPZy/k3mFNF4dEw7h7dLW/bmhcwRyTkd5eUs1kz1LX/GA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777478648; c=relaxed/simple; bh=cCNeHP2K3DZ5eB7CnBGBoxVYnTk8psBYGKvKXknOr8E=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=furkPZCxKzpN/uDFxEeHOlLlr0tCbJw3fZqo0wZ/n/16wJL9VUe6A0X34Zu7NQKRELi/EIjsR1ZoIDWzwHzZBtDTFuRwtwsYiscop24n0EZGS8tcnEkqWQ1LI2KH9iO82Y789xXWX43dY6hwW/JeffXtoXtdpAIkEEADKbn+hF8= 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.224.235]) by frasgout12.his.huawei.com (SkyGuard) with ESMTPS id 4g5MSh50VBzvQm1; Wed, 29 Apr 2026 23:59:48 +0800 (CST) Received: from mail02.huawei.com (unknown [7.182.16.27]) by mail.maildlp.com (Postfix) with ESMTP id 8BFEA40560; Thu, 30 Apr 2026 00:04:04 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP2 (Coremail) with SMTP id GxC2BwBHPmrYK_JpRQ1BAA--.12298S4; Wed, 29 Apr 2026 17:04:03 +0100 (CET) From: Roberto Sassu To: corbet@lwn.net, skhan@linuxfoundation.org, zohar@linux.ibm.com, dmitry.kasatkin@gmail.com, eric.snowberg@oracle.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com Cc: linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, gregorylumen@linux.microsoft.com, chenste@linux.microsoft.com, nramas@linux.microsoft.com, Roberto Sassu Subject: [PATCH v5 02/13] ima: Replace static htable queue with dynamically allocated array Date: Wed, 29 Apr 2026 18:03:08 +0200 Message-ID: <20260429160319.4162918-3-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260429160319.4162918-1-roberto.sassu@huaweicloud.com> References: <20260429160319.4162918-1-roberto.sassu@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: GxC2BwBHPmrYK_JpRQ1BAA--.12298S4 X-Coremail-Antispam: 1UD129KBjvJXoW3Xw1fuw45Kr1fCr4rKryxGrg_yoWxWF4Dpa 9rWFy7Kr4UAFWxKr97Ja93Kr4fur4vgryUG398G3sYy3W3Ar1Igr1fGFy2vF98ArZ5J3WS qr4jq3Z8AwsYyrJanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUPYb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUXw A2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxS w2x7M28EF7xvwVC0I7IYx2IY67AKxVWUJVWUCwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxV W8JVWxJwA2z4x0Y4vEx4A2jsIE14v26r1j6r4UM28EF7xvwVC2z280aVCY1x0267AKxVW8 JVW8Jr1le2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrVC2j2WlYx 0E2Ix0cI8IcVAFwI0_Jr0_Jr4lYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE7xkEbVWU JVW8JwACjcxG0xvY0x0EwIxGrwACI402YVCY1x02628vn2kIc2xKxwCY1x0262kKe7AKxV WUtVW8ZwCF04k20xvY0x0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02F40E 14v26r1j6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_GFv_WrylIx kGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVWUJVWUCwCI42IY6xIIjxv20xvEc7CjxVAF wI0_Gr0_Cr1lIxAIcVCF04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26r1j6r 4UMIIF0xvEx4A2jsIEc7CjxVAFwI0_Gr0_Gr1UYxBIdaVFxhVjvjDU0xZFpf9x07UCZXrU UUUU= X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAgASBGnx6jEGFAAAsF Content-Type: text/plain; charset="utf-8" From: Roberto Sassu The IMA hash table is a fixed-size array of hlist_head buckets: struct hlist_head ima_htable[IMA_MEASURE_HTABLE_SIZE]; IMA_MEASURE_HTABLE_SIZE is (1 << IMA_HASH_BITS) =3D 1024 buckets, each a struct hlist_head (one pointer, 8 bytes on 64-bit). That is 8 KiB allocated in BSS for every kernel, regardless of whether IMA is ever used, and regardless of how many measurements are actually made. Replace the fixed-size array with a RCU-protected pointer to a dynamically allocated array that is initialized in ima_init_htable(), which is called from ima_init() during early boot. ima_init_htable() calls the static function ima_alloc_replace_htable() which, other than initializing the hash table the first time, can also hot-swap the existing hash table with a blank one. The allocation in ima_alloc_replace_htable() uses kcalloc() so the buckets are zero-initialised (equivalent to HLIST_HEAD_INIT { .first =3D NULL }). Callers of ima_alloc_replace_htable() must call synchronize_rcu() and free the returned hash table. Finally, access the hash table with rcu_dereference() in ima_lookup_digest_entry() (reader side) and with rcu_dereference_protected() in ima_add_digest_entry() (writer side). No functional change: bucket count, hash function, and all locking remain identical. Link: https://github.com/linux-integrity/linux/issues/1 Signed-off-by: Roberto Sassu Reviewed-by: Mimi Zohar Tested-by: Stefan Berger --- security/integrity/ima/ima.h | 3 +- security/integrity/ima/ima_init.c | 5 ++++ security/integrity/ima/ima_queue.c | 48 ++++++++++++++++++++++++++---- 3 files changed, 50 insertions(+), 6 deletions(-) diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 51a8a582df56..94bf890628e5 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -311,6 +311,7 @@ bool ima_template_has_modsig(const struct ima_template_= desc *ima_template); int ima_restore_measurement_entry(struct ima_template_entry *entry); int ima_restore_measurement_list(loff_t bufsize, void *buf); int ima_measurements_show(struct seq_file *m, void *v); +int __init ima_init_htable(void); unsigned long ima_get_binary_runtime_size(void); int ima_init_template(void); void ima_init_template_list(void); @@ -326,7 +327,7 @@ extern spinlock_t ima_queue_lock; =20 extern atomic_long_t ima_num_entries; extern atomic_long_t ima_num_violations; -extern struct hlist_head ima_htable[IMA_MEASURE_HTABLE_SIZE]; +extern struct hlist_head __rcu *ima_htable; =20 static inline unsigned int ima_hash_key(u8 *digest) { diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima= _init.c index a2f34f2d8ad7..7e0aa09a12e6 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -140,6 +140,11 @@ int __init ima_init(void) rc =3D ima_init_digests(); if (rc !=3D 0) return rc; + + rc =3D ima_init_htable(); + if (rc !=3D 0) + return rc; + rc =3D ima_add_boot_aggregate(); /* boot aggregate must be first entry */ if (rc !=3D 0) return rc; diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/im= a_queue.c index 1f6515f7d015..41f4941ceaad 100644 --- a/security/integrity/ima/ima_queue.c +++ b/security/integrity/ima/ima_queue.c @@ -38,9 +38,7 @@ atomic_long_t ima_num_entries =3D ATOMIC_LONG_INIT(0); atomic_long_t ima_num_violations =3D ATOMIC_LONG_INIT(0); =20 /* key: inode (before secure-hashing a file) */ -struct hlist_head ima_htable[IMA_MEASURE_HTABLE_SIZE] =3D { - [0 ... IMA_MEASURE_HTABLE_SIZE - 1] =3D HLIST_HEAD_INIT -}; +struct hlist_head __rcu *ima_htable; =20 /* mutex protects atomicity of extending measurement list * and extending the TPM PCR aggregate. Since tpm_extend can take @@ -54,17 +52,53 @@ static DEFINE_MUTEX(ima_extend_list_mutex); */ static bool ima_measurements_suspended; =20 +/* Callers must call synchronize_rcu() and free the hash table. */ +static struct hlist_head *ima_alloc_replace_htable(void) +{ + struct hlist_head *old_htable, *new_htable; + + /* Initializing to zeros is equivalent to call HLIST_HEAD_INIT. */ + new_htable =3D kcalloc(IMA_MEASURE_HTABLE_SIZE, sizeof(struct hlist_head), + GFP_KERNEL); + if (!new_htable) + return ERR_PTR(-ENOMEM); + + old_htable =3D rcu_replace_pointer(ima_htable, new_htable, + lockdep_is_held(&ima_extend_list_mutex)); + + return old_htable; +} + +int __init ima_init_htable(void) +{ + struct hlist_head *old_htable; + + mutex_lock(&ima_extend_list_mutex); + old_htable =3D ima_alloc_replace_htable(); + mutex_unlock(&ima_extend_list_mutex); + + if (IS_ERR(old_htable)) + return PTR_ERR(old_htable); + + /* Synchronize_rcu() and kfree() not necessary, only for robustness. */ + synchronize_rcu(); + kfree(old_htable); + return 0; +} + /* lookup up the digest value in the hash table, and return the entry */ static struct ima_queue_entry *ima_lookup_digest_entry(u8 *digest_value, int pcr) { struct ima_queue_entry *qe, *ret =3D NULL; + struct hlist_head *htable; unsigned int key; int rc; =20 key =3D ima_hash_key(digest_value); rcu_read_lock(); - hlist_for_each_entry_rcu(qe, &ima_htable[key], hnext) { + htable =3D rcu_dereference(ima_htable); + hlist_for_each_entry_rcu(qe, &htable[key], hnext) { rc =3D memcmp(qe->entry->digests[ima_hash_algo_idx].digest, digest_value, hash_digest_size[ima_hash_algo]); if ((rc =3D=3D 0) && (qe->entry->pcr =3D=3D pcr)) { @@ -104,6 +138,7 @@ static int ima_add_digest_entry(struct ima_template_ent= ry *entry, bool update_htable) { struct ima_queue_entry *qe; + struct hlist_head *htable; unsigned int key; =20 qe =3D kmalloc_obj(*qe); @@ -116,10 +151,13 @@ static int ima_add_digest_entry(struct ima_template_e= ntry *entry, INIT_LIST_HEAD(&qe->later); list_add_tail_rcu(&qe->later, &ima_measurements); =20 + htable =3D rcu_dereference_protected(ima_htable, + lockdep_is_held(&ima_extend_list_mutex)); + atomic_long_inc(&ima_num_entries); if (update_htable) { key =3D ima_hash_key(entry->digests[ima_hash_algo_idx].digest); - hlist_add_head_rcu(&qe->hnext, &ima_htable[key]); + hlist_add_head_rcu(&qe->hnext, &htable[key]); } =20 if (binary_runtime_size !=3D ULONG_MAX) { --=20 2.43.0 From nobody Sat Jun 13 04:53:58 2026 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 4C5D12EDD69; Wed, 29 Apr 2026 16:04:14 +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=1777478657; cv=none; b=XJMmtzYQnPCwomVlOXWI07K6+xKXF8igroiJ2qCfh4CXGJWMYRyWeiIizs3dMrgWCsOTH1Yb50+2749F63L7D17EgmKe5yfEzMhHf9VKOP6xr8X9oyvvEHTCATbdTmtDk4WBOARIzlxNcAH/RTxZhhAMX3rmIIwKGkCYmhnUYh8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777478657; c=relaxed/simple; bh=EgU6d1CRqpfGMSXnoMt82OSRaXdG6fZk7N274hWxYkg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=s3UbtL4xtZdWxO+080z17QErpjR6OkaCEPc6sDX7DL6X1M6N7PZdSfkdROaDqI5SWELyLUqTexldRHYpbz1IyKhivl3l56/YdS44BOjH70W+ObZyye/vt8HGU0F2eGRJAC76268Ow0iBk8NndXDHUnqe8GJAl7Ak9mpHU9JDdTI= 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.224.235]) by frasgout13.his.huawei.com (SkyGuard) with ESMTPS id 4g5MSZ19qmzpTqm; Wed, 29 Apr 2026 23:59:42 +0800 (CST) Received: from mail02.huawei.com (unknown [7.182.16.27]) by mail.maildlp.com (Postfix) with ESMTP id 5CC864056A; Thu, 30 Apr 2026 00:04:12 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP2 (Coremail) with SMTP id GxC2BwBHPmrYK_JpRQ1BAA--.12298S5; Wed, 29 Apr 2026 17:04:11 +0100 (CET) From: Roberto Sassu To: corbet@lwn.net, skhan@linuxfoundation.org, zohar@linux.ibm.com, dmitry.kasatkin@gmail.com, eric.snowberg@oracle.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com Cc: linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, gregorylumen@linux.microsoft.com, chenste@linux.microsoft.com, nramas@linux.microsoft.com, Roberto Sassu Subject: [PATCH v5 03/13] ima: Introduce per binary measurements list type ima_num_entries counter Date: Wed, 29 Apr 2026 18:03:09 +0200 Message-ID: <20260429160319.4162918-4-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260429160319.4162918-1-roberto.sassu@huaweicloud.com> References: <20260429160319.4162918-1-roberto.sassu@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: GxC2BwBHPmrYK_JpRQ1BAA--.12298S5 X-Coremail-Antispam: 1UD129KBjvJXoWxGw1kZr4fKFy3CF4rAF47Jwb_yoWrXF17pa nIgF1UJr18XFy2krykCa47Aa9Yg3yrKryUW3y5Wwnay3ZxXr1UXFn8AF12kFn5Gr90yr1I qwn0qw45Aa1vyrJanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUP2b4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUWw A2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxS w2x7M28EF7xvwVC0I7IYx2IY67AKxVWUJVWUCwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxV WxJVW8Jr1l84ACjcxK6I8E87Iv67AKxVWUJVW8JwA2z4x0Y4vEx4A2jsIEc7CjxVAFwI0_ Gr0_Gr1UM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7xfMc Ij6xIIjxv20xvE14v26r1j6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Yz7v_ Jr0_Gr1lF7xvr2IYc2Ij64vIr41lFIxGxcIEc7CjxVA2Y2ka0xkIwI1lc7CjxVAaw2AFwI 0_Jw0_GFyl42xK82IYc2Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG 67AKxVWUJVWUGwC20s026x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26r4a6rW5MI IYrxkI7VAKI48JMIIF0xvE2Ix0cI8IcVAFwI0_Jr0_JF4lIxAIcVC0I7IYx2IY6xkF7I0E 14v26F4j6r4UJwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_Jr 0_Gr1lIxAIcVC2z280aVCY1x0267AKxVW8JVW8JrUvcSsGvfC2KfnxnUUI43ZEXa7IU14x RDUUUUU== X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAQASBGnx6jgGGwAAsA Content-Type: text/plain; charset="utf-8" From: Roberto Sassu Make ima_num_entries as an array, to have separate counters per binary measurements list type. Currently, define the BINARY type for the existing binary measurements list. No functional change: the BINARY type is equivalent to the value without the array. Link: https://github.com/linux-integrity/linux/issues/1 Signed-off-by: Roberto Sassu Reviewed-by: Mimi Zohar Tested-by: Stefan Berger --- security/integrity/ima/ima.h | 9 ++++++++- security/integrity/ima/ima_fs.c | 3 +-- security/integrity/ima/ima_kexec.c | 2 +- security/integrity/ima/ima_queue.c | 7 +++++-- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 94bf890628e5..b417c9d792d8 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -28,6 +28,13 @@ enum ima_show_type { IMA_SHOW_BINARY, IMA_SHOW_BINARY_NO= _FIELD_LEN, IMA_SHOW_BINARY_OLD_STRING_FMT, IMA_SHOW_ASCII }; enum tpm_pcrs { TPM_PCR0 =3D 0, TPM_PCR8 =3D 8, TPM_PCR10 =3D 10 }; =20 +/* + * BINARY: current binary measurements list + */ +enum binary_lists { + BINARY, BINARY__LAST +}; + /* digest size for IMA, fits SHA1 or MD5 */ #define IMA_DIGEST_SIZE SHA1_DIGEST_SIZE #define IMA_EVENT_NAME_LEN_MAX 255 @@ -325,7 +332,7 @@ int ima_lsm_policy_change(struct notifier_block *nb, un= signed long event, */ extern spinlock_t ima_queue_lock; =20 -extern atomic_long_t ima_num_entries; +extern atomic_long_t ima_num_entries[BINARY__LAST]; extern atomic_long_t ima_num_violations; extern struct hlist_head __rcu *ima_htable; =20 diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_f= s.c index aaa460d70ff7..79b0f287c668 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -63,8 +63,7 @@ static ssize_t ima_show_measurements_count(struct file *f= ilp, char __user *buf, size_t count, loff_t *ppos) { - return ima_show_counter(buf, count, ppos, &ima_num_entries); - + return ima_show_counter(buf, count, ppos, &ima_num_entries[BINARY]); } =20 static const struct file_operations ima_measurements_count_ops =3D { diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/im= a_kexec.c index 5801649fbbef..40962dc0ca86 100644 --- a/security/integrity/ima/ima_kexec.c +++ b/security/integrity/ima/ima_kexec.c @@ -43,7 +43,7 @@ void ima_measure_kexec_event(const char *event_name) int n; =20 buf_size =3D ima_get_binary_runtime_size(); - len =3D atomic_long_read(&ima_num_entries); + len =3D atomic_long_read(&ima_num_entries[BINARY]); =20 n =3D scnprintf(ima_kexec_event, IMA_KEXEC_EVENT_LEN, "kexec_segment_size=3D%lu;ima_binary_runtime_size=3D%lu;" diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/im= a_queue.c index 41f4941ceaad..952172a4905d 100644 --- a/security/integrity/ima/ima_queue.c +++ b/security/integrity/ima/ima_queue.c @@ -33,7 +33,10 @@ static unsigned long binary_runtime_size =3D ULONG_MAX; #endif =20 /* num of stored measurements in the list */ -atomic_long_t ima_num_entries =3D ATOMIC_LONG_INIT(0); +atomic_long_t ima_num_entries[BINARY__LAST] =3D { + [0 ... BINARY__LAST - 1] =3D ATOMIC_LONG_INIT(0) +}; + /* num of violations in the list */ atomic_long_t ima_num_violations =3D ATOMIC_LONG_INIT(0); =20 @@ -154,7 +157,7 @@ static int ima_add_digest_entry(struct ima_template_ent= ry *entry, htable =3D rcu_dereference_protected(ima_htable, lockdep_is_held(&ima_extend_list_mutex)); =20 - atomic_long_inc(&ima_num_entries); + atomic_long_inc(&ima_num_entries[BINARY]); if (update_htable) { key =3D ima_hash_key(entry->digests[ima_hash_algo_idx].digest); hlist_add_head_rcu(&qe->hnext, &htable[key]); --=20 2.43.0 From nobody Sat Jun 13 04:53:58 2026 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 CD8FA40DFD7; Wed, 29 Apr 2026 16:04:21 +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=1777478664; cv=none; b=touoYz+n1lTgsV3Yq+ONCWow+apecUQuCE+XK6+vIgOJSZa+VPiHWhuQv96037XjtWjp0hr6djw/zHUVn1zIfy/H69/O2XSbOPXwxQX2ta2VyaF6RBZbbdjV5tSTp/zzBaN1X/Rcvx/INFDX78xI7Kf6tQd7GZpU1jz4mRKJET4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777478664; c=relaxed/simple; bh=mI8e3kANvrWe3Uy1cnVbu2cjSNYlTRHBfbdsDNXcYyA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=u6zFNnxjpf0AXlrX/GGxPvN802ESYWwCTkbVxoRhg911ieQwNrP+kFheivHv7oivO8KqMt5fHA5Yo2YIS6BULnukr3I6vSKFLwJid7b6E7j8Zfutag2bIPsxg579BWIeIyHLBepUW4wJJru6oH8q4oJN8bAb50espnhS0pZ1sfk= 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.224.235]) by frasgout13.his.huawei.com (SkyGuard) with ESMTPS id 4g5MSj6v6tzpV1W; Wed, 29 Apr 2026 23:59:49 +0800 (CST) Received: from mail02.huawei.com (unknown [7.182.16.27]) by mail.maildlp.com (Postfix) with ESMTP id 2D62640569; Thu, 30 Apr 2026 00:04:20 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP2 (Coremail) with SMTP id GxC2BwBHPmrYK_JpRQ1BAA--.12298S6; Wed, 29 Apr 2026 17:04:19 +0100 (CET) From: Roberto Sassu To: corbet@lwn.net, skhan@linuxfoundation.org, zohar@linux.ibm.com, dmitry.kasatkin@gmail.com, eric.snowberg@oracle.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com Cc: linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, gregorylumen@linux.microsoft.com, chenste@linux.microsoft.com, nramas@linux.microsoft.com, Roberto Sassu Subject: [PATCH v5 04/13] ima: Introduce per binary measurements list type binary_runtime_size value Date: Wed, 29 Apr 2026 18:03:10 +0200 Message-ID: <20260429160319.4162918-5-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260429160319.4162918-1-roberto.sassu@huaweicloud.com> References: <20260429160319.4162918-1-roberto.sassu@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: GxC2BwBHPmrYK_JpRQ1BAA--.12298S6 X-Coremail-Antispam: 1UD129KBjvJXoW3Jw15Xr1ftr4kGF1kGrWxWFg_yoW7CrWUpa nxZF18tr4kXay7KFZ5GF97ZFWrW3yrXry7Jas8W3WI9Fs7Ar1jqF15tryjkFW5G3s8t3W7 JrWqqr4fAanrt3DanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUPvb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVWUJVWUCwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVWxJVW8Jr1l84ACjcxK6I8E87Iv67AKxVWUJVW8JwA2z4x0Y4vEx4A2jsIEc7CjxVAF wI0_Gr1j6F4UJwAS0I0E0xvYzxvE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG6I 80ewAv7VC0I7IYx2IY67AKxVWUJVWUGwAv7VC2z280aVAFwI0_Jr0_Gr1lOx8S6xCaFVCj c4AY6r1j6r4UM4x0Y48IcxkI7VAKI48JM4IIrI8v6xkF7I0E8cxan2IY04v7MxkF7I0En4 kS14v26r1q6r43MxAIw28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY6r1j6r4UMI8I3I0E 5I8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVW8ZV WrXwCIc40Y0x0EwIxGrwCI42IY6xIIjxv20xvE14v26r1j6r1xMIIF0xvE2Ix0cI8IcVCY 1x0267AKxVWxJVW8Jr1lIxAIcVCF04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14 v26r1j6r4UMIIF0xvEx4A2jsIEc7CjxVAFwI0_Gr1j6F4UJbIYCTnIWIevJa73UjIFyTuY vjxUF9NVUUUUU X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAQASBGnx6jgGGwABsB Content-Type: text/plain; charset="utf-8" From: Roberto Sassu Make binary_runtime_size as an array, to have separate counters per binary measurements list type. Currently, define the BINARY type for the existing binary measurements list. Introduce ima_update_binary_runtime_size() to facilitate updating a binary_runtime_size value with a given binary measurement list type. Also add the binary measurements list type parameter to ima_get_binary_runtime_size(), to retrieve the desired value. Retrieving the value is now done under the ima_extend_list_mutex, since there can be concurrent updates. No functional change (except for the mutex usage, that fixes the concurrency issue): the BINARY array element is equivalent to the old binary_runtime_size. Link: https://github.com/linux-integrity/linux/issues/1 Signed-off-by: Roberto Sassu Tested-by: Stefan Berger --- security/integrity/ima/ima.h | 2 +- security/integrity/ima/ima_kexec.c | 5 ++-- security/integrity/ima/ima_queue.c | 40 +++++++++++++++++++++--------- 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index b417c9d792d8..f8ab6b604c0d 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -319,7 +319,7 @@ int ima_restore_measurement_entry(struct ima_template_e= ntry *entry); int ima_restore_measurement_list(loff_t bufsize, void *buf); int ima_measurements_show(struct seq_file *m, void *v); int __init ima_init_htable(void); -unsigned long ima_get_binary_runtime_size(void); +unsigned long ima_get_binary_runtime_size(enum binary_lists binary_list); int ima_init_template(void); void ima_init_template_list(void); int __init ima_init_digests(void); diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/im= a_kexec.c index 40962dc0ca86..44ebefbdcab0 100644 --- a/security/integrity/ima/ima_kexec.c +++ b/security/integrity/ima/ima_kexec.c @@ -42,7 +42,7 @@ void ima_measure_kexec_event(const char *event_name) long len; int n; =20 - buf_size =3D ima_get_binary_runtime_size(); + buf_size =3D ima_get_binary_runtime_size(BINARY); len =3D atomic_long_read(&ima_num_entries[BINARY]); =20 n =3D scnprintf(ima_kexec_event, IMA_KEXEC_EVENT_LEN, @@ -159,7 +159,8 @@ void ima_add_kexec_buffer(struct kimage *image) else extra_memory =3D CONFIG_IMA_KEXEC_EXTRA_MEMORY_KB * 1024; =20 - binary_runtime_size =3D ima_get_binary_runtime_size() + extra_memory; + binary_runtime_size =3D ima_get_binary_runtime_size(BINARY) + + extra_memory; =20 if (binary_runtime_size >=3D ULONG_MAX - PAGE_SIZE) kexec_segment_size =3D ULONG_MAX; diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/im= a_queue.c index 952172a4905d..b6d10dceb669 100644 --- a/security/integrity/ima/ima_queue.c +++ b/security/integrity/ima/ima_queue.c @@ -27,9 +27,11 @@ static struct tpm_digest *digests; =20 LIST_HEAD(ima_measurements); /* list of all measurements */ #ifdef CONFIG_IMA_KEXEC -static unsigned long binary_runtime_size; +static unsigned long binary_runtime_size[BINARY__LAST]; #else -static unsigned long binary_runtime_size =3D ULONG_MAX; +static unsigned long binary_runtime_size[BINARY__LAST] =3D { + [0 ... BINARY__LAST - 1] =3D ULONG_MAX +}; #endif =20 /* num of stored measurements in the list */ @@ -131,6 +133,20 @@ static int get_binary_runtime_size(struct ima_template= _entry *entry) return size; } =20 +static void ima_update_binary_runtime_size(struct ima_template_entry *entr= y, + enum binary_lists binary_list) +{ + int size; + + if (binary_runtime_size[binary_list] =3D=3D ULONG_MAX) + return; + + size =3D get_binary_runtime_size(entry); + binary_runtime_size[binary_list] =3D + (binary_runtime_size[binary_list] < ULONG_MAX - size) ? + binary_runtime_size[binary_list] + size : ULONG_MAX; +} + /* ima_add_template_entry helper function: * - Add template entry to the measurement list and hash table, for * all entries except those carried across kexec. @@ -163,13 +179,7 @@ static int ima_add_digest_entry(struct ima_template_en= try *entry, hlist_add_head_rcu(&qe->hnext, &htable[key]); } =20 - if (binary_runtime_size !=3D ULONG_MAX) { - int size; - - size =3D get_binary_runtime_size(entry); - binary_runtime_size =3D (binary_runtime_size < ULONG_MAX - size) ? - binary_runtime_size + size : ULONG_MAX; - } + ima_update_binary_runtime_size(entry, BINARY); return 0; } =20 @@ -178,12 +188,18 @@ static int ima_add_digest_entry(struct ima_template_e= ntry *entry, * entire binary_runtime_measurement list, including the ima_kexec_hdr * structure. */ -unsigned long ima_get_binary_runtime_size(void) +unsigned long ima_get_binary_runtime_size(enum binary_lists binary_list) { - if (binary_runtime_size >=3D (ULONG_MAX - sizeof(struct ima_kexec_hdr))) + unsigned long val; + + mutex_lock(&ima_extend_list_mutex); + val =3D binary_runtime_size[binary_list]; + mutex_unlock(&ima_extend_list_mutex); + + if (val >=3D (ULONG_MAX - sizeof(struct ima_kexec_hdr))) return ULONG_MAX; else - return binary_runtime_size + sizeof(struct ima_kexec_hdr); + return val + sizeof(struct ima_kexec_hdr); } =20 static int ima_pcr_extend(struct tpm_digest *digests_arg, int pcr) --=20 2.43.0 From nobody Sat Jun 13 04:53:58 2026 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 C0BB8336882; Wed, 29 Apr 2026 16:04:30 +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=1777478672; cv=none; b=b05A2H3GXI80QEEsThfAoM8HRvKE3fqYYNyXkiFEq6mMnWZNrJ+R9NH0bLcMsXH12nufXff+xRPwxa16GyPR1R2zdsGwNYVWyg6K22iWz6rX1sVLuBfzF7tnllycEsWHJl7i7Kzog9M+lPKpsBsX8L4cPCoQRLpW59u1/EU5sbk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777478672; c=relaxed/simple; bh=3ASW5h9Qjj/PBWMoihRtUZCUgJ9yLdTRrgCN/5L4wck=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Nu8mZ5tBdTs/2opI5gxZuXNbAvWOxh+l8pdMB2Gbek9+H1ax5tyNcGVDBmK1gpCpm8/bUNOidA5ioxaKj1Nsyx7+fyn9WluehVVemCLywHR1Fdc7lz4UuQT5E/vT8kib6wypktVY12av8nWuD3cPP2EV8Ncgrk3iQW/xMgaeKTM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=none 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=none smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.18.224.235]) by frasgout12.his.huawei.com (SkyGuard) with ESMTPS id 4g5MT80t4ZzvQm6; Thu, 30 Apr 2026 00:00:12 +0800 (CST) Received: from mail02.huawei.com (unknown [7.182.16.27]) by mail.maildlp.com (Postfix) with ESMTP id F23B440560; Thu, 30 Apr 2026 00:04:27 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP2 (Coremail) with SMTP id GxC2BwBHPmrYK_JpRQ1BAA--.12298S7; Wed, 29 Apr 2026 17:04:27 +0100 (CET) From: Roberto Sassu To: corbet@lwn.net, skhan@linuxfoundation.org, zohar@linux.ibm.com, dmitry.kasatkin@gmail.com, eric.snowberg@oracle.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com Cc: linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, gregorylumen@linux.microsoft.com, chenste@linux.microsoft.com, nramas@linux.microsoft.com, Roberto Sassu Subject: [PATCH v5 05/13] ima: Introduce _ima_measurements_start() and _ima_measurements_next() Date: Wed, 29 Apr 2026 18:03:11 +0200 Message-ID: <20260429160319.4162918-6-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260429160319.4162918-1-roberto.sassu@huaweicloud.com> References: <20260429160319.4162918-1-roberto.sassu@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: GxC2BwBHPmrYK_JpRQ1BAA--.12298S7 X-Coremail-Antispam: 1UD129KBjvJXoW7Kry8Jw4fAryrGFWxZw1xGrg_yoW5JFyxpa sxua4rCF4kJ3yxWF1xGrWDWr4ru3sag3WDWrWUJ34vvF1UJr1v9r43Aw12vrn0y348Xr1v vr90gr45Cw4FyaDanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUPvb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVWUCVW8JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVWxJVW8Jr1l84ACjcxK6I8E87Iv67AKxVWUJVW8JwA2z4x0Y4vEx4A2jsIEc7CjxVAF wI0_Gr1j6F4UJwAS0I0E0xvYzxvE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG6I 80ewAv7VC0I7IYx2IY67AKxVWUJVWUGwAv7VC2z280aVAFwI0_Jr0_Gr1lOx8S6xCaFVCj c4AY6r1j6r4UM4x0Y48IcxkI7VAKI48JM4IIrI8v6xkF7I0E8cxan2IY04v7MxkF7I0En4 kS14v26r1q6r43MxAIw28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY6r1j6r4UMI8I3I0E 5I8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVW8ZV WrXwCIc40Y0x0EwIxGrwCI42IY6xIIjxv20xvE14v26r1I6r4UMIIF0xvE2Ix0cI8IcVCY 1x0267AKxVWxJVW8Jr1lIxAIcVCF04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14 v26r1j6r4UMIIF0xvEx4A2jsIEc7CjxVAFwI0_Gr1j6F4UJbIYCTnIWIevJa73UjIFyTuY vjxUF9NVUUUUU X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAQASBGnx6jgGGwACsC Content-Type: text/plain; charset="utf-8" From: Roberto Sassu Introduce _ima_measurements_start() and _ima_measurements_next(), renamed from ima_measurements_start() and ima_measurements_next(), to include the list head as an additional parameter, so that iteration on different lists can be implemented by calling those functions. No functional change: ima_measurements_start() and ima_measurements_next() pass the ima_measurements list head, used before. Link: https://github.com/linux-integrity/linux/issues/1 Signed-off-by: Roberto Sassu Reviewed-by: Mimi Zohar Tested-by: Stefan Berger --- security/integrity/ima/ima_fs.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_f= s.c index 79b0f287c668..9a8dba14d82a 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -72,14 +72,15 @@ static const struct file_operations ima_measurements_co= unt_ops =3D { }; =20 /* returns pointer to hlist_node */ -static void *ima_measurements_start(struct seq_file *m, loff_t *pos) +static void *_ima_measurements_start(struct seq_file *m, loff_t *pos, + struct list_head *head) { loff_t l =3D *pos; struct ima_queue_entry *qe; =20 /* we need a lock since pos could point beyond last element */ rcu_read_lock(); - list_for_each_entry_rcu(qe, &ima_measurements, later) { + list_for_each_entry_rcu(qe, head, later) { if (!l--) { rcu_read_unlock(); return qe; @@ -89,7 +90,13 @@ static void *ima_measurements_start(struct seq_file *m, = loff_t *pos) return NULL; } =20 -static void *ima_measurements_next(struct seq_file *m, void *v, loff_t *po= s) +static void *ima_measurements_start(struct seq_file *m, loff_t *pos) +{ + return _ima_measurements_start(m, pos, &ima_measurements); +} + +static void *_ima_measurements_next(struct seq_file *m, void *v, loff_t *p= os, + struct list_head *head) { struct ima_queue_entry *qe =3D v; =20 @@ -101,7 +108,12 @@ static void *ima_measurements_next(struct seq_file *m,= void *v, loff_t *pos) rcu_read_unlock(); (*pos)++; =20 - return (&qe->later =3D=3D &ima_measurements) ? NULL : qe; + return (&qe->later =3D=3D head) ? NULL : qe; +} + +static void *ima_measurements_next(struct seq_file *m, void *v, loff_t *po= s) +{ + return _ima_measurements_next(m, v, pos, &ima_measurements); } =20 static void ima_measurements_stop(struct seq_file *m, void *v) --=20 2.43.0 From nobody Sat Jun 13 04:53:58 2026 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 B7A282701C4; Wed, 29 Apr 2026 16:04:37 +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=1777478680; cv=none; b=DMG5J9QV56q5YpYSZE/ALQspeKzo+C12HxCRP55bqpDFGj6RdIO9bZUOYcq6frlfKZrZUwMpgSTgn+98itxe0g8ccFJAHjtq0YBdgILPuRAGo2N6mvN3/6fWibWc3q8Vv6JgSYrBRUwmEl+t+2zaEnIHBgk8pE2p1zhz7uO/dr0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777478680; c=relaxed/simple; bh=EOZOjyjMg6/Fn5W/fcIBelXq1e2DV8pmyX8Hk++1dSw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Flu8DOZRNSEN0oU0UfROhM6vFaGBSgNrJpcv8DfQi22qxjT471Qrf+IvNel/oTzAfw17GWuTZBaJFKCU+JCS6abGVnJjpY97VeNGM78C1sHYUyuIxp2Nan534l5zSRjwzfRM/2z6KWwzSnpowrri6I6uVrOW8lKdkIuhhXzDvsg= 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.224.196]) by frasgout11.his.huawei.com (SkyGuard) with ESMTPS id 4g5MT06dnqz1HCcG; Thu, 30 Apr 2026 00:00:04 +0800 (CST) Received: from mail02.huawei.com (unknown [7.182.16.27]) by mail.maildlp.com (Postfix) with ESMTP id C1F0940565; Thu, 30 Apr 2026 00:04:35 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP2 (Coremail) with SMTP id GxC2BwBHPmrYK_JpRQ1BAA--.12298S8; Wed, 29 Apr 2026 17:04:35 +0100 (CET) From: Roberto Sassu To: corbet@lwn.net, skhan@linuxfoundation.org, zohar@linux.ibm.com, dmitry.kasatkin@gmail.com, eric.snowberg@oracle.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com Cc: linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, gregorylumen@linux.microsoft.com, chenste@linux.microsoft.com, nramas@linux.microsoft.com, Roberto Sassu Subject: [PATCH v5 06/13] ima: Mediate open/release method of the measurements list Date: Wed, 29 Apr 2026 18:03:12 +0200 Message-ID: <20260429160319.4162918-7-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260429160319.4162918-1-roberto.sassu@huaweicloud.com> References: <20260429160319.4162918-1-roberto.sassu@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: GxC2BwBHPmrYK_JpRQ1BAA--.12298S8 X-Coremail-Antispam: 1UD129KBjvJXoWxur1kCFW7ZFy5CFyDJryUAwb_yoWrCr43pa 93C3yrCr1kJrWfWFn7Ga47Zr4F9a4rKa15Wr4DJa4fAF1rJr9F9F4Yyr12kFs8tryrGr18 Xw4qqr45uas0yaDanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUPlb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVWUCVW8JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_Jr0_Gr1l84ACjcxK6I8E87Iv6xkF7I0E 14v26r4UJVWxJr1le2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrV C2j2WlYx0E2Ix0cI8IcVAFwI0_Jr0_Jr4lYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE 7xkEbVWUJVW8JwACjcxG0xvY0x0EwIxGrwACI402YVCY1x02628vn2kIc2xKxwCY1x0262 kKe7AKxVWUtVW8ZwCF04k20xvY0x0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s02 6c02F40E14v26r1j6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_GF v_WrylIxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVWUCVW8JwCI42IY6xIIjxv20xvE c7CjxVAFwI0_Gr1j6F4UJwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aV AFwI0_Jr0_Gr1lIxAIcVC2z280aVCY1x0267AKxVW8Jr0_Cr1UYxBIdaVFxhVjvjDU0xZF pf9x07UZTmfUUUUU= X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAgASBGnx6jEGFgAAsH Content-Type: text/plain; charset="utf-8" From: Roberto Sassu Introduce the ima_measure_users counter, to implement a semaphore-like locking scheme where the binary and ASCII measurements list interfaces can be concurrently open by multiple readers, or alternatively by a single writer. A semaphore cannot be used because the kernel cannot return to user space with a lock held. Introduce the ima_measure_lock() and ima_measure_unlock() primitives, to respectively lock/unlock the interfaces (safely with the ima_measure_users counter, without holding a lock). Finally, introduce _ima_measurements_open() to lock the interface before seq_open(), and call it from ima_measurements_open() and ima_ascii_measurements_open(). And, introduce ima_measurements_release(), to unlock the interface. Require CAP_SYS_ADMIN if the interface is opened for write (not possible for the current measurements interfaces, since they only have read permission). No functional changes: multiple readers are allowed as before. Link: https://github.com/linux-integrity/linux/issues/1 Signed-off-by: Roberto Sassu Tested-by: Stefan Berger --- security/integrity/ima/ima_fs.c | 71 +++++++++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 4 deletions(-) diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_f= s.c index 9a8dba14d82a..68edea7139d5 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -25,6 +25,8 @@ #include "ima.h" =20 static DEFINE_MUTEX(ima_write_mutex); +static DEFINE_MUTEX(ima_measure_mutex); +static long ima_measure_users; =20 bool ima_canonical_fmt; static int __init default_canonical_fmt_setup(char *str) @@ -209,16 +211,76 @@ static const struct seq_operations ima_measurments_se= qops =3D { .show =3D ima_measurements_show }; =20 +static int ima_measure_lock(bool write) +{ + mutex_lock(&ima_measure_mutex); + if ((write && ima_measure_users !=3D 0) || + (!write && ima_measure_users < 0)) { + mutex_unlock(&ima_measure_mutex); + return -EBUSY; + } + + if (write) + ima_measure_users--; + else + ima_measure_users++; + mutex_unlock(&ima_measure_mutex); + return 0; +} + +static void ima_measure_unlock(bool write) +{ + mutex_lock(&ima_measure_mutex); + if (write) + ima_measure_users++; + else + ima_measure_users--; + mutex_unlock(&ima_measure_mutex); +} + +static int _ima_measurements_open(struct inode *inode, struct file *file, + const struct seq_operations *seq_ops) +{ + bool write =3D (file->f_mode & FMODE_WRITE); + int ret; + + if (write && !capable(CAP_SYS_ADMIN)) + return -EPERM; + + ret =3D ima_measure_lock(write); + if (ret < 0) + return ret; + + ret =3D seq_open(file, seq_ops); + if (ret < 0) + ima_measure_unlock(write); + + return ret; +} + static int ima_measurements_open(struct inode *inode, struct file *file) { - return seq_open(file, &ima_measurments_seqops); + return _ima_measurements_open(inode, file, &ima_measurments_seqops); +} + +static int ima_measurements_release(struct inode *inode, struct file *file) +{ + bool write =3D (file->f_mode & FMODE_WRITE); + int ret; + + /* seq_release() always returns zero. */ + ret =3D seq_release(inode, file); + + ima_measure_unlock(write); + + return ret; } =20 static const struct file_operations ima_measurements_ops =3D { .open =3D ima_measurements_open, .read =3D seq_read, .llseek =3D seq_lseek, - .release =3D seq_release, + .release =3D ima_measurements_release, }; =20 void ima_print_digest(struct seq_file *m, u8 *digest, u32 size) @@ -283,14 +345,15 @@ static const struct seq_operations ima_ascii_measurem= ents_seqops =3D { =20 static int ima_ascii_measurements_open(struct inode *inode, struct file *f= ile) { - return seq_open(file, &ima_ascii_measurements_seqops); + return _ima_measurements_open(inode, file, + &ima_ascii_measurements_seqops); } =20 static const struct file_operations ima_ascii_measurements_ops =3D { .open =3D ima_ascii_measurements_open, .read =3D seq_read, .llseek =3D seq_lseek, - .release =3D seq_release, + .release =3D ima_measurements_release, }; =20 static ssize_t ima_read_policy(char *path) --=20 2.43.0 From nobody Sat Jun 13 04:53:58 2026 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 417CA3290DB; Wed, 29 Apr 2026 16:04:45 +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=1777478687; cv=none; b=n1nvH6sldN9EvdVAX5x7IyiQ7sZAW9D8GPlq3ZUYpabDB7x/ixThTpMszfBm1Rf+F3NnyuNDsXt5nhhcz4HNvAf5ntSgAnFpz0yJvmdpjA7tOwy2cNlUpTRraVM1ao4SBYdUZlfNZoUm+RweMVQHKdC5MA2VgBXmUYL3SMzD6m4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777478687; c=relaxed/simple; bh=XrG5Rzjw97/k4hs9NuHnDSP9PLebkbtARyW+dgXrZZk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=nz0HfiBdQFfO4AvF57BPoNEsox+WGVJRprnGR/IHwqjwh2qFF7Bmrkfbie9lFc+pSIjUZ9R6TxRwIfQCNZ9OYgR3OJZ+622J65Dd4+NibJXMKHA/ITO6gLzuM+ZVHaorQupZw6LSc//yEsq048YhJqTxcjk7C6tnSjSLxWwU7gs= 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.224.196]) by frasgout11.his.huawei.com (SkyGuard) with ESMTPS id 4g5MT85GmNz1HC7j; Thu, 30 Apr 2026 00:00:12 +0800 (CST) Received: from mail02.huawei.com (unknown [7.182.16.27]) by mail.maildlp.com (Postfix) with ESMTP id 93EF04056B; Thu, 30 Apr 2026 00:04:43 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP2 (Coremail) with SMTP id GxC2BwBHPmrYK_JpRQ1BAA--.12298S9; Wed, 29 Apr 2026 17:04:43 +0100 (CET) From: Roberto Sassu To: corbet@lwn.net, skhan@linuxfoundation.org, zohar@linux.ibm.com, dmitry.kasatkin@gmail.com, eric.snowberg@oracle.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com Cc: linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, gregorylumen@linux.microsoft.com, chenste@linux.microsoft.com, nramas@linux.microsoft.com, Roberto Sassu Subject: [PATCH v5 07/13] ima: Use snprintf() in create_securityfs_measurement_lists Date: Wed, 29 Apr 2026 18:03:13 +0200 Message-ID: <20260429160319.4162918-8-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260429160319.4162918-1-roberto.sassu@huaweicloud.com> References: <20260429160319.4162918-1-roberto.sassu@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: GxC2BwBHPmrYK_JpRQ1BAA--.12298S9 X-Coremail-Antispam: 1UD129KBjvJXoW7tFy5XFWDWw1rtF1kWr4rXwb_yoW8tF48pa ySgF18Crs5J3yxKFn3K3Z7uaySk3yagF1UW3yvg3WkAFn3XrWFkr4vkr1jkr95Kr10yFy8 XrsFqF13C3Z0yaDanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUPlb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVWUCVW8JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_Jr0_Gr1l84ACjcxK6I8E87Iv6xkF7I0E 14v26r4UJVWxJr1le2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrV C2j2WlYx0E2Ix0cI8IcVAFwI0_Jr0_Jr4lYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE 7xkEbVWUJVW8JwACjcxG0xvY0x0EwIxGrwACI402YVCY1x02628vn2kIc2xKxwCY1x0262 kKe7AKxVWUtVW8ZwCF04k20xvY0x0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s02 6c02F40E14v26r1j6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_GF v_WrylIxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVWUCVW8JwCI42IY6xIIjxv20xvE c7CjxVAFwI0_Gr1j6F4UJwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aV AFwI0_Jr0_Gr1lIxAIcVC2z280aVCY1x0267AKxVW8Jr0_Cr1UYxBIdaVFxhVjvjDU0xZF pf9x07UZTmfUUUUU= X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAQASBGnx6jgGHAAAsH Content-Type: text/plain; charset="utf-8" From: Roberto Sassu Use the more secure snprintf() function (accepting the buffer size) in create_securityfs_measurement_lists(). No functional change: sprintf() and snprintf() have the same behavior. Link: https://github.com/linux-integrity/linux/issues/1 Signed-off-by: Roberto Sassu Reviewed-by: Mimi Zohar Tested-by: Stefan Berger --- security/integrity/ima/ima_fs.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_f= s.c index 68edea7139d5..7709a4576322 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -472,11 +472,13 @@ static int __init create_securityfs_measurement_lists= (void) struct dentry *dentry; =20 if (algo =3D=3D HASH_ALGO__LAST) - sprintf(file_name, "ascii_runtime_measurements_tpm_alg_%x", - ima_tpm_chip->allocated_banks[i].alg_id); + snprintf(file_name, sizeof(file_name), + "ascii_runtime_measurements_tpm_alg_%x", + ima_tpm_chip->allocated_banks[i].alg_id); else - sprintf(file_name, "ascii_runtime_measurements_%s", - hash_algo_name[algo]); + snprintf(file_name, sizeof(file_name), + "ascii_runtime_measurements_%s", + hash_algo_name[algo]); dentry =3D securityfs_create_file(file_name, S_IRUSR | S_IRGRP, ima_dir, (void *)(uintptr_t)i, &ima_ascii_measurements_ops); @@ -484,11 +486,13 @@ static int __init create_securityfs_measurement_lists= (void) return PTR_ERR(dentry); =20 if (algo =3D=3D HASH_ALGO__LAST) - sprintf(file_name, "binary_runtime_measurements_tpm_alg_%x", - ima_tpm_chip->allocated_banks[i].alg_id); + snprintf(file_name, sizeof(file_name), + "binary_runtime_measurements_tpm_alg_%x", + ima_tpm_chip->allocated_banks[i].alg_id); else - sprintf(file_name, "binary_runtime_measurements_%s", - hash_algo_name[algo]); + snprintf(file_name, sizeof(file_name), + "binary_runtime_measurements_%s", + hash_algo_name[algo]); dentry =3D securityfs_create_file(file_name, S_IRUSR | S_IRGRP, ima_dir, (void *)(uintptr_t)i, &ima_measurements_ops); --=20 2.43.0 From nobody Sat Jun 13 04:53:58 2026 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 1C3C9329C66; Wed, 29 Apr 2026 16:04:52 +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=1777478695; cv=none; b=T9/jBQMzdXs73scMB7cxqnHZ2cYpUB9pL+TaFTUWwZBZ+IAGEGVHynZP8qplTtj95zxs8Mms3RAJnFOJaCp/ZLQ9ATDEgUO2/Pu7bJ7l4OffZkCiq8l9amrurpc871xcBlOyQdZko/LXHDHfqJ3TtZrHUxOmhFrh2+ONKp7vjwg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777478695; c=relaxed/simple; bh=lTEMSdWntKFwJ7UZj396vRRLvGqDKzB88Vh6/ciMCuk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=siMOCRurHoTg0n8tJ8/LVNsjcTdbLkANftAHT+rgzLScujKMt2S6LJjK0FVWGpk4Py2Z80BbUiY+HNf7NcYoO0ram633MhORPQVmi3ln5vaOe91RaJ0XSTTCwXvxUGSauh9WwWeYOfnlqUfiGW9q2zFKvFWP+lcbjF6mIuSjlYM= 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.224.196]) by frasgout11.his.huawei.com (SkyGuard) with ESMTPS id 4g5MTJ3wWZz1HCXJ; Thu, 30 Apr 2026 00:00:20 +0800 (CST) Received: from mail02.huawei.com (unknown [7.182.16.27]) by mail.maildlp.com (Postfix) with ESMTP id 6624D40565; Thu, 30 Apr 2026 00:04:51 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP2 (Coremail) with SMTP id GxC2BwBHPmrYK_JpRQ1BAA--.12298S10; Wed, 29 Apr 2026 17:04:50 +0100 (CET) From: Roberto Sassu To: corbet@lwn.net, skhan@linuxfoundation.org, zohar@linux.ibm.com, dmitry.kasatkin@gmail.com, eric.snowberg@oracle.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com Cc: linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, gregorylumen@linux.microsoft.com, chenste@linux.microsoft.com, nramas@linux.microsoft.com, Roberto Sassu Subject: [PATCH v5 08/13] ima: Introduce ima_dump_measurement() Date: Wed, 29 Apr 2026 18:03:14 +0200 Message-ID: <20260429160319.4162918-9-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260429160319.4162918-1-roberto.sassu@huaweicloud.com> References: <20260429160319.4162918-1-roberto.sassu@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: GxC2BwBHPmrYK_JpRQ1BAA--.12298S10 X-Coremail-Antispam: 1UD129KBjvJXoW7CFyfXryDAw1rKFyfCFy7trb_yoW8AF43pa 9IgFy8Cr18tFyxKrn3GF98Ja1F93y8AF1UW3yDWwn3XF1DJr1Dur95Cr1IvrZ8GrZayF1x tw4agF4ruan0yaDanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUPlb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVWUCVW8JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_Jr0_Gr1l84ACjcxK6I8E87Iv6xkF7I0E 14v26r4UJVWxJr1le2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrV C2j2WlYx0E2Ix0cI8IcVAFwI0_Jr0_Jr4lYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE 7xkEbVWUJVW8JwACjcxG0xvY0x0EwIxGrwACI402YVCY1x02628vn2kIc2xKxwCY1x0262 kKe7AKxVWUtVW8ZwCF04k20xvY0x0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s02 6c02F40E14v26r1j6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_GF v_WrylIxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVWUCVW8JwCI42IY6xIIjxv20xvE c7CjxVAFwI0_Gr1j6F4UJwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aV AFwI0_Jr0_Gr1lIxAIcVC2z280aVCY1x0267AKxVW8Jr0_Cr1UYxBIdaVFxhVjvjDU0xZF pf9x07UZTmfUUUUU= X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAgASBGnx6jEGFwAAsG Content-Type: text/plain; charset="utf-8" From: Roberto Sassu Introduce ima_dump_measurement() to simplify the code of ima_dump_measurement_list() and to avoid repeating the ima_dump_measurement() code block if iteration occurs on multiple lists. No functional change: only code moved to a separate function. Link: https://github.com/linux-integrity/linux/issues/1 Signed-off-by: Roberto Sassu Reviewed-by: Mimi Zohar Tested-by: Stefan Berger --- security/integrity/ima/ima_kexec.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/im= a_kexec.c index 44ebefbdcab0..d7d0fb639d99 100644 --- a/security/integrity/ima/ima_kexec.c +++ b/security/integrity/ima/ima_kexec.c @@ -80,6 +80,17 @@ static int ima_alloc_kexec_file_buf(size_t segment_size) return 0; } =20 +static int ima_dump_measurement(struct ima_kexec_hdr *khdr, + struct ima_queue_entry *qe) +{ + if (ima_kexec_file.count >=3D ima_kexec_file.size) + return -EINVAL; + + khdr->count++; + ima_measurements_show(&ima_kexec_file, qe); + return 0; +} + static int ima_dump_measurement_list(unsigned long *buffer_size, void **bu= ffer, unsigned long segment_size) { @@ -97,13 +108,9 @@ static int ima_dump_measurement_list(unsigned long *buf= fer_size, void **buffer, khdr.version =3D 1; /* This is an append-only list, no need to hold the RCU read lock */ list_for_each_entry_rcu(qe, &ima_measurements, later, true) { - if (ima_kexec_file.count < ima_kexec_file.size) { - khdr.count++; - ima_measurements_show(&ima_kexec_file, qe); - } else { - ret =3D -EINVAL; + ret =3D ima_dump_measurement(&khdr, qe); + if (ret < 0) break; - } } =20 /* --=20 2.43.0 From nobody Sat Jun 13 04:53:58 2026 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 D46D52EDD69; Wed, 29 Apr 2026 16:05:00 +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=1777478703; cv=none; b=PtME8QxpBKkLnX0FTj1AH8PY3QcsKBQFMvnBLkuyNDEaK45q6X0kpPcEIAkpkKfiEJjiwsqWNENRndolBlDjqMaNC1/d4a1y2sCnrm6KDg+zlYsJQsL8P2BnMoTSO4nSjxMZPmN9iTzL+ofqer6IcJA3ONdBdw4m6s+NpXQfW3Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777478703; c=relaxed/simple; bh=ljCYgHBJ1hbi8pS68mBcBRy4pBBo936diAluNUl7ku0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=JBcjGcvgv2fuyeGb2lFTwk3DrmPu8wjaDGid2uyteXRmemi2id6kEGQBMP9nu5mPW718OWC5t4OBtOl1syYxBfsWU097bIC+stg/qEt/NX0q4mIJ3wk4zrhg10EE/DGzoxpefH01gXmssX3VmvAqOFGhm+eH86Lhl5b5r5nEqPA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=none 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=none smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.18.224.235]) by frasgout11.his.huawei.com (SkyGuard) with ESMTPS id 4g5MTS2YTpz1HCTV; Thu, 30 Apr 2026 00:00:28 +0800 (CST) Received: from mail02.huawei.com (unknown [7.182.16.27]) by mail.maildlp.com (Postfix) with ESMTP id 35F114056A; Thu, 30 Apr 2026 00:04:59 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP2 (Coremail) with SMTP id GxC2BwBHPmrYK_JpRQ1BAA--.12298S11; Wed, 29 Apr 2026 17:04:58 +0100 (CET) From: Roberto Sassu To: corbet@lwn.net, skhan@linuxfoundation.org, zohar@linux.ibm.com, dmitry.kasatkin@gmail.com, eric.snowberg@oracle.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com Cc: linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, gregorylumen@linux.microsoft.com, chenste@linux.microsoft.com, nramas@linux.microsoft.com, Roberto Sassu Subject: [PATCH v5 09/13] ima: Add support for staging measurements with prompt Date: Wed, 29 Apr 2026 18:03:15 +0200 Message-ID: <20260429160319.4162918-10-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260429160319.4162918-1-roberto.sassu@huaweicloud.com> References: <20260429160319.4162918-1-roberto.sassu@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: GxC2BwBHPmrYK_JpRQ1BAA--.12298S11 X-Coremail-Antispam: 1UD129KBjvAXoWfAr1rZrW7tFy7Wr48AFyfCrg_yoW8ZF47Jo Za9FZ8GF48Wrn3Cr4UKrsxtFy8WFZ5Wws7tr4rtrs8CF12gr15GayIq3WUAa1Iqw4rWryU Gw1kA348XFs2q3Z3n29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjp_UUUOo7kC6x804xWl14x267AKxVWrJVCq3wAFc2x0x2IEx4CE42xK 8VAvwI8IcIk0rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2048vs2IY020E87I2jVAFwI0_JF 0E3s1l82xGYIkIc2x26xkF7I0E14v26ryj6s0DM28lY4IEw2IIxxk0rwA2F7IY1VAKz4vE j48ve4kI8wA2z4x0Y4vE2Ix0cI8IcVAFwI0_JFI_Gr1l84ACjcxK6xIIjxv20xvEc7CjxV AFwI0_Gr1j6F4UJwA2z4x0Y4vEx4A2jsIE14v26r4j6F4UM28EF7xvwVC2z280aVCY1x02 67AKxVW8Jr0_Cr1UM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F4 0Ex7xfMcIj6xIIjxv20xvE14v26r1j6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC 6x0Yz7v_Jr0_Gr1lF7xvr2IYc2Ij64vIr41lFIxGxcIEc7CjxVA2Y2ka0xkIwI1lc7CjxV Aaw2AFwI0_Jw0_GFyl42xK82IYc2Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2Iq xVAqx4xG67AKxVWUJVWUGwC20s026x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26r 4a6rW5MIIYrxkI7VAKI48JMIIF0xvE2Ix0cI8IcVAFwI0_JFI_Gr1lIxAIcVC0I7IYx2IY 6xkF7I0E14v26r4UJVWxJr1lIxAIcVCF04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2js IE14v26r4j6F4UMIIF0xvEx4A2jsIEc7CjxVAFwI0_Gr1j6F4UJbIYCTnIWIevJa73UjIF yTuYvjxUF9NVUUUUU X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAQASBGnx6jgGHwAAsE Content-Type: text/plain; charset="utf-8" From: Roberto Sassu Introduce the ability of staging the IMA measurement list and deleting them with a prompt. Staging means moving the current content of the measurement list to a separate location, and allowing users to read and delete it. This causes the measurement list to be atomically truncated before new measurements can be added. Staging can be done only once at a time. In the event of kexec(), staging is reverted and staged entries will be carried over to the new kernel. Introduce ascii_runtime_measurements__staged and binary_runtime_measurements__staged interfaces to access and delete the measurements. Also, add write permission to the original measurement interfaces. Use 'echo A > ' and 'echo D > ' to respectively stage and delete the entire measurements list. Locking of these interfaces is also mediated with a call to _ima_measurements_open() and with ima_measurements_release(). Implement the staging functionality by introducing the new global measurements list ima_measurements_staged, and ima_queue_stage() and ima_queue_staged_delete_all() to respectively move measurements from the current measurements list to the staged one, and to move staged measurements to the ima_measurements_trim list for deletion. Introduce ima_queue_delete() to delete the measurements. Finally, introduce the BINARY_STAGED and BINARY_FULL binary measurements list types, to maintain the counters and the binary size of staged measurements and the full measurements list (including entries that were staged). BINARY still represents the current binary measurements list. Use the binary size for the BINARY + BINARY_STAGED types in ima_add_kexec_buffer(), since both measurements list types are copied to the secondary kernel during kexec. Use BINARY_FULL in ima_measure_kexec_event(), to generate a critical data record. It should be noted that the BINARY_FULL counter is not passed through kexec. Thus, the number of entries included in the kexec critical data records refers to the entries since the previous kexec records. Note: This code derives from the Alt-IMA Huawei project, whose license is GPL-2.0 OR MIT. Link: https://github.com/linux-integrity/linux/issues/1 Suggested-by: Gregory Lumen (staging rev= ert) Signed-off-by: Roberto Sassu Tested-by: Stefan Berger --- security/integrity/ima/Kconfig | 13 +++ security/integrity/ima/ima.h | 8 +- security/integrity/ima/ima_fs.c | 181 ++++++++++++++++++++++++++--- security/integrity/ima/ima_kexec.c | 24 +++- security/integrity/ima/ima_queue.c | 97 +++++++++++++++- 5 files changed, 302 insertions(+), 21 deletions(-) diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig index 862fbee2b174..48c906793efb 100644 --- a/security/integrity/ima/Kconfig +++ b/security/integrity/ima/Kconfig @@ -332,4 +332,17 @@ config IMA_KEXEC_EXTRA_MEMORY_KB If set to the default value of 0, an extra half page of memory for those additional measurements will be allocated. =20 +config IMA_STAGING + bool "Support for staging the measurements list" + default y + help + Add support for staging the measurements list. + + It allows user space to stage the measurements list for deletion and + to delete the staged measurements after confirmation. + + On kexec, staging is reverted and staged measurements are prepended + to the current measurements list when measurements are copied to the + secondary kernel. + endif diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index f8ab6b604c0d..ca8fa43ec72b 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -30,9 +30,11 @@ enum tpm_pcrs { TPM_PCR0 =3D 0, TPM_PCR8 =3D 8, TPM_PCR1= 0 =3D 10 }; =20 /* * BINARY: current binary measurements list + * BINARY_STAGED: staged binary measurements list + * BINARY_FULL: binary measurements list since IMA init (lost after kexec) */ enum binary_lists { - BINARY, BINARY__LAST + BINARY, BINARY_STAGED, BINARY_FULL, BINARY__LAST }; =20 /* digest size for IMA, fits SHA1 or MD5 */ @@ -125,6 +127,7 @@ struct ima_queue_entry { struct ima_template_entry *entry; }; extern struct list_head ima_measurements; /* list of all measurements */ +extern struct list_head ima_measurements_staged; /* list of staged meas. */ =20 /* Some details preceding the binary serialized measurement list */ struct ima_kexec_hdr { @@ -315,6 +318,8 @@ struct ima_template_desc *ima_template_desc_current(voi= d); struct ima_template_desc *ima_template_desc_buf(void); struct ima_template_desc *lookup_template_desc(const char *name); bool ima_template_has_modsig(const struct ima_template_desc *ima_template); +int ima_queue_stage(void); +int ima_queue_staged_delete_all(void); int ima_restore_measurement_entry(struct ima_template_entry *entry); int ima_restore_measurement_list(loff_t bufsize, void *buf); int ima_measurements_show(struct seq_file *m, void *v); @@ -335,6 +340,7 @@ extern spinlock_t ima_queue_lock; extern atomic_long_t ima_num_entries[BINARY__LAST]; extern atomic_long_t ima_num_violations; extern struct hlist_head __rcu *ima_htable; +extern struct mutex ima_extend_list_mutex; =20 static inline unsigned int ima_hash_key(u8 *digest) { diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_f= s.c index 7709a4576322..088d5a69aa92 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -24,6 +24,13 @@ =20 #include "ima.h" =20 +/* + * Requests: + * 'A\n': stage the entire measurements list + * 'D\n': delete all staged measurements + */ +#define STAGED_REQ_LENGTH 21 + static DEFINE_MUTEX(ima_write_mutex); static DEFINE_MUTEX(ima_measure_mutex); static long ima_measure_users; @@ -97,6 +104,11 @@ static void *ima_measurements_start(struct seq_file *m,= loff_t *pos) return _ima_measurements_start(m, pos, &ima_measurements); } =20 +static void *ima_measurements_staged_start(struct seq_file *m, loff_t *pos) +{ + return _ima_measurements_start(m, pos, &ima_measurements_staged); +} + static void *_ima_measurements_next(struct seq_file *m, void *v, loff_t *p= os, struct list_head *head) { @@ -118,6 +130,12 @@ static void *ima_measurements_next(struct seq_file *m,= void *v, loff_t *pos) return _ima_measurements_next(m, v, pos, &ima_measurements); } =20 +static void *ima_measurements_staged_next(struct seq_file *m, void *v, + loff_t *pos) +{ + return _ima_measurements_next(m, v, pos, &ima_measurements_staged); +} + static void ima_measurements_stop(struct seq_file *m, void *v) { } @@ -211,6 +229,13 @@ static const struct seq_operations ima_measurments_seq= ops =3D { .show =3D ima_measurements_show }; =20 +static const struct seq_operations ima_measurments_staged_seqops =3D { + .start =3D ima_measurements_staged_start, + .next =3D ima_measurements_staged_next, + .stop =3D ima_measurements_stop, + .show =3D ima_measurements_show +}; + static int ima_measure_lock(bool write) { mutex_lock(&ima_measure_mutex); @@ -276,9 +301,78 @@ static int ima_measurements_release(struct inode *inod= e, struct file *file) return ret; } =20 +static int ima_measurements_staged_open(struct inode *inode, struct file *= file) +{ + return _ima_measurements_open(inode, file, + &ima_measurments_staged_seqops); +} + +static ssize_t _ima_measurements_write(struct file *file, + const char __user *buf, size_t datalen, + loff_t *ppos, bool staged_interface) +{ + char req[STAGED_REQ_LENGTH]; + int ret; + + if (*ppos > 0 || datalen < 2 || datalen > STAGED_REQ_LENGTH) + return -EINVAL; + + if (copy_from_user(req, buf, datalen) !=3D 0) + return -EFAULT; + + if (req[datalen - 1] !=3D '\n') + return -EINVAL; + + req[datalen - 1] =3D '\0'; + + switch (req[0]) { + case 'A': + if (datalen !=3D 2 || staged_interface) + return -EINVAL; + + ret =3D ima_queue_stage(); + break; + case 'D': + if (datalen !=3D 2 || !staged_interface) + return -EINVAL; + + ret =3D ima_queue_staged_delete_all(); + break; + default: + ret =3D -EINVAL; + } + + if (ret < 0) + return ret; + + return datalen; +} + +static ssize_t ima_measurements_write(struct file *file, const char __user= *buf, + size_t datalen, loff_t *ppos) +{ + return _ima_measurements_write(file, buf, datalen, ppos, false); +} + +static ssize_t ima_measurements_staged_write(struct file *file, + const char __user *buf, + size_t datalen, loff_t *ppos) +{ + return _ima_measurements_write(file, buf, datalen, ppos, true); +} + static const struct file_operations ima_measurements_ops =3D { .open =3D ima_measurements_open, .read =3D seq_read, + .write =3D ima_measurements_write, + .llseek =3D seq_lseek, + .release =3D ima_measurements_release, +}; + +static const struct file_operations ima_measurements_staged_ops =3D { + .open =3D ima_measurements_staged_open, + .read =3D seq_read, + .write =3D ima_measurements_staged_write, .llseek =3D seq_lseek, .release =3D ima_measurements_release, }; @@ -352,6 +446,29 @@ static int ima_ascii_measurements_open(struct inode *i= node, struct file *file) static const struct file_operations ima_ascii_measurements_ops =3D { .open =3D ima_ascii_measurements_open, .read =3D seq_read, + .write =3D ima_measurements_write, + .llseek =3D seq_lseek, + .release =3D ima_measurements_release, +}; + +static const struct seq_operations ima_ascii_measurements_staged_seqops = =3D { + .start =3D ima_measurements_staged_start, + .next =3D ima_measurements_staged_next, + .stop =3D ima_measurements_stop, + .show =3D ima_ascii_measurements_show +}; + +static int ima_ascii_measurements_staged_open(struct inode *inode, + struct file *file) +{ + return _ima_measurements_open(inode, file, + &ima_ascii_measurements_staged_seqops); +} + +static const struct file_operations ima_ascii_measurements_staged_ops =3D { + .open =3D ima_ascii_measurements_staged_open, + .read =3D seq_read, + .write =3D ima_measurements_staged_write, .llseek =3D seq_lseek, .release =3D ima_measurements_release, }; @@ -459,10 +576,20 @@ static const struct seq_operations ima_policy_seqops = =3D { }; #endif =20 -static int __init create_securityfs_measurement_lists(void) +static int __init create_securityfs_measurement_lists(bool staging) { + const struct file_operations *ascii_ops =3D &ima_ascii_measurements_ops; + const struct file_operations *binary_ops =3D &ima_measurements_ops; + mode_t permissions =3D (S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP); + const char *file_suffix =3D ""; int count =3D NR_BANKS(ima_tpm_chip); =20 + if (staging) { + ascii_ops =3D &ima_ascii_measurements_staged_ops; + binary_ops =3D &ima_measurements_staged_ops; + file_suffix =3D "_staged"; + } + if (ima_sha1_idx >=3D NR_BANKS(ima_tpm_chip)) count++; =20 @@ -473,29 +600,32 @@ static int __init create_securityfs_measurement_lists= (void) =20 if (algo =3D=3D HASH_ALGO__LAST) snprintf(file_name, sizeof(file_name), - "ascii_runtime_measurements_tpm_alg_%x", - ima_tpm_chip->allocated_banks[i].alg_id); + "ascii_runtime_measurements_tpm_alg_%x%s", + ima_tpm_chip->allocated_banks[i].alg_id, + file_suffix); else snprintf(file_name, sizeof(file_name), - "ascii_runtime_measurements_%s", - hash_algo_name[algo]); - dentry =3D securityfs_create_file(file_name, S_IRUSR | S_IRGRP, + "ascii_runtime_measurements_%s%s", + hash_algo_name[algo], file_suffix); + dentry =3D securityfs_create_file(file_name, permissions, ima_dir, (void *)(uintptr_t)i, - &ima_ascii_measurements_ops); + ascii_ops); if (IS_ERR(dentry)) return PTR_ERR(dentry); =20 if (algo =3D=3D HASH_ALGO__LAST) snprintf(file_name, sizeof(file_name), - "binary_runtime_measurements_tpm_alg_%x", - ima_tpm_chip->allocated_banks[i].alg_id); + "binary_runtime_measurements_tpm_alg_%x%s", + ima_tpm_chip->allocated_banks[i].alg_id, + file_suffix); else snprintf(file_name, sizeof(file_name), - "binary_runtime_measurements_%s", - hash_algo_name[algo]); - dentry =3D securityfs_create_file(file_name, S_IRUSR | S_IRGRP, + "binary_runtime_measurements_%s%s", + hash_algo_name[algo], file_suffix); + + dentry =3D securityfs_create_file(file_name, permissions, ima_dir, (void *)(uintptr_t)i, - &ima_measurements_ops); + binary_ops); if (IS_ERR(dentry)) return PTR_ERR(dentry); } @@ -503,6 +633,23 @@ static int __init create_securityfs_measurement_lists(= void) return 0; } =20 +static int __init create_securityfs_staging_links(void) +{ + struct dentry *dentry; + + dentry =3D securityfs_create_symlink("binary_runtime_measurements_staged", + ima_dir, "binary_runtime_measurements_sha1_staged", NULL); + if (IS_ERR(dentry)) + return PTR_ERR(dentry); + + dentry =3D securityfs_create_symlink("ascii_runtime_measurements_staged", + ima_dir, "ascii_runtime_measurements_sha1_staged", NULL); + if (IS_ERR(dentry)) + return PTR_ERR(dentry); + + return 0; +} + /* * ima_open_policy: sequentialize access to the policy file */ @@ -595,7 +742,13 @@ int __init ima_fs_init(void) goto out; } =20 - ret =3D create_securityfs_measurement_lists(); + ret =3D create_securityfs_measurement_lists(false); + if (ret =3D=3D 0 && IS_ENABLED(CONFIG_IMA_STAGING)) { + ret =3D create_securityfs_measurement_lists(true); + if (ret =3D=3D 0) + ret =3D create_securityfs_staging_links(); + } + if (ret !=3D 0) goto out; =20 diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/im= a_kexec.c index d7d0fb639d99..064cfce0c318 100644 --- a/security/integrity/ima/ima_kexec.c +++ b/security/integrity/ima/ima_kexec.c @@ -42,8 +42,8 @@ void ima_measure_kexec_event(const char *event_name) long len; int n; =20 - buf_size =3D ima_get_binary_runtime_size(BINARY); - len =3D atomic_long_read(&ima_num_entries[BINARY]); + buf_size =3D ima_get_binary_runtime_size(BINARY_FULL); + len =3D atomic_long_read(&ima_num_entries[BINARY_FULL]); =20 n =3D scnprintf(ima_kexec_event, IMA_KEXEC_EVENT_LEN, "kexec_segment_size=3D%lu;ima_binary_runtime_size=3D%lu;" @@ -106,13 +106,28 @@ static int ima_dump_measurement_list(unsigned long *b= uffer_size, void **buffer, =20 memset(&khdr, 0, sizeof(khdr)); khdr.version =3D 1; - /* This is an append-only list, no need to hold the RCU read lock */ - list_for_each_entry_rcu(qe, &ima_measurements, later, true) { + /* + * It can race with ima_queue_stage() and ima_queue_staged_delete_all(). + */ + mutex_lock(&ima_extend_list_mutex); + + list_for_each_entry_rcu(qe, &ima_measurements_staged, later, + lockdep_is_held(&ima_extend_list_mutex)) { ret =3D ima_dump_measurement(&khdr, qe); if (ret < 0) break; } =20 + list_for_each_entry_rcu(qe, &ima_measurements, later, + lockdep_is_held(&ima_extend_list_mutex)) { + if (!ret) + ret =3D ima_dump_measurement(&khdr, qe); + if (ret < 0) + break; + } + + mutex_unlock(&ima_extend_list_mutex); + /* * fill in reserved space with some buffer details * (eg. version, buffer size, number of measurements) @@ -167,6 +182,7 @@ void ima_add_kexec_buffer(struct kimage *image) extra_memory =3D CONFIG_IMA_KEXEC_EXTRA_MEMORY_KB * 1024; =20 binary_runtime_size =3D ima_get_binary_runtime_size(BINARY) + + ima_get_binary_runtime_size(BINARY_STAGED) + extra_memory; =20 if (binary_runtime_size >=3D ULONG_MAX - PAGE_SIZE) diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/im= a_queue.c index b6d10dceb669..50519ed837d4 100644 --- a/security/integrity/ima/ima_queue.c +++ b/security/integrity/ima/ima_queue.c @@ -26,6 +26,7 @@ static struct tpm_digest *digests; =20 LIST_HEAD(ima_measurements); /* list of all measurements */ +LIST_HEAD(ima_measurements_staged); /* list of staged measurements */ #ifdef CONFIG_IMA_KEXEC static unsigned long binary_runtime_size[BINARY__LAST]; #else @@ -45,11 +46,11 @@ atomic_long_t ima_num_violations =3D ATOMIC_LONG_INIT(0= ); /* key: inode (before secure-hashing a file) */ struct hlist_head __rcu *ima_htable; =20 -/* mutex protects atomicity of extending measurement list +/* mutex protects atomicity of extending and staging measurement list * and extending the TPM PCR aggregate. Since tpm_extend can take * long (and the tpm driver uses a mutex), we can't use the spinlock. */ -static DEFINE_MUTEX(ima_extend_list_mutex); +DEFINE_MUTEX(ima_extend_list_mutex); =20 /* * Used internally by the kernel to suspend measurements. @@ -174,12 +175,16 @@ static int ima_add_digest_entry(struct ima_template_e= ntry *entry, lockdep_is_held(&ima_extend_list_mutex)); =20 atomic_long_inc(&ima_num_entries[BINARY]); + atomic_long_inc(&ima_num_entries[BINARY_FULL]); + if (update_htable) { key =3D ima_hash_key(entry->digests[ima_hash_algo_idx].digest); hlist_add_head_rcu(&qe->hnext, &htable[key]); } =20 ima_update_binary_runtime_size(entry, BINARY); + ima_update_binary_runtime_size(entry, BINARY_FULL); + return 0; } =20 @@ -280,6 +285,94 @@ int ima_add_template_entry(struct ima_template_entry *= entry, int violation, return result; } =20 +int ima_queue_stage(void) +{ + int ret =3D 0; + + mutex_lock(&ima_extend_list_mutex); + if (!list_empty(&ima_measurements_staged)) { + ret =3D -EEXIST; + goto out_unlock; + } + + if (list_empty(&ima_measurements)) { + ret =3D -ENOENT; + goto out_unlock; + } + + list_replace(&ima_measurements, &ima_measurements_staged); + INIT_LIST_HEAD(&ima_measurements); + + atomic_long_set(&ima_num_entries[BINARY_STAGED], + atomic_long_read(&ima_num_entries[BINARY])); + atomic_long_set(&ima_num_entries[BINARY], 0); + + if (IS_ENABLED(CONFIG_IMA_KEXEC)) { + binary_runtime_size[BINARY_STAGED] =3D + binary_runtime_size[BINARY]; + binary_runtime_size[BINARY] =3D 0; + } +out_unlock: + mutex_unlock(&ima_extend_list_mutex); + return ret; +} + +static void ima_queue_delete(struct list_head *head); + +int ima_queue_staged_delete_all(void) +{ + LIST_HEAD(ima_measurements_trim); + + mutex_lock(&ima_extend_list_mutex); + if (list_empty(&ima_measurements_staged)) { + mutex_unlock(&ima_extend_list_mutex); + return -ENOENT; + } + + list_replace(&ima_measurements_staged, &ima_measurements_trim); + INIT_LIST_HEAD(&ima_measurements_staged); + + atomic_long_set(&ima_num_entries[BINARY_STAGED], 0); + + if (IS_ENABLED(CONFIG_IMA_KEXEC)) + binary_runtime_size[BINARY_STAGED] =3D 0; + + mutex_unlock(&ima_extend_list_mutex); + + ima_queue_delete(&ima_measurements_trim); + return 0; +} + +static void ima_queue_delete(struct list_head *head) +{ + struct ima_queue_entry *qe, *qe_tmp; + unsigned int i; + + list_for_each_entry_safe(qe, qe_tmp, head, later) { + /* + * Safe to free template_data here without synchronize_rcu() + * because the only htable reader, ima_lookup_digest_entry(), + * accesses only entry->digests, not template_data. If new + * htable readers are added that access template_data, a + * synchronize_rcu() is required here. + */ + for (i =3D 0; i < qe->entry->template_desc->num_fields; i++) { + kfree(qe->entry->template_data[i].data); + qe->entry->template_data[i].data =3D NULL; + qe->entry->template_data[i].len =3D 0; + } + + list_del(&qe->later); + + /* No leak if condition is false, referenced by ima_htable. */ + if (IS_ENABLED(CONFIG_IMA_DISABLE_HTABLE)) { + kfree(qe->entry->digests); + kfree(qe->entry); + kfree(qe); + } + } +} + int ima_restore_measurement_entry(struct ima_template_entry *entry) { int result =3D 0; --=20 2.43.0 From nobody Sat Jun 13 04:53:58 2026 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 78B5A3859F9; Wed, 29 Apr 2026 16:06:13 +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=1777478779; cv=none; b=dNy6/yffeFjg9aEB7E77crtolduqg+1J+scPsRV5Fbrv83rZhzfwjHS3xNKI8u6b22MYlyd4J7YxxFEWtLRaGGSCgNStAtcErLVRJcKu0ylpbzWGwNdyneYwriVv7jSfGrZNQ6vwXoDgcza/MO6uRO+7UXTyOoazXiBknBaTpEk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777478779; c=relaxed/simple; bh=gfs60nu77haj0uHnBta0PUQkspPBlJkNZsDH5x8r6t0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=RTJQJPk12aU9xBrR5Cwmj6nH9bDZyg0PAWOWcp0WJJqiR2rlgrlu3RWDNM7OYLpiWNbYwsprWyCRqDzEi99Bv1q2jkqQlzGFLKlOqDhhn4UbyZPnCTjsheZ6eiZI749DowLqoZzTv3/PccnJJbFSOYPfehQBhcjIQ5aaQsgBW5M= 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.224.235]) by frasgout13.his.huawei.com (SkyGuard) with ESMTPS id 4g5MVs1SyTzpSwl; Thu, 30 Apr 2026 00:01:41 +0800 (CST) Received: from mail02.huawei.com (unknown [7.182.16.27]) by mail.maildlp.com (Postfix) with ESMTP id 67E7D40560; Thu, 30 Apr 2026 00:06:11 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP2 (Coremail) with SMTP id GxC2BwC3rWlpLPJp2RNBAA--.11842S2; Wed, 29 Apr 2026 17:06:10 +0100 (CET) From: Roberto Sassu To: corbet@lwn.net, skhan@linuxfoundation.org, zohar@linux.ibm.com, dmitry.kasatkin@gmail.com, eric.snowberg@oracle.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com Cc: linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, gregorylumen@linux.microsoft.com, chenste@linux.microsoft.com, nramas@linux.microsoft.com, Roberto Sassu Subject: [PATCH v5 10/13] ima: Add support for flushing the hash table when staging measurements Date: Wed, 29 Apr 2026 18:03:16 +0200 Message-ID: <20260429160319.4162918-11-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260429160319.4162918-1-roberto.sassu@huaweicloud.com> References: <20260429160319.4162918-1-roberto.sassu@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: GxC2BwC3rWlpLPJp2RNBAA--.11842S2 X-Coremail-Antispam: 1UD129KBjvJXoWxJF1xtFyruFWrJw4UXFWDArb_yoWrAFWUpa yDWry8KrZ5JF1Igry8ArZayFya9397WF1UG3yrG3s5AF15Xr4jgr1akryS9Fn5uryrtF1f trsIqr4Yya1ftrJanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUvvb4IE77IF4wAFF20E14v26ryj6rWUM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28lY4IEw2IIxxk0rwA2F7IY1VAKz4 vEj48ve4kI8wA2z4x0Y4vE2Ix0cI8IcVAFwI0_Gr0_Xr1l84ACjcxK6xIIjxv20xvEc7Cj xVAFwI0_Gr1j6F4UJwA2z4x0Y4vEx4A2jsIE14v26r4j6F4UM28EF7xvwVC2z280aVCY1x 0267AKxVW8Jr0_Cr1UM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02 F40Ex7xfMcIj6xIIjxv20xvE14v26r106r15McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4I kC6x0Yz7v_Jr0_Gr1lF7xvr2IYc2Ij64vIr41lFIxGxcIEc7CjxVA2Y2ka0xkIwI1lc7Cj xVAaw2AFwI0_Jw0_GFyl42xK82IYc2Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2 IqxVAqx4xG67AKxVWUJVWUGwC20s026x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v2 6r4a6rW5MIIYrxkI7VAKI48JMIIF0xvE2Ix0cI8IcVAFwI0_Gr0_Xr1lIxAIcVC0I7IYx2 IY6xkF7I0E14v26r4UJVWxJr1lIxAIcVCF04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2 jsIE14v26r4j6F4UMIIF0xvEx4A2jsIEc7CjxVAFwI0_Gr1j6F4UJbIYCTnIWIevJa73Uj IFyTuYvjxUoYFADUUUU X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAgASBGnx6jEGHgAAsP Content-Type: text/plain; charset="utf-8" From: Roberto Sassu Introduce the new kernel option ima_flush_htable to decide whether or not the digests of staged measurement entries are flushed from the hash table, when they are deleted. When the option is enabled, replace the old hash table with a new one, by calling ima_alloc_replace_htable(), and completely delete the measurements entries. Note: This code derives from the Alt-IMA Huawei project, whose license is GPL-2.0 OR MIT. Link: https://github.com/linux-integrity/linux/issues/1 Signed-off-by: Roberto Sassu Tested-by: Stefan Berger --- .../admin-guide/kernel-parameters.txt | 4 +++ security/integrity/ima/ima.h | 1 + security/integrity/ima/ima_queue.c | 36 ++++++++++++++++--- 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentatio= n/admin-guide/kernel-parameters.txt index 4d0f545fb3ec..56efb8bfcc4e 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -2343,6 +2343,10 @@ Kernel parameters Use the canonical format for the binary runtime measurements, instead of host native format. =20 + ima_flush_htable [IMA] + Flush the IMA hash table when deleting all the + staged measurement entries. + ima_hash=3D [IMA] Format: { md5 | sha1 | rmd160 | sha256 | sha384 | sha512 | ... } diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index ca8fa43ec72b..4af66c1de4dc 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -341,6 +341,7 @@ extern atomic_long_t ima_num_entries[BINARY__LAST]; extern atomic_long_t ima_num_violations; extern struct hlist_head __rcu *ima_htable; extern struct mutex ima_extend_list_mutex; +extern bool ima_flush_htable; =20 static inline unsigned int ima_hash_key(u8 *digest) { diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/im= a_queue.c index 50519ed837d4..f5c18acfbc43 100644 --- a/security/integrity/ima/ima_queue.c +++ b/security/integrity/ima/ima_queue.c @@ -22,6 +22,20 @@ =20 #define AUDIT_CAUSE_LEN_MAX 32 =20 +bool ima_flush_htable; + +static int __init ima_flush_htable_setup(char *str) +{ + if (IS_ENABLED(CONFIG_IMA_DISABLE_HTABLE)) { + pr_warn("Hash table not enabled, ignoring request to flush\n"); + return 1; + } + + ima_flush_htable =3D true; + return 1; +} +__setup("ima_flush_htable", ima_flush_htable_setup); + /* pre-allocated array of tpm_digest structures to extend a PCR */ static struct tpm_digest *digests; =20 @@ -317,10 +331,11 @@ int ima_queue_stage(void) return ret; } =20 -static void ima_queue_delete(struct list_head *head); +static void ima_queue_delete(struct list_head *head, bool flush_htable); =20 int ima_queue_staged_delete_all(void) { + struct hlist_head *old_queue =3D NULL; LIST_HEAD(ima_measurements_trim); =20 mutex_lock(&ima_extend_list_mutex); @@ -337,13 +352,26 @@ int ima_queue_staged_delete_all(void) if (IS_ENABLED(CONFIG_IMA_KEXEC)) binary_runtime_size[BINARY_STAGED] =3D 0; =20 + if (ima_flush_htable) { + old_queue =3D ima_alloc_replace_htable(); + if (IS_ERR(old_queue)) { + mutex_unlock(&ima_extend_list_mutex); + return PTR_ERR(old_queue); + } + } + mutex_unlock(&ima_extend_list_mutex); =20 - ima_queue_delete(&ima_measurements_trim); + if (ima_flush_htable) { + synchronize_rcu(); + kfree(old_queue); + } + + ima_queue_delete(&ima_measurements_trim, ima_flush_htable); return 0; } =20 -static void ima_queue_delete(struct list_head *head) +static void ima_queue_delete(struct list_head *head, bool flush_htable) { struct ima_queue_entry *qe, *qe_tmp; unsigned int i; @@ -365,7 +393,7 @@ static void ima_queue_delete(struct list_head *head) list_del(&qe->later); =20 /* No leak if condition is false, referenced by ima_htable. */ - if (IS_ENABLED(CONFIG_IMA_DISABLE_HTABLE)) { + if (IS_ENABLED(CONFIG_IMA_DISABLE_HTABLE) || flush_htable) { kfree(qe->entry->digests); kfree(qe->entry); kfree(qe); --=20 2.43.0 From nobody Sat Jun 13 04:53:58 2026 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 32168388364; Wed, 29 Apr 2026 16:06:22 +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=1777478785; cv=none; b=NVhDeBFIqCPBe5pm5oenirfv3anGSdDZUSENjeAkCFK7yT5CavrmqtrD5uQafMJCAJvDC0ysWrYNhyhz6j1Pa36p4RD/eKw3NaQrPM+3OF89CsZ0mxuWTjz69gGgUhYtLiytor6+Kz7mjivaLv119L2SoAkH89TRKv2ZegkgPNA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777478785; c=relaxed/simple; bh=S1PnzrcZiFF2Muvhhg6xR2hu1pWceJZo3cff+Ua6lkk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=OfB5DielPRAd4wxhueobjvKGR9Q3Yu+lCSq8i3C/1ubWKuxcrFqwx0mFGHB832VTZb07sjqioGSy/EF+zx6syEe7WC3E5MgCzrKPCczXc6nAFsnMkI+Nbx4NIhTGUk80er0xxIvfrHfDRz2lEgy/OGXZ9GRLlXPXQSDc8yICyJI= 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.224.196]) by frasgout12.his.huawei.com (SkyGuard) with ESMTPS id 4g5MWH1Z48zvQkC; Thu, 30 Apr 2026 00:02:03 +0800 (CST) Received: from mail02.huawei.com (unknown [7.182.16.27]) by mail.maildlp.com (Postfix) with ESMTP id 1635D40562; Thu, 30 Apr 2026 00:06:19 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP2 (Coremail) with SMTP id GxC2BwC3rWlpLPJp2RNBAA--.11842S3; Wed, 29 Apr 2026 17:06:18 +0100 (CET) From: Roberto Sassu To: corbet@lwn.net, skhan@linuxfoundation.org, zohar@linux.ibm.com, dmitry.kasatkin@gmail.com, eric.snowberg@oracle.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com Cc: linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, gregorylumen@linux.microsoft.com, chenste@linux.microsoft.com, nramas@linux.microsoft.com, Roberto Sassu Subject: [PATCH v5 11/13] ima: Support staging and deleting N measurements entries Date: Wed, 29 Apr 2026 18:03:17 +0200 Message-ID: <20260429160319.4162918-12-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260429160319.4162918-1-roberto.sassu@huaweicloud.com> References: <20260429160319.4162918-1-roberto.sassu@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: GxC2BwC3rWlpLPJp2RNBAA--.11842S3 X-Coremail-Antispam: 1UD129KBjvJXoWxKFykWFyrKr15JFW3ZFy7Wrg_yoWxtr17pa 9Iga48Gry8JryfKr97J3Z7Cr4F93ykGF1UGwsxGasFyF13XFyUurnxCry29r4rCr95JFyx twsIqrs8Ca1DtFJanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUPqb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUGw A2048vs2IY020Ec7CjxVAFwI0_Gr0_Xr1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxS w2x7M28EF7xvwVC0I7IYx2IY67AKxVW8JVW5JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxV W8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_Gr0_Cr1l84ACjcxK6I8E87Iv6xkF7I0E14v2 6r4UJVWxJr1le2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrVC2j2 WlYx0E2Ix0cI8IcVAFwI0_JrI_JrylYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE7xkE bVWUJVW8JwACjcxG0xvY0x0EwIxGrwACI402YVCY1x02628vn2kIc2xKxwCY1x0262kKe7 AKxVWUtVW8ZwCF04k20xvY0x0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02 F40E14v26r1j6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_GFv_Wr ylIxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVW8JVW5JwCI42IY6xIIjxv20xvEc7Cj xVAFwI0_Gr1j6F4UJwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI 0_Gr0_Cr1lIxAIcVC2z280aVCY1x0267AKxVW8Jr0_Cr1UYxBIdaVFxhVjvjDU0xZFpf9x 07jjuWdUUUUU= X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAQASBGnx6jgGJAAAs- Content-Type: text/plain; charset="utf-8" From: Roberto Sassu Add support for sending a value N between 1 and ULONG_MAX to the IMA original measurement interface. This value represents the number of measurements that should be deleted from the current measurements list. In this case, measurements are staged in an internal non-user visible list, and immediately deleted. This staging method allows the remote attestation agents to easily separate the measurements that were verified (staged and deleted) from those that weren't due to the race between taking a TPM quote and reading the measurements list. In order to minimize the locking time of ima_extend_list_mutex, deleting N entries is realized by doing a lockless walk in the current measurements list to determine the N-th entry to cut, to cut the current measurements list under the lock, and by deleting the excess entries after releasing the lock. Flushing the hash table is not supported for N entries, since it would require removing the N entries one by one from the hash table under the ima_extend_list_mutex lock, which would increase the locking time. The ima_extend_list_mutex lock is necessary in ima_dump_measurement_list() because ima_queue_delete_partial() uses __list_cut_position() to modify ima_measurements, for which no RCU-safe variant exists. For the staging with prompt flavor alone, list_replace_rcu() could have been used instead, but since both flavors share the same kexec serialization path, the mutex is required regardless. Link: https://github.com/linux-integrity/linux/issues/1 Suggested-by: Steven Chen Signed-off-by: Roberto Sassu Reviewed-by: Mimi Zohar Reviewed-by: Steven Chen Tested-by: Stefan Berger Tested-by: Steven Chen --- security/integrity/ima/Kconfig | 3 +++ security/integrity/ima/ima.h | 1 + security/integrity/ima/ima_fs.c | 21 ++++++++++++++- security/integrity/ima/ima_kexec.c | 3 ++- security/integrity/ima/ima_queue.c | 43 ++++++++++++++++++++++++++++++ 5 files changed, 69 insertions(+), 2 deletions(-) diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig index 48c906793efb..4f4373859a4f 100644 --- a/security/integrity/ima/Kconfig +++ b/security/integrity/ima/Kconfig @@ -341,6 +341,9 @@ config IMA_STAGING It allows user space to stage the measurements list for deletion and to delete the staged measurements after confirmation. =20 + Or, alternatively, it allows user space to specify N measurements + entries to stage internally, so that they can be immediately deleted. + On kexec, staging is reverted and staged measurements are prepended to the current measurements list when measurements are copied to the secondary kernel. diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 4af66c1de4dc..9a741b33d524 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -320,6 +320,7 @@ struct ima_template_desc *lookup_template_desc(const ch= ar *name); bool ima_template_has_modsig(const struct ima_template_desc *ima_template); int ima_queue_stage(void); int ima_queue_staged_delete_all(void); +int ima_queue_delete_partial(unsigned long req_value); int ima_restore_measurement_entry(struct ima_template_entry *entry); int ima_restore_measurement_list(loff_t bufsize, void *buf); int ima_measurements_show(struct seq_file *m, void *v); diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_f= s.c index 088d5a69aa92..6843dc203b54 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -28,6 +28,7 @@ * Requests: * 'A\n': stage the entire measurements list * 'D\n': delete all staged measurements + * '[1, ULONG_MAX]\n' delete N measurements entries */ #define STAGED_REQ_LENGTH 21 =20 @@ -312,6 +313,7 @@ static ssize_t _ima_measurements_write(struct file *fil= e, loff_t *ppos, bool staged_interface) { char req[STAGED_REQ_LENGTH]; + unsigned long req_value; int ret; =20 if (*ppos > 0 || datalen < 2 || datalen > STAGED_REQ_LENGTH) @@ -339,7 +341,24 @@ static ssize_t _ima_measurements_write(struct file *fi= le, ret =3D ima_queue_staged_delete_all(); break; default: - ret =3D -EINVAL; + if (staged_interface) + return -EINVAL; + + if (ima_flush_htable) { + pr_debug("Deleting staged N measurements not supported when flushing th= e hash table is requested\n"); + return -EINVAL; + } + + ret =3D kstrtoul(req, 10, &req_value); + if (ret < 0) + return ret; + + if (req_value =3D=3D 0) { + pr_debug("Must delete at least one entry\n"); + return -EINVAL; + } + + ret =3D ima_queue_delete_partial(req_value); } =20 if (ret < 0) diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/im= a_kexec.c index 064cfce0c318..e7bde3d917b2 100644 --- a/security/integrity/ima/ima_kexec.c +++ b/security/integrity/ima/ima_kexec.c @@ -107,7 +107,8 @@ static int ima_dump_measurement_list(unsigned long *buf= fer_size, void **buffer, memset(&khdr, 0, sizeof(khdr)); khdr.version =3D 1; /* - * It can race with ima_queue_stage() and ima_queue_staged_delete_all(). + * It can race with ima_queue_stage(), ima_queue_staged_delete_all() + * and ima_queue_delete_partial(). */ mutex_lock(&ima_extend_list_mutex); =20 diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/im= a_queue.c index f5c18acfbc43..64c4fe73dd5f 100644 --- a/security/integrity/ima/ima_queue.c +++ b/security/integrity/ima/ima_queue.c @@ -371,6 +371,49 @@ int ima_queue_staged_delete_all(void) return 0; } =20 +int ima_queue_delete_partial(unsigned long req_value) +{ + unsigned long req_value_copy =3D req_value; + unsigned long size_to_remove =3D 0, num_to_remove =3D 0; + LIST_HEAD(ima_measurements_trim); + struct ima_queue_entry *qe; + int ret =3D 0; + + /* + * Safe to walk without rcu_read_lock(): single-writer + * exclusion in ima_fs.c prevents any concurrent modification + * to ima_measurements during this walk. + */ + list_for_each_entry_rcu(qe, &ima_measurements, later, true) { + size_to_remove +=3D get_binary_runtime_size(qe->entry); + num_to_remove++; + + if (--req_value_copy =3D=3D 0) + break; + } + + /* Not enough entries to delete. */ + if (req_value_copy > 0) + return -ENOENT; + + mutex_lock(&ima_extend_list_mutex); + /* + * qe remains valid because ima_fs.c enforces single-writer exclusion. + */ + __list_cut_position(&ima_measurements_trim, &ima_measurements, + &qe->later); + + atomic_long_sub(num_to_remove, &ima_num_entries[BINARY]); + + if (IS_ENABLED(CONFIG_IMA_KEXEC)) + binary_runtime_size[BINARY] -=3D size_to_remove; + + mutex_unlock(&ima_extend_list_mutex); + + ima_queue_delete(&ima_measurements_trim, false); + return ret; +} + static void ima_queue_delete(struct list_head *head, bool flush_htable) { struct ima_queue_entry *qe, *qe_tmp; --=20 2.43.0 From nobody Sat Jun 13 04:53:58 2026 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 0AC3E3859F9; Wed, 29 Apr 2026 16:06:28 +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=1777478804; cv=none; b=JRkkJZSfVivPw27Ehbdi3XghPPNnJL4oWKm0kYiu/oaMO8wSNezx5aropNmHgdCnrF+00MNtjIqrUQzQ+N+DPvXaLpXFpTPLjE4f//aGUHGD6UAnd4NreCmYHh+VC8dWdWkSFH1Th8GVa1zzzaDY8t+XkNA7Ijxgtooi8PrCor0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777478804; c=relaxed/simple; bh=XpSOz3g/ZHv1XrTBg+oShdF7wJ4s6tJ9FLb9BqKftGc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Qni8hrpUDnEMqxEL6D0SnyGeBJgEHoVc3LpVRDosWwoiA2r0mDkWeQuYZ9G1MobOGEOSeu9J9ZpoHTenFFzXJvtjSN5E0eG9ey2D6NffKPkbpPm7uTxOzdVKPhaA5knfMsaatA6fPXcuhesREvrS4513TdUPmRMNVLMMlSyxUw0= 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.224.235]) by frasgout11.his.huawei.com (SkyGuard) with ESMTPS id 4g5MW76K8Lz1HCGR; Thu, 30 Apr 2026 00:01:55 +0800 (CST) Received: from mail02.huawei.com (unknown [7.182.16.27]) by mail.maildlp.com (Postfix) with ESMTP id B893A4056A; Thu, 30 Apr 2026 00:06:26 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP2 (Coremail) with SMTP id GxC2BwC3rWlpLPJp2RNBAA--.11842S4; Wed, 29 Apr 2026 17:06:26 +0100 (CET) From: Roberto Sassu To: corbet@lwn.net, skhan@linuxfoundation.org, zohar@linux.ibm.com, dmitry.kasatkin@gmail.com, eric.snowberg@oracle.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com Cc: linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, gregorylumen@linux.microsoft.com, chenste@linux.microsoft.com, nramas@linux.microsoft.com, Roberto Sassu Subject: [PATCH v5 12/13] ima: Return error on deleting measurements already copied during kexec Date: Wed, 29 Apr 2026 18:03:18 +0200 Message-ID: <20260429160319.4162918-13-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260429160319.4162918-1-roberto.sassu@huaweicloud.com> References: <20260429160319.4162918-1-roberto.sassu@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: GxC2BwC3rWlpLPJp2RNBAA--.11842S4 X-Coremail-Antispam: 1UD129KBjvJXoWxJF1fXrW3Jr1DGr45GFW3ZFb_yoW5tw4kpa sI9Fy7GryUJFyI9r97AF9xC3yfu3yrWF4UGw43C3WvkFyrXF1j9rn3Cw12kFn5GrZ5JFyx tw4Yqrs8Ca1DtFJanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUPqb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUXw A2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxS w2x7M28EF7xvwVC0I7IYx2IY67AKxVW8JVW5JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxV W8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_Gr0_Cr1l84ACjcxK6I8E87Iv6xkF7I0E14v2 6r4UJVWxJr1le2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrVC2j2 WlYx0E2Ix0cI8IcVAFwI0_JrI_JrylYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE7xkE bVWUJVW8JwACjcxG0xvY0x0EwIxGrwACI402YVCY1x02628vn2kIc2xKxwCY1x0262kKe7 AKxVWUtVW8ZwCF04k20xvY0x0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02 F40E14v26r1j6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_GFv_Wr ylIxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVW8JVW5JwCI42IY6xIIjxv20xvEc7Cj xVAFwI0_Gr1j6F4UJwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI 0_Gr0_Cr1lIxAIcVC2z280aVCY1x0267AKxVW8Jr0_Cr1UYxBIdaVFxhVjvjDU0xZFpf9x 07Ud5rcUUUUU= X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAQASBGnx6jgGJAABs+ Content-Type: text/plain; charset="utf-8" From: Roberto Sassu Refuse to delete staged or active list measurements, if a kexec racing with the deletion already copied those measurements in the kexec buffer. In this way, user space becomes aware that those measurements are going to appear in the secondary kernel, and thus they don't have to be saved twice. Link: https://github.com/linux-integrity/linux/issues/1 Signed-off-by: Roberto Sassu Tested-by: Stefan Berger --- security/integrity/ima/ima.h | 5 +++++ security/integrity/ima/ima_kexec.c | 6 ++++++ security/integrity/ima/ima_queue.c | 17 +++++++++++++++++ 3 files changed, 28 insertions(+) diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 9a741b33d524..9be4c35d7ec1 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -344,6 +344,11 @@ extern struct hlist_head __rcu *ima_htable; extern struct mutex ima_extend_list_mutex; extern bool ima_flush_htable; =20 +#define IMA_MEASUREMENTS_STAGED_COPIED 1 +#define IMA_MEASUREMENTS_COPIED 2 + +extern u8 ima_copied_flags; + static inline unsigned int ima_hash_key(u8 *digest) { /* there is no point in taking a hash of part of a digest */ diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/im= a_kexec.c index e7bde3d917b2..5c7abde114f2 100644 --- a/security/integrity/ima/ima_kexec.c +++ b/security/integrity/ima/ima_kexec.c @@ -119,6 +119,9 @@ static int ima_dump_measurement_list(unsigned long *buf= fer_size, void **buffer, break; } =20 + if (!list_empty(&ima_measurements_staged)) + ima_copied_flags |=3D IMA_MEASUREMENTS_STAGED_COPIED; + list_for_each_entry_rcu(qe, &ima_measurements, later, lockdep_is_held(&ima_extend_list_mutex)) { if (!ret) @@ -127,6 +130,9 @@ static int ima_dump_measurement_list(unsigned long *buf= fer_size, void **buffer, break; } =20 + if (!list_empty(&ima_measurements)) + ima_copied_flags |=3D IMA_MEASUREMENTS_COPIED; + mutex_unlock(&ima_extend_list_mutex); =20 /* diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/im= a_queue.c index 64c4fe73dd5f..7f09cce53772 100644 --- a/security/integrity/ima/ima_queue.c +++ b/security/integrity/ima/ima_queue.c @@ -72,6 +72,13 @@ DEFINE_MUTEX(ima_extend_list_mutex); */ static bool ima_measurements_suspended; =20 +/* + * Used to determine if staged or active list measurements were copied dur= ing + * kexec, so that an error can be sent to user space during deletion, and = they + * don't store those measurements twice. + */ +u8 ima_copied_flags; + /* Callers must call synchronize_rcu() and free the hash table. */ static struct hlist_head *ima_alloc_replace_htable(void) { @@ -344,6 +351,11 @@ int ima_queue_staged_delete_all(void) return -ENOENT; } =20 + if (ima_copied_flags & IMA_MEASUREMENTS_STAGED_COPIED) { + mutex_unlock(&ima_extend_list_mutex); + return -ESTALE; + } + list_replace(&ima_measurements_staged, &ima_measurements_trim); INIT_LIST_HEAD(&ima_measurements_staged); =20 @@ -397,6 +409,11 @@ int ima_queue_delete_partial(unsigned long req_value) return -ENOENT; =20 mutex_lock(&ima_extend_list_mutex); + if (ima_copied_flags & IMA_MEASUREMENTS_COPIED) { + mutex_unlock(&ima_extend_list_mutex); + return -ESTALE; + } + /* * qe remains valid because ima_fs.c enforces single-writer exclusion. */ --=20 2.43.0 From nobody Sat Jun 13 04:53:58 2026 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 254DE386439; Wed, 29 Apr 2026 16:06:36 +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=1777478801; cv=none; b=JCikYthEhr+F12M4ZPXeaiL8uvRA82+0nDhMCKldBlCd8e6hiZMqivj7sSe2SHMTamTgV5XatB9czWInzDmAc9NsYtjolCOQ/ly9yXvsbqCZW+TW5WWuvDxK0n3T71Y2FhjF/sCW54hLKLYv4HN46w4uehUG8kFRJB9E5DleNjA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777478801; c=relaxed/simple; bh=udkiGPvoFK9xj/NIixWnyYrvzD7LNLsgzhYBzJesNvM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=tb6AoX5WYgDOmbxeYvFzhnIFPc42+JlXs9kFuizKMbijPv5QRttD2B+KNMAjzPjbA0xm4YHOGlGWercEWlk9CF/q0lnahN/qeTZFpCfG/0bNyrrFgYWbGpuKn0k6rsuAC+9G+0ZlS1zn2b5zfyVKeNoD7nv8usykkjMHXc0YdDM= 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.224.196]) by frasgout12.his.huawei.com (SkyGuard) with ESMTPS id 4g5MWZ3yMMzvQdx; Thu, 30 Apr 2026 00:02:18 +0800 (CST) Received: from mail02.huawei.com (unknown [7.182.16.27]) by mail.maildlp.com (Postfix) with ESMTP id 671B940565; Thu, 30 Apr 2026 00:06:34 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP2 (Coremail) with SMTP id GxC2BwC3rWlpLPJp2RNBAA--.11842S5; Wed, 29 Apr 2026 17:06:33 +0100 (CET) From: Roberto Sassu To: corbet@lwn.net, skhan@linuxfoundation.org, zohar@linux.ibm.com, dmitry.kasatkin@gmail.com, eric.snowberg@oracle.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com Cc: linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, gregorylumen@linux.microsoft.com, chenste@linux.microsoft.com, nramas@linux.microsoft.com, Roberto Sassu Subject: [PATCH v5 13/13] doc: security: Add documentation of the IMA staging mechanism Date: Wed, 29 Apr 2026 18:03:19 +0200 Message-ID: <20260429160319.4162918-14-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260429160319.4162918-1-roberto.sassu@huaweicloud.com> References: <20260429160319.4162918-1-roberto.sassu@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: GxC2BwC3rWlpLPJp2RNBAA--.11842S5 X-Coremail-Antispam: 1UD129KBjvJXoW3XFW7Xw18WrWftr4rCry7Awb_yoWfJF1fpa 9IgFyfGwn5Ja4xJwn5Jw1xGr4ru3yrGa1UGrn7tw1xtFn8Wryvvr4akrWY9FsxKr1vvryY v3ZFvr45Cw4qqFJanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUPqb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUWw A2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxS w2x7M28EF7xvwVC0I7IYx2IY67AKxVW8JVW5JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxV W8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_Gr0_Cr1l84ACjcxK6I8E87Iv6xkF7I0E14v2 6r4UJVWxJr1le2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrVC2j2 WlYx0E2Ix0cI8IcVAFwI0_JrI_JrylYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE7xkE bVWUJVW8JwACjcxG0xvY0x0EwIxGrwACI402YVCY1x02628vn2kIc2xKxwCY1x0262kKe7 AKxVWUtVW8ZwCF04k20xvY0x0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02 F40E14v26r1j6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_GFv_Wr ylIxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVW8JVW5JwCI42IY6xIIjxv20xvEc7Cj xVAFwI0_Gr1j6F4UJwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI 0_Gr0_Cr1lIxAIcVC2z280aVCY1x0267AKxVW8Jr0_Cr1UYxBIdaVFxhVjvjDU0xZFpf9x 07UHnmiUUUUU= X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAQASBGnx6jgGJgAAs9 Content-Type: text/plain; charset="utf-8" From: Roberto Sassu Add the documentation of the IMA staging mechanism in Documentation/security/IMA-staging.rst. Also add the missing Documentation/security/IMA-templates.rst file in MAINTAINERS. Link: https://github.com/linux-integrity/linux/issues/1 Signed-off-by: Roberto Sassu Tested-by: Stefan Berger --- Documentation/security/IMA-staging.rst | 163 +++++++++++++++++++++++++ Documentation/security/index.rst | 1 + MAINTAINERS | 2 + 3 files changed, 166 insertions(+) create mode 100644 Documentation/security/IMA-staging.rst diff --git a/Documentation/security/IMA-staging.rst b/Documentation/securit= y/IMA-staging.rst new file mode 100644 index 000000000000..de6428893f0e --- /dev/null +++ b/Documentation/security/IMA-staging.rst @@ -0,0 +1,163 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +IMA Measurements Staging Mechanism +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + + +Introduction +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +The IMA measurements list is currently stored in the kernel memory. Memory +occupation grows linearly with the number of entries, and can become a +problem especially in environments with reduced resources. + +While there is an advantage in keeping the IMA measurements list in kernel +memory, so that it is always available for reading from the securityfs +interfaces, storing it elsewhere would make it possible to free precious +memory for other kernel components. + +Storing the IMA measurements list outside the kernel does not introduce +security issues, since its integrity is anyway protected by the TPM. + +Hence, the new IMA staging mechanism is introduced to allow user space +to remove the desired portion of the measurements list from the kernel. + + +Usage +=3D=3D=3D=3D=3D + +The IMA staging mechanism can be enabled from the kernel configuration with +the CONFIG_IMA_STAGING option. + +If it is enabled, IMA duplicates the current measurements interfaces (both +binary and ASCII), by adding the ``_staged`` file suffix. Both the original +and the staging interfaces gain the write permission for the root user and +group, but require the process to have CAP_SYS_ADMIN set. + +The staging mechanism supports two flavors. + + +Staging with prompt +~~~~~~~~~~~~~~~~~~~ + +The current measurements list is moved to a temporary staging area, and +staged measurements are deleted upon confirmation. + +This staging process is achieved with the following steps. + + 1. ``echo A > ``: the user requests IMA to stage the + entire measurements list; + 2. ``cat <_staged interface>``: the user reads the staged measurements; + 3. ``echo D > <_staged interface>``: the user requests IMA to delete + staged measurements. + + +Staging and deleting +~~~~~~~~~~~~~~~~~~~~ + +N measurements are staged to a temporary staging area, and immediately +deleted without further confirmation. + +This staging process is achieved with the following steps. + + 1. ``cat ``: the user reads the current measurements + list and determines what the value N for staging should be; + 2. ``echo N > ``: the user requests IMA to delete N + measurements from the current measurements list. + + +Interface Access +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +In order to avoid the IMA measurements list be suddenly truncated by the +staging mechanism during a read, or having multiple concurrent staging, a +semaphore-like locking scheme has been implemented on all the measurements +list interfaces. + +Multiple readers can access concurrently the original and staged +interfaces, and they can be in mutual exclusion with one writer. + +If an illegal access occurs, the open to the measurements list interface is +denied. + + +Management of Staged Measurements +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D + +Since with the staging mechanism measurement entries are removed from the +kernel, the user needs to save the staged ones in a storage and concatenate +them together, so that it can present them to remote attestation agents as +if staging was never done. + +Coordination is necessary in the case where there are multiple actors +requesting measurements to be staged. + +In the staging with prompt case, the measurement interfaces can be accessed +only by one actor (writer) at a time, so the others will get an error until +the former closes it. Since the actors don't care about N, when they gain +access to the interface, they will get all the staged measurements at the +time of their request. + +In the case of staging and deleting, coordination is more important, since +there is the risk that two actors unaware of each other compute the value N +on the current measurements list and request IMA to stage N twice. + + +Remote Attestation Agent Workflow +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D + +Users can choose the staging method they find more appropriate for their +workflow. + +If, as an example, a remote attestation agent would like to present to the +remote attestation server only the measurements that are required to +verify the TPM quote, its workflow would be the following. + +With staging with prompt, the agent stages the current measurements list, +reads and stores the measurements in a storage and immediately requests +IMA to delete the staged measurements from kernel memory. Afterwards, it +calculates N by replaying the PCR extend on the stored measurements until +the calculated PCRs match the quoted PCRs. It then keeps the measurements +in excess for the next attestation request. + +At the next attestation request, the agent performs the same steps above, +and concatenates the new measurements to the ones in excess from the +previous request. Also in this case, the agent replays the PCR extend until +it matches the currently quoted PCRs, keeps the measurements in excess and +presents the new N measurements entries to the remote attestation server. + +With the staging and deleting method, the agent reads the current +measurements list, calculates N and requests IMA to delete only those. The +measurements in excess are kept in the IMA measurements list and can be +retrieved at the next remote attestation request. + +Kexec +=3D=3D=3D=3D=3D + +In the event a kexec() system call occurs between staging and deleting, the +staged measurements entries are prepended to the current measurements list, +so that they are both available when the secondary kernel starts. In that +case, IMA returns an error to the user when attempting to delete staged +measurements to notify about their copy to the kexec buffer, so that the +user does not store them twice. + + +Hash table +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +By default, the template digest of staged measurement entries are kept in +kernel memory (only template data are freed), to be able to detect +duplicate entries independently of staging. + +The new kernel option ``ima_flush_htable`` has been introduced to +explicitly request a complete deletion of the staged measurements, for +maximum kernel memory saving. If the option has been specified, duplicate +entries are still avoided on entries of the current measurements list, +but there can be duplicates between different groups of staged +measurements. + +Flushing the hash table is supported only for the staging with prompt +flavor. For the staging and deleting flavor, it would have been necessary +to lock the hot path adding new measurements for the time needed to remove +each selected measurement individually. diff --git a/Documentation/security/index.rst b/Documentation/security/inde= x.rst index 3e0a7114a862..cec064dc1c83 100644 --- a/Documentation/security/index.rst +++ b/Documentation/security/index.rst @@ -8,6 +8,7 @@ Security Documentation credentials snp-tdx-threat-model IMA-templates + IMA-staging keys/index lsm lsm-development diff --git a/MAINTAINERS b/MAINTAINERS index 2fb1c75afd16..5bc816ab4a5b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12740,6 +12740,8 @@ R: Eric Snowberg L: linux-integrity@vger.kernel.org S: Supported T: git git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity= .git +F: Documentation/security/IMA-staging.rst +F: Documentation/security/IMA-templates.rst F: include/linux/secure_boot.h F: security/integrity/ F: security/integrity/ima/ --=20 2.43.0