From 510e75f76624b8ab4748a380b3ecb4d50166338d Mon Sep 17 00:00:00 2001 From: Yeoreum Yun Date: Fri, 5 Jun 2026 15:43:22 +0100 Subject: [PATCH 1/5] security: lsm: allow LSMs to register for late_initcall_sync init There are situations where LSMs have dependencies that might mean they want to be initialised later in the boot process, to ensure those dependencies are available. In particular there are some TPM setups (Arm FF-A devices, SPI attached TPMs) required by IMA which are not guaranteed to be initialised for regular initcall_late. Add an initcall_late_sync option that can be used in these situations. Signed-off-by: Yeoreum Yun Cc: Paul Moore Acked-by: Paul Moore Signed-off-by: Mimi Zohar --- include/linux/lsm_hooks.h | 2 ++ security/lsm_init.c | 13 +++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index b4f8cad53ddb..c4488c4a6d8a 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -167,6 +167,7 @@ enum lsm_order { * @initcall_fs: LSM callback for fs_initcall setup, optional * @initcall_device: LSM callback for device_initcall() setup, optional * @initcall_late: LSM callback for late_initcall() setup, optional + * @initcall_late_sync: LSM callback for late_initcall_sync() setup, optional */ struct lsm_info { const struct lsm_id *id; @@ -182,6 +183,7 @@ struct lsm_info { int (*initcall_fs)(void); int (*initcall_device)(void); int (*initcall_late)(void); + int (*initcall_late_sync)(void); }; #define DEFINE_LSM(lsm) \ diff --git a/security/lsm_init.c b/security/lsm_init.c index 7c0fd17f1601..a1ad641811de 100644 --- a/security/lsm_init.c +++ b/security/lsm_init.c @@ -556,13 +556,22 @@ device_initcall(security_initcall_device); * security_initcall_late - Run the LSM late initcalls */ static int __init security_initcall_late(void) +{ + return lsm_initcall(late); +} +late_initcall(security_initcall_late); + +/** + * security_initcall_late_sync - Run the LSM late initcalls sync + */ +static int __init security_initcall_late_sync(void) { int rc; - rc = lsm_initcall(late); + rc = lsm_initcall(late_sync); lsm_pr_dbg("all enabled LSMs fully activated\n"); call_blocking_lsm_notifier(LSM_STARTED_ALL, NULL); return rc; } -late_initcall(security_initcall_late); +late_initcall_sync(security_initcall_late_sync); From 42f66395c3e5aae17eb1a60bdd7ac48ca27b1f41 Mon Sep 17 00:00:00 2001 From: Yeoreum Yun Date: Fri, 5 Jun 2026 15:43:23 +0100 Subject: [PATCH 2/5] security: ima: introduce IMA_INIT_LATE_SYNC option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To generate the boot_aggregate log in the IMA subsystem with TPM PCR values, the TPM driver must be built as built-in and must be probed before the IMA subsystem is initialized. However, when the TPM device operates over the FF-A protocol using the CRB interface, probing fails and returns -EPROBE_DEFER if the tpm_crb_ffa device — an FF-A device that provides the communication interface to the tpm_crb driver — has not yet been probed. To ensure the TPM device operating over the FF-A protocol with the CRB interface is probed before IMA initialization, the following conditions must be met: 1. The corresponding ffa_device must be registered, which is done via ffa_init(). 2. The tpm_crb_driver must successfully probe this device via tpm_crb_ffa_init(). 3. The tpm_crb driver using CRB over FF-A can then be probed successfully. (See crb_acpi_add() and tpm_crb_ffa_init() for reference.) Unfortunately, ffa_init(), tpm_crb_ffa_init(), and crb_acpi_driver_init() are all registered with device_initcall, which means crb_acpi_driver_init() may be invoked before ffa_init() and tpm_crb_ffa_init() are completed. When this occurs, probing the TPM device is deferred. However, the deferred probe can happen after the IMA subsystem has already been initialized, since IMA initialization is performed during late_initcall, and deferred_probe_initcall() is performed at the same level. And the similar situation is reported on TPM devices attached on SPI bus[0]. To resolve this, introduce IMA_INIT_LATE_SYNC option to initialise IMA at late_inicall_sync so that IMA is initialized with the TPM device probed deferred. When this option is enabled, modules that access files in the initramfs through usermode helper calls such as request_module() during initcall must not be built-in. Otherwise, IMA may miss measuring those files [1]. Link: https://lore.kernel.org/all/aYXEepLhUouN5f99@earth.li/ [0] Link: https://lore.kernel.org/all/2b3782398cc17ce9d355490a0c42ebce9120a9ae.camel@linux.ibm.com/ [1] Suggested-by: Mimi Zohar Signed-off-by: Yeoreum Yun [zohar@linux.ibm.com: Fixed Kconfig merge conflict] Signed-off-by: Mimi Zohar --- security/integrity/ima/Kconfig | 10 ++++++++++ security/integrity/ima/ima_main.c | 4 ++++ 2 files changed, 14 insertions(+) diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig index f4d25e045808..b3a9f86809b0 100644 --- a/security/integrity/ima/Kconfig +++ b/security/integrity/ima/Kconfig @@ -347,4 +347,14 @@ config IMA_STAGING On kexec, staging is aborted and any staged measurement records are copied to the secondary kernel. +config IMA_INIT_LATE_SYNC + bool "Initialise IMA at late_initcall_sync" + default n + help + This option initialises IMA at late_initcall_sync for platforms + where TPM device probing is deferred. + When this option is enabled, modules that access files in the + initramfs through usermode helper calls such as request_module() + during initcall must not be built-in. Otherwise, IMA may miss + file measurements for them. endif diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 5cea53fc36df..1cfae4b83dc5 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -1337,5 +1337,9 @@ DEFINE_LSM(ima) = { .order = LSM_ORDER_LAST, .blobs = &ima_blob_sizes, /* Start IMA after the TPM is available */ +#ifndef CONFIG_IMA_INIT_LATE_SYNC .initcall_late = init_ima, +#else + .initcall_late_sync = init_ima, +#endif }; From 81429cd0161ae654454c2b277a1db2c0ecb7712e Mon Sep 17 00:00:00 2001 From: Jonathan McDowell Date: Fri, 5 Jun 2026 15:43:24 +0100 Subject: [PATCH 3/5] security: ima: rename boot_aggregate when ima is initialised at late_sync MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Linux IMA (Integrity Measurement Architecture) subsystem used for secure boot, file integrity, or remote attestation cannot be a loadable module for few reasons listed below: o Boot-Time Integrity: IMA’s main role is to measure and appraise files before they are used. This includes measuring critical system files during early boot (e.g., init, init scripts, login binaries). If IMA were a module, it would be loaded too late to cover those. o TPM Dependency: IMA integrates tightly with the TPM to record measurements into PCRs. The TPM must be initialized early (ideally before init_ima()), which aligns with IMA being built-in. o Security Model: IMA is part of a Trusted Computing Base (TCB). Making it a module would weaken the security model, as a potentially compromised system could delay or tamper with its initialization. IMA must be built-in to ensure it starts measuring from the earliest possible point in boot which inturn implies TPM must be initialised and ready to use before IMA. Unfortunately some TPM drivers (such as Arm FF-A, or SPI attached TPM devices) are not reliably available during the initcall_late stage, resulting in a log error: ima: No TPM chip found, activating TPM-bypass! To address this issue, IMA_INIT_LATE_SYNC is introduced. However, a remote attestation service cannot determine when IMA has been initialized because the boot_aggregate measurement name remains unchanged, even though IMA is initialized later at late_initcall_sync when IMA_INIT_LATE_SYNC is enabled. Therefore, use a distinct boot_aggregate name when IMA_INIT_LATE_SYNC is enabled, allowing the remote attestation service to identify when IMA has been initialized. Signed-off-by: Jonathan McDowell [yeoreum.yun@arm.com: modified to align with the IMA_INIT_LATE_SYNC change] Signed-off-by: Yeoreum Yun Signed-off-by: Mimi Zohar --- security/integrity/ima/ima.h | 1 + security/integrity/ima/ima_init.c | 15 +++++++++++---- security/integrity/ima/ima_template_lib.c | 3 ++- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index caaedd4b58fd..cebaeb620b89 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -75,6 +75,7 @@ extern struct ima_algo_desc *ima_algo_array __ro_after_init; extern int ima_appraise; extern struct tpm_chip *ima_tpm_chip; extern const char boot_aggregate_name[]; +extern const char boot_aggregate_late_name[]; /* IMA event related data */ struct ima_event_data { diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index 7e0aa09a12e6..d53f4d89a53e 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -22,6 +22,7 @@ /* name for boot aggregate entry */ const char boot_aggregate_name[] = "boot_aggregate"; +const char boot_aggregate_late_name[] = "boot_aggregate_late"; struct tpm_chip *ima_tpm_chip; /* Add the boot aggregate to the IMA measurement list and extend @@ -45,11 +46,11 @@ static int __init ima_add_boot_aggregate(void) const char *audit_cause = "ENOMEM"; struct ima_template_entry *entry; struct ima_iint_cache tmp_iint, *iint = &tmp_iint; - struct ima_event_data event_data = { .iint = iint, - .filename = boot_aggregate_name }; + struct ima_event_data event_data = { .iint = iint }; struct ima_max_digest_data hash; struct ima_digest_data *hash_hdr = container_of(&hash.hdr, struct ima_digest_data, hdr); + const char *filename; int result = -ENOMEM; int violation = 0; @@ -59,6 +60,12 @@ static int __init ima_add_boot_aggregate(void) iint->ima_hash->algo = ima_hash_algo; iint->ima_hash->length = hash_digest_size[ima_hash_algo]; + if (IS_ENABLED(CONFIG_IMA_INIT_LATE_SYNC)) + filename = boot_aggregate_late_name; + else + filename = boot_aggregate_name; + event_data.filename = filename; + /* * With TPM 2.0 hash agility, TPM chips could support multiple TPM * PCR banks, allowing firmware to configure and enable different @@ -86,7 +93,7 @@ static int __init ima_add_boot_aggregate(void) } result = ima_store_template(entry, violation, NULL, - boot_aggregate_name, + filename, CONFIG_IMA_MEASURE_PCR_IDX); if (result < 0) { ima_free_template_entry(entry); @@ -95,7 +102,7 @@ static int __init ima_add_boot_aggregate(void) } return 0; err_out: - integrity_audit_msg(AUDIT_INTEGRITY_PCR, NULL, boot_aggregate_name, op, + integrity_audit_msg(AUDIT_INTEGRITY_PCR, NULL, filename, op, audit_cause, result, 0); return result; } diff --git a/security/integrity/ima/ima_template_lib.c b/security/integrity/ima/ima_template_lib.c index 0e627eac9c33..8a89236f926c 100644 --- a/security/integrity/ima/ima_template_lib.c +++ b/security/integrity/ima/ima_template_lib.c @@ -363,7 +363,8 @@ int ima_eventdigest_init(struct ima_event_data *event_data, goto out; } - if ((const char *)event_data->filename == boot_aggregate_name) { + if ((const char *)event_data->filename == boot_aggregate_name || + (const char *)event_data->filename == boot_aggregate_late_name) { if (ima_tpm_chip) { hash.hdr.algo = HASH_ALGO_SHA1; result = ima_calc_boot_aggregate(hash_hdr); From 12ca6fae798bd567348369ced3531131278f979b Mon Sep 17 00:00:00 2001 From: Enrico Bravi Date: Mon, 13 Jul 2026 10:09:56 +0200 Subject: [PATCH 4/5] ima: add critical data measurement for loaded policy IMA policy can be written multiple times in the securityfs policy file at runtime if CONFIG_IMA_WRITE_POLICY=y. When IMA_APPRAISE_POLICY is required, the policy needs to be signed to be loaded, writing the absolute path of the file containing the new policy: echo /path/of/custom_ima_policy > /sys/kernel/security/ima/policy When this is not required, policy can be written directly, rule by rule: echo -e "measure func=BPRM_CHECK mask=MAY_EXEC\n" \ "audit func=BPRM_CHECK mask=MAY_EXEC\n" \ > /sys/kernel/security/ima/policy In this case, a new policy can be loaded without being measured or appraised. Add a new critical data record to measure the textual policy representation when it becomes effective. Include in the architecture-specific policy the new critical data record only when it is not mandatory to load a signed policy. Additionally, enable the policy serialization code even when CONFIG_IMA_READ_POLICY=n. To verify the template data hash value, convert the buffer policy data to binary: grep "ima_policy_loaded" \ /sys/kernel/security/integrity/ima/ascii_runtime_measurements | \ tail -1 | cut -d' ' -f 6 | xxd -r -p | sha256sum Signed-off-by: Enrico Bravi Signed-off-by: Mimi Zohar --- security/integrity/ima/ima.h | 3 + security/integrity/ima/ima_efi.c | 2 + security/integrity/ima/ima_fs.c | 8 ++- security/integrity/ima/ima_policy.c | 89 ++++++++++++++++++++++++++++- 4 files changed, 99 insertions(+), 3 deletions(-) diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index cebaeb620b89..6817ee53ed9e 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -55,6 +55,8 @@ enum binary_lists { /* current content of the policy */ extern int ima_policy_flag; +extern struct mutex ima_write_mutex; + /* bitset of digests algorithms allowed in the setxattr hook */ extern atomic_t ima_setxattr_allowed_hash_algorithms; @@ -467,6 +469,7 @@ void *ima_policy_start(struct seq_file *m, loff_t *pos); 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); /* Appraise integrity measurements */ #define IMA_APPRAISE_ENFORCE 0x01 diff --git a/security/integrity/ima/ima_efi.c b/security/integrity/ima/ima_efi.c index bca57d836cb9..be7911009454 100644 --- a/security/integrity/ima/ima_efi.c +++ b/security/integrity/ima/ima_efi.c @@ -17,6 +17,8 @@ static const char * const sb_arch_rules[] = { #endif #if IS_ENABLED(CONFIG_INTEGRITY_MACHINE_KEYRING) && IS_ENABLED(CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY) "appraise func=POLICY_CHECK appraise_type=imasig", +#else + "measure func=CRITICAL_DATA label=ima_policy", #endif "measure func=MODULE_CHECK", NULL diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index 174a94740da1..92ca4d62c94d 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -32,7 +32,9 @@ */ #define STAGED_REQ_LENGTH 21 -static DEFINE_MUTEX(ima_write_mutex); +/* lock for protecting concurrent IMA policy updates */ +DEFINE_MUTEX(ima_write_mutex); + static DEFINE_MUTEX(ima_measure_mutex); static long ima_measure_users; static struct task_struct *measure_writer; @@ -752,6 +754,10 @@ static int ima_release_policy(struct inode *inode, struct file *file) } ima_update_policy(); + + mutex_lock(&ima_write_mutex); + ima_measure_loaded_policy(); + mutex_unlock(&ima_write_mutex); #if !defined(CONFIG_IMA_WRITE_POLICY) && !defined(CONFIG_IMA_READ_POLICY) securityfs_remove(file->f_path.dentry); #elif defined(CONFIG_IMA_WRITE_POLICY) diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index b1c010e8eb13..09da140de67c 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -53,6 +53,8 @@ #define INVALID_PCR(a) (((a) < 0) || \ (a) >= (sizeof_field(struct ima_iint_cache, measured_pcrs) * 8)) +static size_t max_rule_len; + int ima_policy_flag; static int temp_ima_appraise; static int build_ima_appraise __ro_after_init; @@ -955,6 +957,8 @@ void __init ima_init_policy(void) { int build_appraise_entries, arch_entries; + max_rule_len = 255; + /* if !ima_policy, we load NO default rules */ if (ima_policy) add_rules(dont_measure_rules, ARRAY_SIZE(dont_measure_rules), @@ -1994,6 +1998,9 @@ ssize_t ima_parse_add_rule(char *rule) list_add_tail(&entry->list, &ima_temp_rules); + if (len > max_rule_len) + max_rule_len = len; + return len; } @@ -2021,7 +2028,6 @@ const char *const func_tokens[] = { __ima_hooks(__ima_hook_stringify) }; -#ifdef CONFIG_IMA_READ_POLICY enum { mask_exec = 0, mask_write, mask_read, mask_append }; @@ -2323,7 +2329,6 @@ int ima_policy_show(struct seq_file *m, void *v) seq_puts(m, "\n"); return 0; } -#endif /* CONFIG_IMA_READ_POLICY */ #if defined(CONFIG_IMA_APPRAISE) && defined(CONFIG_INTEGRITY_TRUSTED_KEYRING) /* @@ -2380,3 +2385,83 @@ bool ima_appraise_signature(enum kernel_read_file_id id) return found; } #endif /* CONFIG_IMA_APPRAISE && CONFIG_INTEGRITY_TRUSTED_KEYRING */ + +/** + * ima_measure_loaded_policy - measure the active IMA policy ruleset + * + * Must be called with ima_write_mutex held, as it performs two + * separate RCU read passes over ima_rules and relies on the mutex + * to prevent concurrent policy updates between them. + */ +void ima_measure_loaded_policy(void) +{ + const char *event_name = "ima_policy_loaded"; + const char *op = "measure_loaded_ima_policy"; + size_t rule_len = max_rule_len + 2; + struct ima_rule_entry *rule_entry; + struct list_head *ima_rules_tmp; + struct seq_file file = { 0 }; + int result = -ENOMEM; + size_t file_len = 0; + char *rule; + + lockdep_assert_held(&ima_write_mutex); + + rule = kmalloc(rule_len, GFP_KERNEL); + if (!rule) { + integrity_audit_msg(AUDIT_INTEGRITY_PCR, NULL, event_name, + op, "ENOMEM", result, 0); + return; + } + + /* calculate IMA policy rules memory size */ + file.buf = rule; + file.read_pos = 0; + file.size = rule_len; + file.count = 0; + + rcu_read_lock(); + ima_rules_tmp = rcu_dereference(ima_rules); + list_for_each_entry_rcu(rule_entry, ima_rules_tmp, list) { + ima_policy_show(&file, rule_entry); + + if (seq_has_overflowed(&file)) { + result = -E2BIG; + integrity_audit_msg(AUDIT_INTEGRITY_PCR, NULL, + event_name, op, "rule_length", + result, 0); + rcu_read_unlock(); + goto free_rule; + } + + file_len += file.count; + file.count = 0; + } + rcu_read_unlock(); + + /* copy IMA policy rules to a buffer for measuring */ + file.buf = kmalloc(file_len, GFP_KERNEL); + if (!file.buf) { + integrity_audit_msg(AUDIT_INTEGRITY_PCR, NULL, event_name, + op, "ENOMEM", result, 0); + goto free_rule; + } + + file.read_pos = 0; + file.size = file_len; + file.count = 0; + + rcu_read_lock(); + ima_rules_tmp = rcu_dereference(ima_rules); + list_for_each_entry_rcu(rule_entry, ima_rules_tmp, list) { + ima_policy_show(&file, rule_entry); + } + rcu_read_unlock(); + + ima_measure_critical_data("ima_policy", event_name, file.buf, + file.count, false, NULL, 0); + + kfree(file.buf); +free_rule: + kfree(rule); +} From 1da739feb31b4fecae465ebf87ba44a97e44101b Mon Sep 17 00:00:00 2001 From: Enrico Bravi Date: Mon, 13 Jul 2026 10:09:58 +0200 Subject: [PATCH 5/5] ima: measure userspace policy writes before parsing 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, regardless of whether the new policy will be accepted or not. This 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 Signed-off-by: Enrico Bravi Signed-off-by: Mimi Zohar --- security/integrity/ima/ima.h | 1 + security/integrity/ima/ima_fs.c | 1 + security/integrity/ima/ima_main.c | 22 ++++++++++++++++++++++ security/integrity/ima/ima_policy.c | 6 ++++++ 4 files changed, 30 insertions(+) diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 6817ee53ed9e..10214f73ca1e 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -470,6 +470,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_raw_policy(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 92ca4d62c94d..2a0bca554316 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -598,6 +598,7 @@ static ssize_t ima_write_policy(struct file *file, const char __user *buf, 1, 0); result = -EACCES; } else { + ima_measure_raw_policy(data, datalen); 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 1cfae4b83dc5..334e21be4075 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -1221,6 +1221,28 @@ int ima_measure_critical_data(const char *event_label, } EXPORT_SYMBOL_GPL(ima_measure_critical_data); +/** + * ima_measure_raw_policy - Measure the raw policy write buffer + * @buf: pointer to the buffer containing the raw policy data + * @buf_len: size of the buffer + * + * Measure the raw policy buffer sent to the IMA policy securityfs file. The + * buffer is written from userspace, and the measurement is performed before + * parsing it. This measurement includes any data written on the policy file + * such as malformed policy rules and comments. + * + * Return 0 on success, a negative value otherwise. + */ +int ima_measure_raw_policy(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 /** diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 09da140de67c..f79d07bb63c6 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -542,6 +542,8 @@ static bool ima_match_rule_data(struct ima_rule_entry *rule, opt_list = rule->label; break; + case POLICY_CHECK: + return true; default: return false; } @@ -588,6 +590,10 @@ static bool ima_match_rules(struct ima_rule_entry *rule, return false; switch (func) { + case POLICY_CHECK: + if (inode) + break; + fallthrough; case KEY_CHECK: case CRITICAL_DATA: return ((rule->func == func) &&