* [PATCH 0/1] Trim N entries of IMA event logs
@ 2025-12-02 23:28 steven chen
2025-12-02 23:28 ` [PATCH 1/1] IMA event log trimming steven chen
0 siblings, 1 reply; 12+ messages in thread
From: steven chen @ 2025-12-02 23:28 UTC (permalink / raw)
To: linux-integrity
Cc: zohar, roberto.sassu, dmitry.kasatkin, eric.snowberg, paul,
jmorris, serge, linux-security-module, anirudhve, chenste,
gregorylumen, nramas, sushring
The Integrity Measurement Architecture (IMA) maintains a measurement list
—a record of system events used for integrity verification. The IMA event
logs are the entries within this measurement list, each representing a
specific event or measurement that contributes to the system's integrity
assessment.
This update introduces the ability to trim, or remove, N entries from the
current measurement list. Trimming involves deleting N entries from the
list and clearing the corresponding entries from the hash table. This
action atomically truncates the measurement list, ensuring that no new
measurements can be added until the operation is complete. Importantly,
only one writer can initiate this trimming process at a time, maintaining
consistency and preventing race conditions.
A userspace interface, ima_trim_log, has been provided for this purpose.
By writing a number N to this interface, userspace can request the kernel
to trim N entries from the IMA event logs. When this interface is read,
it returns the number of entries trimmed during the last operation. This
value is not preserved across kexec soft reboots, as it is not considered
important information.
To maintain a complete record, userspace is responsible for concatenating
and storing the logs before initiating trimming. Userspace can then send
the collected data to remote verifiers for validation. After receiving
confirmation from the remote verifiers, userspace may instruct the kernel
to proceed with trimming the IMA event logs accordingly.
The primary benefit of this solution is the ability to free valuable
kernel memory by delegating the task of reconstructing the full
measurement list from log chunks to userspace. Trust is not required in
userspace for the integrity of the measurement list, as its integrity is
cryptographically protected by the Trusted Platform Module (TPM).
Multiple readers are allowed to access the ima_trim_log interface
concurrently, while only one writer can trigger log trimming at any time.
During trimming, readers do not see the list and cannot access it while
deletion is in progress, ensuring atomicity.
The time required for trimming is minimal, and IMA event logs are briefly
on hold during this process, preventing read or add operations. This short
interruption has no impact on the overall functionality of IMA.
steven chen (1):
IMA event log trimming
security/integrity/ima/ima.h | 2 +
security/integrity/ima/ima_fs.c | 78 ++++++++++++++++++++++++++++++
security/integrity/ima/ima_queue.c | 42 ++++++++++++++++
3 files changed, 122 insertions(+)
--
2.43.0
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 1/1] IMA event log trimming
2025-12-02 23:28 [PATCH 0/1] Trim N entries of IMA event logs steven chen
@ 2025-12-02 23:28 ` steven chen
2025-12-05 9:30 ` Roberto Sassu
0 siblings, 1 reply; 12+ messages in thread
From: steven chen @ 2025-12-02 23:28 UTC (permalink / raw)
To: linux-integrity
Cc: zohar, roberto.sassu, dmitry.kasatkin, eric.snowberg, paul,
jmorris, serge, linux-security-module, anirudhve, chenste,
gregorylumen, nramas, sushring
This patch is for trimming N entries of the IMA event logs as well as
cleaning the hash table.
It provides a userspace interface ima_trim_log that can be used to input
number N to let kernel to trim N entries of IMA event logs. When read
this interface, it returns number of entries trimmed last tim.
A mutex ima_trim_list_mutex is provided to allow one trimming request
at a time.
Signed-off-by: steven chen <chenste@linux.microsoft.com>
---
security/integrity/ima/ima.h | 2 +
security/integrity/ima/ima_fs.c | 78 ++++++++++++++++++++++++++++++
security/integrity/ima/ima_queue.c | 42 ++++++++++++++++
3 files changed, 122 insertions(+)
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index e3d71d8d56e3..ab0e30ee25ea 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -246,8 +246,10 @@ void ima_post_key_create_or_update(struct key *keyring, struct key *key,
#ifdef CONFIG_IMA_KEXEC
void ima_measure_kexec_event(const char *event_name);
+long ima_purge_event_log(long number_logs);
#else
static inline void ima_measure_kexec_event(const char *event_name) {}
+static inline long ima_purge_event_log(long number_logs) { return 0; }
#endif
/*
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index 87045b09f120..ea93448feedd 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -38,6 +38,11 @@ __setup("ima_canonical_fmt", default_canonical_fmt_setup);
static int valid_policy = 1;
+#define IMA_LOG_TRIM_REQ_LENGTH 11
+static long trimcount;
+/* mutex protects atomicity of trimming measurement list requests */
+static DEFINE_MUTEX(ima_trim_list_mutex);
+
static ssize_t ima_show_htable_value(char __user *buf, size_t count,
loff_t *ppos, atomic_long_t *val)
{
@@ -289,6 +294,69 @@ static const struct file_operations ima_ascii_measurements_ops = {
.release = seq_release,
};
+static int ima_log_trim_open(struct inode *inode, struct file *filp)
+{
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ return 0;
+}
+
+static ssize_t ima_log_trim_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
+{
+ char tmpbuf[IMA_LOG_TRIM_REQ_LENGTH]; /* greater than largest 'long' string value */
+ ssize_t len;
+
+ len = scnprintf(tmpbuf, sizeof(tmpbuf), "%li\n", trimcount);
+ return simple_read_from_buffer(buf, size, ppos, tmpbuf, len);
+}
+
+static ssize_t ima_log_trim_write(struct file *file,
+ const char __user *buf, size_t datalen, loff_t *ppos)
+{
+ unsigned char req[IMA_LOG_TRIM_REQ_LENGTH];
+ long count, n;
+ int ret;
+
+ mutex_lock(&ima_trim_list_mutex);
+
+ if (*ppos > 0 || datalen > IMA_LOG_TRIM_REQ_LENGTH || datalen < 2) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ n = (int)datalen;
+
+ ret = copy_from_user(req, buf, datalen);
+ if (ret < 0)
+ goto out;
+
+ count = 0;
+ for (int i = 0; i < n; ++i) {
+ if (req[i] < '0' || req[i] > '9') {
+ ret = -EINVAL;
+ goto out;
+ }
+ count = count * 10 + req[i] - '0';
+ }
+ ret = ima_purge_event_log(count);
+
+ if (ret < 0)
+ goto out;
+
+ trimcount = ret;
+ ret = datalen;
+out:
+ mutex_unlock(&ima_trim_list_mutex);
+ return ret;
+}
+
+static const struct file_operations ima_log_trim_ops = {
+ .open = ima_log_trim_open,
+ .read = ima_log_trim_read,
+ .write = ima_log_trim_write,
+ .llseek = generic_file_llseek,
+};
+
static ssize_t ima_read_policy(char *path)
{
void *data = NULL;
@@ -528,6 +596,16 @@ int __init ima_fs_init(void)
goto out;
}
+ dentry = securityfs_create_file("ima_trim_log",
+ S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP,
+ ima_dir, NULL, &ima_log_trim_ops);
+ if (IS_ERR(dentry)) {
+ ret = PTR_ERR(dentry);
+ goto out;
+ }
+
+ trimcount = 0;
+
dentry = securityfs_create_file("runtime_measurements_count",
S_IRUSR | S_IRGRP, ima_dir, NULL,
&ima_measurements_count_ops);
diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c
index 590637e81ad1..999cd42c517c 100644
--- a/security/integrity/ima/ima_queue.c
+++ b/security/integrity/ima/ima_queue.c
@@ -220,6 +220,48 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation,
return result;
}
+/* Delete the IMA event logs */
+long ima_purge_event_log(long number_logs)
+{
+ struct ima_queue_entry *qe;
+ long cur = 0;
+
+ if (number_logs <= 0)
+ return number_logs;
+
+ mutex_lock(&ima_extend_list_mutex);
+ rcu_read_lock();
+
+ /*
+ * Remove this entry from both hash table and the measurement list
+ * When removing from hash table, decrease the length counter
+ * so that the hash table re-sizing logic works correctly
+ */
+ list_for_each_entry_rcu(qe, &ima_measurements, later) {
+ int i;
+
+ /* if CONFIG_IMA_DISABLE_HTABLE is set, the hash table is not used */
+ if (!IS_ENABLED(CONFIG_IMA_DISABLE_HTABLE))
+ hlist_del_rcu(&qe->hnext);
+
+ for (i = 0; i < qe->entry->template_desc->num_fields; i++) {
+ kfree(qe->entry->template_data[i].data);
+ qe->entry->template_data[i].data = NULL;
+ qe->entry->template_data[i].len = 0;
+ }
+
+ atomic_long_dec(&ima_htable.len);
+ list_del_rcu(&qe->later);
+ ++cur;
+ if (cur >= number_logs)
+ break;
+ }
+
+ rcu_read_unlock();
+ mutex_unlock(&ima_extend_list_mutex);
+ return cur;
+}
+
int ima_restore_measurement_entry(struct ima_template_entry *entry)
{
int result = 0;
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH 1/1] IMA event log trimming
2025-12-02 23:28 ` [PATCH 1/1] IMA event log trimming steven chen
@ 2025-12-05 9:30 ` Roberto Sassu
2025-12-05 14:21 ` Roberto Sassu
` (2 more replies)
0 siblings, 3 replies; 12+ messages in thread
From: Roberto Sassu @ 2025-12-05 9:30 UTC (permalink / raw)
To: steven chen, linux-integrity
Cc: zohar, roberto.sassu, dmitry.kasatkin, eric.snowberg, paul,
jmorris, serge, linux-security-module, anirudhve, gregorylumen,
nramas, sushring
On Tue, 2025-12-02 at 15:28 -0800, steven chen wrote:
> This patch is for trimming N entries of the IMA event logs as well as
> cleaning the hash table.
>
> It provides a userspace interface ima_trim_log that can be used to input
> number N to let kernel to trim N entries of IMA event logs. When read
> this interface, it returns number of entries trimmed last tim.
High-level comments:
- It does not offer the possibility to keep the hash table
- There is no coordination between taking a snapshot and the readers of
the measurements list (I think it is necessary, since reading is
based on *pos, which contains the entries read until a given point;
if there is a truncate in the middle of the read, *pos would still
refer to the non-truncated list and the next read will skip some
measurement entries)
- While trimming per se is ok, I like more the idea of staging changes
and letting the user delete the staged measurements list later
> A mutex ima_trim_list_mutex is provided to allow one trimming request
> at a time.
>
> Signed-off-by: steven chen <chenste@linux.microsoft.com>
> ---
> security/integrity/ima/ima.h | 2 +
> security/integrity/ima/ima_fs.c | 78 ++++++++++++++++++++++++++++++
> security/integrity/ima/ima_queue.c | 42 ++++++++++++++++
> 3 files changed, 122 insertions(+)
>
> diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
> index e3d71d8d56e3..ab0e30ee25ea 100644
> --- a/security/integrity/ima/ima.h
> +++ b/security/integrity/ima/ima.h
> @@ -246,8 +246,10 @@ void ima_post_key_create_or_update(struct key *keyring, struct key *key,
>
> #ifdef CONFIG_IMA_KEXEC
> void ima_measure_kexec_event(const char *event_name);
> +long ima_purge_event_log(long number_logs);
> #else
> static inline void ima_measure_kexec_event(const char *event_name) {}
> +static inline long ima_purge_event_log(long number_logs) { return 0; }
> #endif
>
> /*
> diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
> index 87045b09f120..ea93448feedd 100644
> --- a/security/integrity/ima/ima_fs.c
> +++ b/security/integrity/ima/ima_fs.c
> @@ -38,6 +38,11 @@ __setup("ima_canonical_fmt", default_canonical_fmt_setup);
>
> static int valid_policy = 1;
>
> +#define IMA_LOG_TRIM_REQ_LENGTH 11
> +static long trimcount;
> +/* mutex protects atomicity of trimming measurement list requests */
> +static DEFINE_MUTEX(ima_trim_list_mutex);
> +
> static ssize_t ima_show_htable_value(char __user *buf, size_t count,
> loff_t *ppos, atomic_long_t *val)
> {
> @@ -289,6 +294,69 @@ static const struct file_operations ima_ascii_measurements_ops = {
> .release = seq_release,
> };
>
> +static int ima_log_trim_open(struct inode *inode, struct file *filp)
> +{
> + if (!capable(CAP_SYS_ADMIN))
> + return -EPERM;
> + return 0;
> +}
> +
> +static ssize_t ima_log_trim_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
> +{
> + char tmpbuf[IMA_LOG_TRIM_REQ_LENGTH]; /* greater than largest 'long' string value */
> + ssize_t len;
> +
> + len = scnprintf(tmpbuf, sizeof(tmpbuf), "%li\n", trimcount);
> + return simple_read_from_buffer(buf, size, ppos, tmpbuf, len);
> +}
> +
> +static ssize_t ima_log_trim_write(struct file *file,
> + const char __user *buf, size_t datalen, loff_t *ppos)
> +{
> + unsigned char req[IMA_LOG_TRIM_REQ_LENGTH];
> + long count, n;
> + int ret;
> +
> + mutex_lock(&ima_trim_list_mutex);
> +
> + if (*ppos > 0 || datalen > IMA_LOG_TRIM_REQ_LENGTH || datalen < 2) {
> + ret = -EINVAL;
> + goto out;
> + }
> +
> + n = (int)datalen;
> +
> + ret = copy_from_user(req, buf, datalen);
> + if (ret < 0)
> + goto out;
> +
> + count = 0;
> + for (int i = 0; i < n; ++i) {
> + if (req[i] < '0' || req[i] > '9') {
> + ret = -EINVAL;
> + goto out;
> + }
> + count = count * 10 + req[i] - '0';
> + }
> + ret = ima_purge_event_log(count);
> +
> + if (ret < 0)
> + goto out;
> +
> + trimcount = ret;
> + ret = datalen;
> +out:
> + mutex_unlock(&ima_trim_list_mutex);
> + return ret;
> +}
> +
> +static const struct file_operations ima_log_trim_ops = {
> + .open = ima_log_trim_open,
> + .read = ima_log_trim_read,
> + .write = ima_log_trim_write,
> + .llseek = generic_file_llseek,
> +};
> +
> static ssize_t ima_read_policy(char *path)
> {
> void *data = NULL;
> @@ -528,6 +596,16 @@ int __init ima_fs_init(void)
> goto out;
> }
>
> + dentry = securityfs_create_file("ima_trim_log",
> + S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP,
> + ima_dir, NULL, &ima_log_trim_ops);
> + if (IS_ERR(dentry)) {
> + ret = PTR_ERR(dentry);
> + goto out;
> + }
> +
> + trimcount = 0;
> +
> dentry = securityfs_create_file("runtime_measurements_count",
> S_IRUSR | S_IRGRP, ima_dir, NULL,
> &ima_measurements_count_ops);
> diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c
> index 590637e81ad1..999cd42c517c 100644
> --- a/security/integrity/ima/ima_queue.c
> +++ b/security/integrity/ima/ima_queue.c
> @@ -220,6 +220,48 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation,
> return result;
> }
>
> +/* Delete the IMA event logs */
> +long ima_purge_event_log(long number_logs)
> +{
> + struct ima_queue_entry *qe;
> + long cur = 0;
> +
> + if (number_logs <= 0)
> + return number_logs;
> +
> + mutex_lock(&ima_extend_list_mutex);
> + rcu_read_lock();
Sorry, I'm missing why rcu_read_lock() is needed.
> +
> + /*
> + * Remove this entry from both hash table and the measurement list
> + * When removing from hash table, decrease the length counter
> + * so that the hash table re-sizing logic works correctly
> + */
> + list_for_each_entry_rcu(qe, &ima_measurements, later) {
> + int i;
> +
> + /* if CONFIG_IMA_DISABLE_HTABLE is set, the hash table is not used */
> + if (!IS_ENABLED(CONFIG_IMA_DISABLE_HTABLE))
> + hlist_del_rcu(&qe->hnext);
> +
> + for (i = 0; i < qe->entry->template_desc->num_fields; i++) {
> + kfree(qe->entry->template_data[i].data);
> + qe->entry->template_data[i].data = NULL;
> + qe->entry->template_data[i].len = 0;
> + }
> +
> + atomic_long_dec(&ima_htable.len);
> + list_del_rcu(&qe->later);
Missing kfree() of qe->entry and qe?
Thanks
Roberto
> + ++cur;
> + if (cur >= number_logs)
> + break;
> + }
> +
> + rcu_read_unlock();
> + mutex_unlock(&ima_extend_list_mutex);
> + return cur;
> +}
> +
> int ima_restore_measurement_entry(struct ima_template_entry *entry)
> {
> int result = 0;
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/1] IMA event log trimming
2025-12-05 9:30 ` Roberto Sassu
@ 2025-12-05 14:21 ` Roberto Sassu
2025-12-05 18:30 ` James Bottomley
2025-12-06 1:28 ` steven chen
2 siblings, 0 replies; 12+ messages in thread
From: Roberto Sassu @ 2025-12-05 14:21 UTC (permalink / raw)
To: steven chen, linux-integrity
Cc: zohar, roberto.sassu, dmitry.kasatkin, eric.snowberg, paul,
jmorris, serge, linux-security-module, anirudhve, gregorylumen,
nramas, sushring
On Fri, 2025-12-05 at 10:30 +0100, Roberto Sassu wrote:
> On Tue, 2025-12-02 at 15:28 -0800, steven chen wrote:
> > This patch is for trimming N entries of the IMA event logs as well as
> > cleaning the hash table.
> >
> > It provides a userspace interface ima_trim_log that can be used to input
> > number N to let kernel to trim N entries of IMA event logs. When read
> > this interface, it returns number of entries trimmed last tim.
>
> High-level comments:
> - It does not offer the possibility to keep the hash table
> - There is no coordination between taking a snapshot and the readers of
> the measurements list (I think it is necessary, since reading is
> based on *pos, which contains the entries read until a given point;
> if there is a truncate in the middle of the read, *pos would still
> refer to the non-truncated list and the next read will skip some
> measurement entries)
> - While trimming per se is ok, I like more the idea of staging changes
> and letting the user delete the staged measurements list later
>
> > A mutex ima_trim_list_mutex is provided to allow one trimming request
> > at a time.
> >
> > Signed-off-by: steven chen <chenste@linux.microsoft.com>
> > ---
> > security/integrity/ima/ima.h | 2 +
> > security/integrity/ima/ima_fs.c | 78 ++++++++++++++++++++++++++++++
> > security/integrity/ima/ima_queue.c | 42 ++++++++++++++++
> > 3 files changed, 122 insertions(+)
> >
> > diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
> > index e3d71d8d56e3..ab0e30ee25ea 100644
> > --- a/security/integrity/ima/ima.h
> > +++ b/security/integrity/ima/ima.h
> > @@ -246,8 +246,10 @@ void ima_post_key_create_or_update(struct key *keyring, struct key *key,
> >
> > #ifdef CONFIG_IMA_KEXEC
> > void ima_measure_kexec_event(const char *event_name);
> > +long ima_purge_event_log(long number_logs);
> > #else
> > static inline void ima_measure_kexec_event(const char *event_name) {}
> > +static inline long ima_purge_event_log(long number_logs) { return 0; }
> > #endif
> >
> > /*
> > diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
> > index 87045b09f120..ea93448feedd 100644
> > --- a/security/integrity/ima/ima_fs.c
> > +++ b/security/integrity/ima/ima_fs.c
> > @@ -38,6 +38,11 @@ __setup("ima_canonical_fmt", default_canonical_fmt_setup);
> >
> > static int valid_policy = 1;
> >
> > +#define IMA_LOG_TRIM_REQ_LENGTH 11
> > +static long trimcount;
> > +/* mutex protects atomicity of trimming measurement list requests */
> > +static DEFINE_MUTEX(ima_trim_list_mutex);
> > +
> > static ssize_t ima_show_htable_value(char __user *buf, size_t count,
> > loff_t *ppos, atomic_long_t *val)
> > {
> > @@ -289,6 +294,69 @@ static const struct file_operations ima_ascii_measurements_ops = {
> > .release = seq_release,
> > };
> >
> > +static int ima_log_trim_open(struct inode *inode, struct file *filp)
> > +{
> > + if (!capable(CAP_SYS_ADMIN))
> > + return -EPERM;
> > + return 0;
> > +}
> > +
> > +static ssize_t ima_log_trim_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
> > +{
> > + char tmpbuf[IMA_LOG_TRIM_REQ_LENGTH]; /* greater than largest 'long' string value */
> > + ssize_t len;
> > +
> > + len = scnprintf(tmpbuf, sizeof(tmpbuf), "%li\n", trimcount);
> > + return simple_read_from_buffer(buf, size, ppos, tmpbuf, len);
> > +}
> > +
> > +static ssize_t ima_log_trim_write(struct file *file,
> > + const char __user *buf, size_t datalen, loff_t *ppos)
> > +{
> > + unsigned char req[IMA_LOG_TRIM_REQ_LENGTH];
> > + long count, n;
> > + int ret;
> > +
> > + mutex_lock(&ima_trim_list_mutex);
> > +
> > + if (*ppos > 0 || datalen > IMA_LOG_TRIM_REQ_LENGTH || datalen < 2) {
> > + ret = -EINVAL;
> > + goto out;
> > + }
> > +
> > + n = (int)datalen;
> > +
> > + ret = copy_from_user(req, buf, datalen);
> > + if (ret < 0)
> > + goto out;
> > +
> > + count = 0;
> > + for (int i = 0; i < n; ++i) {
> > + if (req[i] < '0' || req[i] > '9') {
> > + ret = -EINVAL;
> > + goto out;
> > + }
> > + count = count * 10 + req[i] - '0';
> > + }
> > + ret = ima_purge_event_log(count);
> > +
> > + if (ret < 0)
> > + goto out;
> > +
> > + trimcount = ret;
> > + ret = datalen;
> > +out:
> > + mutex_unlock(&ima_trim_list_mutex);
> > + return ret;
> > +}
> > +
> > +static const struct file_operations ima_log_trim_ops = {
> > + .open = ima_log_trim_open,
> > + .read = ima_log_trim_read,
> > + .write = ima_log_trim_write,
> > + .llseek = generic_file_llseek,
> > +};
> > +
> > static ssize_t ima_read_policy(char *path)
> > {
> > void *data = NULL;
> > @@ -528,6 +596,16 @@ int __init ima_fs_init(void)
> > goto out;
> > }
> >
> > + dentry = securityfs_create_file("ima_trim_log",
> > + S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP,
> > + ima_dir, NULL, &ima_log_trim_ops);
> > + if (IS_ERR(dentry)) {
> > + ret = PTR_ERR(dentry);
> > + goto out;
> > + }
> > +
> > + trimcount = 0;
> > +
> > dentry = securityfs_create_file("runtime_measurements_count",
> > S_IRUSR | S_IRGRP, ima_dir, NULL,
> > &ima_measurements_count_ops);
> > diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c
> > index 590637e81ad1..999cd42c517c 100644
> > --- a/security/integrity/ima/ima_queue.c
> > +++ b/security/integrity/ima/ima_queue.c
> > @@ -220,6 +220,48 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation,
> > return result;
> > }
> >
> > +/* Delete the IMA event logs */
> > +long ima_purge_event_log(long number_logs)
> > +{
> > + struct ima_queue_entry *qe;
> > + long cur = 0;
> > +
> > + if (number_logs <= 0)
> > + return number_logs;
> > +
> > + mutex_lock(&ima_extend_list_mutex);
> > + rcu_read_lock();
>
> Sorry, I'm missing why rcu_read_lock() is needed.
Ah, I guess it is because of list_for_each_entry_rcu(). In that case, I
think you can add 'true' as 4th argument, since you are holding
ima_extend_list_mutex.
Roberto
> > +
> > + /*
> > + * Remove this entry from both hash table and the measurement list
> > + * When removing from hash table, decrease the length counter
> > + * so that the hash table re-sizing logic works correctly
> > + */
> > + list_for_each_entry_rcu(qe, &ima_measurements, later) {
> > + int i;
> > +
> > + /* if CONFIG_IMA_DISABLE_HTABLE is set, the hash table is not used */
> > + if (!IS_ENABLED(CONFIG_IMA_DISABLE_HTABLE))
> > + hlist_del_rcu(&qe->hnext);
> > +
> > + for (i = 0; i < qe->entry->template_desc->num_fields; i++) {
> > + kfree(qe->entry->template_data[i].data);
> > + qe->entry->template_data[i].data = NULL;
> > + qe->entry->template_data[i].len = 0;
> > + }
> > +
> > + atomic_long_dec(&ima_htable.len);
> > + list_del_rcu(&qe->later);
>
> Missing kfree() of qe->entry and qe?
>
> Thanks
>
> Roberto
>
> > + ++cur;
> > + if (cur >= number_logs)
> > + break;
> > + }
> > +
> > + rcu_read_unlock();
> > + mutex_unlock(&ima_extend_list_mutex);
> > + return cur;
> > +}
> > +
> > int ima_restore_measurement_entry(struct ima_template_entry *entry)
> > {
> > int result = 0;
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/1] IMA event log trimming
2025-12-05 9:30 ` Roberto Sassu
2025-12-05 14:21 ` Roberto Sassu
@ 2025-12-05 18:30 ` James Bottomley
2025-12-08 9:40 ` Roberto Sassu
2025-12-06 1:28 ` steven chen
2 siblings, 1 reply; 12+ messages in thread
From: James Bottomley @ 2025-12-05 18:30 UTC (permalink / raw)
To: Roberto Sassu, steven chen, linux-integrity
Cc: zohar, roberto.sassu, dmitry.kasatkin, eric.snowberg, paul,
jmorris, serge, linux-security-module, anirudhve, gregorylumen,
nramas, sushring
On Fri, 2025-12-05 at 10:30 +0100, Roberto Sassu wrote:
> On Tue, 2025-12-02 at 15:28 -0800, steven chen wrote:
> > This patch is for trimming N entries of the IMA event logs as well
> > as cleaning the hash table.
> >
> > It provides a userspace interface ima_trim_log that can be used to
> > input number N to let kernel to trim N entries of IMA event logs.
> > When read this interface, it returns number of entries trimmed last
> > tim.
>
> High-level comments:
> - It does not offer the possibility to keep the hash table
> - There is no coordination between taking a snapshot and the readers
> of
> the measurements list (I think it is necessary, since reading is
> based on *pos, which contains the entries read until a given point;
> if there is a truncate in the middle of the read, *pos would still
> refer to the non-truncated list and the next read will skip some
> measurement entries)
Rather than designing the interface absent use cases, could we give use
cases first so we know it fits? I really only have one: the keylime
agent, but I believe it's pattern, which would be get TPM quote of
logging PCRs, certify quote and then trim the log up to the point the
quote was obtained will be a common pattern (at least I don't think
anyone would trim the log without quoting it). If you're trimming
based on a quote, you know the end hash of all the PCRs and you want to
trim up to that. Since the log is fixed, you can work out what the
index offset is, but it does seem a bit suboptimal to have to compute
that, which is why I think trimming by end PCR hash is useful. The
main point in all of this is, I think, that you don't really get to
decide which point in the log the TPM will quote: it always quotes it's
current PCR values, so no-one who cares about log quotes can select the
number of entries first, they all have to see what PCR values the quote
returns.
> - While trimming per se is ok, I like more the idea of staging
> changes and letting the user delete the staged measurements list
> later
I'm not averse to this, but keylime won't care ... it gets the quote
and the log and it will verify the log before it will get the agent to
issue a trim. Is there a use case that would actually need this
behaviour?
I also think having the base PCRs stored in the kernel after the trim
(in a way that's easily consumed, like a non measured log entry), thus
allowing verification from the log up to any current quote is useful.
The reason I think it's useful is the attestation token one: I can see
the keylime verifier giving an I've verified the log up to here and all
the entries look good token that contains the base PCRs and if there
are quite a few of these floating around (especially if the log isn't
always trimmed) I could see the kernel base PCR storage being used to
ask which is the relevant attestation token I should use to verify the
rest of the log (or even used to detect nefarious trimming designed to
hide records).
Regards,
James
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/1] IMA event log trimming
2025-12-05 9:30 ` Roberto Sassu
2025-12-05 14:21 ` Roberto Sassu
2025-12-05 18:30 ` James Bottomley
@ 2025-12-06 1:28 ` steven chen
2 siblings, 0 replies; 12+ messages in thread
From: steven chen @ 2025-12-06 1:28 UTC (permalink / raw)
To: Roberto Sassu, linux-integrity
Cc: zohar, roberto.sassu, dmitry.kasatkin, eric.snowberg, paul,
jmorris, serge, linux-security-module, anirudhve, gregorylumen,
nramas, sushring, steven chen
On 12/5/2025 1:30 AM, Roberto Sassu wrote:
> On Tue, 2025-12-02 at 15:28 -0800, steven chen wrote:
>> This patch is for trimming N entries of the IMA event logs as well as
>> cleaning the hash table.
>>
>> It provides a userspace interface ima_trim_log that can be used to input
>> number N to let kernel to trim N entries of IMA event logs. When read
>> this interface, it returns number of entries trimmed last tim.
> High-level comments:
> - It does not offer the possibility to keep the hash table
Hi Roberto,
Should the hash table persist after log removal? Log trimming is
infrequent, right?
Thanks,
Steven
> - There is no coordination between taking a snapshot and the readers of
> the measurements list (I think it is necessary, since reading is
> based on *pos, which contains the entries read until a given point;
> if there is a truncate in the middle of the read, *pos would still
> refer to the non-truncated list and the next read will skip some
> measurement entries)
Hi Roberto,
What’s your suggestion for this? Leave user space handle this (check log
trimming
happened)?
Thanks!
Steven.
> - While trimming per se is ok, I like more the idea of staging changes
> and letting the user delete the staged measurements list later
Hi Roberto,
This approach simplifies both the user space agent and the kernel. The
main difference
lies in whether log purging requires one step or two; I think a single
step is preferable
since logs must be removed from the kernel regardless.
Thanks,
Steven
>> A mutex ima_trim_list_mutex is provided to allow one trimming request
>> at a time.
>>
>> Signed-off-by: steven chen <chenste@linux.microsoft.com>
>> ---
>> security/integrity/ima/ima.h | 2 +
>> security/integrity/ima/ima_fs.c | 78 ++++++++++++++++++++++++++++++
>> security/integrity/ima/ima_queue.c | 42 ++++++++++++++++
>> 3 files changed, 122 insertions(+)
>>
>> diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
>> index e3d71d8d56e3..ab0e30ee25ea 100644
>> --- a/security/integrity/ima/ima.h
>> +++ b/security/integrity/ima/ima.h
>> @@ -246,8 +246,10 @@ void ima_post_key_create_or_update(struct key *keyring, struct key *key,
>>
>> #ifdef CONFIG_IMA_KEXEC
>> void ima_measure_kexec_event(const char *event_name);
>> +long ima_purge_event_log(long number_logs);
>> #else
>> static inline void ima_measure_kexec_event(const char *event_name) {}
>> +static inline long ima_purge_event_log(long number_logs) { return 0; }
>> #endif
>>
>> /*
>> diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
>> index 87045b09f120..ea93448feedd 100644
>> --- a/security/integrity/ima/ima_fs.c
>> +++ b/security/integrity/ima/ima_fs.c
>> @@ -38,6 +38,11 @@ __setup("ima_canonical_fmt", default_canonical_fmt_setup);
>>
>> static int valid_policy = 1;
>>
>> +#define IMA_LOG_TRIM_REQ_LENGTH 11
>> +static long trimcount;
>> +/* mutex protects atomicity of trimming measurement list requests */
>> +static DEFINE_MUTEX(ima_trim_list_mutex);
>> +
>> static ssize_t ima_show_htable_value(char __user *buf, size_t count,
>> loff_t *ppos, atomic_long_t *val)
>> {
>> @@ -289,6 +294,69 @@ static const struct file_operations ima_ascii_measurements_ops = {
>> .release = seq_release,
>> };
>>
>> +static int ima_log_trim_open(struct inode *inode, struct file *filp)
>> +{
>> + if (!capable(CAP_SYS_ADMIN))
>> + return -EPERM;
>> + return 0;
>> +}
>> +
>> +static ssize_t ima_log_trim_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
>> +{
>> + char tmpbuf[IMA_LOG_TRIM_REQ_LENGTH]; /* greater than largest 'long' string value */
>> + ssize_t len;
>> +
>> + len = scnprintf(tmpbuf, sizeof(tmpbuf), "%li\n", trimcount);
>> + return simple_read_from_buffer(buf, size, ppos, tmpbuf, len);
>> +}
>> +
>> +static ssize_t ima_log_trim_write(struct file *file,
>> + const char __user *buf, size_t datalen, loff_t *ppos)
>> +{
>> + unsigned char req[IMA_LOG_TRIM_REQ_LENGTH];
>> + long count, n;
>> + int ret;
>> +
>> + mutex_lock(&ima_trim_list_mutex);
>> +
>> + if (*ppos > 0 || datalen > IMA_LOG_TRIM_REQ_LENGTH || datalen < 2) {
>> + ret = -EINVAL;
>> + goto out;
>> + }
>> +
>> + n = (int)datalen;
>> +
>> + ret = copy_from_user(req, buf, datalen);
>> + if (ret < 0)
>> + goto out;
>> +
>> + count = 0;
>> + for (int i = 0; i < n; ++i) {
>> + if (req[i] < '0' || req[i] > '9') {
>> + ret = -EINVAL;
>> + goto out;
>> + }
>> + count = count * 10 + req[i] - '0';
>> + }
>> + ret = ima_purge_event_log(count);
>> +
>> + if (ret < 0)
>> + goto out;
>> +
>> + trimcount = ret;
>> + ret = datalen;
>> +out:
>> + mutex_unlock(&ima_trim_list_mutex);
>> + return ret;
>> +}
>> +
>> +static const struct file_operations ima_log_trim_ops = {
>> + .open = ima_log_trim_open,
>> + .read = ima_log_trim_read,
>> + .write = ima_log_trim_write,
>> + .llseek = generic_file_llseek,
>> +};
>> +
>> static ssize_t ima_read_policy(char *path)
>> {
>> void *data = NULL;
>> @@ -528,6 +596,16 @@ int __init ima_fs_init(void)
>> goto out;
>> }
>>
>> + dentry = securityfs_create_file("ima_trim_log",
>> + S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP,
>> + ima_dir, NULL, &ima_log_trim_ops);
>> + if (IS_ERR(dentry)) {
>> + ret = PTR_ERR(dentry);
>> + goto out;
>> + }
>> +
>> + trimcount = 0;
>> +
>> dentry = securityfs_create_file("runtime_measurements_count",
>> S_IRUSR | S_IRGRP, ima_dir, NULL,
>> &ima_measurements_count_ops);
>> diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c
>> index 590637e81ad1..999cd42c517c 100644
>> --- a/security/integrity/ima/ima_queue.c
>> +++ b/security/integrity/ima/ima_queue.c
>> @@ -220,6 +220,48 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation,
>> return result;
>> }
>>
>> +/* Delete the IMA event logs */
>> +long ima_purge_event_log(long number_logs)
>> +{
>> + struct ima_queue_entry *qe;
>> + long cur = 0;
>> +
>> + if (number_logs <= 0)
>> + return number_logs;
>> +
>> + mutex_lock(&ima_extend_list_mutex);
>> + rcu_read_lock();
> Sorry, I'm missing why rcu_read_lock() is needed.
Hi Roberto,
I will add "true" parameter in list_for_each_entry_rcu api.
Thanks,
Steven
>> +
>> + /*
>> + * Remove this entry from both hash table and the measurement list
>> + * When removing from hash table, decrease the length counter
>> + * so that the hash table re-sizing logic works correctly
>> + */
>> + list_for_each_entry_rcu(qe, &ima_measurements, later) {
>> + int i;
>> +
>> + /* if CONFIG_IMA_DISABLE_HTABLE is set, the hash table is not used */
>> + if (!IS_ENABLED(CONFIG_IMA_DISABLE_HTABLE))
>> + hlist_del_rcu(&qe->hnext);
>> +
>> + for (i = 0; i < qe->entry->template_desc->num_fields; i++) {
>> + kfree(qe->entry->template_data[i].data);
>> + qe->entry->template_data[i].data = NULL;
>> + qe->entry->template_data[i].len = 0;
>> + }
>> +
>> + atomic_long_dec(&ima_htable.len);
>> + list_del_rcu(&qe->later);
> Missing kfree() of qe->entry and qe?
>
> Thanks
>
> Roberto
Hi Roberto,
I will update in next version.
Thanks,
Steven
>> + ++cur;
>> + if (cur >= number_logs)
>> + break;
>> + }
>> +
>> + rcu_read_unlock();
>> + mutex_unlock(&ima_extend_list_mutex);
>> + return cur;
>> +}
>> +
>> int ima_restore_measurement_entry(struct ima_template_entry *entry)
>> {
>> int result = 0;
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/1] IMA event log trimming
2025-12-05 18:30 ` James Bottomley
@ 2025-12-08 9:40 ` Roberto Sassu
2025-12-08 17:21 ` Gregory Lumen
2025-12-08 22:17 ` James Bottomley
0 siblings, 2 replies; 12+ messages in thread
From: Roberto Sassu @ 2025-12-08 9:40 UTC (permalink / raw)
To: James Bottomley, steven chen, linux-integrity
Cc: zohar, roberto.sassu, dmitry.kasatkin, eric.snowberg, paul,
jmorris, serge, linux-security-module, anirudhve, gregorylumen,
nramas, sushring
On Fri, 2025-12-05 at 13:30 -0500, James Bottomley wrote:
> On Fri, 2025-12-05 at 10:30 +0100, Roberto Sassu wrote:
> > On Tue, 2025-12-02 at 15:28 -0800, steven chen wrote:
> > > This patch is for trimming N entries of the IMA event logs as well
> > > as cleaning the hash table.
> > >
> > > It provides a userspace interface ima_trim_log that can be used to
> > > input number N to let kernel to trim N entries of IMA event logs.
> > > When read this interface, it returns number of entries trimmed last
> > > tim.
> >
> > High-level comments:
> > - It does not offer the possibility to keep the hash table
> > - There is no coordination between taking a snapshot and the readers
> > of
> > the measurements list (I think it is necessary, since reading is
> > based on *pos, which contains the entries read until a given point;
> > if there is a truncate in the middle of the read, *pos would still
> > refer to the non-truncated list and the next read will skip some
> > measurement entries)
>
> Rather than designing the interface absent use cases, could we give use
> cases first so we know it fits? I really only have one: the keylime
> agent, but I believe it's pattern, which would be get TPM quote of
> logging PCRs, certify quote and then trim the log up to the point the
> quote was obtained will be a common pattern (at least I don't think
> anyone would trim the log without quoting it). If you're trimming
> based on a quote, you know the end hash of all the PCRs and you want to
> trim up to that. Since the log is fixed, you can work out what the
> index offset is, but it does seem a bit suboptimal to have to compute
> that, which is why I think trimming by end PCR hash is useful. The
> main point in all of this is, I think, that you don't really get to
> decide which point in the log the TPM will quote: it always quotes it's
> current PCR values, so no-one who cares about log quotes can select the
> number of entries first, they all have to see what PCR values the quote
> returns.
>
> > - While trimming per se is ok, I like more the idea of staging
> > changes and letting the user delete the staged measurements list
> > later
>
> I'm not averse to this, but keylime won't care ... it gets the quote
> and the log and it will verify the log before it will get the agent to
> issue a trim. Is there a use case that would actually need this
> behaviour?
>
> I also think having the base PCRs stored in the kernel after the trim
> (in a way that's easily consumed, like a non measured log entry), thus
> allowing verification from the log up to any current quote is useful.
> The reason I think it's useful is the attestation token one: I can see
> the keylime verifier giving an I've verified the log up to here and all
> the entries look good token that contains the base PCRs and if there
> are quite a few of these floating around (especially if the log isn't
> always trimmed) I could see the kernel base PCR storage being used to
> ask which is the relevant attestation token I should use to verify the
> rest of the log (or even used to detect nefarious trimming designed to
> hide records).
I have the impression that none the functionality you cited has to be
implemented in the kernel, because the only component one can trust to
verify the integrity of the IMA measurements list is the TPM. Whether
either the kernel or user space retain the measurements is irrelevant.
I believe that the only role of the kernel is to get rid of the
measurements entries as fast as possible (the kernel would act more
like a buffer).
This was actually the intent of my original proposal in
https://github.com/linux-integrity/linux/issues/1 . The idea of staging
(was snapshotting, but Mimi thinks the term is not accurate) is simply
to detach the entire IMA measurement list as fast as possible. Further
read and delete after staging is done without interfering with new
measurements (sure, the detaching of the hash table is not yet as
efficient as I hoped).
Anything that you said about verifying the measurements up to a certain
TPM quote can be implemented in user space without a decrease in
security. I don't see the need to synchronize the trim with the
verification in the kernel.
Roberto
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/1] IMA event log trimming
2025-12-08 9:40 ` Roberto Sassu
@ 2025-12-08 17:21 ` Gregory Lumen
2025-12-08 17:50 ` Roberto Sassu
2025-12-08 22:17 ` James Bottomley
1 sibling, 1 reply; 12+ messages in thread
From: Gregory Lumen @ 2025-12-08 17:21 UTC (permalink / raw)
To: Roberto Sassu
Cc: James Bottomley, steven chen, linux-integrity, zohar,
roberto.sassu, dmitry.kasatkin, eric.snowberg, paul, jmorris,
serge, linux-security-module, anirudhve, nramas, sushring
[-- Attachment #1: Type: text/plain, Size: 1701 bytes --]
> Rather than designing the interface absent use cases, could we give use
> cases first so we know it fits?
I would also like to request that we include operational considerations in
the interface design; specifically, which additional signals can or should
be made available to UM to assist in diagnosing log validation failures.
This seems called for as any form of log trimming will introduce a new
potential cause for validation failures (unexpected trimming).
With the proposed changes, the only signal available to system operators
is the validation failure itself, with no signal that could be used to
determine if the failure was the result of an unexpected trim or a loss of
synchronization between the log and the PCRs (either through an unexpected
PCR extend, or tampering with the measurement list). Any of these may
indicate malicious activity, but they may also result from system
configuration issues that operators would need to diagnose and resolve.
Tracking and exposing either the total number of trimmed measurements or
the most recent trimmed-to PCR values by the kernel would allow system
operators to determine whether a failure was caused by unexpected trimming
or integrity issues. (Storing the PCR values also enables validation of
the retained measurements even after an unexpected trim, though I’m unsure
how often that signal would prove useful.)
Neither approach appears to add any additional attack surface beyond
raising the likelihood of incorrectly or insecurely implemented UM
attestation agents. Though that risk (and the additional kernel
complexity) should be weighed against the value of the additional
diagnostic signals.
-Gregory Lumen
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/1] IMA event log trimming
2025-12-08 17:21 ` Gregory Lumen
@ 2025-12-08 17:50 ` Roberto Sassu
0 siblings, 0 replies; 12+ messages in thread
From: Roberto Sassu @ 2025-12-08 17:50 UTC (permalink / raw)
To: Gregory Lumen
Cc: James Bottomley, steven chen, linux-integrity, zohar,
roberto.sassu, dmitry.kasatkin, eric.snowberg, paul, jmorris,
serge, linux-security-module, anirudhve, nramas, sushring
On Mon, 2025-12-08 at 09:21 -0800, Gregory Lumen wrote:
> > Rather than designing the interface absent use cases, could we give use
> > cases first so we know it fits?
>
> I would also like to request that we include operational considerations in
> the interface design; specifically, which additional signals can or should
> be made available to UM to assist in diagnosing log validation failures.
> This seems called for as any form of log trimming will introduce a new
> potential cause for validation failures (unexpected trimming).
>
> With the proposed changes, the only signal available to system operators
> is the validation failure itself, with no signal that could be used to
> determine if the failure was the result of an unexpected trim or a loss of
> synchronization between the log and the PCRs (either through an unexpected
> PCR extend, or tampering with the measurement list). Any of these may
> indicate malicious activity, but they may also result from system
> configuration issues that operators would need to diagnose and resolve.
I don't agree with this. User space can keep a persistent state, and
resume from where it was interrupted. There is no risk of loss of data,
if user space deletes staged measurements only after the read is
complete.
The same comment applies for coordination between different user space
agents. It would not be too hard to expose an interface managed by a
new user space component, providing similar data as IMA (even showing
the full measurements list without its users being aware of the
snapshots). The other agents can fetch the data from the new interface.
And also, I don't see the problem in developing more complex user space
programs which link the measurement entries to PCR values, and anything
that is desirable.
And if from the kernel perspective all we need to do is a list replace,
for me that is the most efficient solution.
Roberto
> Tracking and exposing either the total number of trimmed measurements or
> the most recent trimmed-to PCR values by the kernel would allow system
> operators to determine whether a failure was caused by unexpected trimming
> or integrity issues. (Storing the PCR values also enables validation of
> the retained measurements even after an unexpected trim, though I’m unsure
> how often that signal would prove useful.)
>
> Neither approach appears to add any additional attack surface beyond
> raising the likelihood of incorrectly or insecurely implemented UM
> attestation agents. Though that risk (and the additional kernel
> complexity) should be weighed against the value of the additional
> diagnostic signals.
>
> -Gregory Lumen
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/1] IMA event log trimming
2025-12-08 9:40 ` Roberto Sassu
2025-12-08 17:21 ` Gregory Lumen
@ 2025-12-08 22:17 ` James Bottomley
2025-12-09 9:36 ` Roberto Sassu
1 sibling, 1 reply; 12+ messages in thread
From: James Bottomley @ 2025-12-08 22:17 UTC (permalink / raw)
To: Roberto Sassu, steven chen, linux-integrity
Cc: zohar, roberto.sassu, dmitry.kasatkin, eric.snowberg, paul,
jmorris, serge, linux-security-module, anirudhve, gregorylumen,
nramas, sushring
On Mon, 2025-12-08 at 10:40 +0100, Roberto Sassu wrote:
> I have the impression that none the functionality you cited has to be
> implemented in the kernel, because the only component one can trust
> to verify the integrity of the IMA measurements list is the TPM.
> Whether either the kernel or user space retain the measurements is
> irrelevant.
That's correct, I'm not advocating moving quoting into the kernel. Co-
ordinating the trim with where the quote gets you to is phenomenally
useful. While you could theoretically store any mismatch in userspace,
having two locations for the log makes it more error prone.
> I believe that the only role of the kernel is to get rid of the
> measurements entries as fast as possible (the kernel would act more
> like a buffer).
I wouldn't say that, I'd say to get rid of measurements that the user
has indicated are of no further use.
> This was actually the intent of my original proposal in
> https://github.com/linux-integrity/linux/issues/1 . The idea of
> staging (was snapshotting, but Mimi thinks the term is not accurate)
> is simply to detach the entire IMA measurement list as fast as
> possible. Further read and delete after staging is done without
> interfering with new measurements (sure, the detaching of the hash
> table is not yet as efficient as I hoped).
From the application point of view, offloading the log and random
points is a bit more work because now the log collector has to be
modified to look in multiple locations and we'd also need an agreement
of where those locations are and how the log is sequenced in a naming
scheme so it's the same for every distribution. If the application is
in charge of trimming the log at a particular point, collection remains
the same (it can simply be the existing in-kernel location), so we
don't need a cross distro agreement, and the trim can simply be added
as an extra function.
Regards,
James
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/1] IMA event log trimming
2025-12-08 22:17 ` James Bottomley
@ 2025-12-09 9:36 ` Roberto Sassu
2025-12-10 19:16 ` Mimi Zohar
0 siblings, 1 reply; 12+ messages in thread
From: Roberto Sassu @ 2025-12-09 9:36 UTC (permalink / raw)
To: James Bottomley, steven chen, linux-integrity
Cc: zohar, roberto.sassu, dmitry.kasatkin, eric.snowberg, paul,
jmorris, serge, linux-security-module, anirudhve, gregorylumen,
nramas, sushring
On Tue, 2025-12-09 at 07:17 +0900, James Bottomley wrote:
> On Mon, 2025-12-08 at 10:40 +0100, Roberto Sassu wrote:
> > I have the impression that none the functionality you cited has to be
> > implemented in the kernel, because the only component one can trust
> > to verify the integrity of the IMA measurements list is the TPM.
> > Whether either the kernel or user space retain the measurements is
> > irrelevant.
>
> That's correct, I'm not advocating moving quoting into the kernel. Co-
> ordinating the trim with where the quote gets you to is phenomenally
> useful. While you could theoretically store any mismatch in userspace,
> having two locations for the log makes it more error prone.
>
> > I believe that the only role of the kernel is to get rid of the
> > measurements entries as fast as possible (the kernel would act more
> > like a buffer).
>
> I wouldn't say that, I'd say to get rid of measurements that the user
> has indicated are of no further use.
Different users could have different and conflicting requirements, and
we would spend time trying to conciliate those. We can avoid that by
doing it the same for everyone, and the additional cost of handling it
I believe it is fair.
I could accept staging N entries since I already agreed with Gregory
and Steven, and since it requires only an extra iteration in the linked
list. The other desired functionality should be implemented in user
space.
> > This was actually the intent of my original proposal in
> > https://github.com/linux-integrity/linux/issues/1 . The idea of
> > staging (was snapshotting, but Mimi thinks the term is not accurate)
> > is simply to detach the entire IMA measurement list as fast as
> > possible. Further read and delete after staging is done without
> > interfering with new measurements (sure, the detaching of the hash
> > table is not yet as efficient as I hoped).
>
> From the application point of view, offloading the log and random
> points is a bit more work because now the log collector has to be
> modified to look in multiple locations and we'd also need an agreement
> of where those locations are and how the log is sequenced in a naming
> scheme so it's the same for every distribution. If the application is
> in charge of trimming the log at a particular point, collection remains
> the same (it can simply be the existing in-kernel location), so we
> don't need a cross distro agreement, and the trim can simply be added
> as an extra function.
It could be a single location, the user space program would be
responsible to present the IMA measurement list as if it was never
trimmed.
Roberto
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/1] IMA event log trimming
2025-12-09 9:36 ` Roberto Sassu
@ 2025-12-10 19:16 ` Mimi Zohar
0 siblings, 0 replies; 12+ messages in thread
From: Mimi Zohar @ 2025-12-10 19:16 UTC (permalink / raw)
To: Roberto Sassu, James Bottomley, steven chen, linux-integrity
Cc: roberto.sassu, dmitry.kasatkin, eric.snowberg, paul, jmorris,
serge, linux-security-module, anirudhve, gregorylumen, nramas,
sushring
On Tue, 2025-12-09 at 10:36 +0100, Roberto Sassu wrote:
> On Tue, 2025-12-09 at 07:17 +0900, James Bottomley wrote:
> > On Mon, 2025-12-08 at 10:40 +0100, Roberto Sassu wrote:
> > > I have the impression that none the functionality you cited has to be
> > > implemented in the kernel, because the only component one can trust
> > > to verify the integrity of the IMA measurements list is the TPM.
> > > Whether either the kernel or user space retain the measurements is
> > > irrelevant.
> >
> > That's correct, I'm not advocating moving quoting into the kernel. Co-
> > ordinating the trim with where the quote gets you to is phenomenally
> > useful. While you could theoretically store any mismatch in userspace,
> > having two locations for the log makes it more error prone.
> >
> > > I believe that the only role of the kernel is to get rid of the
> > > measurements entries as fast as possible (the kernel would act more
> > > like a buffer).
> >
> > I wouldn't say that, I'd say to get rid of measurements that the user
> > has indicated are of no further use\
I really hope I'm wrong, but I don't like the sound of "No further use". The
complete IMA measurement needs to be saved somewhere to support multiple
verifiers.
>
> Different users could have different and conflicting requirements, and
> we would spend time trying to conciliate those. We can avoid that by
> doing it the same for everyone, and the additional cost of handling it
> I believe it is fair.
>
> I could accept staging N entries since I already agreed with Gregory
> and Steven, and since it requires only an extra iteration in the linked
> list. The other desired functionality should be implemented in user
> space.
>
> > > This was actually the intent of my original proposal in
> > > https://github.com/linux-integrity/linux/issues/1 . The idea of
> > > staging (was snapshotting, but Mimi thinks the term is not accurate)
> > > is simply to detach the entire IMA measurement list as fast as
> > > possible. Further read and delete after staging is done without
> > > interfering with new measurements (sure, the detaching of the hash
> > > table is not yet as efficient as I hoped).
> >
> > From the application point of view, offloading the log and random
> > points is a bit more work because now the log collector has to be
> > modified to look in multiple locations and we'd also need an agreement
> > of where those locations are and how the log is sequenced in a naming
> > scheme so it's the same for every distribution. If the application is
> > in charge of trimming the log at a particular point, collection remains
> > the same (it can simply be the existing in-kernel location), so we
> > don't need a cross distro agreement, and the trim can simply be added
> > as an extra function.
>
> It could be a single location, the user space program would be
> responsible to present the IMA measurement list as if it was never
> trimmed.
Even if it is a single, new location or user space program/daemon, it needs to
be documented. The user space program/daemon would be responsible for returning
the IMA measurement list.
Keylime, for example, supports incremental verification[1], meaning initially
the verification would be from the beginning of the IMA measurement list, but
subsequently the verifier could do an incremental verification. For incremental
verification, state information (e.g. number of records verified, pcr value)
needs to be preserved by the verifier, not the kernel.
[1] Keylime commit 7870f45f909f ("ima: Remember the number of lines successfully
processed and last IMA PCR value(s)")
--
thanks,
Mimi
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2025-12-10 19:17 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-02 23:28 [PATCH 0/1] Trim N entries of IMA event logs steven chen
2025-12-02 23:28 ` [PATCH 1/1] IMA event log trimming steven chen
2025-12-05 9:30 ` Roberto Sassu
2025-12-05 14:21 ` Roberto Sassu
2025-12-05 18:30 ` James Bottomley
2025-12-08 9:40 ` Roberto Sassu
2025-12-08 17:21 ` Gregory Lumen
2025-12-08 17:50 ` Roberto Sassu
2025-12-08 22:17 ` James Bottomley
2025-12-09 9:36 ` Roberto Sassu
2025-12-10 19:16 ` Mimi Zohar
2025-12-06 1:28 ` steven chen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).