public inbox for linux-security-module@vger.kernel.org
 help / color / mirror / Atom feed
From: steven chen <chenste@linux.microsoft.com>
To: Roberto Sassu <roberto.sassu@huaweicloud.com>,
	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, nramas@linux.microsoft.com,
	Roberto Sassu <roberto.sassu@huawei.com>
Subject: Re: [PATCH v4 11/13] ima: Support staging and deleting N measurements entries
Date: Thu, 26 Mar 2026 16:19:58 -0700	[thread overview]
Message-ID: <0e186faf-8111-4fd9-a7df-bff30f7fb20a@linux.microsoft.com> (raw)
In-Reply-To: <20260326173011.1191815-12-roberto.sassu@huaweicloud.com>

On 3/26/2026 10:30 AM, Roberto Sassu wrote:
> From: Roberto Sassu <roberto.sassu@huawei.com>
>
> Add support for sending a value N between 1 and ULONG_MAX to the staging
> interface. This value represents the number of measurements that should be
> deleted from the current measurements list.
>
> 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 staging the entire current measurements list
> (with the lock), by determining the N-th staged entry (without the lock),
> and by splicing the entries in excess back to the current measurements list
> (with the lock). Finally, the N entries are deleted (without 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_staged_delete_partial() uses __list_cut_position() to
> modify ima_measurements_staged, 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 <chenste@linux.microsoft.com>
> Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
> ---
>   security/integrity/ima/Kconfig     |  3 ++
>   security/integrity/ima/ima.h       |  1 +
>   security/integrity/ima/ima_fs.c    | 22 +++++++++-
>   security/integrity/ima/ima_queue.c | 70 ++++++++++++++++++++++++++++++
>   4 files changed, 95 insertions(+), 1 deletion(-)
>
> diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
> index e714726f3384..6ddb4e77bff5 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.
>   
> +	  Or, alternatively, it allows user space to specify N measurements
> +	  entries to be 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 699b735dec7d..de0693fce53c 100644
> --- a/security/integrity/ima/ima.h
> +++ b/security/integrity/ima/ima.h
> @@ -319,6 +319,7 @@ 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_queue_staged_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_fs.c
> index 39d9128e9f22..eb3f343c1138 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
>   
> @@ -319,6 +320,7 @@ static ssize_t ima_measurements_staged_write(struct file *file,
>   					     size_t datalen, loff_t *ppos)
>   {
>   	char req[STAGED_REQ_LENGTH];
> +	unsigned long req_value;
>   	int ret;
>   
>   	if (*ppos > 0 || datalen < 2 || datalen > STAGED_REQ_LENGTH)
> @@ -346,7 +348,25 @@ static ssize_t ima_measurements_staged_write(struct file *file,
>   		ret = ima_queue_staged_delete_all();
>   		break;
>   	default:
> -		ret = -EINVAL;
> +		if (ima_flush_htable) {
> +			pr_debug("Deleting staged N measurements not supported when flushing the hash table is requested\n");
> +			return -EINVAL;
> +		}
> +
> +		ret = kstrtoul(req, 10, &req_value);
> +		if (ret < 0)
> +			return ret;
> +
> +		if (req_value == 0) {
> +			pr_debug("Must delete at least one entry\n");
> +			return -EINVAL;
> +		}
> +
> +		ret = ima_queue_stage();
> +		if (ret < 0)
> +			return ret;
> +
> +		ret = ima_queue_staged_delete_partial(req_value);
The default processing is "Trim N" idea plus performance improvement.

Here do everything in one time. And this is what I said in v3.

[PATCH v3 1/3] ima: Remove ima_h_table structure 
<https://lore.kernel.org/linux-integrity/c61aeaa79929a98cb3a6d30835972891fac3570f.camel@linux.ibm.com/T/#t>


The important two parts of trimming is "trim N" and performance improvement.

The performance improvement include two parts:
     hash table staging
     active log list staging

And I think "Trim N" plus performance improvement is the right direction 
to go.
Lots of code for two steps "stage and trim" "stage" part can be removed.

Also race condition may happen if not holding the list all time in user 
space
during attestation period: from stage, read list, attestation and trimming.

So in order to improve the above user space lock time, "Trim T:N" can be 
used
not to hold list long in user space during attestation.

For Trim T:N, T represent total log trimmed since system boot up. Please 
refer to
https://lore.kernel.org/linux-integrity/20260205235849.7086-1-chenste@linux.microsoft.com/T/#t

Thanks,

Steven
>   	}
>   
>   	if (ret < 0)
> diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c
> index f5c18acfbc43..4fb557d61a88 100644
> --- a/security/integrity/ima/ima_queue.c
> +++ b/security/integrity/ima/ima_queue.c
> @@ -371,6 +371,76 @@ int ima_queue_staged_delete_all(void)
>   	return 0;
>   }
>   
> +int ima_queue_staged_delete_partial(unsigned long req_value)
> +{
> +	unsigned long req_value_copy = req_value;
> +	unsigned long size_to_remove = 0, num_to_remove = 0;
> +	struct list_head *cut_pos = NULL;
> +	LIST_HEAD(ima_measurements_trim);
> +	struct ima_queue_entry *qe;
> +	int ret = 0;
> +
> +	/*
> +	 * Safe walk (no concurrent write), not under ima_extend_list_mutex
> +	 * for performance reasons.
> +	 */
> +	list_for_each_entry(qe, &ima_measurements_staged, later) {
> +		size_to_remove += get_binary_runtime_size(qe->entry);
> +		num_to_remove++;
> +
> +		if (--req_value_copy == 0) {
> +			/* qe->later always points to a valid list entry. */
> +			cut_pos = &qe->later;
> +			break;
> +		}
> +	}
> +
> +	/* Nothing to remove, undoing staging. */
> +	if (req_value_copy > 0) {
> +		size_to_remove = 0;
> +		num_to_remove = 0;
> +		ret = -ENOENT;
> +	}
> +
> +	mutex_lock(&ima_extend_list_mutex);
> +	if (list_empty(&ima_measurements_staged)) {
> +		mutex_unlock(&ima_extend_list_mutex);
> +		return -ENOENT;
> +	}
> +
> +	if (cut_pos != NULL)
> +		/*
> +		 * ima_dump_measurement_list() does not modify the list,
> +		 * cut_pos remains the same even if it was computed before
> +		 * the lock.
> +		 */
> +		__list_cut_position(&ima_measurements_trim,
> +				    &ima_measurements_staged, cut_pos);
> +
> +	atomic_long_sub(num_to_remove, &ima_num_entries[BINARY_STAGED]);
> +	atomic_long_add(atomic_long_read(&ima_num_entries[BINARY_STAGED]),
> +			&ima_num_entries[BINARY]);
> +	atomic_long_set(&ima_num_entries[BINARY_STAGED], 0);
> +
> +	if (IS_ENABLED(CONFIG_IMA_KEXEC)) {
> +		binary_runtime_size[BINARY_STAGED] -= size_to_remove;
> +		binary_runtime_size[BINARY] +=
> +					binary_runtime_size[BINARY_STAGED];
> +		binary_runtime_size[BINARY_STAGED] = 0;
> +	}
> +
> +	/*
> +	 * Splice (prepend) any remaining non-deleted staged entries to the
> +	 * active list (RCU not needed, there cannot be concurrent readers).
> +	 */
> +	list_splice(&ima_measurements_staged, &ima_measurements);
> +	INIT_LIST_HEAD(&ima_measurements_staged);
> +	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;



  reply	other threads:[~2026-03-26 23:20 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-26 17:29 [PATCH v4 00/13] ima: Introduce staging mechanism Roberto Sassu
2026-03-26 17:29 ` [PATCH v4 01/13] ima: Remove ima_h_table structure Roberto Sassu
2026-03-26 17:30 ` [PATCH v4 02/13] ima: Replace static htable queue with dynamically allocated array Roberto Sassu
2026-03-26 17:30 ` [PATCH v4 03/13] ima: Introduce per binary measurements list type ima_num_entries counter Roberto Sassu
2026-03-26 17:30 ` [PATCH v4 04/13] ima: Introduce per binary measurements list type binary_runtime_size value Roberto Sassu
2026-03-26 17:30 ` [PATCH v4 05/13] ima: Introduce _ima_measurements_start() and _ima_measurements_next() Roberto Sassu
2026-03-26 17:30 ` [PATCH v4 06/13] ima: Mediate open/release method of the measurements list Roberto Sassu
2026-03-26 17:30 ` [PATCH v4 07/13] ima: Use snprintf() in create_securityfs_measurement_lists Roberto Sassu
2026-03-26 17:30 ` [PATCH v4 08/13] ima: Introduce ima_dump_measurement() Roberto Sassu
2026-03-26 17:30 ` [PATCH v4 09/13] ima: Add support for staging measurements with prompt Roberto Sassu
2026-03-26 22:44   ` steven chen
2026-03-27 16:45     ` Roberto Sassu
2026-03-26 17:30 ` [PATCH v4 10/13] ima: Add support for flushing the hash table when staging measurements Roberto Sassu
2026-03-26 17:30 ` [PATCH v4 11/13] ima: Support staging and deleting N measurements entries Roberto Sassu
2026-03-26 23:19   ` steven chen [this message]
2026-03-27 17:02     ` Roberto Sassu
2026-03-26 17:30 ` [PATCH v4 12/13] ima: Return error on deleting staged measurements after kexec Roberto Sassu
2026-03-26 17:30 ` [PATCH v4 13/13] doc: security: Add documentation of the IMA staging mechanism Roberto Sassu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=0e186faf-8111-4fd9-a7df-bff30f7fb20a@linux.microsoft.com \
    --to=chenste@linux.microsoft.com \
    --cc=corbet@lwn.net \
    --cc=dmitry.kasatkin@gmail.com \
    --cc=eric.snowberg@oracle.com \
    --cc=gregorylumen@linux.microsoft.com \
    --cc=jmorris@namei.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-integrity@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=nramas@linux.microsoft.com \
    --cc=paul@paul-moore.com \
    --cc=roberto.sassu@huawei.com \
    --cc=roberto.sassu@huaweicloud.com \
    --cc=serge@hallyn.com \
    --cc=skhan@linuxfoundation.org \
    --cc=zohar@linux.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox