public inbox for linux-security-module@vger.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH v3 0/4] Fix IMA + TPM initialisation ordering issue
@ 2026-04-24 13:23 Jonathan McDowell
  2026-04-24 13:24 ` [RFC PATCH v3 1/4] lsm: Allow LSMs to register for late_initcall_sync init Jonathan McDowell
                   ` (3 more replies)
  0 siblings, 4 replies; 11+ messages in thread
From: Jonathan McDowell @ 2026-04-24 13:23 UTC (permalink / raw)
  To: linux-security-module, linux-kernel, linux-integrity,
	linux-arm-kernel, kvmarm
  Cc: paul, jmorris, serge, zohar, roberto.sassu, dmitry.kasatkin,
	eric.snowberg, jarkko, jgg, sudeep.holla, maz, oupton, joey.gouly,
	suzuki.poulose, yuzenghui, catalin.marinas, will, noodles,
	sebastianene, Yeoreum Yun

This is a slight reworking of the series from Yeoreum Yun, adding
functionality for IMA initialisation during the late_initcall_sync
stage. This solves the situation where the TPM is not fully registered
at the point IMA wants to initialise, avoiding a failure to correctly
extend TPM measurements from IMA. This has been observed on both Arm
FF-A and SPI attached TPM setups.

As part of this series we also revert the original changes made to the
FF-A driver to try and solve this problem.

(I have left Yeoreum credited in all the diffs except my rework of the
 IMA piece. Yeoreum, please yell if you're not happy with this.)

Patch history
=============
from v2 to v3:
  - Drop ff-a/pKVM diff (this seems to have a separate set of
    discussion)
  - Rework IMA delayed initialisation to avoid delaying when unnecessary
  - Ensure IMA log clearly indicates when we've initialised late

from v1 to v2:
  - add notifier to make ffa-driver pkvm initialised.
  - modify to try initailisation again when IMA coudln't find proper TPM device.
  - https://lore.kernel.org/all/20260417175759.3191279-1-yeoreum.yun@arm.com/#t


Jonathan McDowell (1):
  security: ima: call ima_init() again at late_initcall_sync for defered
    TPM

Yeoreum Yun (3):
  lsm: Allow LSMs to register for late_initcall_sync init
  Revert "tpm: tpm_crb_ffa: try to probe tpm_crb_ffa when it's built-in"
  Revert "firmware: arm_ffa: Change initcall level of ffa_init() to
    rootfs_initcall"

 drivers/char/tpm/tpm_crb_ffa.c            | 19 ++----------
 drivers/firmware/arm_ffa/driver.c         |  2 +-
 include/linux/lsm_hooks.h                 |  2 ++
 security/integrity/ima/ima.h              |  3 +-
 security/integrity/ima/ima_init.c         | 25 ++++++++-------
 security/integrity/ima/ima_main.c         | 37 ++++++++++++++++++++---
 security/integrity/ima/ima_template_lib.c |  3 +-
 security/lsm_init.c                       | 13 ++++++--
 8 files changed, 67 insertions(+), 37 deletions(-)

-- 
2.53.0


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [RFC PATCH v3 1/4] lsm: Allow LSMs to register for late_initcall_sync init
  2026-04-24 13:23 [RFC PATCH v3 0/4] Fix IMA + TPM initialisation ordering issue Jonathan McDowell
@ 2026-04-24 13:24 ` Jonathan McDowell
  2026-04-24 13:24 ` [RFC PATCH v3 2/4] security: ima: call ima_init() again at late_initcall_sync for defered TPM Jonathan McDowell
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 11+ messages in thread
From: Jonathan McDowell @ 2026-04-24 13:24 UTC (permalink / raw)
  To: linux-security-module, linux-kernel, linux-integrity,
	linux-arm-kernel, kvmarm
  Cc: paul, jmorris, serge, zohar, roberto.sassu, dmitry.kasatkin,
	eric.snowberg, jarkko, jgg, sudeep.holla, maz, oupton, joey.gouly,
	suzuki.poulose, yuzenghui, catalin.marinas, will, noodles,
	sebastianene, Yeoreum Yun

From: Yeoreum Yun <yeoreum.yun@arm.com>

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.

[noodles: Split out from actual IMA changes]
Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
Signed-off-by: Jonathan McDowell <noodles@meta.com>
---
 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 d48bf0ad26f4..88fe105b7f00 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -166,6 +166,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;
@@ -181,6 +182,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 573e2a7250c4..4e5c59beb82a 100644
--- a/security/lsm_init.c
+++ b/security/lsm_init.c
@@ -547,13 +547,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);
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [RFC PATCH v3 2/4] security: ima: call ima_init() again at late_initcall_sync for defered TPM
  2026-04-24 13:23 [RFC PATCH v3 0/4] Fix IMA + TPM initialisation ordering issue Jonathan McDowell
  2026-04-24 13:24 ` [RFC PATCH v3 1/4] lsm: Allow LSMs to register for late_initcall_sync init Jonathan McDowell
@ 2026-04-24 13:24 ` Jonathan McDowell
  2026-04-24 16:55   ` Yeoreum Yun
  2026-04-24 20:25   ` Mimi Zohar
  2026-04-24 13:24 ` [RFC PATCH v3 3/4] Revert "tpm: tpm_crb_ffa: try to probe tpm_crb_ffa when it's built-in" Jonathan McDowell
  2026-04-24 13:24 ` [RFC PATCH v3 4/4] Revert "firmware: arm_ffa: Change initcall level of ffa_init() to rootfs_initcall" Jonathan McDowell
  3 siblings, 2 replies; 11+ messages in thread
From: Jonathan McDowell @ 2026-04-24 13:24 UTC (permalink / raw)
  To: linux-security-module, linux-kernel, linux-integrity,
	linux-arm-kernel, kvmarm
  Cc: paul, jmorris, serge, zohar, roberto.sassu, dmitry.kasatkin,
	eric.snowberg, jarkko, jgg, sudeep.holla, maz, oupton, joey.gouly,
	suzuki.poulose, yuzenghui, catalin.marinas, will, noodles,
	sebastianene, Yeoreum Yun

From: Jonathan McDowell <noodles@meta.com>

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!

and no measurements into the TPM by IMA. We can avoid this by doing IMA
init in the initcall_late_sync stage, after the drivers have completed
their init + registration.

Rather than do this everywhere, and needlessly delay the initialisation
of IMA when there is no need to do so, we continue to try to initialise
at the earlier stage, only deferring to the later point if the TPM is
not available yet.

Signed-off-by: Jonathan McDowell <noodles@meta.com>
---
 security/integrity/ima/ima.h              |  3 +-
 security/integrity/ima/ima_init.c         | 25 ++++++++-------
 security/integrity/ima/ima_main.c         | 37 ++++++++++++++++++++---
 security/integrity/ima/ima_template_lib.c |  3 +-
 4 files changed, 50 insertions(+), 18 deletions(-)

diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 89ebe98ffc5e..b3677b403a5a 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -65,6 +65,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 {
@@ -257,7 +258,7 @@ static inline void ima_measure_kexec_event(const char *event_name) {}
 extern bool ima_canonical_fmt;
 
 /* Internal IMA function definitions */
-int ima_init(void);
+int ima_init_core(bool late);
 int ima_fs_init(void);
 int ima_add_template_entry(struct ima_template_entry *entry, int violation,
 			   const char *op, struct inode *inode,
diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c
index a2f34f2d8ad7..5f335834a9bb 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
@@ -39,17 +40,17 @@ struct tpm_chip *ima_tpm_chip;
  * a different value.) Violations add a zero entry to the measurement
  * list and extend the aggregate PCR value with ff...ff's.
  */
-static int __init ima_add_boot_aggregate(void)
+static int __init ima_add_boot_aggregate(bool late)
 {
 	static const char op[] = "add_boot_aggregate";
 	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 (late)
+		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;
 }
@@ -115,14 +122,10 @@ void __init ima_load_x509(void)
 }
 #endif
 
-int __init ima_init(void)
+int __init ima_init_core(bool late)
 {
 	int rc;
 
-	ima_tpm_chip = tpm_default_chip();
-	if (!ima_tpm_chip)
-		pr_info("No TPM chip found, activating TPM-bypass!\n");
-
 	rc = integrity_init_keyring(INTEGRITY_KEYRING_IMA);
 	if (rc)
 		return rc;
@@ -140,7 +143,7 @@ int __init ima_init(void)
 	rc = ima_init_digests();
 	if (rc != 0)
 		return rc;
-	rc = ima_add_boot_aggregate();	/* boot aggregate must be first entry */
+	rc = ima_add_boot_aggregate(late);	/* boot aggregate must be first entry */
 	if (rc != 0)
 		return rc;
 
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 1d6229b156fb..0b93a286c0d3 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -1237,7 +1237,7 @@ static int ima_kernel_module_request(char *kmod_name)
 
 #endif /* CONFIG_INTEGRITY_ASYMMETRIC_KEYS */
 
-static int __init init_ima(void)
+static int __init init_ima(bool late)
 {
 	int error;
 
@@ -1247,10 +1247,26 @@ static int __init init_ima(void)
 		return 0;
 	}
 
+	/*
+	 * If we found the TPM during our first attempt, or we know there's no
+	 * TPM, nothing further to do
+	 */
+	if (late && (ima_tpm_chip || !IS_ENABLED(CONFIG_TCG_TPM)))
+		return 0;
+
+	ima_tpm_chip = tpm_default_chip();
+	if (!ima_tpm_chip && !late && IS_ENABLED(CONFIG_TCG_TPM)) {
+		pr_debug("TPM not available, will try later\n");
+		return -EPROBE_DEFER;
+	}
+
+	if (!ima_tpm_chip)
+		pr_info("No TPM chip found, activating TPM-bypass!\n");
+
 	ima_appraise_parse_cmdline();
 	ima_init_template_list();
 	hash_setup(CONFIG_IMA_DEFAULT_HASH);
-	error = ima_init();
+	error = ima_init_core(late);
 
 	if (error && strcmp(hash_algo_name[ima_hash_algo],
 			    CONFIG_IMA_DEFAULT_HASH) != 0) {
@@ -1258,7 +1274,7 @@ static int __init init_ima(void)
 			hash_algo_name[ima_hash_algo], CONFIG_IMA_DEFAULT_HASH);
 		hash_setup_done = 0;
 		hash_setup(CONFIG_IMA_DEFAULT_HASH);
-		error = ima_init();
+		error = ima_init_core(late);
 	}
 
 	if (error)
@@ -1274,6 +1290,16 @@ static int __init init_ima(void)
 	return error;
 }
 
+static int __init init_ima_late(void)
+{
+	return init_ima(false);
+}
+
+static int __init init_ima_late_sync(void)
+{
+	return init_ima(true);
+}
+
 static struct security_hook_list ima_hooks[] __ro_after_init = {
 	LSM_HOOK_INIT(bprm_check_security, ima_bprm_check),
 	LSM_HOOK_INIT(bprm_creds_for_exec, ima_bprm_creds_for_exec),
@@ -1319,6 +1345,7 @@ DEFINE_LSM(ima) = {
 	.init = init_ima_lsm,
 	.order = LSM_ORDER_LAST,
 	.blobs = &ima_blob_sizes,
-	/* Start IMA after the TPM is available */
-	.initcall_late = init_ima,
+	/* Ensure we start IMA after the TPM is available */
+	.initcall_late = init_ima_late,
+	.initcall_late_sync = init_ima_late_sync,
 };
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);
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [RFC PATCH v3 3/4] Revert "tpm: tpm_crb_ffa: try to probe tpm_crb_ffa when it's built-in"
  2026-04-24 13:23 [RFC PATCH v3 0/4] Fix IMA + TPM initialisation ordering issue Jonathan McDowell
  2026-04-24 13:24 ` [RFC PATCH v3 1/4] lsm: Allow LSMs to register for late_initcall_sync init Jonathan McDowell
  2026-04-24 13:24 ` [RFC PATCH v3 2/4] security: ima: call ima_init() again at late_initcall_sync for defered TPM Jonathan McDowell
@ 2026-04-24 13:24 ` Jonathan McDowell
  2026-04-24 16:10   ` Sudeep Holla
  2026-04-24 13:24 ` [RFC PATCH v3 4/4] Revert "firmware: arm_ffa: Change initcall level of ffa_init() to rootfs_initcall" Jonathan McDowell
  3 siblings, 1 reply; 11+ messages in thread
From: Jonathan McDowell @ 2026-04-24 13:24 UTC (permalink / raw)
  To: linux-security-module, linux-kernel, linux-integrity,
	linux-arm-kernel, kvmarm
  Cc: paul, jmorris, serge, zohar, roberto.sassu, dmitry.kasatkin,
	eric.snowberg, jarkko, jgg, sudeep.holla, maz, oupton, joey.gouly,
	suzuki.poulose, yuzenghui, catalin.marinas, will, noodles,
	sebastianene, Yeoreum Yun

From: Yeoreum Yun <yeoreum.yun@arm.com>

This reverts commit 746d9e9f62a6e8ba0eba2b83fc61cfe7fa8797ce.

Now that IMA will retry in the late_initcall_sync level if the TPM is
not available at first, this change is no longer required.

Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
Signed-off-by: Jonathan McDowell <noodles@meta.com>
---
 drivers/char/tpm/tpm_crb_ffa.c | 19 +++----------------
 1 file changed, 3 insertions(+), 16 deletions(-)

diff --git a/drivers/char/tpm/tpm_crb_ffa.c b/drivers/char/tpm/tpm_crb_ffa.c
index 99f1c1e5644b..05f19c0ebf82 100644
--- a/drivers/char/tpm/tpm_crb_ffa.c
+++ b/drivers/char/tpm/tpm_crb_ffa.c
@@ -123,7 +123,6 @@ struct tpm_crb_ffa {
 };
 
 static struct tpm_crb_ffa *tpm_crb_ffa;
-static struct ffa_driver tpm_crb_ffa_driver;
 
 static int tpm_crb_ffa_to_linux_errno(int errno)
 {
@@ -177,23 +176,13 @@ static int tpm_crb_ffa_to_linux_errno(int errno)
  */
 int tpm_crb_ffa_init(void)
 {
-	int ret = 0;
-
-	if (!IS_MODULE(CONFIG_TCG_ARM_CRB_FFA)) {
-		ret = ffa_register(&tpm_crb_ffa_driver);
-		if (ret) {
-			tpm_crb_ffa = ERR_PTR(-ENODEV);
-			return ret;
-		}
-	}
-
 	if (!tpm_crb_ffa)
-		ret = -ENOENT;
+		return -ENOENT;
 
 	if (IS_ERR_VALUE(tpm_crb_ffa))
-		ret = -ENODEV;
+		return -ENODEV;
 
-	return ret;
+	return 0;
 }
 EXPORT_SYMBOL_GPL(tpm_crb_ffa_init);
 
@@ -405,9 +394,7 @@ static struct ffa_driver tpm_crb_ffa_driver = {
 	.id_table = tpm_crb_ffa_device_id,
 };
 
-#ifdef MODULE
 module_ffa_driver(tpm_crb_ffa_driver);
-#endif
 
 MODULE_AUTHOR("Arm");
 MODULE_DESCRIPTION("TPM CRB FFA driver");
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [RFC PATCH v3 4/4] Revert "firmware: arm_ffa: Change initcall level of ffa_init() to rootfs_initcall"
  2026-04-24 13:23 [RFC PATCH v3 0/4] Fix IMA + TPM initialisation ordering issue Jonathan McDowell
                   ` (2 preceding siblings ...)
  2026-04-24 13:24 ` [RFC PATCH v3 3/4] Revert "tpm: tpm_crb_ffa: try to probe tpm_crb_ffa when it's built-in" Jonathan McDowell
@ 2026-04-24 13:24 ` Jonathan McDowell
  2026-04-24 16:09   ` Sudeep Holla
  2026-04-25 14:19   ` Jarkko Sakkinen
  3 siblings, 2 replies; 11+ messages in thread
From: Jonathan McDowell @ 2026-04-24 13:24 UTC (permalink / raw)
  To: linux-security-module, linux-kernel, linux-integrity,
	linux-arm-kernel, kvmarm
  Cc: paul, jmorris, serge, zohar, roberto.sassu, dmitry.kasatkin,
	eric.snowberg, jarkko, jgg, sudeep.holla, maz, oupton, joey.gouly,
	suzuki.poulose, yuzenghui, catalin.marinas, will, noodles,
	sebastianene, Yeoreum Yun

From: Yeoreum Yun <yeoreum.yun@arm.com>

This reverts commit 0e0546eabcd6c19765a8dbf5b5db3723e7b0ea75, which was
added to address ordering issues with the IMA LSM initialisation where
the TPM would not be fully ready by the time IMA wanted it. This has
been resolved within IMA by retrying setup during late_initcall_sync if
the TPM is not available at first.

Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
Signed-off-by: Jonathan McDowell <noodles@meta.com>
---
 drivers/firmware/arm_ffa/driver.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index f2f94d4d533e..01547c5c0e38 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -2106,7 +2106,7 @@ static int __init ffa_init(void)
 	kfree(drv_info);
 	return ret;
 }
-rootfs_initcall(ffa_init);
+module_init(ffa_init);
 
 static void __exit ffa_exit(void)
 {
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [RFC PATCH v3 4/4] Revert "firmware: arm_ffa: Change initcall level of ffa_init() to rootfs_initcall"
  2026-04-24 13:24 ` [RFC PATCH v3 4/4] Revert "firmware: arm_ffa: Change initcall level of ffa_init() to rootfs_initcall" Jonathan McDowell
@ 2026-04-24 16:09   ` Sudeep Holla
  2026-04-25 14:19   ` Jarkko Sakkinen
  1 sibling, 0 replies; 11+ messages in thread
From: Sudeep Holla @ 2026-04-24 16:09 UTC (permalink / raw)
  To: Jonathan McDowell
  Cc: linux-security-module, linux-kernel, Sudeep Holla,
	linux-integrity, linux-arm-kernel, kvmarm, paul, jmorris, serge,
	zohar, roberto.sassu, dmitry.kasatkin, eric.snowberg, jarkko, jgg,
	maz, oupton, joey.gouly, suzuki.poulose, yuzenghui,
	catalin.marinas, will, noodles, sebastianene, Yeoreum Yun

On Fri, Apr 24, 2026 at 02:24:42PM +0100, Jonathan McDowell wrote:
> From: Yeoreum Yun <yeoreum.yun@arm.com>
> 
> This reverts commit 0e0546eabcd6c19765a8dbf5b5db3723e7b0ea75, which was
> added to address ordering issues with the IMA LSM initialisation where
> the TPM would not be fully ready by the time IMA wanted it. This has
> been resolved within IMA by retrying setup during late_initcall_sync if
> the TPM is not available at first.
> 

Reviewed-by: Sudeep Holla <sudeep.holla@kernel.org>

-- 
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC PATCH v3 3/4] Revert "tpm: tpm_crb_ffa: try to probe tpm_crb_ffa when it's built-in"
  2026-04-24 13:24 ` [RFC PATCH v3 3/4] Revert "tpm: tpm_crb_ffa: try to probe tpm_crb_ffa when it's built-in" Jonathan McDowell
@ 2026-04-24 16:10   ` Sudeep Holla
  0 siblings, 0 replies; 11+ messages in thread
From: Sudeep Holla @ 2026-04-24 16:10 UTC (permalink / raw)
  To: Jonathan McDowell
  Cc: linux-security-module, linux-kernel, Sudeep Holla,
	linux-integrity, linux-arm-kernel, kvmarm, paul, jmorris, serge,
	zohar, roberto.sassu, dmitry.kasatkin, eric.snowberg, jarkko, jgg,
	maz, oupton, joey.gouly, suzuki.poulose, yuzenghui,
	catalin.marinas, will, noodles, sebastianene, Yeoreum Yun

On Fri, Apr 24, 2026 at 02:24:30PM +0100, Jonathan McDowell wrote:
> From: Yeoreum Yun <yeoreum.yun@arm.com>
> 
> This reverts commit 746d9e9f62a6e8ba0eba2b83fc61cfe7fa8797ce.
> 
> Now that IMA will retry in the late_initcall_sync level if the TPM is
> not available at first, this change is no longer required.
> 

Acked-by: Sudeep Holla <sudeep.holla@kernel.org>

-- 
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC PATCH v3 2/4] security: ima: call ima_init() again at late_initcall_sync for defered TPM
  2026-04-24 13:24 ` [RFC PATCH v3 2/4] security: ima: call ima_init() again at late_initcall_sync for defered TPM Jonathan McDowell
@ 2026-04-24 16:55   ` Yeoreum Yun
  2026-04-24 20:25   ` Mimi Zohar
  1 sibling, 0 replies; 11+ messages in thread
From: Yeoreum Yun @ 2026-04-24 16:55 UTC (permalink / raw)
  To: Jonathan McDowell
  Cc: linux-security-module, linux-kernel, linux-integrity,
	linux-arm-kernel, kvmarm, paul, jmorris, serge, zohar,
	roberto.sassu, dmitry.kasatkin, eric.snowberg, jarkko, jgg,
	sudeep.holla, maz, oupton, joey.gouly, suzuki.poulose, yuzenghui,
	catalin.marinas, will, noodles, sebastianene

> From: Jonathan McDowell <noodles@meta.com>
>
> 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!
>
> and no measurements into the TPM by IMA. We can avoid this by doing IMA
> init in the initcall_late_sync stage, after the drivers have completed
> their init + registration.
>
> Rather than do this everywhere, and needlessly delay the initialisation
> of IMA when there is no need to do so, we continue to try to initialise
> at the earlier stage, only deferring to the later point if the TPM is
> not available yet.
>
> Signed-off-by: Jonathan McDowell <noodles@meta.com>
> ---
>  security/integrity/ima/ima.h              |  3 +-
>  security/integrity/ima/ima_init.c         | 25 ++++++++-------
>  security/integrity/ima/ima_main.c         | 37 ++++++++++++++++++++---
>  security/integrity/ima/ima_template_lib.c |  3 +-
>  4 files changed, 50 insertions(+), 18 deletions(-)
>
> diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
> index 89ebe98ffc5e..b3677b403a5a 100644
> --- a/security/integrity/ima/ima.h
> +++ b/security/integrity/ima/ima.h
> @@ -65,6 +65,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 {
> @@ -257,7 +258,7 @@ static inline void ima_measure_kexec_event(const char *event_name) {}
>  extern bool ima_canonical_fmt;
>
>  /* Internal IMA function definitions */
> -int ima_init(void);
> +int ima_init_core(bool late);
>  int ima_fs_init(void);
>  int ima_add_template_entry(struct ima_template_entry *entry, int violation,
>  			   const char *op, struct inode *inode,
> diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c
> index a2f34f2d8ad7..5f335834a9bb 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
> @@ -39,17 +40,17 @@ struct tpm_chip *ima_tpm_chip;
>   * a different value.) Violations add a zero entry to the measurement
>   * list and extend the aggregate PCR value with ff...ff's.
>   */
> -static int __init ima_add_boot_aggregate(void)
> +static int __init ima_add_boot_aggregate(bool late)
>  {
>  	static const char op[] = "add_boot_aggregate";
>  	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 (late)
> +		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;
>  }
> @@ -115,14 +122,10 @@ void __init ima_load_x509(void)
>  }
>  #endif
>
> -int __init ima_init(void)
> +int __init ima_init_core(bool late)
>  {
>  	int rc;
>
> -	ima_tpm_chip = tpm_default_chip();
> -	if (!ima_tpm_chip)
> -		pr_info("No TPM chip found, activating TPM-bypass!\n");
> -
>  	rc = integrity_init_keyring(INTEGRITY_KEYRING_IMA);
>  	if (rc)
>  		return rc;
> @@ -140,7 +143,7 @@ int __init ima_init(void)
>  	rc = ima_init_digests();
>  	if (rc != 0)
>  		return rc;
> -	rc = ima_add_boot_aggregate();	/* boot aggregate must be first entry */
> +	rc = ima_add_boot_aggregate(late);	/* boot aggregate must be first entry */
>  	if (rc != 0)
>  		return rc;
>
> diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
> index 1d6229b156fb..0b93a286c0d3 100644
> --- a/security/integrity/ima/ima_main.c
> +++ b/security/integrity/ima/ima_main.c
> @@ -1237,7 +1237,7 @@ static int ima_kernel_module_request(char *kmod_name)
>
>  #endif /* CONFIG_INTEGRITY_ASYMMETRIC_KEYS */
>
> -static int __init init_ima(void)
> +static int __init init_ima(bool late)
>  {
>  	int error;
>
> @@ -1247,10 +1247,26 @@ static int __init init_ima(void)
>  		return 0;
>  	}
>
> +	/*
> +	 * If we found the TPM during our first attempt, or we know there's no
> +	 * TPM, nothing further to do
> +	 */
> +	if (late && (ima_tpm_chip || !IS_ENABLED(CONFIG_TCG_TPM)))
> +		return 0;
> +
> +	ima_tpm_chip = tpm_default_chip();
> +	if (!ima_tpm_chip && !late && IS_ENABLED(CONFIG_TCG_TPM)) {
> +		pr_debug("TPM not available, will try later\n");
> +		return -EPROBE_DEFER;
> +	}
> +
> +	if (!ima_tpm_chip)
> +		pr_info("No TPM chip found, activating TPM-bypass!\n");
> +
>  	ima_appraise_parse_cmdline();
>  	ima_init_template_list();
>  	hash_setup(CONFIG_IMA_DEFAULT_HASH);
> -	error = ima_init();
> +	error = ima_init_core(late);
>
>  	if (error && strcmp(hash_algo_name[ima_hash_algo],
>  			    CONFIG_IMA_DEFAULT_HASH) != 0) {
> @@ -1258,7 +1274,7 @@ static int __init init_ima(void)
>  			hash_algo_name[ima_hash_algo], CONFIG_IMA_DEFAULT_HASH);
>  		hash_setup_done = 0;
>  		hash_setup(CONFIG_IMA_DEFAULT_HASH);
> -		error = ima_init();
> +		error = ima_init_core(late);
>  	}
>
>  	if (error)
> @@ -1274,6 +1290,16 @@ static int __init init_ima(void)
>  	return error;
>  }
>
> +static int __init init_ima_late(void)
> +{
> +	return init_ima(false);
> +}
> +
> +static int __init init_ima_late_sync(void)
> +{
> +	return init_ima(true);
> +}
> +
>  static struct security_hook_list ima_hooks[] __ro_after_init = {
>  	LSM_HOOK_INIT(bprm_check_security, ima_bprm_check),
>  	LSM_HOOK_INIT(bprm_creds_for_exec, ima_bprm_creds_for_exec),
> @@ -1319,6 +1345,7 @@ DEFINE_LSM(ima) = {
>  	.init = init_ima_lsm,
>  	.order = LSM_ORDER_LAST,
>  	.blobs = &ima_blob_sizes,
> -	/* Start IMA after the TPM is available */
> -	.initcall_late = init_ima,
> +	/* Ensure we start IMA after the TPM is available */
> +	.initcall_late = init_ima_late,
> +	.initcall_late_sync = init_ima_late_sync,
>  };
> 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);
> --
> 2.53.0
>

This looks good to me. Feel free to add:
Reviewed-by: Yeoreum Yun <yeoreum.yun@arm.com>

Thanks!

--
Sincerely,
Yeoreum Yun

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC PATCH v3 2/4] security: ima: call ima_init() again at late_initcall_sync for defered TPM
  2026-04-24 13:24 ` [RFC PATCH v3 2/4] security: ima: call ima_init() again at late_initcall_sync for defered TPM Jonathan McDowell
  2026-04-24 16:55   ` Yeoreum Yun
@ 2026-04-24 20:25   ` Mimi Zohar
  2026-04-25  9:10     ` Jonathan McDowell
  1 sibling, 1 reply; 11+ messages in thread
From: Mimi Zohar @ 2026-04-24 20:25 UTC (permalink / raw)
  To: Jonathan McDowell, linux-security-module, linux-kernel,
	linux-integrity, linux-arm-kernel, kvmarm
  Cc: paul, jmorris, serge, roberto.sassu, dmitry.kasatkin,
	eric.snowberg, jarkko, jgg, sudeep.holla, maz, oupton, joey.gouly,
	suzuki.poulose, yuzenghui, catalin.marinas, will, noodles,
	sebastianene, Yeoreum Yun

Thanks, Jonathan!

On Fri, 2026-04-24 at 14:24 +0100, Jonathan McDowell wrote:
> -static int __init init_ima(void)
> +static int __init init_ima(bool late)
>  {
>  	int error;
>  
> @@ -1247,10 +1247,26 @@ static int __init init_ima(void)
>  		return 0;
>  	}
>  
> +	/*
> +	 * If we found the TPM during our first attempt, or we know there's no
> +	 * TPM, nothing further to do
> +	 */

Perhaps it's just me, but the comment wording is a bit off.  Could I change it
to: If we either found the TPM or knew there's no TPM during our first attempt,
nothing futher to do.

Otherwise the patch looks good.

Mimi


> +	if (late && (ima_tpm_chip || !IS_ENABLED(CONFIG_TCG_TPM)))
> +		return 0;
> +
> +	ima_tpm_chip = tpm_default_chip();
> +	if (!ima_tpm_chip && !late && IS_ENABLED(CONFIG_TCG_TPM)) {
> +		pr_debug("TPM not available, will try later\n");
> +		return -EPROBE_DEFER;
> +	}
> +
> +	if (!ima_tpm_chip)
> +		pr_info("No TPM chip found, activating TPM-bypass!\n");
> +

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC PATCH v3 2/4] security: ima: call ima_init() again at late_initcall_sync for defered TPM
  2026-04-24 20:25   ` Mimi Zohar
@ 2026-04-25  9:10     ` Jonathan McDowell
  0 siblings, 0 replies; 11+ messages in thread
From: Jonathan McDowell @ 2026-04-25  9:10 UTC (permalink / raw)
  To: Mimi Zohar
  Cc: linux-security-module, linux-kernel, linux-integrity,
	linux-arm-kernel, kvmarm, paul, jmorris, serge, roberto.sassu,
	dmitry.kasatkin, eric.snowberg, jarkko, jgg, sudeep.holla, maz,
	oupton, joey.gouly, suzuki.poulose, yuzenghui, catalin.marinas,
	will, noodles, sebastianene, Yeoreum Yun

On Fri, Apr 24, 2026 at 04:25:31PM -0400, Mimi Zohar wrote:
>Thanks, Jonathan!
>
>On Fri, 2026-04-24 at 14:24 +0100, Jonathan McDowell wrote:
>> -static int __init init_ima(void)
>> +static int __init init_ima(bool late)
>>  {
>>  	int error;
>>  
>> @@ -1247,10 +1247,26 @@ static int __init init_ima(void)
>>  		return 0;
>>  	}
>>  
>> +	/*
>> +	 * If we found the TPM during our first attempt, or we know there's no
>> +	 * TPM, nothing further to do
>> +	 */
>
>Perhaps it's just me, but the comment wording is a bit off.  Could I change it
>to: If we either found the TPM or knew there's no TPM during our first attempt,
>nothing futher to do.

No objections to that updated wording from me.

>Otherwise the patch looks good.
>
>Mimi
>
>
>> +	if (late && (ima_tpm_chip || !IS_ENABLED(CONFIG_TCG_TPM)))
>> +		return 0;
>> +
>> +	ima_tpm_chip = tpm_default_chip();
>> +	if (!ima_tpm_chip && !late && IS_ENABLED(CONFIG_TCG_TPM)) {
>> +		pr_debug("TPM not available, will try later\n");
>> +		return -EPROBE_DEFER;
>> +	}
>> +
>> +	if (!ima_tpm_chip)
>> +		pr_info("No TPM chip found, activating TPM-bypass!\n");
>> +

J.

-- 
Revd Jonathan McDowell, ULC | Run like hell!

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC PATCH v3 4/4] Revert "firmware: arm_ffa: Change initcall level of ffa_init() to rootfs_initcall"
  2026-04-24 13:24 ` [RFC PATCH v3 4/4] Revert "firmware: arm_ffa: Change initcall level of ffa_init() to rootfs_initcall" Jonathan McDowell
  2026-04-24 16:09   ` Sudeep Holla
@ 2026-04-25 14:19   ` Jarkko Sakkinen
  1 sibling, 0 replies; 11+ messages in thread
From: Jarkko Sakkinen @ 2026-04-25 14:19 UTC (permalink / raw)
  To: Jonathan McDowell
  Cc: linux-security-module, linux-kernel, linux-integrity,
	linux-arm-kernel, kvmarm, paul, jmorris, serge, zohar,
	roberto.sassu, dmitry.kasatkin, eric.snowberg, jgg, sudeep.holla,
	maz, oupton, joey.gouly, suzuki.poulose, yuzenghui,
	catalin.marinas, will, noodles, sebastianene, Yeoreum Yun

On Fri, Apr 24, 2026 at 02:24:42PM +0100, Jonathan McDowell wrote:
> From: Yeoreum Yun <yeoreum.yun@arm.com>
> 
> This reverts commit 0e0546eabcd6c19765a8dbf5b5db3723e7b0ea75, which was
> added to address ordering issues with the IMA LSM initialisation where
> the TPM would not be fully ready by the time IMA wanted it. This has
> been resolved within IMA by retrying setup during late_initcall_sync if
> the TPM is not available at first.
> 
> Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
> Signed-off-by: Jonathan McDowell <noodles@meta.com>
> ---
>  drivers/firmware/arm_ffa/driver.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
> index f2f94d4d533e..01547c5c0e38 100644
> --- a/drivers/firmware/arm_ffa/driver.c
> +++ b/drivers/firmware/arm_ffa/driver.c
> @@ -2106,7 +2106,7 @@ static int __init ffa_init(void)
>  	kfree(drv_info);
>  	return ret;
>  }
> -rootfs_initcall(ffa_init);
> +module_init(ffa_init);
>  
>  static void __exit ffa_exit(void)
>  {
> -- 
> 2.53.0
> 

LGTM (for both tpm patches).

However, I'll hold on any further comments/tags up until I've sorted 7.1 PRs
(just so that I have full focus).

BR, Jarkko

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2026-04-25 14:19 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-24 13:23 [RFC PATCH v3 0/4] Fix IMA + TPM initialisation ordering issue Jonathan McDowell
2026-04-24 13:24 ` [RFC PATCH v3 1/4] lsm: Allow LSMs to register for late_initcall_sync init Jonathan McDowell
2026-04-24 13:24 ` [RFC PATCH v3 2/4] security: ima: call ima_init() again at late_initcall_sync for defered TPM Jonathan McDowell
2026-04-24 16:55   ` Yeoreum Yun
2026-04-24 20:25   ` Mimi Zohar
2026-04-25  9:10     ` Jonathan McDowell
2026-04-24 13:24 ` [RFC PATCH v3 3/4] Revert "tpm: tpm_crb_ffa: try to probe tpm_crb_ffa when it's built-in" Jonathan McDowell
2026-04-24 16:10   ` Sudeep Holla
2026-04-24 13:24 ` [RFC PATCH v3 4/4] Revert "firmware: arm_ffa: Change initcall level of ffa_init() to rootfs_initcall" Jonathan McDowell
2026-04-24 16:09   ` Sudeep Holla
2026-04-25 14:19   ` Jarkko Sakkinen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox