The Subject line describes "how", not "what". Consider renaming it to "ima: measure userspace policy writes before parsing".
On Wed, 2026-06-17 at 17:58 +0200, Enrico Bravi wrote: > When a signed policy is not mandatory, it is possible to write the IMA > policy directly on the corresponding securityfs file: When a signed policy is not mandatory, userspace can write IMA policy rules directly to the securityfs policy file: > > echo -e "measure func=BPRM_CHECK mask=MAY_EXEC\n" \ > "audit func=BPRM_CHECK mask=MAY_EXEC\n" \ > > /sys/kernel/security/ima/policy > > or by cat'ing the entire IMA custom policy file: > > cat ima-policy-file > /sys/kernel/security/ima/policy Because these rules originate from userspace and cross the userspace/kernel trust boundary, measure the raw write buffer before parsing. > > Add input buffer measurement, regardless of whether the new policy > will be accepted or not, that can be caught when > 'measure func=POLICY_CHECK' is enabled (e.g., ima_policy=tcb). The > measurement template is forced to ima-buf. > This follows the "measure & load" paradigm, exposing potential bugs in > the policy code and detecting attempts to corrupt IMA. It also completes > the POLICY_CHECK hook, which already measures partial policy load by file. > > To verify the template data hash value, convert the buffer policy data > to binary: > grep "ima_policy_written" \ > /sys/kernel/security/integrity/ima/ascii_runtime_measurements | \ > tail -1 | cut -d' ' -f 6 | xxd -r -p | sha256sum > > Suggested-by: Roberto Sassu <[email protected]> > Signed-off-by: Enrico Bravi <[email protected]> > --- > security/integrity/ima/ima.h | 1 + > security/integrity/ima/ima_fs.c | 1 + > security/integrity/ima/ima_main.c | 19 +++++++++++++++++++ > security/integrity/ima/ima_policy.c | 3 +++ > 4 files changed, 24 insertions(+) > > diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h > index befa221716e5..d477fc06821f 100644 > --- a/security/integrity/ima/ima.h > +++ b/security/integrity/ima/ima.h > @@ -455,6 +455,7 @@ void *ima_policy_next(struct seq_file *m, void *v, loff_t > *pos); > void ima_policy_stop(struct seq_file *m, void *v); > int ima_policy_show(struct seq_file *m, void *v); > void ima_measure_loaded_policy(void); > +int ima_measure_policy_buf(const char *buf, size_t buf_len); > > /* Appraise integrity measurements */ > #define IMA_APPRAISE_ENFORCE 0x01 > diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c > index 65e7812c702f..a277c9135944 100644 > --- a/security/integrity/ima/ima_fs.c > +++ b/security/integrity/ima/ima_fs.c > @@ -356,6 +356,7 @@ static ssize_t ima_write_policy(struct file *file, const > char __user *buf, > 1, 0); > result = -EACCES; > } else { > + ima_measure_policy_buf(data, datalen); Should failure to measure the input policy rules be audited? > result = ima_parse_add_rule(data); > } > mutex_unlock(&ima_write_mutex); > diff --git a/security/integrity/ima/ima_main.c > b/security/integrity/ima/ima_main.c > index 5cea53fc36df..599495304712 100644 > --- a/security/integrity/ima/ima_main.c > +++ b/security/integrity/ima/ima_main.c > @@ -1221,6 +1221,25 @@ int ima_measure_critical_data(const char *event_label, > } > EXPORT_SYMBOL_GPL(ima_measure_critical_data); > > +/** > + * ima_measure_policy_buf - Measure the policy write buffer Consider renaming this function to ima_measure_policy_input(), which parallels the function ima_measure_loaded_policy() in the first patch. Mimi > + * @buf: pointer to the buffer containing the policy write data > + * @buf_len: size of the buffer > + * > + * Measure the buffer sent to the IMA policy securityfs file. > + * > + * Return 0 on success, a negative value otherwise. > + */ > +int ima_measure_policy_buf(const char *buf, size_t buf_len) > +{ > + if (!buf || !buf_len) > + return -EINVAL; > + > + return process_buffer_measurement(&nop_mnt_idmap, NULL, buf, buf_len, > + "ima_policy_written", POLICY_CHECK, 0, > + NULL, false, NULL, 0); > +} > + > #ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS > > /**
