Linux Integrity Measurement development
 help / color / mirror / Atom feed
* Re: [RFC 0/4] tpm_crb: Add command and response buffer chunking support
From: Arun Menon @ 2026-04-23 10:43 UTC (permalink / raw)
  To: Jarkko Sakkinen, Stefan Berger
  Cc: linux-kernel, linux-integrity, Jason Gunthorpe, Peter Huewe
In-Reply-To: <adYTLq0qgWpA1kIS@kernel.org>

On Wed, Apr 08, 2026 at 11:34:54AM +0300, Jarkko Sakkinen wrote:
> On Tue, Mar 24, 2026 at 06:11:11PM +0530, Arun Menon wrote:
> > Hi Jarkko,
> > 
> > On Tue, Mar 24, 2026 at 12:41:26PM +0200, Jarkko Sakkinen wrote:
> > > On Tue, Mar 24, 2026 at 12:47:59PM +0530, Arun Menon wrote:
> > > > The new version of TCG TPM v185 (currently under review [1]) supports
> > > > sending data/commands in chunks for the CRB (Command Response Buffer)
> > > > interface. This is in line with the initiative to support PQC algorithms.
> > > > 
> > > > This series implements the logic to send and receive larger TPM
> > > > cmd/rsp between the linux guest and the TPM backend in chunks.
> > > > Currently, the TPM CRB driver is limited by the physical size of the
> > > > MMIO window. When userspace attempts to send a payload that exceeds this
> > > > size, the driver rejects it.
> > > > 
> > > > This series introduces chunking support. The driver now checks the CRB
> > > > interface capability for CRB_INTF_CAP_CRB_CHUNK. If supported by the
> > > > backend, the driver will slice oversized commands into MMIO-sized
> > > > chunks, signalling the backend via CRB_START_NEXT_CHUNK, and finalizing
> > > > with CRB_START_INVOKE. Responses are also read back in a similar chunked
> > > > manner.
> > > > 
> > > > If the backend does not support chunking, the driver retains its legacy
> > > > behaviour and enforces the standard size limits.
> > > > 
> > > > This feature also requires the QEMU to interpret the data in chunks and
> > > > forward it to the TPM backend and subsequently dispatch the TPM response
> > > > in chunks back to the linux guest. This is implemented in [2]
> > > > 
> > > > [1] https://trustedcomputinggroup.org/wp-content/uploads/PC-Client-Specific-Platform-TPM-Profile-for-TPM-2p0-v1p07_rc1_121225.pdf
> > > > [2] https://lore.kernel.org/qemu-devel/20260319135316.37412-1-armenon@redhat.com/
> > > > 
> > > > Arun Menon (4):
> > > >   tpm_crb: Add definition of TPM CRB chunking fields
> > > >   tpm_crb: Add new wrapper function to invoke start method
> > > >   tpm_crb: Implement command and response chunking logic
> > > >   tpm: Increase TPM_BUFSIZE to 64kB for chunking support
> > > > 
> > > >  drivers/char/tpm/tpm.h     |   2 +-
> > > >  drivers/char/tpm/tpm_crb.c | 194 ++++++++++++++++++++++++++-----------
> > > >  2 files changed, 137 insertions(+), 59 deletions(-)
> > > > 
> > > > -- 
> > > > 2.53.0
> > > > 
> > > 
> > > When QEMU has the feature available?
> > 
> > The QEMU patches are in review at the moment,
> > here is the link: https://lore.kernel.org/qemu-devel/20260319135316.37412-1-armenon@redhat.com/
> > Hoping to have them merged soon.
> 
> Right, and additional question: what about swtpm?

Hi Jarkko,

Apologies for the delay in following up.
Regarding your question about swtpm, I’ve looped in Stefan Berger who 
should be able to provide more technical context on that front.

I also wanted to gently point you toward the latest revision of this
series v2, as I’ve addressed some feedback since our last exchange.
latest : https://lore.kernel.org/lkml/20260324181244.17741-1-armenon@redhat.com/

I’ve been working on the QEMU integration side in the meantime to ensure
the end-to-end flow is solid.
qemu link : https://lore.kernel.org/qemu-devel/20260422103018.123608-1-armenon@redhat.com/

I look forward to your feedback when time permits.

> 
> For both, to give detailed review, good enough is their main branch
> (i.e. as long as upstream accepts them I can use them).
> 
> > 
> > > 
> > > BR, Jarkko
> > > 
> > 
> > Regards,
> > Arun Menon
> > 
> 
> BR, Jarkko

Regards,
Arun Menon


^ permalink raw reply

* Re: [RFC PATCH v2 4/4] firmware: arm_ffa: check pkvm initailised when initailise ffa driver
From: Yeoreum Yun @ 2026-04-23 10:29 UTC (permalink / raw)
  To: Marc Zyngier
  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, oupton, joey.gouly, suzuki.poulose, yuzenghui,
	catalin.marinas, will, noodles, sebastianene
In-Reply-To: <865x5i13dl.wl-maz@kernel.org>

Hi Marc,

> On Wed, 22 Apr 2026 17:24:49 +0100,
> Yeoreum Yun <yeoreum.yun@arm.com> wrote:
> >
> > When pKVM is enabled, the FF-A driver must be initialized after pKVM.
> > Otherwise, pKVM cannot negotiate the FF-A version or
> > obtain RX/TX buffer information, leading to failures in FF-A calls.
> >
> > During FF-A driver initialization, check whether pKVM has been initialized.
> > If pKVM isn't initailised, register notifier and do initialisation
> > of FF-A driver when pKVM is initialized.
> >
> > Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
> > ---
> >  arch/arm64/include/asm/virt.h     | 11 ++++++++++
> >  arch/arm64/kvm/arm.c              | 21 ++++++++++++++++++
> >  arch/arm64/kvm/pkvm.c             |  2 ++
> >  drivers/firmware/arm_ffa/common.h |  4 ++--
> >  drivers/firmware/arm_ffa/driver.c | 36 ++++++++++++++++++++++++++++++-
> >  drivers/firmware/arm_ffa/smccc.c  |  2 +-
> >  6 files changed, 72 insertions(+), 4 deletions(-)
> >
> > diff --git a/arch/arm64/include/asm/virt.h b/arch/arm64/include/asm/virt.h
> > index b51ab6840f9c..ad038a3b8727 100644
> > --- a/arch/arm64/include/asm/virt.h
> > +++ b/arch/arm64/include/asm/virt.h
> > @@ -68,6 +68,8 @@
> >  #include <asm/sysreg.h>
> >  #include <asm/cpufeature.h>
> >
> > +struct notifier_block;
> > +
> >  /*
> >   * __boot_cpu_mode records what mode CPUs were booted in.
> >   * A correctly-implemented bootloader must start all CPUs in the same mode:
> > @@ -166,6 +168,15 @@ static inline bool is_hyp_nvhe(void)
> >  	return is_hyp_mode_available() && !is_kernel_in_hyp_mode();
> >  }
> >
> > +enum kvm_arm_event {
> > +	PKVM_INITIALISED,
> > +	KVM_ARM_EVENT_MAX,
> > +};
>
> Well, no.
>
> You are adding a whole infrastructure for something that happens
> *once* in the lifetime of the system. What's next? D-Bus?
>
> We already have a dependency mechanism, which I pointed to you last
> time, and that you conveniently ignored. If that's not working for
> you, then consider improving it.
>
> If we had a whole set of in-kernel users depending on some global KVM
> state change, we could look into it. But they are none, and all KVM
> state changes are per-vcpu rather global.
>
> So I'm not entertaining this invasive infrastructure for something so
> limited.

I think I misunderstood your suggestion at first — I wasn’t ignoring it,
and I apologise for that.

I initially considered hooking into /dev/kvm registration,
but there doesn’t seem to be a dedicated class or bus notifier for misc devices:

  - https://lore.kernel.org/all/aecf57rWloQwDh6v@e129823.arm.com/


Also, as I understand it, to make use of device_link,
FF-A would need to represent itself (and pKVM) as proper devices.

However, even if we rely on notifiers for when the pKVM device and
FF-A device are added, the ordering becomes problematic.
When the pKVM device is added and probed, the FF-A consumer would add into
deferred list be device core and  deferred_probe is triggered later
(during late_initcall).

In other words, once FF-A itself is deferred,
the deferred probe queue would look something like:

  (device depending on FF-A) → (some FF-A device) → (FF-A core)

especially since finalise_pkvm() runs at late_initcall_sync.

Unfortunately, deferred_probe_initcall() (also at late_initcall) only
calls driver_deferred_probe_trigger() twice. In this scenario,
the last device in the chain would not be probed immediately but only after a timeout.
As a result, IMA would also fail to find the device in time.

This is why I felt that device_link might not be suitable in this case —
although I may be misunderstanding something.

If this understanding is correct, I’m not sure what alternative we have,
other than adding some kind of notifier support (bus or class) to
the misc driver, or introducing a custom notifier.

Am I missing something?

--
Sincerely,
Yeoreum Yun

^ permalink raw reply

* Re: [PATCH v3 0/2] tpm_tis: fix retry exhaustion and add logging
From: Jarkko Sakkinen @ 2026-04-23 10:21 UTC (permalink / raw)
  To: Axel Rasmussen
  Cc: Jacqueline Wong, linux-integrity, peterhuewe, jgg, jhand, LKML
In-Reply-To: <CAJHvVcgnsh-PeSsemRd6crAUP85sqzMSZ1mcS08ATJr7cAvAaA@mail.gmail.com>

On Wed, Apr 22, 2026 at 04:00:17PM -0700, Axel Rasmussen wrote:
> On Wed, Apr 15, 2026 at 9:00 AM Jacqueline Wong <jacqwong@google.com> wrote:
> >
> > The Fix:
> > - Patch 1: Adds error logs to identify the specific hardware status mismatch.
> > - Patch 2: Stops execution immediately when retries are exhausted.
> >
> > v3 changes:
> > - Improved code alignment to pass checkpatch --strict.
> 
> Thanks for sending the v3 Jacqueline!
> I suspect this may have slipped under folks' radar by not CC'ing +linux-kernel@.

Please check that I carry the correct version of patches:

https://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd.git/log/?h=for-next-tpm

This is related to:

1. https://lore.kernel.org/linux-integrity/aeVSbVIFaCDRXf7C@kernel.org/
2. https://lore.kernel.org/linux-integrity/CAHk-=wiPWCUHsNvzKep7z4VGaL-Brx6Zmh7Efn28WWTPbwn5dA@mail.gmail.com/
3. https://lore.kernel.org/all/aee_mCW8p2J6IbIO@kernel.org/

I will try to send PRs after my split next branches are sync to -next.

BR, Jarkko

^ permalink raw reply

* Re: [RFC PATCH v2 2/4] tpm: tpm_crb_ffa: revert defered_probed when tpm_crb_ffa is built-in
From: Jarkko Sakkinen @ 2026-04-23 10:17 UTC (permalink / raw)
  To: Yeoreum Yun
  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
In-Reply-To: <20260422162449.1814615-3-yeoreum.yun@arm.com>

On Wed, Apr 22, 2026 at 05:24:47PM +0100, Yeoreum Yun wrote:
> commit 746d9e9f62a6 ("tpm: tpm_crb_ffa: try to probe tpm_crb_ffa when it's build_in")
> probe tpm_crb_ffa forcefully when it's built-in to integrate with IMA.
> 
> However, as IMA init function is changed to late_initcall_sync level.
> So, this change isn't required anymore.
> 
> Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
> ---
>  drivers/char/tpm/tpm_crb_ffa.c | 18 +++---------------
>  1 file changed, 3 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/char/tpm/tpm_crb_ffa.c b/drivers/char/tpm/tpm_crb_ffa.c
> index 99f1c1e5644b..025c4d4b17ca 100644
> --- a/drivers/char/tpm/tpm_crb_ffa.c
> +++ b/drivers/char/tpm/tpm_crb_ffa.c
> @@ -177,23 +177,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 +395,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");
> --
> LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}
> 

I'll hold review to next version i.e. after Mimi's concerns
have been addressed.

BR, Jarkko

^ permalink raw reply

* Re: [PATCH v2] evm: terminate and bound the evm_xattrs read buffer
From: Roberto Sassu @ 2026-04-23  9:31 UTC (permalink / raw)
  To: Pengpeng Hou, Mimi Zohar, Roberto Sassu
  Cc: Dmitry Kasatkin, Eric Snowberg, Paul Moore, James Morris,
	Serge Hallyn, linux-integrity, linux-security-module,
	linux-kernel
In-Reply-To: <b28a714c-aabe-49f3-a8ab-274feff34d85@huaweicloud.com>

On Fri, 2026-04-17 at 10:30 +0200, Roberto Sassu wrote:
> On 4/17/2026 2:44 PM, Pengpeng Hou wrote:
> > evm_read_xattrs() allocates size + 1 bytes, fills them from the list of
> > enabled xattrs, and then passes strlen(temp) to
> > simple_read_from_buffer(). When no configured xattrs are enabled, the
> > fill loop stores nothing and temp[0] remains uninitialized, so strlen()
> > reads beyond initialized memory.
> > 
> > Explicitly terminate the buffer after allocation, use snprintf() for
> > each formatted line, and pass the accumulated length to
> 
> pass the accumulate length (without risk of truncation) to ...
> 
> > simple_read_from_buffer().
> > 
> > Fixes: fa516b66a1bf ("EVM: Allow runtime modification of the set of verified xattrs")
> > Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
> > ---
> > Changes since v1:
> > - add the Fixes tag
> > - replace sprintf() with snprintf()
> > - explicitly terminate the buffer instead of switching to kzalloc()
> > 
> >   security/integrity/evm/evm_secfs.c | 11 ++++++-----
> >   1 file changed, 6 insertions(+), 5 deletions(-)
> > 
> > diff --git a/security/integrity/evm/evm_secfs.c b/security/integrity/evm/evm_secfs.c
> > index acd840461902..b7882a4ce9d0 100644
> > --- a/security/integrity/evm/evm_secfs.c
> > +++ b/security/integrity/evm/evm_secfs.c
> > @@ -127,8 +127,8 @@ static ssize_t evm_read_xattrs(struct file *filp, char __user *buf,
> >   			       size_t count, loff_t *ppos)
> >   {
> >   	char *temp;
> > -	int offset = 0;
> > -	ssize_t rc, size = 0;
> > +	size_t offset = 0, size = 0;
> > +	ssize_t rc;
> >   	struct xattr_list *xattr;
> >   
> >   	if (*ppos != 0)
> > @@ -150,17 +150,18 @@ static ssize_t evm_read_xattrs(struct file *filp, char __user *buf,
> >   		mutex_unlock(&xattr_list_mutex);
> >   		return -ENOMEM;
> >   	}
> 
> Please add a newline here.
> 
> > +	temp[size] = '\0';
> >   
> >   	list_for_each_entry(xattr, &evm_config_xattrnames, list) {
> >   		if (!xattr->enabled)
> >   			continue;
> >   
> > -		sprintf(temp + offset, "%s\n", xattr->name);
> > -		offset += strlen(xattr->name) + 1;
> 
> Also a comment like:
> 
> /*
>   * No truncation possible: size is computed over the same
>   * enabled xattrs under xattr_list_mutex, so offset never exceeds size.
>   */
> 
> to motivate why it is fine to increment offset without checking.

Any progress? The changes should be straightforward.

Thanks

Roberto

> Thanks
> 
> Roberto
> 
> > +		offset += snprintf(temp + offset, size + 1 - offset, "%s\n",
> > +				   xattr->name);
> >   	}
> >   
> >   	mutex_unlock(&xattr_list_mutex);
> > -	rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
> > +	rc = simple_read_from_buffer(buf, count, ppos, temp, offset);
> >   
> >   	kfree(temp);
> >   


^ permalink raw reply

* Re: [RFC PATCH v2 3/4] firmware: arm_ffa: revert ffa_init() initcall level to device_initcall
From: Sudeep Holla @ 2026-04-23  9:13 UTC (permalink / raw)
  To: Yeoreum Yun
  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
In-Reply-To: <20260422162449.1814615-4-yeoreum.yun@arm.com>

On Wed, Apr 22, 2026 at 05:24:48PM +0100, Yeoreum Yun wrote:
> commit 0e0546eabcd6 ("firmware: arm_ffa: Change initcall level of ffa_init() to rootfs_initcall")
> changed the initcall level of ffa_init() to rootfs_initcall to address
> an issue where IMA could not properly recognize the TPM device.
> 
> However, this introduces a problem: pKVM fails to handle any FF-A calls
> because it cannot trap the FFA_VERSION call invoked by ffa_init().
> 
> Since the IMA init function level has been changed to late_initcall_sync,
> there is no longer a need to keep ffa_init() at rootfs_initcall.
> Revert it back to device_initcall.
> 

I prefer you do actual git revert on the original commit for this as well
as the TPM CRM FFA driver explaining how the original idea fails in certain
conditions. Don't add it as separate commit and add fixes tag to the
original commits.

-- 
Regards,
Sudeep

^ permalink raw reply

* Re: [RFC PATCH 4/4] firmware: arm_ffa: check pkvm initailised when initailise ffa driver
From: Will Deacon @ 2026-04-23  8:57 UTC (permalink / raw)
  To: Yeoreum Yun
  Cc: Sudeep Holla, Marc Zyngier, linux-security-module, linux-kernel,
	linux-integrity, linux-arm-kernel, kvmarm, paul, jmorris, zohar,
	roberto.sassu, dmitry.kasatkin, eric.snowberg, jarkko, oupton,
	joey.gouly, suzuki.poulose, yuzenghui, catalin.marinas,
	sebastianene
In-Reply-To: <aejN52lwaqfoMuGJ@e129823.arm.com>

On Wed, Apr 22, 2026 at 02:32:23PM +0100, Yeoreum Yun wrote:
> Hi All,
> 
> > > On Tue, Apr 21, 2026 at 07:57:43AM +0100, Yeoreum Yun wrote:
> > >
> > > [...]
> > >
> > > >
> > > > Also, the FF-A initialization is not driven by a device probe, but rather
> > > > happens as part of the bus registration itself,
> > > > so it does not fit well with a device_link or probe deferral based approach.
> > > >
> > > > Instead, perhaps we could go with the idea I mentioned previously:
> > > > either introduce a notifier, or create a pseudo ffa_device
> > > > once pKVM initialization has completed, and
> > > > then let the ffa driver perform the additional initialization from there.
> > > >
> > > > Am I missing something?
> > > >
> > >
> > > In order to handle/cleanup some ugliness in interrupt management in the
> > > FF-A driver, we may introduce DT node eventually. But it will take sometime.
> >
> > Unfortunately, I think this DT node wouldn't be helpful to solve
> > this situation for dependency with the kvm misc device...
> >
> > IMHO, current situation, the notifier seems to good option. unless
> > we make the initcall to recongise this dependency.
> >
> 
> I think the best approach for now is to introduce a notifier to handle this situation.
> If there are no further suggestions, I’ll send a v2 based on:
>   - https://lore.kernel.org/all/aeS4rAeVQ0yJIPYw@e129823.arm.com/

I can't say that I'm a huge fan of that :/

The notifier will literally fire once, for a single listener. That's
called a function call.

Will

^ permalink raw reply

* Re: [RFC PATCH v2 4/4] firmware: arm_ffa: check pkvm initailised when initailise ffa driver
From: Marc Zyngier @ 2026-04-23  8:34 UTC (permalink / raw)
  To: Yeoreum Yun
  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, oupton, joey.gouly, suzuki.poulose, yuzenghui,
	catalin.marinas, will, noodles, sebastianene
In-Reply-To: <20260422162449.1814615-5-yeoreum.yun@arm.com>

On Wed, 22 Apr 2026 17:24:49 +0100,
Yeoreum Yun <yeoreum.yun@arm.com> wrote:
> 
> When pKVM is enabled, the FF-A driver must be initialized after pKVM.
> Otherwise, pKVM cannot negotiate the FF-A version or
> obtain RX/TX buffer information, leading to failures in FF-A calls.
> 
> During FF-A driver initialization, check whether pKVM has been initialized.
> If pKVM isn't initailised, register notifier and do initialisation
> of FF-A driver when pKVM is initialized.
> 
> Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
> ---
>  arch/arm64/include/asm/virt.h     | 11 ++++++++++
>  arch/arm64/kvm/arm.c              | 21 ++++++++++++++++++
>  arch/arm64/kvm/pkvm.c             |  2 ++
>  drivers/firmware/arm_ffa/common.h |  4 ++--
>  drivers/firmware/arm_ffa/driver.c | 36 ++++++++++++++++++++++++++++++-
>  drivers/firmware/arm_ffa/smccc.c  |  2 +-
>  6 files changed, 72 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/virt.h b/arch/arm64/include/asm/virt.h
> index b51ab6840f9c..ad038a3b8727 100644
> --- a/arch/arm64/include/asm/virt.h
> +++ b/arch/arm64/include/asm/virt.h
> @@ -68,6 +68,8 @@
>  #include <asm/sysreg.h>
>  #include <asm/cpufeature.h>
> 
> +struct notifier_block;
> +
>  /*
>   * __boot_cpu_mode records what mode CPUs were booted in.
>   * A correctly-implemented bootloader must start all CPUs in the same mode:
> @@ -166,6 +168,15 @@ static inline bool is_hyp_nvhe(void)
>  	return is_hyp_mode_available() && !is_kernel_in_hyp_mode();
>  }
> 
> +enum kvm_arm_event {
> +	PKVM_INITIALISED,
> +	KVM_ARM_EVENT_MAX,
> +};

Well, no.

You are adding a whole infrastructure for something that happens
*once* in the lifetime of the system. What's next? D-Bus?

We already have a dependency mechanism, which I pointed to you last
time, and that you conveniently ignored. If that's not working for
you, then consider improving it.

If we had a whole set of in-kernel users depending on some global KVM
state change, we could look into it. But they are none, and all KVM
state changes are per-vcpu rather global.

So I'm not entertaining this invasive infrastructure for something so
limited.

	M.

-- 
Without deviation from the norm, progress is not possible.

^ permalink raw reply

* Re: [RFC PATCH v2 1/4] security: ima: call ima_init() again at late_initcall_sync for defered TPM
From: Yeoreum Yun @ 2026-04-23  5:55 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
In-Reply-To: <82803bb3b471898a77084c449b73c7f7b4eb2149.camel@linux.ibm.com>

> On Wed, 2026-04-22 at 20:41 +0100, Yeoreum Yun wrote:
> > > Hi Mimi,
> > >
> > > > On Wed, 2026-04-22 at 17:24 +0100, Yeoreum Yun wrote:
> > > > > 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.
> > > > >
> > > > > To resolve this, call ima_init() again at late_inicall_sync level
> > > > > so that let IMA not miss TPM PCR value when generating boot_aggregate
> > > > > log though TPM device presents in the system.
> > > > >
> > > > > Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
> > > >
> > > > A lot of change for just detecting whether ima_init() is being called on
> > > > late_initcall or late_initcall_sync(), without any explanation for all the other
> > > > changes (e.g. ima_init_core).
> > > >
> > > > Please just limit the change to just calling ima_init() twice.
> > >
> > > My concern is that ima_update_policy_flags() will be called
> > > when ima_init() is deferred -- not initialised anything.
> > > though functionally, it might be okay however,
> > > I think ima_update_policy_flags() and notifier should work after ima_init()
> > > works logically.
> > >
> > > This change I think not much quite a lot. just wrapper ima_init() with
> > > ima_init_core() with some error handling.
> > >
> > > Am I missing something?
> >
> > Also, if we handle in ima_init() only, but it failed with other reason,
> > we shouldn't call again ima_init() in the late_initcall_sync.
> >
> > To handle this, It wouldn't do in the ima_init() but we need to handle
> > it by caller of ima_init().
>
> Only tpm_default_chip() is being called to set the ima_tpm_chip.  On failure,
> instead of going into TPM-bypass mode, return immediately.  There are no calls
> to anything else.  Just call ima_init() a second time.

I’m not fully convinced this is sufficient.

What I meant is the case where ima_init() fails due to other
initialisation steps, not only tpm_default_chip() (e.g. ima_fs_init()).

If it fails at the late_initcall stage for such reasons, then we
should not call ima_init() again at late_initcall_sync.

For this reason, instead of adding a static variable inside
ima_init(), I think it would be better to manage the state in the
caller and introduce something like an ima_initialised flag. Also, if
initialisation fails for other reasons, the notifier block should be
unregistered.

I’d also like to ask again whether it is fine to call
ima_update_policy_flags() and keep the notifier registered in the
deferred TPM case. While this may be functionally acceptable, it seems
logically questionable to do so when ima_init() has not completed.

There is also a possibility that a deferred case ultimately fails (e.g.
deferred at late_initcall, but then failing at late_initcall_sync
for another reason, even while entering TPM bypass mode). In that case,
it seems more appropriate to handle this state in the caller of
ima_init(), rather than inside ima_init() itself.

Am I still missing something?

--
Sincerely,
Yeoreum Yun

^ permalink raw reply

* Re: [PATCH v3 0/2] tpm_tis: fix retry exhaustion and add logging
From: Axel Rasmussen @ 2026-04-22 23:00 UTC (permalink / raw)
  To: Jacqueline Wong; +Cc: linux-integrity, jarkko, peterhuewe, jgg, jhand, LKML
In-Reply-To: <20260415160006.2275325-1-jacqwong@google.com>

On Wed, Apr 15, 2026 at 9:00 AM Jacqueline Wong <jacqwong@google.com> wrote:
>
> The Fix:
> - Patch 1: Adds error logs to identify the specific hardware status mismatch.
> - Patch 2: Stops execution immediately when retries are exhausted.
>
> v3 changes:
> - Improved code alignment to pass checkpatch --strict.

Thanks for sending the v3 Jacqueline!
I suspect this may have slipped under folks' radar by not CC'ing +linux-kernel@.

>
> v2 changes:
> - Split logging and logic into separate patches.
> - Added retry count to the error message.
> - Included dmesg traces below.
>
> Testing:
> Dmesg traces obtained using error injection to simulate status register mismatches.
>
> Before:
> [  130.288751] tpm tpm0: Operation Timed out
> [  250.306070] tpm tpm0: Operation Timed out
> [  250.310173] tpm tpm0: A TPM error (-62) occurred attempting to determine the timeouts
>
> After:
> [   10.271547] tpm tpm0: TPM_STS_DATA_EXPECT should be unset. sts = 0x00000080
> ...
> [   10.646283] tpm tpm0: TPM_STS_DATA_EXPECT should be unset. sts = 0x00000080
> [   10.653461] tpm tpm0: Exhausted 50 tpm_tis_send_data retries
> [   10.659304] tpm tpm0: tpm_try_transmit: send(): error -5
> [   10.665435] tpm tpm0: TPM_STS_DATA_EXPECT should be unset. sts = 0x00000080
> ...
> [   11.037198] tpm tpm0: TPM_STS_DATA_EXPECT should be unset. sts = 0x00000080
> [   11.044441] tpm tpm0: Exhausted 50 tpm_tis_send_data retries
> [   11.050288] tpm tpm0: tpm_try_transmit: send(): error -5
> [   11.055723] tpm tpm0: A TPM error (-5) occurred attempting to determine the timeouts
>
> Jacqueline Wong (2):
>   tpm: tpm_tis: add error logging for data transfer
>   tpm: tpm_tis: stop transmit if retries are exhausted
>
>  drivers/char/tpm/tpm_tis_core.c | 11 ++++++++++-
>  1 file changed, 10 insertions(+), 1 deletion(-)
>
> --
> 2.54.0.rc0.605.g598a273b03-goog
>

^ permalink raw reply

* Re: [RFC PATCH v2 1/4] security: ima: call ima_init() again at late_initcall_sync for defered TPM
From: Mimi Zohar @ 2026-04-22 21:20 UTC (permalink / raw)
  To: Yeoreum Yun
  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
In-Reply-To: <aekkVQwueKbFtG7C@e129823.arm.com>

On Wed, 2026-04-22 at 20:41 +0100, Yeoreum Yun wrote:
> > Hi Mimi,
> > 
> > > On Wed, 2026-04-22 at 17:24 +0100, Yeoreum Yun wrote:
> > > > 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.
> > > > 
> > > > To resolve this, call ima_init() again at late_inicall_sync level
> > > > so that let IMA not miss TPM PCR value when generating boot_aggregate
> > > > log though TPM device presents in the system.
> > > > 
> > > > Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
> > > 
> > > A lot of change for just detecting whether ima_init() is being called on
> > > late_initcall or late_initcall_sync(), without any explanation for all the other
> > > changes (e.g. ima_init_core).
> > > 
> > > Please just limit the change to just calling ima_init() twice.
> > 
> > My concern is that ima_update_policy_flags() will be called
> > when ima_init() is deferred -- not initialised anything.
> > though functionally, it might be okay however,
> > I think ima_update_policy_flags() and notifier should work after ima_init()
> > works logically.
> > 
> > This change I think not much quite a lot. just wrapper ima_init() with
> > ima_init_core() with some error handling.
> > 
> > Am I missing something?
> 
> Also, if we handle in ima_init() only, but it failed with other reason,
> we shouldn't call again ima_init() in the late_initcall_sync.
> 
> To handle this, It wouldn't do in the ima_init() but we need to handle
> it by caller of ima_init().

Only tpm_default_chip() is being called to set the ima_tpm_chip.  On failure,
instead of going into TPM-bypass mode, return immediately.  There are no calls
to anything else.  Just call ima_init() a second time.

Mimi



^ permalink raw reply

* Re: [RFC PATCH v2 1/4] security: ima: call ima_init() again at late_initcall_sync for defered TPM
From: Yeoreum Yun @ 2026-04-22 19:41 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
In-Reply-To: <aekXaU52fzvNYaUF@e129823.arm.com>

> Hi Mimi,
>
> > On Wed, 2026-04-22 at 17:24 +0100, Yeoreum Yun wrote:
> > > 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.
> > >
> > > To resolve this, call ima_init() again at late_inicall_sync level
> > > so that let IMA not miss TPM PCR value when generating boot_aggregate
> > > log though TPM device presents in the system.
> > >
> > > Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
> >
> > A lot of change for just detecting whether ima_init() is being called on
> > late_initcall or late_initcall_sync(), without any explanation for all the other
> > changes (e.g. ima_init_core).
> >
> > Please just limit the change to just calling ima_init() twice.
>
> My concern is that ima_update_policy_flags() will be called
> when ima_init() is deferred -- not initialised anything.
> though functionally, it might be okay however,
> I think ima_update_policy_flags() and notifier should work after ima_init()
> works logically.
>
> This change I think not much quite a lot. just wrapper ima_init() with
> ima_init_core() with some error handling.
>
> Am I missing something?

Also, if we handle in ima_init() only, but it failed with other reason,
we shouldn't call again ima_init() in the late_initcall_sync.

To handle this, It wouldn't do in the ima_init() but we need to handle
it by caller of ima_init().

--
Sincerely,
Yeoreum Yun

^ permalink raw reply

* Re: [RFC PATCH v2 1/4] security: ima: call ima_init() again at late_initcall_sync for defered TPM
From: Yeoreum Yun @ 2026-04-22 18:46 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
In-Reply-To: <6919248bdc85dac60277fa9d9c83d8bd258ca635.camel@linux.ibm.com>

Hi Mimi,

> On Wed, 2026-04-22 at 17:24 +0100, Yeoreum Yun wrote:
> > 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.
> >
> > To resolve this, call ima_init() again at late_inicall_sync level
> > so that let IMA not miss TPM PCR value when generating boot_aggregate
> > log though TPM device presents in the system.
> >
> > Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
>
> A lot of change for just detecting whether ima_init() is being called on
> late_initcall or late_initcall_sync(), without any explanation for all the other
> changes (e.g. ima_init_core).
>
> Please just limit the change to just calling ima_init() twice.

My concern is that ima_update_policy_flags() will be called
when ima_init() is deferred -- not initialised anything.
though functionally, it might be okay however,
I think ima_update_policy_flags() and notifier should work after ima_init()
works logically.

This change I think not much quite a lot. just wrapper ima_init() with
ima_init_core() with some error handling.

Am I missing something?

>
>
> > ---
> >  include/linux/lsm_hooks.h           |  2 +
> >  security/integrity/ima/ima.h        |  4 +-
> >  security/integrity/ima/ima_init.c   | 10 +++-
> >  security/integrity/ima/ima_main.c   | 76 +++++++++++++++++++++++------
> >  security/integrity/ima/ima_policy.c |  3 ++
> >  security/lsm_init.c                 | 13 ++++-
> >  6 files changed, 87 insertions(+), 21 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/integrity/ima/ima.h b/security/integrity/ima/ima.h
> > index 89ebe98ffc5e..75ee7ad184d0 100644
> > --- a/security/integrity/ima/ima.h
> > +++ b/security/integrity/ima/ima.h
> > @@ -62,6 +62,8 @@ extern int ima_hash_algo_idx __ro_after_init;
> >  extern int ima_extra_slots __ro_after_init;
> >  extern struct ima_algo_desc *ima_algo_array __ro_after_init;
> >
> > +extern bool ima_initialised __ro_after_init;
> > +
> >  extern int ima_appraise;
> >  extern struct tpm_chip *ima_tpm_chip;
> >  extern const char boot_aggregate_name[];
> > @@ -257,7 +259,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(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..c28c71090ad2 100644
> > --- a/security/integrity/ima/ima_init.c
> > +++ b/security/integrity/ima/ima_init.c
> > @@ -115,13 +115,19 @@ void __init ima_load_x509(void)
> >  }
> >  #endif
> >
> > -int __init ima_init(void)
> > +int __init ima_init(bool late)
> >  {
> >  	int rc;
> >
> >  	ima_tpm_chip = tpm_default_chip();
> > -	if (!ima_tpm_chip)
> > +	if (!ima_tpm_chip) {
> > +		if (!late) {
> > +			pr_info("Defer initialisation to the late_initcall_sync stage.\n");
> > +			return -EPROBE_DEFER;
> > +		}
> > +
> >  		pr_info("No TPM chip found, activating TPM-bypass!\n");
> > +	}
> >
> >  	rc = integrity_init_keyring(INTEGRITY_KEYRING_IMA);
> >  	if (rc)
> > diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
> > index 1d6229b156fb..ac444ee600e2 100644
> > --- a/security/integrity/ima/ima_main.c
> > +++ b/security/integrity/ima/ima_main.c
> > @@ -38,6 +38,7 @@ int ima_appraise;
> >  #endif
> >
> >  int __ro_after_init ima_hash_algo = HASH_ALGO_SHA1;
> > +bool ima_initialised __ro_after_init = false;
> >  static int hash_setup_done;
> >  static int ima_disabled __ro_after_init;
> >
> > @@ -1237,6 +1238,35 @@ static int ima_kernel_module_request(char *kmod_name)
> >
> >  #endif /* CONFIG_INTEGRITY_ASYMMETRIC_KEYS */
> >
> > +static int __init init_ima_core(bool late)
> > +{
> > +	int err;
> > +
> > +	if (ima_initialised)
> > +		return 0;
> > +
> > +	err = ima_init(late);
> > +	if (err == -EPROBE_DEFER)
> > +		return 0;
> > +
> > +	if (err && strcmp(hash_algo_name[ima_hash_algo],
> > +			  CONFIG_IMA_DEFAULT_HASH) != 0) {
> > +		pr_info("Allocating %s failed, going to use default hash algorithm %s\n",
> > +			hash_algo_name[ima_hash_algo], CONFIG_IMA_DEFAULT_HASH);
> > +		hash_setup_done = 0;
> > +		hash_setup(CONFIG_IMA_DEFAULT_HASH);
> > +		err = ima_init(late);
> > +	}
> > +
> > +	if (!err) {
> > +		ima_update_policy_flags();
> > +		ima_initialised = true;
> > +	} else
> > +		ima_disabled = 1;
> > +
> > +	return err;
> > +}
> > +
> >  static int __init init_ima(void)
> >  {
> >  	int error;
> > @@ -1250,30 +1280,42 @@ static int __init init_ima(void)
> >  	ima_appraise_parse_cmdline();
> >  	ima_init_template_list();
> >  	hash_setup(CONFIG_IMA_DEFAULT_HASH);
> > -	error = ima_init();
> > -
> > -	if (error && strcmp(hash_algo_name[ima_hash_algo],
> > -			    CONFIG_IMA_DEFAULT_HASH) != 0) {
> > -		pr_info("Allocating %s failed, going to use default hash algorithm %s\n",
> > -			hash_algo_name[ima_hash_algo], CONFIG_IMA_DEFAULT_HASH);
> > -		hash_setup_done = 0;
> > -		hash_setup(CONFIG_IMA_DEFAULT_HASH);
> > -		error = ima_init();
> > -	}
> > -
> > -	if (error)
> > -		return error;
> >
> >  	error = register_blocking_lsm_notifier(&ima_lsm_policy_notifier);
> > -	if (error)
> > +	if (error) {
> >  		pr_warn("Couldn't register LSM notifier, error %d\n", error);
> > +		goto disable_ima;
> > +	}
> >
> > -	if (!error)
> > -		ima_update_policy_flags();
> > +	error = init_ima_core(false);
> > +	if (error) {
> > +		unregister_blocking_lsm_notifier(&ima_lsm_policy_notifier);
> > +		goto disable_ima;
> > +	}
> > +
> > +	return 0;
> >
> > +disable_ima:
> > +	ima_disabled = 1;
> >  	return error;
> >  }
> >
> > +static int __init late_init_ima(void)
> > +{
> > +	int err;
> > +
> > +	if (ima_disabled)
> > +		return 0;
> > +
> > +	err = init_ima_core(true);
> > +	if (err) {
> > +		unregister_blocking_lsm_notifier(&ima_lsm_policy_notifier);
> > +		ima_disabled = 1;
> > +	}
> > +
> > +	return err;
> > +}
> > +
> >  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),
> > @@ -1321,4 +1363,6 @@ DEFINE_LSM(ima) = {
> >  	.blobs = &ima_blob_sizes,
> >  	/* Start IMA after the TPM is available */
> >  	.initcall_late = init_ima,
> > +	/* Start IMA late in case of probing TPM is deferred. */
> > +	.initcall_late_sync = late_init_ima,
> >  };
> > diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
> > index bf2d7ba4c14a..c3bcc3521c81 100644
> > --- a/security/integrity/ima/ima_policy.c
> > +++ b/security/integrity/ima/ima_policy.c
> > @@ -501,6 +501,9 @@ static void ima_lsm_update_rules(void)
> >  int ima_lsm_policy_change(struct notifier_block *nb, unsigned long event,
> >  			  void *lsm_data)
> >  {
> > +	if (!ima_initialised)
> > +		return NOTIFY_DONE;
> > +
> >  	if (event != LSM_POLICY_CHANGE)
> >  		return NOTIFY_DONE;
> >
> > 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);
> > --
> > LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}

--
Sincerely,
Yeoreum Yun

^ permalink raw reply

* Re: [RFC PATCH v2 1/4] security: ima: call ima_init() again at late_initcall_sync for defered TPM
From: Mimi Zohar @ 2026-04-22 17:20 UTC (permalink / raw)
  To: Yeoreum Yun, 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
In-Reply-To: <20260422162449.1814615-2-yeoreum.yun@arm.com>

On Wed, 2026-04-22 at 17:24 +0100, Yeoreum Yun wrote:
> 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.
> 
> To resolve this, call ima_init() again at late_inicall_sync level
> so that let IMA not miss TPM PCR value when generating boot_aggregate
> log though TPM device presents in the system.
> 
> Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>

A lot of change for just detecting whether ima_init() is being called on
late_initcall or late_initcall_sync(), without any explanation for all the other
changes (e.g. ima_init_core).

Please just limit the change to just calling ima_init() twice.

Mimi


> ---
>  include/linux/lsm_hooks.h           |  2 +
>  security/integrity/ima/ima.h        |  4 +-
>  security/integrity/ima/ima_init.c   | 10 +++-
>  security/integrity/ima/ima_main.c   | 76 +++++++++++++++++++++++------
>  security/integrity/ima/ima_policy.c |  3 ++
>  security/lsm_init.c                 | 13 ++++-
>  6 files changed, 87 insertions(+), 21 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/integrity/ima/ima.h b/security/integrity/ima/ima.h
> index 89ebe98ffc5e..75ee7ad184d0 100644
> --- a/security/integrity/ima/ima.h
> +++ b/security/integrity/ima/ima.h
> @@ -62,6 +62,8 @@ extern int ima_hash_algo_idx __ro_after_init;
>  extern int ima_extra_slots __ro_after_init;
>  extern struct ima_algo_desc *ima_algo_array __ro_after_init;
> 
> +extern bool ima_initialised __ro_after_init;
> +
>  extern int ima_appraise;
>  extern struct tpm_chip *ima_tpm_chip;
>  extern const char boot_aggregate_name[];
> @@ -257,7 +259,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(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..c28c71090ad2 100644
> --- a/security/integrity/ima/ima_init.c
> +++ b/security/integrity/ima/ima_init.c
> @@ -115,13 +115,19 @@ void __init ima_load_x509(void)
>  }
>  #endif
> 
> -int __init ima_init(void)
> +int __init ima_init(bool late)
>  {
>  	int rc;
> 
>  	ima_tpm_chip = tpm_default_chip();
> -	if (!ima_tpm_chip)
> +	if (!ima_tpm_chip) {
> +		if (!late) {
> +			pr_info("Defer initialisation to the late_initcall_sync stage.\n");
> +			return -EPROBE_DEFER;
> +		}
> +
>  		pr_info("No TPM chip found, activating TPM-bypass!\n");
> +	}
> 
>  	rc = integrity_init_keyring(INTEGRITY_KEYRING_IMA);
>  	if (rc)
> diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
> index 1d6229b156fb..ac444ee600e2 100644
> --- a/security/integrity/ima/ima_main.c
> +++ b/security/integrity/ima/ima_main.c
> @@ -38,6 +38,7 @@ int ima_appraise;
>  #endif
> 
>  int __ro_after_init ima_hash_algo = HASH_ALGO_SHA1;
> +bool ima_initialised __ro_after_init = false;
>  static int hash_setup_done;
>  static int ima_disabled __ro_after_init;
> 
> @@ -1237,6 +1238,35 @@ static int ima_kernel_module_request(char *kmod_name)
> 
>  #endif /* CONFIG_INTEGRITY_ASYMMETRIC_KEYS */
> 
> +static int __init init_ima_core(bool late)
> +{
> +	int err;
> +
> +	if (ima_initialised)
> +		return 0;
> +
> +	err = ima_init(late);
> +	if (err == -EPROBE_DEFER)
> +		return 0;
> +
> +	if (err && strcmp(hash_algo_name[ima_hash_algo],
> +			  CONFIG_IMA_DEFAULT_HASH) != 0) {
> +		pr_info("Allocating %s failed, going to use default hash algorithm %s\n",
> +			hash_algo_name[ima_hash_algo], CONFIG_IMA_DEFAULT_HASH);
> +		hash_setup_done = 0;
> +		hash_setup(CONFIG_IMA_DEFAULT_HASH);
> +		err = ima_init(late);
> +	}
> +
> +	if (!err) {
> +		ima_update_policy_flags();
> +		ima_initialised = true;
> +	} else
> +		ima_disabled = 1;
> +
> +	return err;
> +}
> +
>  static int __init init_ima(void)
>  {
>  	int error;
> @@ -1250,30 +1280,42 @@ static int __init init_ima(void)
>  	ima_appraise_parse_cmdline();
>  	ima_init_template_list();
>  	hash_setup(CONFIG_IMA_DEFAULT_HASH);
> -	error = ima_init();
> -
> -	if (error && strcmp(hash_algo_name[ima_hash_algo],
> -			    CONFIG_IMA_DEFAULT_HASH) != 0) {
> -		pr_info("Allocating %s failed, going to use default hash algorithm %s\n",
> -			hash_algo_name[ima_hash_algo], CONFIG_IMA_DEFAULT_HASH);
> -		hash_setup_done = 0;
> -		hash_setup(CONFIG_IMA_DEFAULT_HASH);
> -		error = ima_init();
> -	}
> -
> -	if (error)
> -		return error;
> 
>  	error = register_blocking_lsm_notifier(&ima_lsm_policy_notifier);
> -	if (error)
> +	if (error) {
>  		pr_warn("Couldn't register LSM notifier, error %d\n", error);
> +		goto disable_ima;
> +	}
> 
> -	if (!error)
> -		ima_update_policy_flags();
> +	error = init_ima_core(false);
> +	if (error) {
> +		unregister_blocking_lsm_notifier(&ima_lsm_policy_notifier);
> +		goto disable_ima;
> +	}
> +
> +	return 0;
> 
> +disable_ima:
> +	ima_disabled = 1;
>  	return error;
>  }
> 
> +static int __init late_init_ima(void)
> +{
> +	int err;
> +
> +	if (ima_disabled)
> +		return 0;
> +
> +	err = init_ima_core(true);
> +	if (err) {
> +		unregister_blocking_lsm_notifier(&ima_lsm_policy_notifier);
> +		ima_disabled = 1;
> +	}
> +
> +	return err;
> +}
> +
>  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),
> @@ -1321,4 +1363,6 @@ DEFINE_LSM(ima) = {
>  	.blobs = &ima_blob_sizes,
>  	/* Start IMA after the TPM is available */
>  	.initcall_late = init_ima,
> +	/* Start IMA late in case of probing TPM is deferred. */
> +	.initcall_late_sync = late_init_ima,
>  };
> diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
> index bf2d7ba4c14a..c3bcc3521c81 100644
> --- a/security/integrity/ima/ima_policy.c
> +++ b/security/integrity/ima/ima_policy.c
> @@ -501,6 +501,9 @@ static void ima_lsm_update_rules(void)
>  int ima_lsm_policy_change(struct notifier_block *nb, unsigned long event,
>  			  void *lsm_data)
>  {
> +	if (!ima_initialised)
> +		return NOTIFY_DONE;
> +
>  	if (event != LSM_POLICY_CHANGE)
>  		return NOTIFY_DONE;
> 
> 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);
> --
> LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}

^ permalink raw reply

* [RFC PATCH v2 4/4] firmware: arm_ffa: check pkvm initailised when initailise ffa driver
From: Yeoreum Yun @ 2026-04-22 16: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
In-Reply-To: <20260422162449.1814615-1-yeoreum.yun@arm.com>

When pKVM is enabled, the FF-A driver must be initialized after pKVM.
Otherwise, pKVM cannot negotiate the FF-A version or
obtain RX/TX buffer information, leading to failures in FF-A calls.

During FF-A driver initialization, check whether pKVM has been initialized.
If pKVM isn't initailised, register notifier and do initialisation
of FF-A driver when pKVM is initialized.

Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
---
 arch/arm64/include/asm/virt.h     | 11 ++++++++++
 arch/arm64/kvm/arm.c              | 21 ++++++++++++++++++
 arch/arm64/kvm/pkvm.c             |  2 ++
 drivers/firmware/arm_ffa/common.h |  4 ++--
 drivers/firmware/arm_ffa/driver.c | 36 ++++++++++++++++++++++++++++++-
 drivers/firmware/arm_ffa/smccc.c  |  2 +-
 6 files changed, 72 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/include/asm/virt.h b/arch/arm64/include/asm/virt.h
index b51ab6840f9c..ad038a3b8727 100644
--- a/arch/arm64/include/asm/virt.h
+++ b/arch/arm64/include/asm/virt.h
@@ -68,6 +68,8 @@
 #include <asm/sysreg.h>
 #include <asm/cpufeature.h>

+struct notifier_block;
+
 /*
  * __boot_cpu_mode records what mode CPUs were booted in.
  * A correctly-implemented bootloader must start all CPUs in the same mode:
@@ -166,6 +168,15 @@ static inline bool is_hyp_nvhe(void)
 	return is_hyp_mode_available() && !is_kernel_in_hyp_mode();
 }

+enum kvm_arm_event {
+	PKVM_INITIALISED,
+	KVM_ARM_EVENT_MAX,
+};
+
+extern int kvm_arm_event_notifier_call_chain(enum kvm_arm_event event, void *data);
+extern int kvm_arm_event_notifier_register(struct notifier_block *nb);
+extern int kvm_arm_event_notifier_unregister(struct notifier_block *nb);
+
 #endif /* __ASSEMBLER__ */

 #endif /* ! __ASM__VIRT_H */
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 410ffd41fd73..8da10049ab65 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -14,6 +14,7 @@
 #include <linux/vmalloc.h>
 #include <linux/fs.h>
 #include <linux/mman.h>
+#include <linux/notifier.h>
 #include <linux/sched.h>
 #include <linux/kvm.h>
 #include <linux/kvm_irqfd.h>
@@ -111,6 +112,8 @@ DECLARE_KVM_NVHE_PER_CPU(struct kvm_nvhe_init_params, kvm_init_params);

 DECLARE_KVM_NVHE_PER_CPU(struct kvm_cpu_context, kvm_hyp_ctxt);

+BLOCKING_NOTIFIER_HEAD(kvm_arm_event_notifier_head);
+
 static bool vgic_present, kvm_arm_initialised;

 static DEFINE_PER_CPU(unsigned char, kvm_hyp_initialized);
@@ -3064,4 +3067,22 @@ enum kvm_mode kvm_get_mode(void)
 	return kvm_mode;
 }

+int kvm_arm_event_notifier_call_chain(enum kvm_arm_event event, void *data)
+{
+	return blocking_notifier_call_chain(&kvm_arm_event_notifier_head,
+					    event, data);
+}
+
+int kvm_arm_event_notifier_register(struct notifier_block *nb)
+{
+	return blocking_notifier_chain_register(&kvm_arm_event_notifier_head, nb);
+}
+EXPORT_SYMBOL_GPL(kvm_arm_event_notifier_register);
+
+int kvm_arm_event_notifier_unregister(struct notifier_block *nb)
+{
+	return blocking_notifier_chain_unregister(&kvm_arm_event_notifier_head, nb);
+}
+EXPORT_SYMBOL_GPL(kvm_arm_event_notifier_unregister);
+
 module_init(kvm_arm_init);
diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c
index d7a0f69a9982..e76562b0a45a 100644
--- a/arch/arm64/kvm/pkvm.c
+++ b/arch/arm64/kvm/pkvm.c
@@ -280,6 +280,8 @@ static int __init finalize_pkvm(void)
 	ret = pkvm_drop_host_privileges();
 	if (ret)
 		pr_err("Failed to finalize Hyp protection: %d\n", ret);
+	else
+		kvm_arm_event_notifier_call_chain(PKVM_INITIALISED, NULL);

 	return ret;
 }
diff --git a/drivers/firmware/arm_ffa/common.h b/drivers/firmware/arm_ffa/common.h
index 9c6425a81d0d..5cdf4bd222c6 100644
--- a/drivers/firmware/arm_ffa/common.h
+++ b/drivers/firmware/arm_ffa/common.h
@@ -18,9 +18,9 @@ bool ffa_device_is_valid(struct ffa_device *ffa_dev);
 void ffa_device_match_uuid(struct ffa_device *ffa_dev, const uuid_t *uuid);

 #ifdef CONFIG_ARM_FFA_SMCCC
-int __init ffa_transport_init(ffa_fn **invoke_ffa_fn);
+int ffa_transport_init(ffa_fn **invoke_ffa_fn);
 #else
-static inline int __init ffa_transport_init(ffa_fn **invoke_ffa_fn)
+static inline int ffa_transport_init(ffa_fn **invoke_ffa_fn)
 {
 	return -EOPNOTSUPP;
 }
diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index 02c76ac1570b..67df053e65b8 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -35,6 +35,7 @@
 #include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/mutex.h>
+#include <linux/notifier.h>
 #include <linux/of_irq.h>
 #include <linux/scatterlist.h>
 #include <linux/slab.h>
@@ -42,6 +43,8 @@
 #include <linux/uuid.h>
 #include <linux/xarray.h>

+#include <asm/virt.h>
+
 #include "common.h"

 #define FFA_DRIVER_VERSION	FFA_VERSION_1_2
@@ -2029,7 +2032,7 @@ static void ffa_notifications_setup(void)
 	ffa_notifications_cleanup();
 }

-static int __init ffa_init(void)
+static int __ffa_init(void)
 {
 	int ret;
 	u32 buf_sz;
@@ -2105,11 +2108,42 @@ static int __init ffa_init(void)
 free_drv_info:
 	kfree(drv_info);
 	return ret;
+
+}
+
+static int ffa_kvm_arm_event_handler(struct notifier_block *nb,
+				     unsigned long event, void *unused)
+{
+	if (event == PKVM_INITIALISED)
+		__ffa_init();
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block ffa_kvm_arm_event_notifier = {
+	.notifier_call = ffa_kvm_arm_event_handler,
+};
+
+static int __init ffa_init(void)
+{
+	/*
+	 * When pKVM is enabled, the FF-A driver must be initialized
+	 * after pKVM initialization. Otherwise, pKVM cannot negotiate
+	 * the FF-A version or obtain RX/TX buffer information,
+	 * which leads to failures in FF-A calls.
+	 */
+	if (IS_ENABLED(CONFIG_KVM) && is_protected_kvm_enabled() &&
+	    !is_pkvm_initialized())
+		return kvm_arm_event_notifier_register(&ffa_kvm_arm_event_notifier);
+
+	return __ffa_init();
 }
 device_initcall(ffa_init);

 static void __exit ffa_exit(void)
 {
+	if (IS_ENABLED(CONFIG_KVM))
+		kvm_arm_event_notifier_unregister(&ffa_kvm_arm_event_notifier);
 	ffa_notifications_cleanup();
 	ffa_partitions_cleanup();
 	ffa_rxtx_unmap();
diff --git a/drivers/firmware/arm_ffa/smccc.c b/drivers/firmware/arm_ffa/smccc.c
index 4d85bfff0a4e..e6125dd9f58f 100644
--- a/drivers/firmware/arm_ffa/smccc.c
+++ b/drivers/firmware/arm_ffa/smccc.c
@@ -17,7 +17,7 @@ static void __arm_ffa_fn_hvc(ffa_value_t args, ffa_value_t *res)
 	arm_smccc_1_2_hvc(&args, res);
 }

-int __init ffa_transport_init(ffa_fn **invoke_ffa_fn)
+int ffa_transport_init(ffa_fn **invoke_ffa_fn)
 {
 	enum arm_smccc_conduit conduit;

--
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}


^ permalink raw reply related

* [RFC PATCH v2 3/4] firmware: arm_ffa: revert ffa_init() initcall level to device_initcall
From: Yeoreum Yun @ 2026-04-22 16: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
In-Reply-To: <20260422162449.1814615-1-yeoreum.yun@arm.com>

commit 0e0546eabcd6 ("firmware: arm_ffa: Change initcall level of ffa_init() to rootfs_initcall")
changed the initcall level of ffa_init() to rootfs_initcall to address
an issue where IMA could not properly recognize the TPM device.

However, this introduces a problem: pKVM fails to handle any FF-A calls
because it cannot trap the FFA_VERSION call invoked by ffa_init().

Since the IMA init function level has been changed to late_initcall_sync,
there is no longer a need to keep ffa_init() at rootfs_initcall.
Revert it back to device_initcall.

Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.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..02c76ac1570b 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);
+device_initcall(ffa_init);

 static void __exit ffa_exit(void)
 {
--
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}


^ permalink raw reply related

* [RFC PATCH v2 2/4] tpm: tpm_crb_ffa: revert defered_probed when tpm_crb_ffa is built-in
From: Yeoreum Yun @ 2026-04-22 16: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
In-Reply-To: <20260422162449.1814615-1-yeoreum.yun@arm.com>

commit 746d9e9f62a6 ("tpm: tpm_crb_ffa: try to probe tpm_crb_ffa when it's build_in")
probe tpm_crb_ffa forcefully when it's built-in to integrate with IMA.

However, as IMA init function is changed to late_initcall_sync level.
So, this change isn't required anymore.

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

diff --git a/drivers/char/tpm/tpm_crb_ffa.c b/drivers/char/tpm/tpm_crb_ffa.c
index 99f1c1e5644b..025c4d4b17ca 100644
--- a/drivers/char/tpm/tpm_crb_ffa.c
+++ b/drivers/char/tpm/tpm_crb_ffa.c
@@ -177,23 +177,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 +395,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");
--
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}


^ permalink raw reply related

* [RFC PATCH v2 1/4] security: ima: call ima_init() again at late_initcall_sync for defered TPM
From: Yeoreum Yun @ 2026-04-22 16: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
In-Reply-To: <20260422162449.1814615-1-yeoreum.yun@arm.com>

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.

To resolve this, call ima_init() again at late_inicall_sync level
so that let IMA not miss TPM PCR value when generating boot_aggregate
log though TPM device presents in the system.

Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
---
 include/linux/lsm_hooks.h           |  2 +
 security/integrity/ima/ima.h        |  4 +-
 security/integrity/ima/ima_init.c   | 10 +++-
 security/integrity/ima/ima_main.c   | 76 +++++++++++++++++++++++------
 security/integrity/ima/ima_policy.c |  3 ++
 security/lsm_init.c                 | 13 ++++-
 6 files changed, 87 insertions(+), 21 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/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 89ebe98ffc5e..75ee7ad184d0 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -62,6 +62,8 @@ extern int ima_hash_algo_idx __ro_after_init;
 extern int ima_extra_slots __ro_after_init;
 extern struct ima_algo_desc *ima_algo_array __ro_after_init;

+extern bool ima_initialised __ro_after_init;
+
 extern int ima_appraise;
 extern struct tpm_chip *ima_tpm_chip;
 extern const char boot_aggregate_name[];
@@ -257,7 +259,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(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..c28c71090ad2 100644
--- a/security/integrity/ima/ima_init.c
+++ b/security/integrity/ima/ima_init.c
@@ -115,13 +115,19 @@ void __init ima_load_x509(void)
 }
 #endif

-int __init ima_init(void)
+int __init ima_init(bool late)
 {
 	int rc;

 	ima_tpm_chip = tpm_default_chip();
-	if (!ima_tpm_chip)
+	if (!ima_tpm_chip) {
+		if (!late) {
+			pr_info("Defer initialisation to the late_initcall_sync stage.\n");
+			return -EPROBE_DEFER;
+		}
+
 		pr_info("No TPM chip found, activating TPM-bypass!\n");
+	}

 	rc = integrity_init_keyring(INTEGRITY_KEYRING_IMA);
 	if (rc)
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 1d6229b156fb..ac444ee600e2 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -38,6 +38,7 @@ int ima_appraise;
 #endif

 int __ro_after_init ima_hash_algo = HASH_ALGO_SHA1;
+bool ima_initialised __ro_after_init = false;
 static int hash_setup_done;
 static int ima_disabled __ro_after_init;

@@ -1237,6 +1238,35 @@ static int ima_kernel_module_request(char *kmod_name)

 #endif /* CONFIG_INTEGRITY_ASYMMETRIC_KEYS */

+static int __init init_ima_core(bool late)
+{
+	int err;
+
+	if (ima_initialised)
+		return 0;
+
+	err = ima_init(late);
+	if (err == -EPROBE_DEFER)
+		return 0;
+
+	if (err && strcmp(hash_algo_name[ima_hash_algo],
+			  CONFIG_IMA_DEFAULT_HASH) != 0) {
+		pr_info("Allocating %s failed, going to use default hash algorithm %s\n",
+			hash_algo_name[ima_hash_algo], CONFIG_IMA_DEFAULT_HASH);
+		hash_setup_done = 0;
+		hash_setup(CONFIG_IMA_DEFAULT_HASH);
+		err = ima_init(late);
+	}
+
+	if (!err) {
+		ima_update_policy_flags();
+		ima_initialised = true;
+	} else
+		ima_disabled = 1;
+
+	return err;
+}
+
 static int __init init_ima(void)
 {
 	int error;
@@ -1250,30 +1280,42 @@ static int __init init_ima(void)
 	ima_appraise_parse_cmdline();
 	ima_init_template_list();
 	hash_setup(CONFIG_IMA_DEFAULT_HASH);
-	error = ima_init();
-
-	if (error && strcmp(hash_algo_name[ima_hash_algo],
-			    CONFIG_IMA_DEFAULT_HASH) != 0) {
-		pr_info("Allocating %s failed, going to use default hash algorithm %s\n",
-			hash_algo_name[ima_hash_algo], CONFIG_IMA_DEFAULT_HASH);
-		hash_setup_done = 0;
-		hash_setup(CONFIG_IMA_DEFAULT_HASH);
-		error = ima_init();
-	}
-
-	if (error)
-		return error;

 	error = register_blocking_lsm_notifier(&ima_lsm_policy_notifier);
-	if (error)
+	if (error) {
 		pr_warn("Couldn't register LSM notifier, error %d\n", error);
+		goto disable_ima;
+	}

-	if (!error)
-		ima_update_policy_flags();
+	error = init_ima_core(false);
+	if (error) {
+		unregister_blocking_lsm_notifier(&ima_lsm_policy_notifier);
+		goto disable_ima;
+	}
+
+	return 0;

+disable_ima:
+	ima_disabled = 1;
 	return error;
 }

+static int __init late_init_ima(void)
+{
+	int err;
+
+	if (ima_disabled)
+		return 0;
+
+	err = init_ima_core(true);
+	if (err) {
+		unregister_blocking_lsm_notifier(&ima_lsm_policy_notifier);
+		ima_disabled = 1;
+	}
+
+	return err;
+}
+
 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),
@@ -1321,4 +1363,6 @@ DEFINE_LSM(ima) = {
 	.blobs = &ima_blob_sizes,
 	/* Start IMA after the TPM is available */
 	.initcall_late = init_ima,
+	/* Start IMA late in case of probing TPM is deferred. */
+	.initcall_late_sync = late_init_ima,
 };
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index bf2d7ba4c14a..c3bcc3521c81 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -501,6 +501,9 @@ static void ima_lsm_update_rules(void)
 int ima_lsm_policy_change(struct notifier_block *nb, unsigned long event,
 			  void *lsm_data)
 {
+	if (!ima_initialised)
+		return NOTIFY_DONE;
+
 	if (event != LSM_POLICY_CHANGE)
 		return NOTIFY_DONE;

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);
--
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}


^ permalink raw reply related

* [RFC PATCH v2 0/4] fix FF-A call failed with pKVM when ff-a driver is built-in
From: Yeoreum Yun @ 2026-04-22 16: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

commit 0e0546eabcd6 ("firmware: arm_ffa: Change initcall level of ffa_init() to rootfs_initcall")
changed the initcall level of ffa_init() to rootfs_initcall to address
an issue where IMA could not properly recognize the TPM device
when FF-A driver is built as built-in.

However, this introduces another problem: pKVM fails to handle FF-A calls
because it cannot trap the FFA_VERSION call invoked by ffa_init().

To ensure the TPM device is recognized when present in the system,
it is preferable to invoke again ima_init() at a later stage.
Deferred probing is resolved by deferred_probe_initcall(),
which runs at the late_initcall level.
Therefore, introduce an LSM initcall at late_initcall_sync and
invode ima_init() again to this level in case of TPM is probed yet
at the late_initcall stage.

With this change, revert the initcall level of ffa_init() back to
device_initcall. Additionally, to handle the case where ffa_init() runs
before kvm_init(), check whether pKVM has been initialized during ffa_init().
If not, defer initialization to prevent failures of FF-A calls
due to the inability to trap FFA_VERSION and FFA_RXTX_MAP in pKVM.

This patch is based on v7.0

Patch History
=============
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

Yeoreum Yun (4):
  security: ima: call ima_init() again at late_initcall_sync for defered
    TPM
  tpm: tpm_crb_ffa: revert defered_probed when tpm_crb_ffa is built-in
  firmware: arm_ffa: revert ffa_init() initcall level to device_initcall
  firmware: arm_ffa: check pkvm initailised when initailise ffa driver

 arch/arm64/include/asm/virt.h       | 11 +++++
 arch/arm64/kvm/arm.c                | 21 ++++++++
 arch/arm64/kvm/pkvm.c               |  2 +
 drivers/char/tpm/tpm_crb_ffa.c      | 18 ++-----
 drivers/firmware/arm_ffa/common.h   |  4 +-
 drivers/firmware/arm_ffa/driver.c   | 38 ++++++++++++++-
 drivers/firmware/arm_ffa/smccc.c    |  2 +-
 include/linux/lsm_hooks.h           |  2 +
 security/integrity/ima/ima.h        |  4 +-
 security/integrity/ima/ima_init.c   | 10 +++-
 security/integrity/ima/ima_main.c   | 76 +++++++++++++++++++++++------
 security/integrity/ima/ima_policy.c |  3 ++
 security/lsm_init.c                 | 13 ++++-
 13 files changed, 163 insertions(+), 41 deletions(-)


base-commit: 028ef9c96e96197026887c0f092424679298aae8
--
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}


^ permalink raw reply

* Re: [RFC PATCH 4/4] firmware: arm_ffa: check pkvm initailised when initailise ffa driver
From: Yeoreum Yun @ 2026-04-22 13:32 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: Marc Zyngier, linux-security-module, linux-kernel,
	linux-integrity, linux-arm-kernel, kvmarm, paul, jmorris, zohar,
	roberto.sassu, dmitry.kasatkin, eric.snowberg, jarkko, oupton,
	joey.gouly, suzuki.poulose, yuzenghui, catalin.marinas, will,
	sebastianene
In-Reply-To: <aec/YSxYO1bOhXhn@e129823.arm.com>

Hi All,

> > On Tue, Apr 21, 2026 at 07:57:43AM +0100, Yeoreum Yun wrote:
> >
> > [...]
> >
> > >
> > > Also, the FF-A initialization is not driven by a device probe, but rather
> > > happens as part of the bus registration itself,
> > > so it does not fit well with a device_link or probe deferral based approach.
> > >
> > > Instead, perhaps we could go with the idea I mentioned previously:
> > > either introduce a notifier, or create a pseudo ffa_device
> > > once pKVM initialization has completed, and
> > > then let the ffa driver perform the additional initialization from there.
> > >
> > > Am I missing something?
> > >
> >
> > In order to handle/cleanup some ugliness in interrupt management in the
> > FF-A driver, we may introduce DT node eventually. But it will take sometime.
>
> Unfortunately, I think this DT node wouldn't be helpful to solve
> this situation for dependency with the kvm misc device...
>
> IMHO, current situation, the notifier seems to good option. unless
> we make the initcall to recongise this dependency.
>

I think the best approach for now is to introduce a notifier to handle this situation.
If there are no further suggestions, I’ll send a v2 based on:
  - https://lore.kernel.org/all/aeS4rAeVQ0yJIPYw@e129823.arm.com/

Thanks!

--
Sincerely,
Yeoreum Yun

^ permalink raw reply

* [PATCH] ima: return error early if file xattr cannot be changed
From: Goldwyn Rodrigues @ 2026-04-22 11:34 UTC (permalink / raw)
  To: linux-integrity

During early boot, the filesystem is read-only and any changes
to xattrs are not allowed. This fails in case of ext4 because
changing xattr starts an ext4 transaction which fails with the
following warning.

WARNING: fs/ext4/ext4_jbd2.c:75 at ext4_journal_check_start+0x63/0xa0 [ext4], CPU#1: systemd-sysroot/561
CPU: 1 UID: 0 PID: 561 Comm: systemd-sysroot Not tainted 6.19.12-1-default #1 PREEMPT(voluntary) openSUSE Tumbleweed  c2dfc3c9d9f6f1233251c5d4410574fe82a348ee
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS unknown 02/02/2022
RIP: 0010:ext4_journal_check_start+0x63/0xa0 [ext4]
Call Trace:
  __ext4_journal_start_sb+0x3e/0x180 [ext4 6d025f3bc52c89a957b89a89d211fadf5e9434e1]
  ext4_xattr_set+0x104/0x150 [ext4 6d025f3bc52c89a957b89a89d211fadf5e9434e1]
  __vfs_setxattr+0x9a/0xd0
  __vfs_setxattr_noperm+0x76/0x1f0
  ima_appraise_measurement+0x23e/0xe40
  ima_d_path+0x5a/0xd0
  process_measurement+0xb29/0xc40
  ? copy_from_kernel_nofault+0x21/0xe0
  ? fscrypt_file_open+0xc0/0xe0
  ? ext4_file_open+0x60/0x490 [ext4 6d025f3bc52c89a957b89a89d211fadf5e9434e1]
  ? bpf_prog_31efb7c56239148b_restrict_filesystems+0xab/0x126
  ? __bpf_prog_exit+0x23/0xd0
  ? __bpf_tramp_exit+0xd/0x50
  ? bpf_trampoline_6442530367+0x9f/0xea
  ima_file_check+0x57/0x80
  security_file_post_open+0x50/0xf0
  path_openat+0x493/0x1650
  do_filp_open+0xc7/0x170

Detect the state of the file early and return the error.

Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
---
 security/integrity/ima/ima_appraise.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index 870dde67707b..6a4dda46114c 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -90,6 +90,11 @@ static int ima_fix_xattr(struct dentry *dentry,
 	int rc, offset;
 	u8 algo = iint->ima_hash->algo;
 
+	if (IS_RDONLY(d_inode(dentry)))
+		return -EROFS;
+	if (IS_IMMUTABLE(d_inode(dentry)))
+		return -EPERM;
+
 	if (algo <= HASH_ALGO_SHA1) {
 		offset = 1;
 		iint->ima_hash->xattr.sha1.type = IMA_XATTR_DIGEST;
-- 
2.53.0

^ permalink raw reply related

* Re: [PATCH AUTOSEL 7.0-6.18] ima: Define and use a digest_size field in the ima_algo_desc structure
From: Mimi Zohar @ 2026-04-21 18:49 UTC (permalink / raw)
  To: Sasha Levin, patches, stable
  Cc: Roberto Sassu, dmitry.kasatkin, paul, jmorris, serge,
	linux-integrity, linux-security-module, linux-kernel
In-Reply-To: <20260420132314.1023554-102-sashal@kernel.org>

On Mon, 2026-04-20 at 09:18 -0400, Sasha Levin wrote:
> From: Roberto Sassu <roberto.sassu@huawei.com>
> 
> [ Upstream commit a74d7197ebe5b1b8028911d47e78c119d9aaf193 ]
> 
> Add the digest_size field to the ima_algo_desc structure to determine the
> digest size from the correct source.
> 
> If the hash algorithm is among allocated PCR banks, take the value from the
> TPM bank info (equal to the value from the crypto subsystem if the TPM
> algorithm is supported by it; otherwise, not exceding the size of the
> digest buffer in the tpm_digest structure, used by IMA).
> 
> If the hash algorithm is SHA1, use the predefined value. Lastly, if the
> hash algorithm is the default one but not among the PCR banks, take the
> digest size from the crypto subsystem (the default hash algorithm is
> checked when parsing the ima_hash= command line option).
> 
> Finally, use the new information to correctly show the template digest in
> ima_measurements_show() and ima_ascii_measurements_show().
> 
> Link: https://github.com/linux-integrity/linux/issues/14
> Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
> Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
> Signed-off-by: Sasha Levin <sashal@kernel.org>
> ---
> 
> LLM Generated explanations, may be completely bogus:
> 
> Now I have complete information. Let me provide the final analysis.
> 
> ## Phase 1: Commit Message Forensics
> 
> ### Step 1.1: Subject Line
> **Record:** Subsystem: `ima:` (Integrity Measurement Architecture, a
> security subsystem). Action verb: "Define and use" - sounds like
> enhancement, but functionally equivalent to "fix digest size source".
> One-line summary: Add a digest_size field to ima_algo_desc for accurate
> template digest output.
> 
> ### Step 1.2: Tags
> **Record:**
> - `Link: https://github.com/linux-integrity/linux/issues/14` (bug
>   tracker for the linux-integrity subsystem)
> - `Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>` (author)
> - `Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>` (IMA maintainer -
>   applied the patch)
> - No `Fixes:`, no `Cc: stable`, no `Reported-by:` tag.
> 
> ### Step 1.3: Commit Body Analysis
> **Record:** The message describes three cases for digest size:
> 1. TPM bank-allocated algos: take from TPM bank info (which may differ
>    from crypto subsystem size)
> 2. SHA1: use predefined value
> 3. Default hash algo not among banks: use crypto subsystem's size
> 
> Author's framing is additive/improvement ("Add the ... field"), but the
> Link points to GitHub issue #14 titled "Out of bound when creating per-
> algo measurement list interfaces" - describing a KASAN out-of-bounds
> read when TPM has unsupported algorithms (e.g., SHA3_256).
> 
> ### Step 1.4: Hidden Bug Fix Detection
> **Record:** This IS a hidden bug fix. The old code used
> `hash_digest_size[algo]` where `algo` can be `HASH_ALGO__LAST` (for
> unsupported TPM algos). Since `hash_digest_size` is declared
> `[HASH_ALGO__LAST]`, that access is out-of-bounds. The new code uses the
> TPM bank's `digest_size` (always valid) or a known constant.
> 
> ## Phase 2: Diff Analysis
> 
> ### Step 2.1: Inventory
> **Record:** 3 files changed:
> - `security/integrity/ima/ima.h` (+1)
> - `security/integrity/ima/ima_crypto.c` (+6)
> - `security/integrity/ima/ima_fs.c` (+6/-12)
> 
> Total: 13 insertions, 12 deletions. Scope: single-subsystem surgical
> change.
> 
> ### Step 2.2-2.3: Code Flow and Bug Mechanism
> **Record:** Bug category: **Out-of-bounds read** (KASAN-detectable).
> 
> Before fix: `ima_putc(m, e->digests[algo_idx].digest,
> hash_digest_size[algo])` where `algo = ima_algo_array[algo_idx].algo`.
> If the TPM has an algorithm not supported by the kernel's crypto
> subsystem (e.g., SHA3_256 which was not yet in `tpm2_hash_map`), `algo
> == HASH_ALGO__LAST`, and `hash_digest_size[HASH_ALGO__LAST]` is an OOB
> read of the `[HASH_ALGO__LAST]`-sized array.
> 
> After fix: `ima_putc(m, e->digests[algo_idx].digest,
> ima_algo_array[algo_idx].digest_size)`. `digest_size` is populated from
> `tpm_bank_info.digest_size` (which is filled via `tpm2_pcr_read` for
> unknown algos, or `hash_digest_size[crypto_algo]` for known ones),
> `SHA1_DIGEST_SIZE`, or `hash_digest_size[ima_hash_algo]` - all safe
> indexes.
> 
> ### Step 2.4: Fix Quality
> **Record:** Fix is obviously correct, minimal, and well-contained. The
> new `digest_size` field is populated once during init (`__init`), then
> only read later. Regression risk is low - the change is semantically
> equivalent to the old code when the TPM algo is supported, and correct
> when it isn't.
> 
> ## Phase 3: Git History
> 
> ### Step 3.1-3.2: Blame and Fixes target
> **Record:** The buggy line `ima_putc(m, e->digests[algo_idx].digest,
> hash_digest_size[algo])` was introduced by commit `9fa8e76250082a`
> ("ima: add crypto agility support for template-hash algorithm", by
> Enrico Bravi, merged in v6.10). This code is present in every stable
> tree from v6.10 onwards (so 6.12.y and newer).
> 
> ### Step 3.3: Related Commits
> **Record:** Companion commit `d7bd8cf0b348d` ("ima_fs: Correctly create
> securityfs files for unsupported hash algos") was applied 12 days after
> this one, sharing the same `Link:` to issue #14. That commit has an
> explicit `Fixes: 9fa8e7625008` tag and includes a KASAN dump showing
> `create_securityfs_measurement_lists+0x396/0x440` OOB in
> `hash_algo_name`. The two commits address two sides of the same bug:
> `a74d7197ebe5b` fixes OOB in `hash_digest_size[algo]` (runtime, at file
> read), `d7bd8cf0b348d` fixes OOB in `hash_algo_name[algo]` (boot, at
> file creation).
> 
> ### Step 3.4: Author Context
> **Record:** Roberto Sassu is a long-term IMA contributor. Mimi Zohar is
> the IMA subsystem maintainer who merged the patch.
> 
> ### Step 3.5: Dependencies
> **Record:** The fix depends on `tpm_bank_info.digest_size` being
> available, which has existed since commit `879b589210a9a` (2019). No new
> dependencies. Applies to any stable tree containing `9fa8e76250082a`
> (v6.10+).
> 
> ## Phase 4: Mailing List Research
> 
> ### Step 4.1-4.4: Patch Discussion
> **Record:**
> - `b4 dig -c a74d7197ebe5b` found single v1 submission at `https://lore.
>   kernel.org/all/20260225125301.87996-1-roberto.sassu@huaweicloud.com/`
> - Discussion thread contains 3 messages from Mimi Zohar (maintainer) and
>   Roberto Sassu. Mimi requested title rename and asked for a note about
>   the design change (from crypto subsystem's digest size to TPM's).
> - No explicit stable nomination, no mention of KASAN in discussion
>   thread itself.
> - GitHub issue #14 (referenced via Link: tag) explicitly documents the
>   OOB bug this is fixing: "If a TPM algorithm is not supported the PCR
>   bank info is initialized with HASH_ALGO__LAST, which passed to
>   hash_algo_name[] causes an out of bound."
> - No v2, applied as single revision.
> 
> ### Step 4.5: Stable Discussion
> **Record:** No prior stable mailing list discussion found for this
> specific commit.
> 
> ## Phase 5: Code Semantic Analysis
> 
> ### Step 5.1-5.4: Call Paths
> **Record:** `ima_measurements_show()` is called when a userspace process
> reads `/sys/kernel/security/ima/binary_runtime_measurements*`.
> `ima_ascii_measurements_show()` similarly for ASCII files. These files
> are readable by root. The path is reachable from userspace via a simple
> `read()` syscall against the securityfs files. `ima_init_crypto()` is
> called once at boot via initcall.
> 
> ### Step 5.5: Similar Patterns
> **Record:** The sister commit `d7bd8cf0b348d` addresses the same pattern
> (`hash_algo_name[algo]` with `algo == HASH_ALGO__LAST`) in the file-
> creation path.
> 
> ## Phase 6: Stable Tree Cross-Reference
> 
> ### Step 6.1-6.3: Applicability
> **Record:**
> - Buggy code exists in 6.12.y (verified via `git blame stable-
>   push/linux-6.12.y` showing line 184 originated from 9fa8e76250082a).
>   Also in 6.15, 6.17, 6.18, 6.19, 7.0.
> - 6.1.y and 6.6.y don't have the crypto agility code
>   (`hash_digest_size[algo]` usage) - the fix is NOT applicable/needed
>   there. 6.6.y uses `TPM_DIGEST_SIZE`.
> - Backport difficulty to 6.12.y: minor rework needed (ima_algo_array
>   allocation uses `kcalloc` instead of `kzalloc_objs` in newer tree, but
>   that's not affected by this patch - the field addition and assignments
>   apply straightforwardly).
> - Neither this commit nor `d7bd8cf0b348d` is yet in 6.12.y (verified via
>   `git log stable-push/linux-6.12.y`).
> 
> ## Phase 7: Subsystem Context
> 
> ### Step 7.1-7.2
> **Record:** Subsystem: IMA (security/integrity/ima/). Criticality:
> IMPORTANT - used for measured boot/attestation on enterprise/embedded
> systems. Activity: active subsystem with regular fixes. The code is only
> reachable when CONFIG_IMA is enabled AND a TPM is present, further
> narrowing impact to TPM-equipped systems.
> 
> ## Phase 8: Impact and Risk
> 
> ### Step 8.1: Affected Users
> **Record:** Users with IMA enabled + TPM 2.0 chip that exposes an
> algorithm not in the kernel's `tpm2_hash_map`. The KASAN dump in
> d7bd8cf0b348d shows this was hit on real hardware (SHA3_256-capable
> TPM).
> 
> ### Step 8.2: Trigger
> **Record:** The secondary OOB fixed by THIS commit
> (hash_digest_size[HASH_ALGO__LAST]) triggers when:
> 1. A TPM exposes an unsupported algorithm (e.g., SHA3_256)
> 2. A user (root) reads the unsupported-algo measurements file
> Root privilege required - not a remote attack vector, but reproducible
> with specific hardware. The primary OOB (in create_securityfs) hits
> every boot with such TPMs, which is what the KASAN report showed.
> 
> ### Step 8.3: Failure Mode
> **Record:** Out-of-bounds read from kernel memory. Under KASAN: reported
> as BUG. Without KASAN: may return garbage digest size, which could cause
> excessive data to be read from `e->digests[algo_idx].digest` (a fixed-
> size `[TPM2_MAX_DIGEST_SIZE]` buffer) or leak a few bytes past the
> `hash_digest_size` array. Severity: **MEDIUM-HIGH** (OOB read is KASAN-
> reportable security-relevant behavior, not a guaranteed crash without
> KASAN but can leak info or cause incorrect behavior).
> 
> ### Step 8.4: Risk vs Benefit
> **Record:**
> - **Benefit: MEDIUM** - Fixes one half of a KASAN-reportable OOB read
>   with real-hardware reproducer.
> - **Risk: LOW** - 13-line structural change, all within the IMA init
>   path + two show functions, no change of external behavior for
>   supported TPM algos.
> - **Ratio: Favorable for backport** - but only valuable when paired with
>   d7bd8cf0b348d (the boot-time crash fix).
> 
> ## Phase 9: Final Synthesis
> 
> ### Step 9.1-9.4: Evidence Summary
> 
> **For backport:**
> - Small, contained (13/12 lines, 3 files)
> - Fixes real OOB read (hash_digest_size[HASH_ALGO__LAST])
> - Obviously correct - reviewed by IMA maintainer (Mimi Zohar)
> - Low regression risk
> - Reachable from userspace (root reads securityfs file)
> - Bug has real-hardware reproducer (SHA3_256 TPMs)
> - Companion commit d7bd8cf0b348d has `Fixes:` tag and will be auto-
>   selected; backporting only d7bd8cf0b348d leaves a latent OOB in the
>   read path
> 
> **Against backport:**
> - No explicit `Fixes:` tag, no `Cc: stable`
> - Framed as enhancement, not bug fix
> - Alone doesn't fix the primary crash (boot-time OOB in
>   `create_securityfs_measurement_lists`) - that's d7bd8cf0b348d
> - Design change (TPM's size vs crypto's size) noted by maintainer in
>   review
> 
> **Exception Category:** Not a device ID/quirk/DT/build/doc. Standard bug
> fix evaluation.
> 
> **Stable Rules Check:**
> 1. Obviously correct: YES (reviewed, simple struct field addition + safe
>    sources)
> 2. Fixes real bug: YES (OOB read)
> 3. Important issue: MEDIUM (KASAN-reportable OOB with real hardware)
> 4. Small and contained: YES (13/12 lines)
> 5. No new features/APIs: YES (internal struct field, not user-visible)
> 6. Applies to stable: YES (6.12.y+ with minor/no conflicts)
> 
> ## Verification
> 
> - [Phase 1] Parsed tags: no Fixes:, no Cc: stable, has `Link:
>   github.com/linux-integrity/linux/issues/14`
> - [Phase 1] Hidden bug fix confirmed: commit uses additive language but
>   eliminates OOB read
> - [Phase 2] Diff analysis: `git show a74d7197ebe5b` confirmed +13/-12
>   across 3 files; key change is replacing `hash_digest_size[algo]` with
>   `ima_algo_array[algo_idx].digest_size`
> - [Phase 3] `git blame stable-push/linux-6.12.y
>   security/integrity/ima/ima_fs.c`: buggy line 184 was introduced by
>   9fa8e76250082a (v6.10)
> - [Phase 3] `git show 9fa8e76250082`: confirmed merged in v6.10
>   (2024-04-12)
> - [Phase 3] Found companion commit d7bd8cf0b348d sharing the same GitHub
>   issue link
> - [Phase 3] Verified `include/linux/tpm.h` defines
>   `tpm_bank_info.digest_size` (dependency satisfied in all target stable
>   trees since 2019 via commit 879b589210a9a)
> - [Phase 4] `b4 dig -c a74d7197ebe5b`: found single v1 submission
> - [Phase 4] `b4 dig -c a74d7197ebe5b -a`: only v1, no earlier revisions
> - [Phase 4] `b4 dig -c a74d7197ebe5b -w`: maintainer Mimi Zohar was a
>   recipient
> - [Phase 4] Read `/tmp/thread.mbx`: confirmed maintainer review, no
>   stable nomination, no KASAN mention in thread
> - [Phase 4] WebFetch github issue #14: confirmed OOB bug rationale
> - [Phase 4] WebFetch marc.info original patch: confirmed patch content
>   matches commit
> - [Phase 5] Verified `ima_measurements_show` is reachable via read() on
>   `/sys/kernel/security/ima/*_runtime_measurements*`
> - [Phase 6] `git show stable-push/linux-6.12.y:.../ima_fs.c`: confirmed
>   buggy line present at 184
> - [Phase 6] `git show stable-push/linux-6.6.y:.../ima_fs.c`: uses
>   `TPM_DIGEST_SIZE`, no crypto agility, bug doesn't exist there
> - [Phase 6] `git show stable-push/linux-6.1.y`: ima_fs.c does not have
>   the buggy code
> - [Phase 6] `git log stable-push/linux-6.12.y`: neither this commit nor
>   d7bd8cf0b348d is yet in 6.12.y
> - [Phase 8] Failure mode: OOB read of
>   `hash_digest_size[HASH_ALGO__LAST]` - triggered by reading per-algo
>   measurement file on TPM with unsupported algo
> - UNVERIFIED: Whether d7bd8cf0b348d has been auto-selected by Fixes:-tag
>   tooling; whether user-visible symptoms (without KASAN) would be
>   observable in the field.
> 
> ## Conclusion
> 
> This commit is a small, surgical fix for a real out-of-bounds read bug
> that affects stable trees from v6.12 onwards. While the commit message
> frames it as an "add a field" improvement rather than a bug fix, the
> code change explicitly eliminates an OOB read in the user-reachable path
> `ima_measurements_show()` / `ima_ascii_measurements_show()` when a TPM
> exposes an algorithm not supported by the kernel crypto subsystem. The
> companion commit `d7bd8cf0b348d` addresses the parallel boot-time OOB
> (in `create_securityfs_measurement_lists`) and has a `Fixes:` tag, so it
> will likely be auto-selected. If d7bd8cf0b348d reaches stable (as it
> should), this commit is needed to plug the remaining runtime OOB on the
> same hardware.
> 
> **YES**

Thanks, Sasha!

The AI's conclusion is correct.  This patch is needed when backporting commit
d7bd8cf0b348 ("ima_fs: Correctly create securityfs files for unsupported hash
algos") is correct.

Mimi

^ permalink raw reply

* Re: tpm: spi: do not call blocking ops when !TASK_RUNNING; during shutdown
From: Jarkko Sakkinen @ 2026-04-21 18:28 UTC (permalink / raw)
  To: Peng Fan
  Cc: Stefan Wahren, Peter Huewe, Jason Gunthorpe,
	linux-arm-kernel@lists.infradead.org,
	linux-integrity@vger.kernel.org, kernel@pengutronix.de, Frank Li,
	Sascha Hauer, imx@lists.linux.dev
In-Reply-To: <PAXPR04MB84598325136E394E0A7D94D6882C2@PAXPR04MB8459.eurprd04.prod.outlook.com>

On Tue, Apr 21, 2026 at 09:04:43AM +0000, Peng Fan wrote:
> > Subject: tpm: spi: do not call blocking ops when !TASK_RUNNING;
> > during shutdown
> > 
> > Hi,
> > we use a custom i.MX93 board, which based on Phytec Phycore i.MX93
> > with a TPM connected via SPI. If I enable
> > CONFIG_DEBUG_ATOMIC_SLEEP=y in our kernel config with mainline
> > kernel 6.18.23 and reboot our board, I will get the following warning:
> > ffff0000000d8000
> 
> The issue seems at drivers/char/tpm/tpm_tis_core.c
>   94                 rc = wait_event_interruptible_timeout(*queue,                                       
>   95                         wait_for_tpm_stat_cond(chip, sts_mask, check_cancel,                        
>   96                                                &canceled),                                          
>   97                         timeout);
> 
> wait_event_interruptible_timeout set task to !TASK_RUNNING,
> but wait_for_tpm_stat_cond still calls into mutex_lock.
> 
> Regards
> Peng
> 
> > [   43.422135] Call trace:
> > [   43.424570]  __might_sleep+0x74/0x7c (P)
> > [   43.428487]  mutex_lock+0x24/0x80
> > [   43.431797]  spi_bus_lock+0x20/0x50
> > [   43.435281]  tpm_tis_spi_transfer_full+0x70/0x2c4
> > [   43.439979]  tpm_tis_spi_read_bytes+0x3c/0x48
> > [   43.444321]  tpm_tis_status+0x58/0xf8
> > [   43.447978]  wait_for_tpm_stat_cond+0x30/0x90
> > [   43.452329]  wait_for_tpm_stat+0x1cc/0x2e0
> > [   43.456419]  tpm_tis_send_data+0xdc/0x334
> > [   43.460423]  tpm_tis_send_main+0x74/0x160
> > [   43.464427]  tpm_tis_send+0xd4/0x13c
> > [   43.467998]  tpm_transmit+0xc4/0x3c4
> > [   43.471569]  tpm_transmit_cmd+0x38/0xd4
> > [   43.475399]  tpm2_shutdown+0x6c/0xa4
> > [   43.478970]  tpm_class_shutdown+0x60/0x88
> > [   43.482974]  device_shutdown+0x130/0x25c
> > [   43.486891]  kernel_restart+0x44/0xa4
> > [   43.490549]  __do_sys_reboot+0x114/0x254
> > [   43.494466]  __arm64_sys_reboot+0x24/0x30
> > [   43.498470]  invoke_syscall+0x48/0x10c
> > [   43.502214]  el0_svc_common.constprop.0+0x40/0xe0
> > [   43.506911]  do_el0_svc+0x1c/0x28
> > [   43.510222]  el0_svc+0x34/0xec
> > [   43.513273]  el0t_64_sync_handler+0xa0/0xe4
> > [   43.517441]  el0t_64_sync+0x198/0x19c
> > 
> > Best regards

On travel this week but thanks for the report. Investigating next weeek

In the meantime, patches are welcome (whcih I will review next week).

Br, Jarkko

^ permalink raw reply

* Re: [PATCH v2] tpm: restore timeout for key creation commands
From: Jarkko Sakkinen @ 2026-04-21 18:24 UTC (permalink / raw)
  To: Baoli Zhang
  Cc: Peter Huewe, Jason Gunthorpe, Serge Hallyn, Lili Li,
	linux-integrity, linux-kernel
In-Reply-To: <20260421005021.13765-1-baoli.zhang@linux.intel.com>

On Tue, Apr 21, 2026 at 08:50:20AM +0800, Baoli Zhang wrote:
> From: "Baoli Zhang" <baoli.zhang@linux.intel.com>
> 
> Commit 207696b17f38 ("tpm: use a map for tpm2_calc_ordinal_duration()")
> inadvertently reduced the timeout for TPM2 key creation commands
> (`CREATE_PRIMARY`, `CREATE`, `CREATE_LOADED`) from 300 seconds to 30
> seconds.
> 
> This causes intermittent timeout failures, with several failures observed
> across hundreds of test runs on some Intel platforms using Infineon
> SLB9670 and SLB9672 TPM modules. Restore the timeout to 300 seconds to
> avoid spurious failures.
> 
> Fixes: 207696b17f38 ("tpm: use a map for tpm2_calc_ordinal_duration()")
> Co-developed-by: Lili Li <lili.li@intel.com>
> Signed-off-by: Lili Li <lili.li@intel.com>
> Signed-off-by: Baoli Zhang <baoli.zhang@linux.intel.com>
> ---
> Changes in v2:
> - Add description of intermittent nature of the timeout issue.
> - Fix Co-developed-by and Signed-off-by tag ordering.
> 
> v1: https://patchwork.kernel.org/project/linux-integrity/patch/20260410014940.3557934-1-baoli.zhang@linux.intel.com/
> 
>  drivers/char/tpm/tpm2-cmd.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
> index 3a77be7ebf4aa..430022f695f24 100644
> --- a/drivers/char/tpm/tpm2-cmd.c
> +++ b/drivers/char/tpm/tpm2-cmd.c
> @@ -71,9 +71,9 @@ static const struct {
>  	{TPM2_CC_HIERARCHY_CHANGE_AUTH, 2000},
>  	{TPM2_CC_GET_CAPABILITY, 750},
>  	{TPM2_CC_NV_READ, 2000},
> -	{TPM2_CC_CREATE_PRIMARY, 30000},
> -	{TPM2_CC_CREATE, 30000},
> -	{TPM2_CC_CREATE_LOADED, 30000},
> +	{TPM2_CC_CREATE_PRIMARY, 300000},
> +	{TPM2_CC_CREATE, 300000},
> +	{TPM2_CC_CREATE_LOADED, 300000},
>  };
>  
>  /**
> -- 
> 2.43.0
> 


Much better! I'm fine with this and it is a regression.

On travel right now but I do have one SLB9670 connected to RPi4.

I'll do peer testing once at home (next week).

BR, Jarkko

^ permalink raw reply

* Re: [RFC PATCH 1/4] security: ima: move ima_init into late_initcall_sync
From: Yeoreum Yun @ 2026-04-21 14:09 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, peterhuewe, jarkko, jgg,
	sudeep.holla, maz, oupton, joey.gouly, suzuki.poulose, yuzenghui,
	catalin.marinas, will
In-Reply-To: <d6bcc9ef98a1e86887c5a79ff2822e70b5534343.camel@linux.ibm.com>

Hi Mimi,

> On Tue, 2026-04-21 at 13:50 +0100, Yeoreum Yun wrote:
> > Hi Mimi,
> >
> > > On Fri, 2026-04-17 at 18:57 +0100, Yeoreum Yun wrote:
> > > > 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.
> > > >
> > > > To resolve this, move ima_init() into late_inicall_sync level
> > > > so that let IMA not miss TPM PCR value when generating boot_aggregate
> > > > log though TPM device presents in the system.
> > > >
> > > > Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
> > >
> > > IMA should be initialized as early as possible. I'm really hesitant to defer
> > > ima_init() to late_initcall_sync() for systems that the TPM is currently
> > > initialized in time. For these systems, continue initializing IMA at
> > > late_initcall(). As a compromise for those systems that the TPM isn't properly
> > > initialized in time, define and instantiate the late_initcall_sync().
> > >
> > > ima_init() would need to differentiate between the late_initcall and
> > > late_initcall_sync.  On late_initcall(), instead of saying "No TPM chip found,
> > > activating TPM-bypass!",  it should say "No TPM chip found, deferring to
> > > late_initcall_sync" or something similar.
> >
> > But can we really move those initialisations to be called again?
> >
> > I am referring to functions such as ima_init_crypto(),
> > ima_add_boot_aggregate(), and ima_measure_critical_data() in ima_init()—
> > first without TPM, and then a second time once TPM becomes available.
> > I don’t think that approach would work.
> >
> > In other words, unless tpm_default_chip() can differentiate between a TPM
> > device that is deferred and one that does not exist, we cannot distinguish
> > between the “defer” case and “-EEXIST”.
> >
> > It might be possible if the TPM core tracked the state when a driver returns
> > -EPROBE_DEFER, but I am not sure that is the right approach.
> > For deferred probe cases, the “device initialised in time” check should
> > likely be done at late_initcall_sync, rather than late_initcall.
> >
> > This implies that any such check performed before late_initcall_sync
> > does not reflect a valid state, as it cannot distinguish between “not
> > present” and “deferred”.
> >
> > Therefore, I think the TPM check in IMA should be performed at
> > late_initcall_sync.
> >
> >
> > Am I missing something?
>
> In ima_init() you short circuit out, when called by late_initcall(), if the TPM
> hasn't been initialized.  So the rest of the ima_init() isn't called.  Roughly
> something like this (needs some cleanup):
>
> int __init ima_init(void)
> {
>         static int first = 1;
>         int rc;
>
>         if (ima_tpm_chip)
>                 return 0;
>
>         ima_tpm_chip = tpm_default_chip();
>         if (!ima_tpm_chip && first) {
>                 pr_info("No TPM chip found, deferring te late_initcall_sync()\n");
>                 first = 0;
>                 return 0;
>         }

I see. then I'll respin in v2.

Thanks!

--
Sincerely,
Yeoreum Yun

^ permalink raw reply


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