Linux Integrity Measurement development
 help / color / mirror / Atom feed
* Re: [PATCH v15 00/28] x86: Secure Launch support for Intel TXT
From: ross.philipson @ 2026-02-18 18:02 UTC (permalink / raw)
  To: Ard Biesheuvel, Daniel P. Smith, linux-kernel, x86,
	linux-integrity, linux-doc, linux-crypto, kexec, linux-efi, iommu,
	dave.hansen
  Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, H . Peter Anvin,
	mjg59, James.Bottomley, peterhuewe, Jarkko Sakkinen, jgg, luto,
	nivedita, Herbert Xu, davem, corbet, ebiederm, dwmw2, baolu.lu,
	kanth.ghatraju, andrew.cooper3, trenchboot-devel
In-Reply-To: <242a0462-7fc5-4902-b71d-22cf8360239e@app.fastmail.com>

On 2/18/26 9:30 AM, 'Ard Biesheuvel' via trenchboot-devel wrote:
> On Thu, 12 Feb 2026, at 21:39, Ard Biesheuvel wrote:
>> On Thu, 12 Feb 2026, at 20:49, Daniel P. Smith wrote:
>>> On 2/9/26 09:04, Ard Biesheuvel wrote:
>> ...
>>>> I've had a stab at implementing all of this in a manner that is more idiomatic for EFI boot:
>>>>
>>>> - GRUB does minimal TXT related preparation upfront, and exposes the remaining functionality via a protocol that is attached to the loaded image by GRUB
>>>> - The SL stub is moved to the core kernel, with some startup code added to pivot to long mode
>>>> - the EFI stub executes and decompresses the kernel as usual
>>>> - if the protocol is present, the EFI stub calls it to pass the bootparams pointer, the base and size of the MLE and the header offset back to the GRUB code
>>>> - after calling ExitBootServices(), it calls another protocol method to trigger the secure launch.
>>>>
>> ...
>>>
>>> I think this is a great approach for UEFI, though we need to reconcile
>>> this with non-UEFI situations such as booting under coreboot.
>>
>> There are two approaches that I think are feasible for coreboot in this model:
>>
>> - just unpack the ELF and boot that - there is already prior art for
>> that with Xen. We can stick the MLE header offset in an ELF note where
>> any loader can find it.
>>
>> - stick with the current approach as much as possible, i.e., disable
>> physical KASLR so that the decompressed kernel will end up right where
>> the decompressor was loaded, which allows much of the secure launch
>> preparation to be done as before. Only the final bits (including the
>> call into the ACM itself) need to be deferred, and we can propose a
>> generic mechanism for that via boot_params.
>>
>> I'm working on a prototype of the latter, but GRUB is an odd beast and
>> my x86 fu is weak.
>>
> 
> I've managed to get a working implementation of the legacy entrypoint, by repurposing the dl_handler() entrypoint you added for EFI [which no longer needs it in my version] as a callback for the legacy boot flow. This /should/ work for i386-coreboot too, but I have no way of testing it (I only tried 'slaunch --legacy-linux' using the x86_64-efi build).

Using that GRUB argument should cause GRUB to choose the legacy boot path. That is where we were going with things.

> 
> I've pushed the changes to the branches I mentioned previously in this thread.

I will pull your latest, thank you Ard

> 
> 
> 
>   
> 


^ permalink raw reply

* Re: [PATCH v15 00/28] x86: Secure Launch support for Intel TXT
From: Ard Biesheuvel @ 2026-02-18 17:30 UTC (permalink / raw)
  To: Daniel P. Smith, Ross Philipson, linux-kernel, x86,
	linux-integrity, linux-doc, linux-crypto, kexec, linux-efi, iommu,
	dave.hansen
  Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, H . Peter Anvin,
	mjg59, James.Bottomley, peterhuewe, Jarkko Sakkinen, jgg, luto,
	nivedita, Herbert Xu, davem, corbet, ebiederm, dwmw2, baolu.lu,
	kanth.ghatraju, andrew.cooper3, trenchboot-devel
In-Reply-To: <49d169bf-0ad2-49be-b7d7-fceb9e7f831a@app.fastmail.com>

On Thu, 12 Feb 2026, at 21:39, Ard Biesheuvel wrote:
> On Thu, 12 Feb 2026, at 20:49, Daniel P. Smith wrote:
>> On 2/9/26 09:04, Ard Biesheuvel wrote:
> ...
>>> I've had a stab at implementing all of this in a manner that is more idiomatic for EFI boot:
>>> 
>>> - GRUB does minimal TXT related preparation upfront, and exposes the remaining functionality via a protocol that is attached to the loaded image by GRUB
>>> - The SL stub is moved to the core kernel, with some startup code added to pivot to long mode
>>> - the EFI stub executes and decompresses the kernel as usual
>>> - if the protocol is present, the EFI stub calls it to pass the bootparams pointer, the base and size of the MLE and the header offset back to the GRUB code
>>> - after calling ExitBootServices(), it calls another protocol method to trigger the secure launch.
>>> 
> ...
>>
>> I think this is a great approach for UEFI, though we need to reconcile 
>> this with non-UEFI situations such as booting under coreboot.
>
> There are two approaches that I think are feasible for coreboot in this model:
>
> - just unpack the ELF and boot that - there is already prior art for 
> that with Xen. We can stick the MLE header offset in an ELF note where 
> any loader can find it.
>
> - stick with the current approach as much as possible, i.e., disable 
> physical KASLR so that the decompressed kernel will end up right where 
> the decompressor was loaded, which allows much of the secure launch 
> preparation to be done as before. Only the final bits (including the 
> call into the ACM itself) need to be deferred, and we can propose a 
> generic mechanism for that via boot_params.
>
> I'm working on a prototype of the latter, but GRUB is an odd beast and 
> my x86 fu is weak.
>

I've managed to get a working implementation of the legacy entrypoint, by repurposing the dl_handler() entrypoint you added for EFI [which no longer needs it in my version] as a callback for the legacy boot flow. This /should/ work for i386-coreboot too, but I have no way of testing it (I only tried 'slaunch --legacy-linux' using the x86_64-efi build).

I've pushed the changes to the branches I mentioned previously in this thread.



 

^ permalink raw reply

* Re: [PATCH 2/2] keys/trusted_keys: move TPM-specific fields into trusted_tpm_options
From: Srish Srinivasan @ 2026-02-17  6:52 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: linux-integrity, keyrings, James.Bottomley, zohar, nayna, stefanb,
	linux-kernel, linux-security-module, Srish Srinivasan
In-Reply-To: <aXZMLbQ2ykqPQp48@kernel.org>

Hi Jarkko,
thanks for taking a look.

And, apologies for the delayed response.

On 1/25/26 10:30 PM, Jarkko Sakkinen wrote:
> On Fri, Jan 23, 2026 at 10:25:04PM +0530, Srish Srinivasan wrote:
>> The trusted_key_options struct contains TPM-specific fields (keyhandle,
>> keyauth, blobauth_len, blobauth, pcrinfo_len, pcrinfo, pcrlock, hash,
>> policydigest_len, policydigest, and policyhandle). This leads to the
>> accumulation of backend-specific fields in the generic options structure.
>>
>> Define trusted_tpm_options structure and move the TPM-specific fields
>> there. Store a pointer to trusted_tpm_options in trusted_key_options's
>> private.
>>
>> No functional change intended.
>>
>> Signed-off-by: Srish Srinivasan <ssrish@linux.ibm.com>
>> Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
>> ---
>>   include/keys/trusted-type.h               |  11 ---
>>   include/keys/trusted_tpm.h                |  14 +++
>>   security/keys/trusted-keys/trusted_tpm1.c | 103 ++++++++++++++--------
>>   security/keys/trusted-keys/trusted_tpm2.c |  62 ++++++++-----
>>   4 files changed, 121 insertions(+), 69 deletions(-)
>>
>> diff --git a/include/keys/trusted-type.h b/include/keys/trusted-type.h
>> index 03527162613f..b80f250305b8 100644
>> --- a/include/keys/trusted-type.h
>> +++ b/include/keys/trusted-type.h
>> @@ -39,17 +39,6 @@ struct trusted_key_payload {
>>   
>>   struct trusted_key_options {
>>   	uint16_t keytype;
>> -	uint32_t keyhandle;
>> -	unsigned char keyauth[TPM_DIGEST_SIZE];
>> -	uint32_t blobauth_len;
>> -	unsigned char blobauth[TPM_DIGEST_SIZE];
>> -	uint32_t pcrinfo_len;
>> -	unsigned char pcrinfo[MAX_PCRINFO_SIZE];
>> -	int pcrlock;
>> -	uint32_t hash;
>> -	uint32_t policydigest_len;
>> -	unsigned char policydigest[MAX_DIGEST_SIZE];
>> -	uint32_t policyhandle;
>>   	void *private;
>>   };
>>   
>> diff --git a/include/keys/trusted_tpm.h b/include/keys/trusted_tpm.h
>> index 0fadc6a4f166..355ebd36cbfd 100644
>> --- a/include/keys/trusted_tpm.h
>> +++ b/include/keys/trusted_tpm.h
>> @@ -7,6 +7,20 @@
>>   
>>   extern struct trusted_key_ops trusted_key_tpm_ops;
>>   
>> +struct trusted_tpm_options {
>> +	uint32_t keyhandle;
>> +	unsigned char keyauth[TPM_DIGEST_SIZE];
>> +	uint32_t blobauth_len;
>> +	unsigned char blobauth[TPM_DIGEST_SIZE];
>> +	uint32_t pcrinfo_len;
>> +	unsigned char pcrinfo[MAX_PCRINFO_SIZE];
>> +	int pcrlock;
>> +	uint32_t hash;
>> +	uint32_t policydigest_len;
>> +	unsigned char policydigest[MAX_DIGEST_SIZE];
>> +	uint32_t policyhandle;
>> +};
>> +
>>   int tpm2_seal_trusted(struct tpm_chip *chip,
>>   		      struct trusted_key_payload *payload,
>>   		      struct trusted_key_options *options);
>> diff --git a/security/keys/trusted-keys/trusted_tpm1.c b/security/keys/trusted-keys/trusted_tpm1.c
>> index 636acb66a4f6..0ab0234ebe37 100644
>> --- a/security/keys/trusted-keys/trusted_tpm1.c
>> +++ b/security/keys/trusted-keys/trusted_tpm1.c
>> @@ -50,12 +50,14 @@ enum {
>>   #if TPM_DEBUG
>>   static inline void dump_options(struct trusted_key_options *o)
>>   {
>> +	struct trusted_tpm_options *tpm_opts = o->private;
>
> TPM context is obvious i.e., actually private would be a better name.


Noted. Will make the change.


>
>> +
>>   	pr_info("sealing key type %d\n", o->keytype);
>> -	pr_info("sealing key handle %0X\n", o->keyhandle);
>> -	pr_info("pcrlock %d\n", o->pcrlock);
>> -	pr_info("pcrinfo %d\n", o->pcrinfo_len);
>> +	pr_info("sealing key handle %0X\n", tpm_opts->keyhandle);
>> +	pr_info("pcrlock %d\n", tpm_opts->pcrlock);
>> +	pr_info("pcrinfo %d\n", tpm_opts->pcrinfo_len);
>>   	print_hex_dump(KERN_INFO, "pcrinfo ", DUMP_PREFIX_NONE,
>> -		       16, 1, o->pcrinfo, o->pcrinfo_len, 0);
>> +		       16, 1, tpm_opts->pcrinfo, tpm_opts->pcrinfo_len, 0);
>>   }
> Should be replaced with pr_debug() and KERN_DEBUG as precursory patch
> (and remove TPM_DEBUG).


Will fix this, and make it a preparatory clean-up patch.


>
>>   
>>   static inline void dump_sess(struct osapsess *s)
>> @@ -624,6 +626,7 @@ static int tpm_unseal(struct tpm_buf *tb,
>>   static int key_seal(struct trusted_key_payload *p,
>>   		    struct trusted_key_options *o)
>>   {
>> +	struct trusted_tpm_options *tpm_opts;
>>   	struct tpm_buf tb;
>>   	int ret;
>>   
>> @@ -634,9 +637,12 @@ static int key_seal(struct trusted_key_payload *p,
>>   	/* include migratable flag at end of sealed key */
>>   	p->key[p->key_len] = p->migratable;
>>   
>> -	ret = tpm_seal(&tb, o->keytype, o->keyhandle, o->keyauth,
>> +	tpm_opts = o->private;
> Not sure why this is not done in the declaration.


Will fix this.


>
>> +
>> +	ret = tpm_seal(&tb, o->keytype, tpm_opts->keyhandle, tpm_opts->keyauth,
>>   		       p->key, p->key_len + 1, p->blob, &p->blob_len,
>> -		       o->blobauth, o->pcrinfo, o->pcrinfo_len);
>> +		       tpm_opts->blobauth, tpm_opts->pcrinfo,
>> +		       tpm_opts->pcrinfo_len);
>>   	if (ret < 0)
>>   		pr_info("srkseal failed (%d)\n", ret);
>>   
>> @@ -650,6 +656,7 @@ static int key_seal(struct trusted_key_payload *p,
>>   static int key_unseal(struct trusted_key_payload *p,
>>   		      struct trusted_key_options *o)
>>   {
>> +	struct trusted_tpm_options *tpm_opts;
>>   	struct tpm_buf tb;
>>   	int ret;
>>   
>> @@ -657,8 +664,10 @@ static int key_unseal(struct trusted_key_payload *p,
>>   	if (ret)
>>   		return ret;
>>   
>> -	ret = tpm_unseal(&tb, o->keyhandle, o->keyauth, p->blob, p->blob_len,
>> -			 o->blobauth, p->key, &p->key_len);
>> +	tpm_opts = o->private;
>> +
>> +	ret = tpm_unseal(&tb, tpm_opts->keyhandle, tpm_opts->keyauth, p->blob,
>> +			 p->blob_len, tpm_opts->blobauth, p->key, &p->key_len);
>>   	if (ret < 0)
>>   		pr_info("srkunseal failed (%d)\n", ret);
>>   	else
>> @@ -695,6 +704,7 @@ static const match_table_t key_tokens = {
>>   static int getoptions(char *c, struct trusted_key_payload *pay,
>>   		      struct trusted_key_options *opt)
>>   {
>> +	struct trusted_tpm_options *tpm_opts;
>>   	substring_t args[MAX_OPT_ARGS];
>>   	char *p = c;
>>   	int token;
>> @@ -710,7 +720,9 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
>>   	if (tpm2 < 0)
>>   		return tpm2;
>>   
>> -	opt->hash = tpm2 ? HASH_ALGO_SHA256 : HASH_ALGO_SHA1;
>> +	tpm_opts = opt->private;
>> +
> I'd remove this empty line.


Will fix this.


>
>> +	tpm_opts->hash = tpm2 ? HASH_ALGO_SHA256 : HASH_ALGO_SHA1;
>>   
>>   	if (!c)
>>   		return 0;
>> @@ -724,11 +736,11 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
>>   
>>   		switch (token) {
>>   		case Opt_pcrinfo:
>> -			opt->pcrinfo_len = strlen(args[0].from) / 2;
>> -			if (opt->pcrinfo_len > MAX_PCRINFO_SIZE)
>> +			tpm_opts->pcrinfo_len = strlen(args[0].from) / 2;
>> +			if (tpm_opts->pcrinfo_len > MAX_PCRINFO_SIZE)
>>   				return -EINVAL;
>> -			res = hex2bin(opt->pcrinfo, args[0].from,
>> -				      opt->pcrinfo_len);
>> +			res = hex2bin(tpm_opts->pcrinfo, args[0].from,
>> +				      tpm_opts->pcrinfo_len);
>>   			if (res < 0)
>>   				return -EINVAL;
>>   			break;
>> @@ -737,12 +749,12 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
>>   			if (res < 0)
>>   				return -EINVAL;
>>   			opt->keytype = SEAL_keytype;
>> -			opt->keyhandle = handle;
>> +			tpm_opts->keyhandle = handle;
>>   			break;
>>   		case Opt_keyauth:
>>   			if (strlen(args[0].from) != 2 * SHA1_DIGEST_SIZE)
>>   				return -EINVAL;
>> -			res = hex2bin(opt->keyauth, args[0].from,
>> +			res = hex2bin(tpm_opts->keyauth, args[0].from,
>>   				      SHA1_DIGEST_SIZE);
>>   			if (res < 0)
>>   				return -EINVAL;
>> @@ -753,21 +765,23 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
>>   			 * hex strings.  TPM 2.0 authorizations are simple
>>   			 * passwords (although it can take a hash as well)
>>   			 */
>> -			opt->blobauth_len = strlen(args[0].from);
>> +			tpm_opts->blobauth_len = strlen(args[0].from);
>>   
>> -			if (opt->blobauth_len == 2 * TPM_DIGEST_SIZE) {
>> -				res = hex2bin(opt->blobauth, args[0].from,
>> +			if (tpm_opts->blobauth_len == 2 * TPM_DIGEST_SIZE) {
>> +				res = hex2bin(tpm_opts->blobauth, args[0].from,
>>   					      TPM_DIGEST_SIZE);
>>   				if (res < 0)
>>   					return -EINVAL;
>>   
>> -				opt->blobauth_len = TPM_DIGEST_SIZE;
>> +				tpm_opts->blobauth_len = TPM_DIGEST_SIZE;
>>   				break;
>>   			}
>>   
>> -			if (tpm2 && opt->blobauth_len <= sizeof(opt->blobauth)) {
>> -				memcpy(opt->blobauth, args[0].from,
>> -				       opt->blobauth_len);
>> +			if (tpm2 &&
>> +			    tpm_opts->blobauth_len <=
>> +				sizeof(tpm_opts->blobauth)) {
>> +				memcpy(tpm_opts->blobauth, args[0].from,
>> +				       tpm_opts->blobauth_len);
>>   				break;
>>   			}
>>   
>> @@ -785,14 +799,14 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
>>   			res = kstrtoul(args[0].from, 10, &lock);
>>   			if (res < 0)
>>   				return -EINVAL;
>> -			opt->pcrlock = lock;
>> +			tpm_opts->pcrlock = lock;
>>   			break;
>>   		case Opt_hash:
>>   			if (test_bit(Opt_policydigest, &token_mask))
>>   				return -EINVAL;
>>   			for (i = 0; i < HASH_ALGO__LAST; i++) {
>>   				if (!strcmp(args[0].from, hash_algo_name[i])) {
>> -					opt->hash = i;
>> +					tpm_opts->hash = i;
>>   					break;
>>   				}
>>   			}
>> @@ -804,14 +818,14 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
>>   			}
>>   			break;
>>   		case Opt_policydigest:
>> -			digest_len = hash_digest_size[opt->hash];
>> +			digest_len = hash_digest_size[tpm_opts->hash];
>>   			if (!tpm2 || strlen(args[0].from) != (2 * digest_len))
>>   				return -EINVAL;
>> -			res = hex2bin(opt->policydigest, args[0].from,
>> +			res = hex2bin(tpm_opts->policydigest, args[0].from,
>>   				      digest_len);
>>   			if (res < 0)
>>   				return -EINVAL;
>> -			opt->policydigest_len = digest_len;
>> +			tpm_opts->policydigest_len = digest_len;
>>   			break;
>>   		case Opt_policyhandle:
>>   			if (!tpm2)
>> @@ -819,7 +833,7 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
>>   			res = kstrtoul(args[0].from, 16, &handle);
>>   			if (res < 0)
>>   				return -EINVAL;
>> -			opt->policyhandle = handle;
>> +			tpm_opts->policyhandle = handle;
>>   			break;
>>   		default:
>>   			return -EINVAL;
>> @@ -830,6 +844,7 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
>>   
>>   static struct trusted_key_options *trusted_options_alloc(void)
>>   {
>> +	struct trusted_tpm_options *tpm_opts;
>>   	struct trusted_key_options *options;
>>   	int tpm2;
>>   
>> @@ -842,14 +857,23 @@ static struct trusted_key_options *trusted_options_alloc(void)
>>   		/* set any non-zero defaults */
>>   		options->keytype = SRK_keytype;
>>   
>> -		if (!tpm2)
>> -			options->keyhandle = SRKHANDLE;
>> +		tpm_opts = kzalloc(sizeof(*tpm_opts), GFP_KERNEL);
>> +		if (!tpm_opts) {
>> +			kfree_sensitive(options);
>> +			options = NULL;
>> +		} else {
>> +			if (!tpm2)
>> +				tpm_opts->keyhandle = SRKHANDLE;
>> +
>> +			options->private = tpm_opts;
>> +		}
>>   	}
>>   	return options;
>>   }
>>   
>>   static int trusted_tpm_seal(struct trusted_key_payload *p, char *datablob)
>>   {
>> +	struct trusted_tpm_options *tpm_opts = NULL;
>>   	struct trusted_key_options *options = NULL;
>>   	int ret = 0;
>>   	int tpm2;
>> @@ -867,7 +891,9 @@ static int trusted_tpm_seal(struct trusted_key_payload *p, char *datablob)
>>   		goto out;
>>   	dump_options(options);
>>   
>> -	if (!options->keyhandle && !tpm2) {
>> +	tpm_opts = options->private;
>> +
>> +	if (!tpm_opts->keyhandle && !tpm2) {
>>   		ret = -EINVAL;
>>   		goto out;
>>   	}
>> @@ -881,20 +907,22 @@ static int trusted_tpm_seal(struct trusted_key_payload *p, char *datablob)
>>   		goto out;
>>   	}
>>   
>> -	if (options->pcrlock) {
>> -		ret = pcrlock(options->pcrlock);
>> +	if (tpm_opts->pcrlock) {
>> +		ret = pcrlock(tpm_opts->pcrlock);
>>   		if (ret < 0) {
>>   			pr_info("pcrlock failed (%d)\n", ret);
>>   			goto out;
>>   		}
>>   	}
>>   out:
>> +	kfree_sensitive(options->private);
>>   	kfree_sensitive(options);
>>   	return ret;
>>   }
>>   
>>   static int trusted_tpm_unseal(struct trusted_key_payload *p, char *datablob)
>>   {
>> +	struct trusted_tpm_options *tpm_opts = NULL;
>>   	struct trusted_key_options *options = NULL;
>>   	int ret = 0;
>>   	int tpm2;
>> @@ -912,7 +940,9 @@ static int trusted_tpm_unseal(struct trusted_key_payload *p, char *datablob)
>>   		goto out;
>>   	dump_options(options);
>>   
>> -	if (!options->keyhandle && !tpm2) {
>> +	tpm_opts = options->private;
>> +
>> +	if (!tpm_opts->keyhandle && !tpm2) {
>>   		ret = -EINVAL;
>>   		goto out;
>>   	}
>> @@ -924,14 +954,15 @@ static int trusted_tpm_unseal(struct trusted_key_payload *p, char *datablob)
>>   	if (ret < 0)
>>   		pr_info("key_unseal failed (%d)\n", ret);
>>   
>> -	if (options->pcrlock) {
>> -		ret = pcrlock(options->pcrlock);
>> +	if (tpm_opts->pcrlock) {
>> +		ret = pcrlock(tpm_opts->pcrlock);
>>   		if (ret < 0) {
>>   			pr_info("pcrlock failed (%d)\n", ret);
>>   			goto out;
>>   		}
>>   	}
>>   out:
>> +	kfree_sensitive(options->private);
>>   	kfree_sensitive(options);
>>   	return ret;
>>   }
>> diff --git a/security/keys/trusted-keys/trusted_tpm2.c b/security/keys/trusted-keys/trusted_tpm2.c
>> index 6340823f8b53..568c4af9010c 100644
>> --- a/security/keys/trusted-keys/trusted_tpm2.c
>> +++ b/security/keys/trusted-keys/trusted_tpm2.c
>> @@ -24,6 +24,7 @@ static int tpm2_key_encode(struct trusted_key_payload *payload,
>>   			   struct trusted_key_options *options,
>>   			   u8 *src, u32 len)
>>   {
>> +	struct trusted_tpm_options *tpm_opts;
>>   	const int SCRATCH_SIZE = PAGE_SIZE;
>>   	u8 *scratch = kmalloc(SCRATCH_SIZE, GFP_KERNEL);
>>   	u8 *work = scratch, *work1;
>> @@ -46,7 +47,9 @@ static int tpm2_key_encode(struct trusted_key_payload *payload,
>>   	work = asn1_encode_oid(work, end_work, tpm2key_oid,
>>   			       asn1_oid_len(tpm2key_oid));
>>   
>> -	if (options->blobauth_len == 0) {
>> +	tpm_opts = options->private;
>> +
>> +	if (tpm_opts->blobauth_len == 0) {
>>   		unsigned char bool[3], *w = bool;
>>   		/* tag 0 is emptyAuth */
>>   		w = asn1_encode_boolean(w, w + sizeof(bool), true);
>> @@ -69,7 +72,7 @@ static int tpm2_key_encode(struct trusted_key_payload *payload,
>>   		goto err;
>>   	}
>>   
>> -	work = asn1_encode_integer(work, end_work, options->keyhandle);
>> +	work = asn1_encode_integer(work, end_work, tpm_opts->keyhandle);
>>   	work = asn1_encode_octet_string(work, end_work, pub, pub_len);
>>   	work = asn1_encode_octet_string(work, end_work, priv, priv_len);
>>   
>> @@ -102,6 +105,7 @@ static int tpm2_key_decode(struct trusted_key_payload *payload,
>>   			   struct trusted_key_options *options,
>>   			   u8 **buf)
>>   {
>> +	struct trusted_tpm_options *tpm_opts;
>>   	int ret;
>>   	struct tpm2_key_context ctx;
>>   	u8 *blob;
>> @@ -120,8 +124,10 @@ static int tpm2_key_decode(struct trusted_key_payload *payload,
>>   	if (!blob)
>>   		return -ENOMEM;
>>   
>> +	tpm_opts = options->private;
>> +
>>   	*buf = blob;
>> -	options->keyhandle = ctx.parent;
>> +	tpm_opts->keyhandle = ctx.parent;
>>   
>>   	memcpy(blob, ctx.priv, ctx.priv_len);
>>   	blob += ctx.priv_len;
>> @@ -233,6 +239,7 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
>>   		      struct trusted_key_payload *payload,
>>   		      struct trusted_key_options *options)
>>   {
>> +	struct trusted_tpm_options *tpm_opts;
>>   	off_t offset = TPM_HEADER_SIZE;
>>   	struct tpm_buf buf, sized;
>>   	int blob_len = 0;
>> @@ -240,11 +247,13 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
>>   	u32 flags;
>>   	int rc;
>>   
>> -	hash = tpm2_find_hash_alg(options->hash);
>> +	tpm_opts = options->private;
>> +
>> +	hash = tpm2_find_hash_alg(tpm_opts->hash);
>>   	if (hash < 0)
>>   		return hash;
>>   
>> -	if (!options->keyhandle)
>> +	if (!tpm_opts->keyhandle)
>>   		return -EINVAL;
>>   
>>   	rc = tpm_try_get_ops(chip);
>> @@ -268,18 +277,19 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
>>   		goto out_put;
>>   	}
>>   
>> -	rc = tpm_buf_append_name(chip, &buf, options->keyhandle, NULL);
>> +	rc = tpm_buf_append_name(chip, &buf, tpm_opts->keyhandle, NULL);
>>   	if (rc)
>>   		goto out;
>>   
>>   	tpm_buf_append_hmac_session(chip, &buf, TPM2_SA_DECRYPT,
>> -				    options->keyauth, TPM_DIGEST_SIZE);
>> +				    tpm_opts->keyauth, TPM_DIGEST_SIZE);
>>   
>>   	/* sensitive */
>> -	tpm_buf_append_u16(&sized, options->blobauth_len);
>> +	tpm_buf_append_u16(&sized, tpm_opts->blobauth_len);
>>   
>> -	if (options->blobauth_len)
>> -		tpm_buf_append(&sized, options->blobauth, options->blobauth_len);
>> +	if (tpm_opts->blobauth_len)
>> +		tpm_buf_append(&sized, tpm_opts->blobauth,
>> +			       tpm_opts->blobauth_len);
>>   
>>   	tpm_buf_append_u16(&sized, payload->key_len);
>>   	tpm_buf_append(&sized, payload->key, payload->key_len);
>> @@ -292,14 +302,15 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
>>   
>>   	/* key properties */
>>   	flags = 0;
>> -	flags |= options->policydigest_len ? 0 : TPM2_OA_USER_WITH_AUTH;
>> +	flags |= tpm_opts->policydigest_len ? 0 : TPM2_OA_USER_WITH_AUTH;
>>   	flags |= payload->migratable ? 0 : (TPM2_OA_FIXED_TPM | TPM2_OA_FIXED_PARENT);
>>   	tpm_buf_append_u32(&sized, flags);
>>   
>>   	/* policy */
>> -	tpm_buf_append_u16(&sized, options->policydigest_len);
>> -	if (options->policydigest_len)
>> -		tpm_buf_append(&sized, options->policydigest, options->policydigest_len);
>> +	tpm_buf_append_u16(&sized, tpm_opts->policydigest_len);
>> +	if (tpm_opts->policydigest_len)
>> +		tpm_buf_append(&sized, tpm_opts->policydigest,
>> +			       tpm_opts->policydigest_len);
>>   
>>   	/* public parameters */
>>   	tpm_buf_append_u16(&sized, TPM_ALG_NULL);
>> @@ -373,6 +384,7 @@ static int tpm2_load_cmd(struct tpm_chip *chip,
>>   			 u32 *blob_handle)
>>   {
>>   	u8 *blob_ref __free(kfree) = NULL;
>> +	struct trusted_tpm_options *tpm_opts;
>>   	struct tpm_buf buf;
>>   	unsigned int private_len;
>>   	unsigned int public_len;
>> @@ -391,8 +403,10 @@ static int tpm2_load_cmd(struct tpm_chip *chip,
>>   		blob_ref = blob;
>>   	}
>>   
>> +	tpm_opts = options->private;
>> +
>>   	/* new format carries keyhandle but old format doesn't */
>> -	if (!options->keyhandle)
>> +	if (!tpm_opts->keyhandle)
>>   		return -EINVAL;
>>   
>>   	/* must be big enough for at least the two be16 size counts */
>> @@ -433,11 +447,11 @@ static int tpm2_load_cmd(struct tpm_chip *chip,
>>   		return rc;
>>   	}
>>   
>> -	rc = tpm_buf_append_name(chip, &buf, options->keyhandle, NULL);
>> +	rc = tpm_buf_append_name(chip, &buf, tpm_opts->keyhandle, NULL);
>>   	if (rc)
>>   		goto out;
>>   
>> -	tpm_buf_append_hmac_session(chip, &buf, 0, options->keyauth,
>> +	tpm_buf_append_hmac_session(chip, &buf, 0, tpm_opts->keyauth,
>>   				    TPM_DIGEST_SIZE);
>>   
>>   	tpm_buf_append(&buf, blob, blob_len);
>> @@ -481,6 +495,7 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip,
>>   			   struct trusted_key_options *options,
>>   			   u32 blob_handle)
>>   {
>> +	struct trusted_tpm_options *tpm_opts;
>>   	struct tpm_header *head;
>>   	struct tpm_buf buf;
>>   	u16 data_len;
>> @@ -502,10 +517,12 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip,
>>   	if (rc)
>>   		goto out;
>>   
>> -	if (!options->policyhandle) {
>> +	tpm_opts = options->private;
>> +
>> +	if (!tpm_opts->policyhandle) {
>>   		tpm_buf_append_hmac_session(chip, &buf, TPM2_SA_ENCRYPT,
>> -					    options->blobauth,
>> -					    options->blobauth_len);
>> +					    tpm_opts->blobauth,
>> +					    tpm_opts->blobauth_len);
>>   	} else {
>>   		/*
>>   		 * FIXME: The policy session was generated outside the
>> @@ -518,9 +535,10 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip,
>>   		 * could repeat our actions with the exfiltrated
>>   		 * password.
>>   		 */
>> -		tpm2_buf_append_auth(&buf, options->policyhandle,
>> +		tpm2_buf_append_auth(&buf, tpm_opts->policyhandle,
>>   				     NULL /* nonce */, 0, 0,
>> -				     options->blobauth, options->blobauth_len);
>> +				     tpm_opts->blobauth,
>> +				     tpm_opts->blobauth_len);
>>   		if (tpm2_chip_auth(chip)) {
>>   			tpm_buf_append_hmac_session(chip, &buf, TPM2_SA_ENCRYPT, NULL, 0);
>>   		} else  {
>> -- 
>> 2.43.0
>>
> BR, Jarkko


I will shortly send out v2 with the changes.

Thanks,
Srish.


^ permalink raw reply

* [PATCH] tpm: Make tcpci_pm_ops variable static const
From: Krzysztof Kozlowski @ 2026-02-16 11:04 UTC (permalink / raw)
  To: Peter Huewe, Jarkko Sakkinen, Jason Gunthorpe, linux-integrity,
	linux-kernel
  Cc: Krzysztof Kozlowski

File-scope 'tcpci_pm_ops' is not used outside of this unit and is not
modified anywhere, so make it static const to silence sparse warning:

  tcpci.c:1002:1: warning: symbol 'tcpci_pm_ops' was not declared. Should it be static?

Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
---
 drivers/char/tpm/tpm2-cmd.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index 3a77be7ebf4a..e00f668f8c84 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -21,7 +21,7 @@ static bool disable_pcr_integrity;
 module_param(disable_pcr_integrity, bool, 0444);
 MODULE_PARM_DESC(disable_pcr_integrity, "Disable integrity protection of TPM2_PCR_Extend");
 
-struct tpm2_hash tpm2_hash_map[] = {
+static const struct tpm2_hash tpm2_hash_map[] = {
 	{HASH_ALGO_SHA1, TPM_ALG_SHA1},
 	{HASH_ALGO_SHA256, TPM_ALG_SHA256},
 	{HASH_ALGO_SHA384, TPM_ALG_SHA384},
-- 
2.51.0


^ permalink raw reply related

* Re: [PATCH v2] ima: fallback to using i_version to detect file change
From: Frederick Lawler @ 2026-02-13 19:51 UTC (permalink / raw)
  To: Mimi Zohar; +Cc: linux-integrity, Jeff Layton, Roberto Sassu, Roberto Sassu
In-Reply-To: <20260213174947.976924-1-zohar@linux.ibm.com>

On Fri, Feb 13, 2026 at 12:49:47PM -0500, Mimi Zohar wrote:
> Commit db1d1e8b9867 ("IMA: use vfs_getattr_nosec to get the i_version")
> replaced detecting file change based on i_version with
> STATX_CHANGE_COOKIE.
> 
> On filesystems without STATX_CHANGE_COOKIE enabled, revert back to
> detecting file change based on i_version.
> 
> On filesystems which do not support either, assume the file changed.
> 

Tested-by: Frederick Lawler <fred@cloudflare.com>

> Reported-by: Roberto Sassu <roberto.sassu@huawei.com>
> Fixes: db1d1e8b9867 ("IMA: use vfs_getattr_nosec to get the i_version")
> Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
> ---
> Changelog v2:
> - Use the real_inode's iversion to detect file change on overlayfs
> - Add Roberto's Reported-by tag
> 
>  security/integrity/ima/ima_api.c  | 13 +++++++----
>  security/integrity/ima/ima_main.c | 39 ++++++++++++++++++++++++-------
>  2 files changed, 40 insertions(+), 12 deletions(-)
> 
> diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
> index c35ea613c9f8..28cf1fe07f8f 100644
> --- a/security/integrity/ima/ima_api.c
> +++ b/security/integrity/ima/ima_api.c
> @@ -267,15 +267,20 @@ int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file,
>  		goto out;
>  
>  	/*
> -	 * Detecting file change is based on i_version. On filesystems
> -	 * which do not support i_version, support was originally limited
> -	 * to an initial measurement/appraisal/audit, but was modified to
> -	 * assume the file changed.
> +	 * Detect file change based on STATX_CHANGE_COOKIE, when supported,
> +	 * and fallback to detecting file change based on i_version.
> +	 *
> +	 * On filesystems which did not support i_version, support was
> +	 * originally limited to an initial measurement/appraisal/audit,
> +	 * but was later modified to assume the file changed.
>  	 */
>  	result = vfs_getattr_nosec(&file->f_path, &stat, STATX_CHANGE_COOKIE,
>  				   AT_STATX_SYNC_AS_STAT);
>  	if (!result && (stat.result_mask & STATX_CHANGE_COOKIE))
>  		i_version = stat.change_cookie;
> +	else if (IS_I_VERSION(real_inode))
> +		i_version = inode_peek_iversion(real_inode);
> +
>  	hash.hdr.algo = algo;
>  	hash.hdr.length = hash_digest_size[algo];
>  
> diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
> index 1d6229b156fb..4fc383479847 100644
> --- a/security/integrity/ima/ima_main.c
> +++ b/security/integrity/ima/ima_main.c
> @@ -180,6 +180,34 @@ static void ima_rdwr_violation_check(struct file *file,
>  				  "invalid_pcr", "open_writers");
>  }
>  
> +/*
> + * Detect file change based on STATX_CHANGE_COOKIE, when supported, and
> + * fallback to detecting file change based on i_version. On filesystems
> + * which do not support either, assume the file changed.
> + */
> +static bool ima_detect_file_change(struct ima_iint_cache *iint,
> +				   struct inode *inode, struct file *file)
> +{
> +	struct kstat stat;
> +	int result;
> +
> +	result = vfs_getattr_nosec(&file->f_path, &stat, STATX_CHANGE_COOKIE,
> +				   AT_STATX_SYNC_AS_STAT);
> +
> +	if (!result && stat.result_mask & STATX_CHANGE_COOKIE &&
> +	    stat.change_cookie != iint->real_inode.version)
> +		return true;
> +	else if (!(stat.result_mask & STATX_CHANGE_COOKIE) &&
> +		 IS_I_VERSION(inode) &&
> +		 !(inode_eq_iversion(inode, iint->real_inode.version)))
> +		return true;
> +	else if (!(stat.result_mask & STATX_CHANGE_COOKIE) &&
> +		 !(IS_I_VERSION(inode)))
> +		return true;
> +
> +	return false;
> +}
> +
>  static void ima_check_last_writer(struct ima_iint_cache *iint,
>  				  struct inode *inode, struct file *file)
>  {
> @@ -191,18 +219,13 @@ static void ima_check_last_writer(struct ima_iint_cache *iint,
>  
>  	mutex_lock(&iint->mutex);
>  	if (atomic_read(&inode->i_writecount) == 1) {
> -		struct kstat stat;
> -
>  		clear_bit(IMA_EMITTED_OPENWRITERS, &iint->atomic_flags);
>  
>  		update = test_and_clear_bit(IMA_UPDATE_XATTR,
>  					    &iint->atomic_flags);
> -		if ((iint->flags & IMA_NEW_FILE) ||
> -		    vfs_getattr_nosec(&file->f_path, &stat,
> -				      STATX_CHANGE_COOKIE,
> -				      AT_STATX_SYNC_AS_STAT) ||
> -		    !(stat.result_mask & STATX_CHANGE_COOKIE) ||
> -		    stat.change_cookie != iint->real_inode.version) {
> +
> +		if (iint->flags & IMA_NEW_FILE ||
> +		    ima_detect_file_change(iint, inode, file)) {
>  			iint->flags &= ~(IMA_DONE_MASK | IMA_NEW_FILE);
>  			iint->measured_pcrs = 0;
>  			if (update)
> -- 
> 2.53.0
> 

^ permalink raw reply

* [PATCH v2] ima: fallback to using i_version to detect file change
From: Mimi Zohar @ 2026-02-13 17:49 UTC (permalink / raw)
  To: linux-integrity
  Cc: Mimi Zohar, Frederick Lawler, Jeff Layton, Roberto Sassu,
	Roberto Sassu

Commit db1d1e8b9867 ("IMA: use vfs_getattr_nosec to get the i_version")
replaced detecting file change based on i_version with
STATX_CHANGE_COOKIE.

On filesystems without STATX_CHANGE_COOKIE enabled, revert back to
detecting file change based on i_version.

On filesystems which do not support either, assume the file changed.

Reported-by: Roberto Sassu <roberto.sassu@huawei.com>
Fixes: db1d1e8b9867 ("IMA: use vfs_getattr_nosec to get the i_version")
Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
---
Changelog v2:
- Use the real_inode's iversion to detect file change on overlayfs
- Add Roberto's Reported-by tag

 security/integrity/ima/ima_api.c  | 13 +++++++----
 security/integrity/ima/ima_main.c | 39 ++++++++++++++++++++++++-------
 2 files changed, 40 insertions(+), 12 deletions(-)

diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index c35ea613c9f8..28cf1fe07f8f 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -267,15 +267,20 @@ int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file,
 		goto out;
 
 	/*
-	 * Detecting file change is based on i_version. On filesystems
-	 * which do not support i_version, support was originally limited
-	 * to an initial measurement/appraisal/audit, but was modified to
-	 * assume the file changed.
+	 * Detect file change based on STATX_CHANGE_COOKIE, when supported,
+	 * and fallback to detecting file change based on i_version.
+	 *
+	 * On filesystems which did not support i_version, support was
+	 * originally limited to an initial measurement/appraisal/audit,
+	 * but was later modified to assume the file changed.
 	 */
 	result = vfs_getattr_nosec(&file->f_path, &stat, STATX_CHANGE_COOKIE,
 				   AT_STATX_SYNC_AS_STAT);
 	if (!result && (stat.result_mask & STATX_CHANGE_COOKIE))
 		i_version = stat.change_cookie;
+	else if (IS_I_VERSION(real_inode))
+		i_version = inode_peek_iversion(real_inode);
+
 	hash.hdr.algo = algo;
 	hash.hdr.length = hash_digest_size[algo];
 
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 1d6229b156fb..4fc383479847 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -180,6 +180,34 @@ static void ima_rdwr_violation_check(struct file *file,
 				  "invalid_pcr", "open_writers");
 }
 
+/*
+ * Detect file change based on STATX_CHANGE_COOKIE, when supported, and
+ * fallback to detecting file change based on i_version. On filesystems
+ * which do not support either, assume the file changed.
+ */
+static bool ima_detect_file_change(struct ima_iint_cache *iint,
+				   struct inode *inode, struct file *file)
+{
+	struct kstat stat;
+	int result;
+
+	result = vfs_getattr_nosec(&file->f_path, &stat, STATX_CHANGE_COOKIE,
+				   AT_STATX_SYNC_AS_STAT);
+
+	if (!result && stat.result_mask & STATX_CHANGE_COOKIE &&
+	    stat.change_cookie != iint->real_inode.version)
+		return true;
+	else if (!(stat.result_mask & STATX_CHANGE_COOKIE) &&
+		 IS_I_VERSION(inode) &&
+		 !(inode_eq_iversion(inode, iint->real_inode.version)))
+		return true;
+	else if (!(stat.result_mask & STATX_CHANGE_COOKIE) &&
+		 !(IS_I_VERSION(inode)))
+		return true;
+
+	return false;
+}
+
 static void ima_check_last_writer(struct ima_iint_cache *iint,
 				  struct inode *inode, struct file *file)
 {
@@ -191,18 +219,13 @@ static void ima_check_last_writer(struct ima_iint_cache *iint,
 
 	mutex_lock(&iint->mutex);
 	if (atomic_read(&inode->i_writecount) == 1) {
-		struct kstat stat;
-
 		clear_bit(IMA_EMITTED_OPENWRITERS, &iint->atomic_flags);
 
 		update = test_and_clear_bit(IMA_UPDATE_XATTR,
 					    &iint->atomic_flags);
-		if ((iint->flags & IMA_NEW_FILE) ||
-		    vfs_getattr_nosec(&file->f_path, &stat,
-				      STATX_CHANGE_COOKIE,
-				      AT_STATX_SYNC_AS_STAT) ||
-		    !(stat.result_mask & STATX_CHANGE_COOKIE) ||
-		    stat.change_cookie != iint->real_inode.version) {
+
+		if (iint->flags & IMA_NEW_FILE ||
+		    ima_detect_file_change(iint, inode, file)) {
 			iint->flags &= ~(IMA_DONE_MASK | IMA_NEW_FILE);
 			iint->measured_pcrs = 0;
 			if (update)
-- 
2.53.0


^ permalink raw reply related

* Re: [PATCH v4 14/17] lockdown: Make the relationship to MODULE_SIG a dependency
From: Nicolas Schier @ 2026-02-13 15:32 UTC (permalink / raw)
  To: Thomas Weißschuh
  Cc: Nathan Chancellor, Arnd Bergmann, Luis Chamberlain, Petr Pavlu,
	Sami Tolvanen, Daniel Gomez, Paul Moore, James Morris,
	Serge E. Hallyn, Jonathan Corbet, Madhavan Srinivasan,
	Michael Ellerman, Nicholas Piggin, Naveen N Rao, Mimi Zohar,
	Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Daniel Gomez,
	Aaron Tomlin, Christophe Leroy (CS GROUP), Nicolas Bouchinet,
	Xiu Jianfeng, Fabian Grünbichler, Arnout Engelen,
	Mattia Rizzolo, kpcyrd, Christian Heusel, Câju Mihai-Drosi,
	Sebastian Andrzej Siewior, linux-kbuild, linux-kernel, linux-arch,
	linux-modules, linux-security-module, linux-doc, linuxppc-dev,
	linux-integrity
In-Reply-To: <20260113-module-hashes-v4-14-0b932db9b56b@weissschuh.net>

On Tue, Jan 13, 2026 at 01:28:58PM +0100, Thomas Weißschuh wrote:
> The new hash-based module integrity checking will also be able to
> satisfy the requirements of lockdown.
> Such an alternative is not representable with "select", so use
> "depends on" instead.
> 
> Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
> ---
>  security/lockdown/Kconfig | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Reviewed-by: Nicolas Schier <nsc@kernel.org>

^ permalink raw reply

* Re: [PATCH v4 11/17] module: Move lockdown check into generic module loader
From: Nicolas Schier @ 2026-02-13 15:14 UTC (permalink / raw)
  To: Thomas Weißschuh
  Cc: Nathan Chancellor, Arnd Bergmann, Luis Chamberlain, Petr Pavlu,
	Sami Tolvanen, Daniel Gomez, Paul Moore, James Morris,
	Serge E. Hallyn, Jonathan Corbet, Madhavan Srinivasan,
	Michael Ellerman, Nicholas Piggin, Naveen N Rao, Mimi Zohar,
	Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Daniel Gomez,
	Aaron Tomlin, Christophe Leroy (CS GROUP), Nicolas Bouchinet,
	Xiu Jianfeng, Fabian Grünbichler, Arnout Engelen,
	Mattia Rizzolo, kpcyrd, Christian Heusel, Câju Mihai-Drosi,
	Sebastian Andrzej Siewior, linux-kbuild, linux-kernel, linux-arch,
	linux-modules, linux-security-module, linux-doc, linuxppc-dev,
	linux-integrity
In-Reply-To: <20260113-module-hashes-v4-11-0b932db9b56b@weissschuh.net>

On Tue, Jan 13, 2026 at 01:28:55PM +0100, Thomas Weißschuh wrote:
> The lockdown check buried in module_sig_check() will not compose well
> with the introduction of hash-based module validation.
> Move it into module_integrity_check() which will work better.
> 
> Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
> ---
>  kernel/module/main.c    | 6 +++++-
>  kernel/module/signing.c | 3 +--
>  2 files changed, 6 insertions(+), 3 deletions(-)
> 

Reviewed-by: Nicolas Schier <nsc@kernel.org>

^ permalink raw reply

* Re: [PATCH v4 10/17] module: Move integrity checks into dedicated function
From: Nicolas Schier @ 2026-02-13 15:09 UTC (permalink / raw)
  To: Thomas Weißschuh
  Cc: Nathan Chancellor, Arnd Bergmann, Luis Chamberlain, Petr Pavlu,
	Sami Tolvanen, Daniel Gomez, Paul Moore, James Morris,
	Serge E. Hallyn, Jonathan Corbet, Madhavan Srinivasan,
	Michael Ellerman, Nicholas Piggin, Naveen N Rao, Mimi Zohar,
	Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Daniel Gomez,
	Aaron Tomlin, Christophe Leroy (CS GROUP), Nicolas Bouchinet,
	Xiu Jianfeng, Fabian Grünbichler, Arnout Engelen,
	Mattia Rizzolo, kpcyrd, Christian Heusel, Câju Mihai-Drosi,
	Sebastian Andrzej Siewior, linux-kbuild, linux-kernel, linux-arch,
	linux-modules, linux-security-module, linux-doc, linuxppc-dev,
	linux-integrity
In-Reply-To: <20260113-module-hashes-v4-10-0b932db9b56b@weissschuh.net>

On Tue, Jan 13, 2026 at 01:28:54PM +0100, Thomas Weißschuh wrote:
> With the addition of hash-based integrity checking, the configuration
> matrix is easier to represent in a dedicated function and with explicit
> usage of IS_ENABLED().
> 
> Drop the now unnecessary stub for module_sig_check().
> 
> Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
> ---
>  kernel/module/internal.h |  7 -------
>  kernel/module/main.c     | 18 ++++++++++++++----
>  2 files changed, 14 insertions(+), 11 deletions(-)
> 

Reviewed-by: Nicolas Schier <nsc@kernel.org>

^ permalink raw reply

* [PATCH v3 3/3] s390: Drop unnecessary CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT
From: Coiby Xu @ 2026-02-13  1:28 UTC (permalink / raw)
  To: linux-integrity
  Cc: Heiko Carstens, Alexander Egorenkov, Ard Biesheuvel, Dave Hansen,
	Vasily Gorbik, Alexander Gordeev, Christian Borntraeger,
	Sven Schnelle, open list:S390 ARCHITECTURE, open list
In-Reply-To: <20260213012851.2532722-1-coxu@redhat.com>

Commit b5ca117365d9 ("ima: prevent kexec_load syscall based on runtime
secureboot flag") and commit 268a78404973 ("s390/kexec_file: Disable
kexec_load when IPLed secure") disabled the kexec_load syscall based
on the secureboot mode. Commit 9e2b4be377f0 ("ima: add a new CONFIG
for loading arch-specific policies") needed to detect the secure boot
mode, not to load an IMA architecture specific policy. Since there is
the new CONFIG_INTEGRITY_SECURE_BOOT, drop
CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT for s390.

Signed-off-by: Coiby Xu <coxu@redhat.com>
---
 arch/s390/Kconfig           | 1 -
 arch/s390/kernel/Makefile   | 1 -
 arch/s390/kernel/ima_arch.c | 8 --------
 3 files changed, 10 deletions(-)
 delete mode 100644 arch/s390/kernel/ima_arch.c

diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index cda697a03abf..f6cb528aae5e 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -83,7 +83,6 @@ config S390
 	#
 	# Note: keep this list sorted alphabetically
 	#
-	imply IMA_SECURE_AND_OR_TRUSTED_BOOT
 	select ALTERNATE_USER_ADDRESS_SPACE
 	select ARCH_32BIT_USTAT_F_TINODE
 	select ARCH_CORRECT_STACKTRACE_ON_KRETPROBE
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 42c83d60d6fa..89a2c8078fe7 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -71,7 +71,6 @@ obj-$(CONFIG_STACKPROTECTOR)	+= stackprotector.o
 obj-$(CONFIG_KEXEC_FILE)	+= machine_kexec_file.o kexec_image.o
 obj-$(CONFIG_KEXEC_FILE)	+= kexec_elf.o
 obj-$(CONFIG_CERT_STORE)	+= cert_store.o
-obj-$(CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT)	+= ima_arch.o
 
 obj-$(CONFIG_PERF_EVENTS)	+= perf_event.o
 obj-$(CONFIG_PERF_EVENTS)	+= perf_cpum_cf.o perf_cpum_sf.o
diff --git a/arch/s390/kernel/ima_arch.c b/arch/s390/kernel/ima_arch.c
deleted file mode 100644
index 6ccbe34ce408..000000000000
--- a/arch/s390/kernel/ima_arch.c
+++ /dev/null
@@ -1,8 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-
-#include <linux/ima.h>
-
-const char * const *arch_get_ima_policy(void)
-{
-	return NULL;
-}
-- 
2.53.0


^ permalink raw reply related

* [PATCH v3 2/3] evm: Don't enable fix mode when secure boot is enabled
From: Coiby Xu @ 2026-02-13  1:28 UTC (permalink / raw)
  To: linux-integrity
  Cc: Heiko Carstens, Alexander Egorenkov, Ard Biesheuvel, Dave Hansen,
	Mimi Zohar, Roberto Sassu, Dmitry Kasatkin, Eric Snowberg,
	Paul Moore, James Morris, Serge E. Hallyn,
	open list:SECURITY SUBSYSTEM, open list
In-Reply-To: <20260213012851.2532722-1-coxu@redhat.com>

Similar to IMA fix mode, forbid EVM fix mode when secure boot is
enabled.

Reported-and-suggested-by: Mimi Zohar <zohar@linux.ibm.com>
Suggested-by: Roberto Sassu <roberto.sassu@huawei.com>
Signed-off-by: Coiby Xu <coxu@redhat.com>
---
 security/integrity/evm/evm_main.c | 24 +++++++++++++++++-------
 1 file changed, 17 insertions(+), 7 deletions(-)

diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
index 73d500a375cb..a54cb73b51ee 100644
--- a/security/integrity/evm/evm_main.c
+++ b/security/integrity/evm/evm_main.c
@@ -72,17 +72,25 @@ static struct xattr_list evm_config_default_xattrnames[] = {
 
 LIST_HEAD(evm_config_xattrnames);
 
+static char *evm_cmdline __initdata;
+core_param(evm, evm_cmdline, charp, 0);
+
 static int evm_fixmode __ro_after_init;
-static int __init evm_set_fixmode(char *str)
+static void __init evm_set_fixmode(void)
 {
-	if (strncmp(str, "fix", 3) == 0)
-		evm_fixmode = 1;
-	else
-		pr_err("invalid \"%s\" mode", str);
+	if (!evm_cmdline)
+		return;
 
-	return 1;
+	if (strncmp(evm_cmdline, "fix", 3) == 0) {
+		if (arch_get_secureboot()) {
+			pr_info("Secure boot enabled: ignoring evm=fix");
+			return;
+		}
+		evm_fixmode = 1;
+	} else {
+		pr_err("invalid \"%s\" mode", evm_cmdline);
+	}
 }
-__setup("evm=", evm_set_fixmode);
 
 static void __init evm_init_config(void)
 {
@@ -1119,6 +1127,8 @@ static int __init init_evm(void)
 
 	evm_init_config();
 
+	evm_set_fixmode();
+
 	error = integrity_init_keyring(INTEGRITY_KEYRING_EVM);
 	if (error)
 		goto error;
-- 
2.53.0


^ permalink raw reply related

* [PATCH v3 1/3] integrity: Make arch_ima_get_secureboot integrity-wide
From: Coiby Xu @ 2026-02-13  1:28 UTC (permalink / raw)
  To: linux-integrity
  Cc: Heiko Carstens, Alexander Egorenkov, Ard Biesheuvel, Dave Hansen,
	Mimi Zohar, Roberto Sassu, Madhavan Srinivasan, Michael Ellerman,
	Nicholas Piggin, Christophe Leroy (CS GROUP), Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen,
	maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT), H. Peter Anvin,
	Dmitry Kasatkin, Eric Snowberg, Paul Moore, James Morris,
	Serge E. Hallyn, Jarkko Sakkinen, open list,
	open list:LINUX FOR POWERPC (32-BIT AND 64-BIT),
	open list:S390 ARCHITECTURE,
	open list:EXTENSIBLE FIRMWARE INTERFACE (EFI),
	open list:SECURITY SUBSYSTEM, open list:KEYS/KEYRINGS_INTEGRITY
In-Reply-To: <20260213012851.2532722-1-coxu@redhat.com>

EVM and other LSMs need the ability to query the secure boot status of
the system, without directly calling the IMA arch_ima_get_secureboot
function. Refactor the secure boot status check into a general function
named arch_get_secureboot.

Reported-and-suggested-by: Mimi Zohar <zohar@linux.ibm.com>
Suggested-by: Roberto Sassu <roberto.sassu@huawei.com>
Signed-off-by: Coiby Xu <coxu@redhat.com>
---
 MAINTAINERS                                   |  1 +
 arch/powerpc/kernel/ima_arch.c                |  5 --
 arch/powerpc/kernel/secure_boot.c             |  6 ++
 arch/s390/kernel/ima_arch.c                   |  6 --
 arch/s390/kernel/ipl.c                        |  5 ++
 arch/x86/include/asm/efi.h                    |  4 +-
 arch/x86/platform/efi/efi.c                   |  2 +-
 include/linux/ima.h                           |  7 +--
 include/linux/secure_boot.h                   | 19 +++++++
 security/integrity/Makefile                   |  3 +-
 security/integrity/efi_secureboot.c           | 56 +++++++++++++++++++
 security/integrity/ima/ima_appraise.c         |  2 +-
 security/integrity/ima/ima_efi.c              | 47 +---------------
 security/integrity/ima/ima_main.c             |  3 +-
 security/integrity/integrity.h                |  1 +
 security/integrity/platform_certs/load_uefi.c |  2 +-
 security/integrity/secure_boot.c              | 16 ++++++
 17 files changed, 115 insertions(+), 70 deletions(-)
 create mode 100644 include/linux/secure_boot.h
 create mode 100644 security/integrity/efi_secureboot.c
 create mode 100644 security/integrity/secure_boot.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 149deedafe2c..56242d78e4a6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12550,6 +12550,7 @@ R:	Eric Snowberg <eric.snowberg@oracle.com>
 L:	linux-integrity@vger.kernel.org
 S:	Supported
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity.git
+F:	include/linux/secure_boot.h
 F:	security/integrity/
 F:	security/integrity/ima/
 
diff --git a/arch/powerpc/kernel/ima_arch.c b/arch/powerpc/kernel/ima_arch.c
index b7029beed847..0d8892a03526 100644
--- a/arch/powerpc/kernel/ima_arch.c
+++ b/arch/powerpc/kernel/ima_arch.c
@@ -7,11 +7,6 @@
 #include <linux/ima.h>
 #include <asm/secure_boot.h>
 
-bool arch_ima_get_secureboot(void)
-{
-	return is_ppc_secureboot_enabled();
-}
-
 /*
  * The "secure_rules" are enabled only on "secureboot" enabled systems.
  * These rules verify the file signatures against known good values.
diff --git a/arch/powerpc/kernel/secure_boot.c b/arch/powerpc/kernel/secure_boot.c
index 3a28795b4ed8..28436c1599e0 100644
--- a/arch/powerpc/kernel/secure_boot.c
+++ b/arch/powerpc/kernel/secure_boot.c
@@ -5,6 +5,7 @@
  */
 #include <linux/types.h>
 #include <linux/of.h>
+#include <linux/secure_boot.h>
 #include <linux/string_choices.h>
 #include <asm/secure_boot.h>
 
@@ -44,6 +45,11 @@ bool is_ppc_secureboot_enabled(void)
 	return enabled;
 }
 
+bool arch_get_secureboot(void)
+{
+	return is_ppc_secureboot_enabled();
+}
+
 bool is_ppc_trustedboot_enabled(void)
 {
 	struct device_node *node;
diff --git a/arch/s390/kernel/ima_arch.c b/arch/s390/kernel/ima_arch.c
index f3c3e6e1c5d3..6ccbe34ce408 100644
--- a/arch/s390/kernel/ima_arch.c
+++ b/arch/s390/kernel/ima_arch.c
@@ -1,12 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 
 #include <linux/ima.h>
-#include <asm/boot_data.h>
-
-bool arch_ima_get_secureboot(void)
-{
-	return ipl_secure_flag;
-}
 
 const char * const *arch_get_ima_policy(void)
 {
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index dcdc7e274848..781deb588557 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -2504,6 +2504,11 @@ void *ipl_report_finish(struct ipl_report *report)
 	return buf;
 }
 
+bool arch_get_secureboot(void)
+{
+	return ipl_secure_flag;
+}
+
 int ipl_report_free(struct ipl_report *report)
 {
 	struct ipl_report_component *comp, *ncomp;
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index f227a70ac91f..ee382b56dd7b 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -401,9 +401,9 @@ extern int __init efi_memmap_split_count(efi_memory_desc_t *md,
 extern void __init efi_memmap_insert(struct efi_memory_map *old_memmap,
 				     void *buf, struct efi_mem_range *mem);
 
-extern enum efi_secureboot_mode __x86_ima_efi_boot_mode(void);
+enum efi_secureboot_mode __x86_efi_boot_mode(void);
 
-#define arch_ima_efi_boot_mode	__x86_ima_efi_boot_mode()
+#define arch_efi_boot_mode __x86_efi_boot_mode()
 
 #ifdef CONFIG_EFI_RUNTIME_MAP
 int efi_get_runtime_map_size(void);
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index d00c6de7f3b7..74032f3ab9b0 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -920,7 +920,7 @@ umode_t efi_attr_is_visible(struct kobject *kobj, struct attribute *attr, int n)
 	return attr->mode;
 }
 
-enum efi_secureboot_mode __x86_ima_efi_boot_mode(void)
+enum efi_secureboot_mode __x86_efi_boot_mode(void)
 {
 	return boot_params.secure_boot;
 }
diff --git a/include/linux/ima.h b/include/linux/ima.h
index 8e29cb4e6a01..b3927b795a60 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -11,6 +11,7 @@
 #include <linux/fs.h>
 #include <linux/security.h>
 #include <linux/kexec.h>
+#include <linux/secure_boot.h>
 #include <crypto/hash_info.h>
 struct linux_binprm;
 
@@ -72,14 +73,8 @@ int __init ima_get_kexec_buffer(void **addr, size_t *size);
 #endif
 
 #ifdef CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT
-extern bool arch_ima_get_secureboot(void);
 extern const char * const *arch_get_ima_policy(void);
 #else
-static inline bool arch_ima_get_secureboot(void)
-{
-	return false;
-}
-
 static inline const char * const *arch_get_ima_policy(void)
 {
 	return NULL;
diff --git a/include/linux/secure_boot.h b/include/linux/secure_boot.h
new file mode 100644
index 000000000000..3ded3f03655c
--- /dev/null
+++ b/include/linux/secure_boot.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2026 Red Hat, Inc. All Rights Reserved.
+ *
+ * Author: Coiby Xu <coxu@redhat.com>
+ */
+
+#ifndef _LINUX_SECURE_BOOT_H
+#define _LINUX_SECURE_BOOT_H
+
+#include <linux/types.h>
+
+/*
+ * Returns true if the platform secure boot is enabled.
+ * Returns false if disabled or not supported.
+ */
+bool arch_get_secureboot(void);
+
+#endif /* _LINUX_SECURE_BOOT_H */
diff --git a/security/integrity/Makefile b/security/integrity/Makefile
index 92b63039c654..548665e2b702 100644
--- a/security/integrity/Makefile
+++ b/security/integrity/Makefile
@@ -5,7 +5,7 @@
 
 obj-$(CONFIG_INTEGRITY) += integrity.o
 
-integrity-y := iint.o
+integrity-y := iint.o secure_boot.o
 integrity-$(CONFIG_INTEGRITY_AUDIT) += integrity_audit.o
 integrity-$(CONFIG_INTEGRITY_SIGNATURE) += digsig.o
 integrity-$(CONFIG_INTEGRITY_ASYMMETRIC_KEYS) += digsig_asymmetric.o
@@ -18,6 +18,7 @@ integrity-$(CONFIG_LOAD_IPL_KEYS) += platform_certs/load_ipl_s390.o
 integrity-$(CONFIG_LOAD_PPC_KEYS) += platform_certs/efi_parser.o \
                                      platform_certs/load_powerpc.o \
                                      platform_certs/keyring_handler.o
+integrity-$(CONFIG_EFI) += efi_secureboot.o
 # The relative order of the 'ima' and 'evm' LSMs depends on the order below.
 obj-$(CONFIG_IMA)			+= ima/
 obj-$(CONFIG_EVM)			+= evm/
diff --git a/security/integrity/efi_secureboot.c b/security/integrity/efi_secureboot.c
new file mode 100644
index 000000000000..bfd4260a83a3
--- /dev/null
+++ b/security/integrity/efi_secureboot.c
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-1.0+
+/*
+ * Copyright (C) 2018 IBM Corporation
+ */
+#include <linux/efi.h>
+#include <linux/secure_boot.h>
+#include <asm/efi.h>
+
+#ifndef arch_efi_boot_mode
+#define arch_efi_boot_mode efi_secureboot_mode_unset
+#endif
+
+static enum efi_secureboot_mode get_sb_mode(void)
+{
+	enum efi_secureboot_mode mode;
+
+	if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE)) {
+		pr_info("integrity: secureboot mode unknown, no efi\n");
+		return efi_secureboot_mode_unknown;
+	}
+
+	mode = efi_get_secureboot_mode(efi.get_variable);
+	if (mode == efi_secureboot_mode_disabled)
+		pr_info("integrity: secureboot mode disabled\n");
+	else if (mode == efi_secureboot_mode_unknown)
+		pr_info("integrity: secureboot mode unknown\n");
+	else
+		pr_info("integrity: secureboot mode enabled\n");
+	return mode;
+}
+
+/*
+ * Query secure boot status
+ *
+ * Note don't call this function too early e.g. in __setup hook otherwise the
+ * kernel may hang when calling efi_get_secureboot_mode.
+ *
+ */
+bool arch_get_secureboot(void)
+{
+	static enum efi_secureboot_mode sb_mode;
+	static bool initialized;
+
+	if (!initialized && efi_enabled(EFI_BOOT)) {
+		sb_mode = arch_efi_boot_mode;
+
+		if (sb_mode == efi_secureboot_mode_unset)
+			sb_mode = get_sb_mode();
+		initialized = true;
+	}
+
+	if (sb_mode == efi_secureboot_mode_enabled)
+		return true;
+	else
+		return false;
+}
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index 5149ff4fd50d..9737bf76ce17 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -27,7 +27,7 @@ core_param(ima_appraise, ima_appraise_cmdline_default, charp, 0);
 void __init ima_appraise_parse_cmdline(void)
 {
 	const char *str = ima_appraise_cmdline_default;
-	bool sb_state = arch_ima_get_secureboot();
+	bool sb_state = arch_get_secureboot();
 	int appraisal_state = ima_appraise;
 
 	if (!str)
diff --git a/security/integrity/ima/ima_efi.c b/security/integrity/ima/ima_efi.c
index 138029bfcce1..78191879dd98 100644
--- a/security/integrity/ima/ima_efi.c
+++ b/security/integrity/ima/ima_efi.c
@@ -2,52 +2,9 @@
 /*
  * Copyright (C) 2018 IBM Corporation
  */
-#include <linux/efi.h>
 #include <linux/module.h>
 #include <linux/ima.h>
-#include <asm/efi.h>
-
-#ifndef arch_ima_efi_boot_mode
-#define arch_ima_efi_boot_mode efi_secureboot_mode_unset
-#endif
-
-static enum efi_secureboot_mode get_sb_mode(void)
-{
-	enum efi_secureboot_mode mode;
-
-	if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE)) {
-		pr_info("ima: secureboot mode unknown, no efi\n");
-		return efi_secureboot_mode_unknown;
-	}
-
-	mode = efi_get_secureboot_mode(efi.get_variable);
-	if (mode == efi_secureboot_mode_disabled)
-		pr_info("ima: secureboot mode disabled\n");
-	else if (mode == efi_secureboot_mode_unknown)
-		pr_info("ima: secureboot mode unknown\n");
-	else
-		pr_info("ima: secureboot mode enabled\n");
-	return mode;
-}
-
-bool arch_ima_get_secureboot(void)
-{
-	static enum efi_secureboot_mode sb_mode;
-	static bool initialized;
-
-	if (!initialized && efi_enabled(EFI_BOOT)) {
-		sb_mode = arch_ima_efi_boot_mode;
-
-		if (sb_mode == efi_secureboot_mode_unset)
-			sb_mode = get_sb_mode();
-		initialized = true;
-	}
-
-	if (sb_mode == efi_secureboot_mode_enabled)
-		return true;
-	else
-		return false;
-}
+#include <linux/secure_boot.h>
 
 /* secureboot arch rules */
 static const char * const sb_arch_rules[] = {
@@ -67,7 +24,7 @@ static const char * const sb_arch_rules[] = {
 
 const char * const *arch_get_ima_policy(void)
 {
-	if (IS_ENABLED(CONFIG_IMA_ARCH_POLICY) && arch_ima_get_secureboot()) {
+	if (IS_ENABLED(CONFIG_IMA_ARCH_POLICY) && arch_get_secureboot()) {
 		if (IS_ENABLED(CONFIG_MODULE_SIG))
 			set_module_sig_enforced();
 		if (IS_ENABLED(CONFIG_KEXEC_SIG))
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 5770cf691912..4aa8f0a20950 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -949,8 +949,7 @@ static int ima_load_data(enum kernel_load_data_id id, bool contents)
 
 	switch (id) {
 	case LOADING_KEXEC_IMAGE:
-		if (IS_ENABLED(CONFIG_KEXEC_SIG)
-		    && arch_ima_get_secureboot()) {
+		if (IS_ENABLED(CONFIG_KEXEC_SIG) && arch_get_secureboot()) {
 			pr_err("impossible to appraise a kernel image without a file descriptor; try using kexec_file_load syscall.\n");
 			return -EACCES;
 		}
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index 7b388b66cf80..4636629533af 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h
@@ -14,6 +14,7 @@
 
 #include <linux/types.h>
 #include <linux/integrity.h>
+#include <linux/secure_boot.h>
 #include <crypto/sha1.h>
 #include <crypto/hash.h>
 #include <linux/key.h>
diff --git a/security/integrity/platform_certs/load_uefi.c b/security/integrity/platform_certs/load_uefi.c
index d1fdd113450a..c0d6948446c3 100644
--- a/security/integrity/platform_certs/load_uefi.c
+++ b/security/integrity/platform_certs/load_uefi.c
@@ -212,7 +212,7 @@ static int __init load_uefi_certs(void)
 	}
 
 	/* the MOK/MOKx can not be trusted when secure boot is disabled */
-	if (!arch_ima_get_secureboot())
+	if (!arch_get_secureboot())
 		return 0;
 
 	mokx = get_cert_list(L"MokListXRT", &mok_var, &mokxsize, &status);
diff --git a/security/integrity/secure_boot.c b/security/integrity/secure_boot.c
new file mode 100644
index 000000000000..fc2693c286f8
--- /dev/null
+++ b/security/integrity/secure_boot.c
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2026 Red Hat, Inc. All Rights Reserved.
+ *
+ * Author: Coiby Xu <coxu@redhat.com>
+ */
+#include <linux/secure_boot.h>
+
+/*
+ * Default weak implementation.
+ * Architectures that support secure boot must override this.
+ */
+__weak bool arch_get_secureboot(void)
+{
+	return false;
+}
-- 
2.53.0


^ permalink raw reply related

* [PATCH v3 0/3] Make detecting the secure boot status integrity-wide
From: Coiby Xu @ 2026-02-13  1:28 UTC (permalink / raw)
  To: linux-integrity
  Cc: Heiko Carstens, Alexander Egorenkov, Ard Biesheuvel, Dave Hansen

EVM and other LSMs need the ability to query the secure boot status of
the system, without directly calling the IMA arch_ima_get_secureboot
function. Make arch_ima_get_secureboot integrity-wide.

v3
 - remove unnecessary line splittings [Mimi]

v2
 - drop CONFIG_INTEGRITY_SECURE_BOOT Kconfig option since it 
   "imply INTEGRITY_SECURE_BOOT" is anti-pattern as pointed out by
   Ard Biesheuvel

Coiby Xu (3):
  integrity: Make arch_ima_get_secureboot integrity-wide
  evm: Don't enable fix mode when secure boot is enabled
  s390: Drop unnecessary CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT

 MAINTAINERS                                   |  1 +
 arch/powerpc/kernel/ima_arch.c                |  5 --
 arch/powerpc/kernel/secure_boot.c             |  6 ++
 arch/s390/Kconfig                             |  1 -
 arch/s390/kernel/Makefile                     |  1 -
 arch/s390/kernel/ima_arch.c                   | 14 -----
 arch/s390/kernel/ipl.c                        |  5 ++
 arch/x86/include/asm/efi.h                    |  4 +-
 arch/x86/platform/efi/efi.c                   |  2 +-
 include/linux/ima.h                           |  7 +--
 include/linux/secure_boot.h                   | 19 +++++++
 security/integrity/Makefile                   |  3 +-
 security/integrity/efi_secureboot.c           | 56 +++++++++++++++++++
 security/integrity/evm/evm_main.c             | 24 +++++---
 security/integrity/ima/ima_appraise.c         |  2 +-
 security/integrity/ima/ima_efi.c              | 47 +---------------
 security/integrity/ima/ima_main.c             |  3 +-
 security/integrity/integrity.h                |  1 +
 security/integrity/platform_certs/load_uefi.c |  2 +-
 security/integrity/secure_boot.c              | 16 ++++++
 20 files changed, 132 insertions(+), 87 deletions(-)
 delete mode 100644 arch/s390/kernel/ima_arch.c
 create mode 100644 include/linux/secure_boot.h
 create mode 100644 security/integrity/efi_secureboot.c
 create mode 100644 security/integrity/secure_boot.c


base-commit: 2619c62b7ef2f463bcbbb34af122689c09855c23
-- 
2.53.0


^ permalink raw reply

* Re: [PATCH v15 00/28] x86: Secure Launch support for Intel TXT
From: Ard Biesheuvel @ 2026-02-12 20:39 UTC (permalink / raw)
  To: Daniel P. Smith, Ross Philipson, linux-kernel, x86,
	linux-integrity, linux-doc, linux-crypto, kexec, linux-efi, iommu,
	dave.hansen
  Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, H . Peter Anvin,
	mjg59, James.Bottomley, peterhuewe, Jarkko Sakkinen, jgg, luto,
	nivedita, Herbert Xu, davem, corbet, ebiederm, dwmw2, baolu.lu,
	kanth.ghatraju, andrew.cooper3, trenchboot-devel
In-Reply-To: <1ffd3cb5-2c76-4371-a067-3e4849907d80@apertussolutions.com>

On Thu, 12 Feb 2026, at 20:49, Daniel P. Smith wrote:
> On 2/9/26 09:04, Ard Biesheuvel wrote:
...
>> Surprisingly, even when doing a secure launch, the EFI runtime services still work happily, which means (AIUI) that code that was excluded from the D-RTM TCB is still being executed at ring 0? Doesn't this defeat D-RTM entirely in the case some exploit is hidden in the EFI runtime code? Should we measure the contents of EfiRuntimeServicesCode regions too?
>
> Yes, in fact in the early days I specifically stated that we should 
> provide for the ability to measure the RS blocks. Particularly if you 
> are not in an environment where you can isolate the calls to RS from the 
> TCB. While the RS can pose runtime corruption risks, the larger concern 
> is integrating the D-RTM validation of the Intel System Resources 
> Defense (ISRD), aka SMI isolation/SMM Supervisor, provided by the Intel 
> System Security Report (ISSR). Within the ISSR is a list of memory 
> regions which the SMM Policy Shim (SPS) restricts a SMI handler's access 
> when running. This allows a kernel to restrict what access a SMI handler 
> are able to reach, thus allowing them to be removed from the TCB when 
> the appropriate guards are put in place.
>
> If you are interested in understanding these further, Satoshi Tanda has 
> probably the best technical explanation without Intel market speak.
>
> ISRD: https://tandasat.github.io/blog/2024/02/29/ISRD.html
> ISSR: https://tandasat.github.io/blog/2024/03/18/ISSR.html
>

Thanks, I'll take a look at those.

But would it be better to disable the runtime services by default when doing a secure launch? PREEMPT_RT already does the same.

> While you all care about Linux specifically, the 
> goal for TrenchBoot is to build a common approach that we can implement
> across any other open source OS.
>

I'd argue that relying on things like setup_header, boot_params and kernel_info is not a great way to achieve that. The reason I care about this is that you are relying on those things even when doing EFI boot, which makes your approach highly Linux/x86 specific.

Given that arm64 has no decompressor at all, it is highly likely (and acceptable) that only EFI boot can do a secure launch. It also implies that the core kernel is the only place where we can put the pieces that execute afterwards. So adopting a model now for x86 that we know does not generalize well across other architectures is something I am not keen on.

...
>> I've had a stab at implementing all of this in a manner that is more idiomatic for EFI boot:
>> 
>> - GRUB does minimal TXT related preparation upfront, and exposes the remaining functionality via a protocol that is attached to the loaded image by GRUB
>> - The SL stub is moved to the core kernel, with some startup code added to pivot to long mode
>> - the EFI stub executes and decompresses the kernel as usual
>> - if the protocol is present, the EFI stub calls it to pass the bootparams pointer, the base and size of the MLE and the header offset back to the GRUB code
>> - after calling ExitBootServices(), it calls another protocol method to trigger the secure launch.
>> 
...
>
> I think this is a great approach for UEFI, though we need to reconcile 
> this with non-UEFI situations such as booting under coreboot.

There are two approaches that I think are feasible for coreboot in this model:

- just unpack the ELF and boot that - there is already prior art for that with Xen. We can stick the MLE header offset in an ELF note where any loader can find it.

- stick with the current approach as much as possible, i.e., disable physical KASLR so that the decompressed kernel will end up right where the decompressor was loaded, which allows much of the secure launch preparation to be done as before. Only the final bits (including the call into the ACM itself) need to be deferred, and we can propose a generic mechanism for that via boot_params.

I'm working on a prototype of the latter, but GRUB is an odd beast and my x86 fu is weak.

I'd be happy to have a call to compare notes and see if we can come up with something we can all agree on (modulo the SHA-1 :-))



^ permalink raw reply

* Re: [PATCH v2 1/3] integrity: Make arch_ima_get_secureboot integrity-wide
From: Mimi Zohar @ 2026-02-12 20:25 UTC (permalink / raw)
  To: Coiby Xu
  Cc: linux-integrity, Heiko Carstens, Alexander Egorenkov,
	Ard Biesheuvel, Dave Hansen, Roberto Sassu, Madhavan Srinivasan,
	Michael Ellerman, Nicholas Piggin, Christophe Leroy (CS GROUP),
	Vasily Gorbik, Alexander Gordeev, Christian Borntraeger,
	Sven Schnelle, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT),
	H. Peter Anvin, Dmitry Kasatkin, Eric Snowberg, Paul Moore,
	James Morris, Serge E. Hallyn, Jarkko Sakkinen, open list,
	open list:LINUX FOR POWERPC (32-BIT AND 64-BIT),
	open list:S390 ARCHITECTURE,
	open list:EXTENSIBLE FIRMWARE INTERFACE (EFI),
	open list:SECURITY SUBSYSTEM, open list:KEYS/KEYRINGS_INTEGRITY
In-Reply-To: <aY0rZp9ROwfjPgD8@Rk>

On Thu, 2026-02-12 at 09:28 +0800, Coiby Xu wrote:
> On Mon, Feb 09, 2026 at 03:43:08PM -0500, Mimi Zohar wrote:
> > On Tue, 2026-02-03 at 12:14 +0800, Coiby Xu wrote:
> > > EVM and other LSMs need the ability to query the secure boot status of
> > > the system, without directly calling the IMA arch_ima_get_secureboot
> > > function. Refactor the secure boot status check into a general function
> > > named arch_get_secureboot.
> > > 
> > > Reported-and-suggested-by: Mimi Zohar <zohar@linux.ibm.com>
> > > Suggested-by: Roberto Sassu <roberto.sassu@huawei.com>
> > > Signed-off-by: Coiby Xu <coxu@redhat.com>
> > 
> > Thanks, Coiby.  Other than unnecessarily splitting a line, the patch set looks
> > good.  As soon as the open window closes, I'll queue these patches for linux-
> > next.
> 
> Hi Mimi, thanks for reviewing the patch set! Would you like me to send a
> new version with the line splitting issue fixed?

Yes, thanks.

Mimi

> 
> > 
> > > diff --git a/security/integrity/ima/ima_efi.c b/security/integrity/ima/ima_efi.c
> > > index 138029bfcce1..27521d665d33 100644
> > > --- a/security/integrity/ima/ima_efi.c
> > > +++ b/security/integrity/ima/ima_efi.c
> [...]
> > >  {
> > > -	if (IS_ENABLED(CONFIG_IMA_ARCH_POLICY) && arch_ima_get_secureboot()) {
> > > +	if (IS_ENABLED(CONFIG_IMA_ARCH_POLICY) &&
> > > +	    arch_get_secureboot()) {
> > 
> > No need to split the line here or below.
> > 
> > 
> > >  		if (IS_ENABLED(CONFIG_MODULE_SIG))
> > >  			set_module_sig_enforced();
> > >  		if (IS_ENABLED(CONFIG_KEXEC_SIG))
> > > diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
> > > index 5770cf691912..6d093ac82a45 100644
> > > --- a/security/integrity/ima/ima_main.c
> > > +++ b/security/integrity/ima/ima_main.c
> > > @@ -949,8 +949,8 @@ static int ima_load_data(enum kernel_load_data_id id, bool contents)
> > > 
> > >  	switch (id) {
> > >  	case LOADING_KEXEC_IMAGE:
> > > -		if (IS_ENABLED(CONFIG_KEXEC_SIG)
> > > -		    && arch_ima_get_secureboot()) {
> > > +		if (IS_ENABLED(CONFIG_KEXEC_SIG) &&
> > > +		    arch_get_secureboot()) {
> > 
> > ===>
> > 
> > Mimi
> > 
> > >  			pr_err("impossible to appraise a kernel image without a file descriptor; try using kexec_file_load syscall.\n");
> > >  			return -EACCES;
> > >  		}
> > 

^ permalink raw reply

* [PATCH] ima: fallback to using i_version
From: Mimi Zohar @ 2026-02-12 20:11 UTC (permalink / raw)
  To: linux-integrity; +Cc: Mimi Zohar, Frederick Lawler, Jeff Layton, Roberto Sassu

Commit db1d1e8b9867 ("IMA: use vfs_getattr_nosec to get the i_version")
replaced detecting file change based on i_version with
STATX_CHANGE_COOKIE.

On filesystems without STATX_CHANGE_COOKIE enabled, revert back to
detecting file change based on i_version.

Fixes: db1d1e8b9867 ("IMA: use vfs_getattr_nosec to get the i_version")
Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
---
 security/integrity/ima/ima_api.c  | 13 ++++++++----
 security/integrity/ima/ima_main.c | 34 +++++++++++++++++++++++++------
 2 files changed, 37 insertions(+), 10 deletions(-)

diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index c35ea613c9f8..3f0c73a8b459 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -267,15 +267,20 @@ int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file,
 		goto out;
 
 	/*
-	 * Detecting file change is based on i_version. On filesystems
-	 * which do not support i_version, support was originally limited
-	 * to an initial measurement/appraisal/audit, but was modified to
-	 * assume the file changed.
+	 * Detect file change based on STATX_CHANGE_COOKIE, when supported,
+	 * and fallback to detecting file change based on i_version.
+	 *
+	 * On filesystems which did not support i_version, support was
+	 * originally limited to an initial measurement/appraisal/audit,
+	 * but was later modified to assume the file changed.
 	 */
 	result = vfs_getattr_nosec(&file->f_path, &stat, STATX_CHANGE_COOKIE,
 				   AT_STATX_SYNC_AS_STAT);
 	if (!result && (stat.result_mask & STATX_CHANGE_COOKIE))
 		i_version = stat.change_cookie;
+	else if (IS_I_VERSION(inode))
+		i_version = inode_peek_iversion(inode);
+
 	hash.hdr.algo = algo;
 	hash.hdr.length = hash_digest_size[algo];
 
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 1d6229b156fb..fc50f727c954 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -184,7 +184,9 @@ static void ima_check_last_writer(struct ima_iint_cache *iint,
 				  struct inode *inode, struct file *file)
 {
 	fmode_t mode = file->f_mode;
+	int modified = 0;
 	bool update;
+	int result;
 
 	if (!(mode & FMODE_WRITE))
 		return;
@@ -197,12 +199,32 @@ static void ima_check_last_writer(struct ima_iint_cache *iint,
 
 		update = test_and_clear_bit(IMA_UPDATE_XATTR,
 					    &iint->atomic_flags);
-		if ((iint->flags & IMA_NEW_FILE) ||
-		    vfs_getattr_nosec(&file->f_path, &stat,
-				      STATX_CHANGE_COOKIE,
-				      AT_STATX_SYNC_AS_STAT) ||
-		    !(stat.result_mask & STATX_CHANGE_COOKIE) ||
-		    stat.change_cookie != iint->real_inode.version) {
+
+		if (iint->flags & IMA_NEW_FILE)
+			modified = 1;
+
+		/*
+		 * Detect file change based on STATX_CHANGE_COOKIE, when
+		 * supported, and fallback to detecting file change based
+		 * on i_version. On filesystems which do not support either,
+		 * assume the file changed.
+		 */
+		 result = vfs_getattr_nosec(&file->f_path, &stat,
+					    STATX_CHANGE_COOKIE,
+					    AT_STATX_SYNC_AS_STAT);
+
+		if (!result && stat.result_mask & STATX_CHANGE_COOKIE &&
+		    stat.change_cookie != iint->real_inode.version)
+			modified = 1;
+		else if (!(stat.result_mask & STATX_CHANGE_COOKIE) &&
+			 IS_I_VERSION(inode) &&
+			 !(inode_eq_iversion(inode, iint->real_inode.version)))
+			modified = 1;
+		else if (!(stat.result_mask & STATX_CHANGE_COOKIE) &&
+			 !(IS_I_VERSION(inode)))
+			modified = 1;
+
+		if (modified) {
 			iint->flags &= ~(IMA_DONE_MASK | IMA_NEW_FILE);
 			iint->measured_pcrs = 0;
 			if (update)
-- 
2.53.0


^ permalink raw reply related

* Re: [PATCH v6 0/3] ima: Detect changes to files via kstat changes rather than i_version
From: Frederick Lawler @ 2026-02-12 20:01 UTC (permalink / raw)
  To: Mimi Zohar
  Cc: Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Paul Moore,
	James Morris, Serge E. Hallyn, Darrick J. Wong, Christian Brauner,
	Josef Bacik, Jeff Layton, linux-kernel, linux-integrity,
	linux-security-module, kernel-team
In-Reply-To: <50c5e00a8c336e8ab393457af009c26902114688.camel@linux.ibm.com>

On Thu, Feb 12, 2026 at 02:45:58PM -0500, Mimi Zohar wrote:
> On Mon, 2026-02-09 at 15:21 -0600, Frederick Lawler wrote:
> > We uncovered a case in kernels >= 6.13 where XFS is no longer updating
> > struct kstat.change_cookie on i_op getattr() access calls. Instead, XFS is
> > using multigrain ctime (as well as other file systems) for
> > change detection in commit 1cf7e834a6fb ("xfs: switch to
> > multigrain timestamps").
> > 
> > Because file systems may implement i_version as they see fit, IMA
> > unnecessarily measures files.
> 
> Statements like this are wrong and certainly unnecessary. Refer to commit
> db1d1e8b9867 ("IMA: use vfs_getattr_nosec to get the i_version").  Directly
> accessing the i_version still worked on local filesystems.

Sorry, that's the intention I was trying to get across.

> 
> I'll be posting a patch shortly that falls back to directly reading the
> i_version, when STATX_CHANGE_COOKIE is not supported.  It cleans up the file
> change detection code, making it more readable and should simplify adding the
> ctime file change detection.
> 
> > We're proposing to compare against the kstat.change_cookie
> > directly to the cached version, and fall back to a ctime comparison,
> > if STATX_CHANGE_COOKIE is not supplied by vfs_getattr_nosec()'s result
> > mask.
> 
> Please rebase your proposed change on this patch.
>

Sounds good. I'll keep an eye out for it.


^ permalink raw reply

* Re: [PATCH v15 00/28] x86: Secure Launch support for Intel TXT
From: Dave Hansen @ 2026-02-12 19:54 UTC (permalink / raw)
  To: Daniel P. Smith, Ard Biesheuvel, Ross Philipson, linux-kernel,
	x86, linux-integrity, linux-doc, linux-crypto, kexec, linux-efi,
	iommu, dave.hansen
  Cc: Thomas Gleixner, mingo, bp, H . Peter Anvin, mjg59,
	James.Bottomley, peterhuewe, jarkko, jgg, luto, nivedita, herbert,
	davem, corbet, ebiederm, dwmw2, baolu.lu, kanth.ghatraju,
	andrew.cooper3, trenchboot-devel
In-Reply-To: <1ffd3cb5-2c76-4371-a067-3e4849907d80@apertussolutions.com>

On 2/12/26 11:49, Daniel P. Smith wrote:
...
> I think this is a great approach for UEFI, though we need to reconcile
> this with non-UEFI situations such as booting under coreboot. The one
> concern we have before committing to yet another rework is to get
> confirmation from the x86 maintainers. Would they be okay with a new
> entry point into the mainline kernel, or any other major sticking points
> they might see from this approach?
> 
> Dave Hansen, since you have been helping us as an x86 maintainer, would
> be willing to provide feedback on our concerns moving forward with the
> above proposal?

The fewer the number of entry points the better, of course.

But, there are always going to be compromises. If you want a new entry
point, just make a good case for it and describe the tradeoffs. Make
sure Ard is on board.

^ permalink raw reply

* Re: [PATCH v15 00/28] x86: Secure Launch support for Intel TXT
From: Daniel P. Smith @ 2026-02-12 19:49 UTC (permalink / raw)
  To: Ard Biesheuvel, Ross Philipson, linux-kernel, x86,
	linux-integrity, linux-doc, linux-crypto, kexec, linux-efi, iommu,
	dave.hansen
  Cc: Thomas Gleixner, mingo, bp, H . Peter Anvin, mjg59,
	James.Bottomley, peterhuewe, jarkko, jgg, luto, nivedita, herbert,
	davem, corbet, ebiederm, dwmw2, baolu.lu, kanth.ghatraju,
	andrew.cooper3, trenchboot-devel
In-Reply-To: <b5f2b5a5-b984-4ed3-a023-c06d634f9146@app.fastmail.com>

On 2/9/26 09:04, Ard Biesheuvel wrote:
> On Tue, 16 Dec 2025, at 00:32, Ross Philipson wrote:
>> Secure Launch is a vendor-neutral approach to implementing TGC Dynamic
>> Root of Trust (DRTM) support in the kernel. This is complementary to
>> better known Static Root of Trust (SRTM) schemes such as UEFI SecureBoot.
>>
>> This series provides the common infrastructure along with Intel TXT
>> support, without needing the tboot exokernel. Support for AMD SKINIT is
>> pending the common infrastructure getting nailed down, and ARM are
>> looking to build on it too.
>>
>> Originally, tboot were approached to see if they'd take support for
>> other vendors, but they elected not to. Hence this approach instead.
>>
>> Work is being coordinated by the Trenchboot project,
>> https://trenchboot.org/,
>> organising Secure Launch support for upstream open source projects
>> including
>> Grub, iPXE and Xen. The goal of the Trenchboot project is to make DTRM
>> easy
>> to use.  e.g. for Grub, it's simply adding "slaunch" as a command in
>> the boot
>> stanza.  See
>> https://trenchboot.org/user-docs/QUICKSTART/#linux-quick-start-guide
>> for more details
>>
>> Patch set based on commit:
>> torvalds/master/fd57572253bc356330dbe5b233c2e1d8426c66fd
>>
>> Depends on v3 of the following TPM patch set (note this patch
>> set is being actively worked on separately):
>> [PATCH v3 00/10]  tpm: Decouple Trenchboot dependencies
>> Message ID: 20250929194832.2913286-1-jarkko@kernel.org
>>
>> Finally we would like to thank everyone for their input and
>> assistance. It has all been very helpful in improving the quality of
>> our solution and in reviewing/strengthening our security posture.
>>
> 
> Hi Daniel and Ross,
> 
> I have finally gotten around to getting the right hardware and building GRUB and Linux with your patches, and I have managed to get them running on an old Skylake HP laptop successfully.

That is great to hear!

> Surprisingly, even when doing a secure launch, the EFI runtime services still work happily, which means (AIUI) that code that was excluded from the D-RTM TCB is still being executed at ring 0? Doesn't this defeat D-RTM entirely in the case some exploit is hidden in the EFI runtime code? Should we measure the contents of EfiRuntimeServicesCode regions too?

Yes, in fact in the early days I specifically stated that we should 
provide for the ability to measure the RS blocks. Particularly if you 
are not in an environment where you can isolate the calls to RS from the 
TCB. While the RS can pose runtime corruption risks, the larger concern 
is integrating the D-RTM validation of the Intel System Resources 
Defense (ISRD), aka SMI isolation/SMM Supervisor, provided by the Intel 
System Security Report (ISSR). Within the ISSR is a list of memory 
regions which the SMM Policy Shim (SPS) restricts a SMI handler's access 
when running. This allows a kernel to restrict what access a SMI handler 
are able to reach, thus allowing them to be removed from the TCB when 
the appropriate guards are put in place.

If you are interested in understanding these further, Satoshi Tanda has 
probably the best technical explanation without Intel market speak.

ISRD: https://tandasat.github.io/blog/2024/02/29/ISRD.html
ISSR: https://tandasat.github.io/blog/2024/03/18/ISSR.html

> In any case, I am aware that upstreaming this work has been a painful experience so far. Unfortunately, I don't think we're quite there yet.
>
> The way the work is divided between GRUB and Linux seems to be predicated entirely (at least originally) on the idea that the GRUB->Linux handover and the secure launch should be one and the same. I.e., GRUB sets the stage, pokes the ACM, which returns to the loaded linux image and boots it. This requires a lot of coordination, e.g., putting a MLE header in the kernel image and exposing it to GRUB in a certain manner, resource tables and other things that have to remain in sync between both sides.

I would add one clarification, where you say GRUB, we would say any 
bootloader and where you say Linux, we would say any kernel that could 
be started with D-RTM. While you all care about Linux specifically, the 
goal for TrenchBoot is to build a common approach that we can implement
across any other open source OS.

> There also appears to be an assumption that the fact that the ACM returns to the loaded image in 32-bit mode requires a round trip through the decompressor, which may relocate itself in memory and do other things that the slaunch code then has to work around again.
> 
> Due to the changes to the EFI boot path, this design has been watered down a bit already, in the sense that GRUB invokes the EFI entry point as usual, and only later, the pivot via the ACM is made.
> 
> Other than the SHA-1 debate [*], the main issue I have with this approach is that it adds things to the boot ABI that are closely tied to TXT on the one hand, and bzImage oddities on the other (kernel_info, setup block etc). IOW, the complete lack of abstractions is going to make this a maintenance burden going forward.
> 
> I've had a stab at implementing all of this in a manner that is more idiomatic for EFI boot:
> 
> - GRUB does minimal TXT related preparation upfront, and exposes the remaining functionality via a protocol that is attached to the loaded image by GRUB
> - The SL stub is moved to the core kernel, with some startup code added to pivot to long mode
> - the EFI stub executes and decompresses the kernel as usual
> - if the protocol is present, the EFI stub calls it to pass the bootparams pointer, the base and size of the MLE and the header offset back to the GRUB code
> - after calling ExitBootServices(), it calls another protocol method to trigger the secure launch.
> 
> The only pre-launch ABI that is being added here is a GRUB-specific protocol that is not necessarily tied to TXT. (For legacy boot, it should be feasible to call back into GRUB too, although it would be more of a ad-hoc construction, via the SLR table perhaps.) But no kernel_info and MLE headers etc being added to the ABI surface. Also, there is no longer a need for the GRUB code to understand how the decompressor is constructed, with a setup block etc, or take special care to perform PMR checks when its moves itself around in memory.

> [*] which I still don't get: why is it fine to cap other banks with a single 0x1 byte [as the ACM does too, apparently], but do we require an SHA-1 implementation for capping the SHA-1 banks? Also, the TXT spec dropped all support for TPM1.2 so I wonder if that should be dropped from this series as well.

I think this is a great approach for UEFI, though we need to reconcile 
this with non-UEFI situations such as booting under coreboot. The one 
concern we have before committing to yet another rework is to get 
confirmation from the x86 maintainers. Would they be okay with a new 
entry point into the mainline kernel, or any other major sticking points 
they might see from this approach?

Dave Hansen, since you have been helping us as an x86 maintainer, would 
be willing to provide feedback on our concerns moving forward with the 
above proposal?

> Code can be found here:
> 
> https://git.kernel.org/pub/scm/linux/kernel/git/ardb/grub.git/log/?h=sl-v2
> https://git.kernel.org/pub/scm/linux/kernel/git/ardb/linux.git/log/?h=x86-slaunch
> 
> I am aware that this is not the feedback you are waiting for at this point, given that we're at v15 already. But there are some warts in the current design that really need to be addressed before we can proceed with this IMHO.
>

V/r,
DPS







^ permalink raw reply

* Re: [PATCH v6 0/3] ima: Detect changes to files via kstat changes rather than i_version
From: Mimi Zohar @ 2026-02-12 19:45 UTC (permalink / raw)
  To: Frederick Lawler, Roberto Sassu, Dmitry Kasatkin, Eric Snowberg,
	Paul Moore, James Morris, Serge E. Hallyn, Darrick J. Wong,
	Christian Brauner, Josef Bacik, Jeff Layton
  Cc: linux-kernel, linux-integrity, linux-security-module, kernel-team
In-Reply-To: <20260209-xfs-ima-fixup-v6-0-72f576f90e67@cloudflare.com>

On Mon, 2026-02-09 at 15:21 -0600, Frederick Lawler wrote:
> We uncovered a case in kernels >= 6.13 where XFS is no longer updating
> struct kstat.change_cookie on i_op getattr() access calls. Instead, XFS is
> using multigrain ctime (as well as other file systems) for
> change detection in commit 1cf7e834a6fb ("xfs: switch to
> multigrain timestamps").
> 
> Because file systems may implement i_version as they see fit, IMA
> unnecessarily measures files.

Statements like this are wrong and certainly unnecessary. Refer to commit
db1d1e8b9867 ("IMA: use vfs_getattr_nosec to get the i_version").  Directly
accessing the i_version still worked on local filesystems.

I'll be posting a patch shortly that falls back to directly reading the
i_version, when STATX_CHANGE_COOKIE is not supported.  It cleans up the file
change detection code, making it more readable and should simplify adding the
ctime file change detection.

> We're proposing to compare against the kstat.change_cookie
> directly to the cached version, and fall back to a ctime comparison,
> if STATX_CHANGE_COOKIE is not supplied by vfs_getattr_nosec()'s result
> mask.

Please rebase your proposed change on this patch.

Mimi

^ permalink raw reply

* Re: [PATCH v2 1/3] integrity: Make arch_ima_get_secureboot integrity-wide
From: Coiby Xu @ 2026-02-12  1:28 UTC (permalink / raw)
  To: Mimi Zohar
  Cc: linux-integrity, Heiko Carstens, Alexander Egorenkov,
	Ard Biesheuvel, Dave Hansen, Roberto Sassu, Madhavan Srinivasan,
	Michael Ellerman, Nicholas Piggin, Christophe Leroy (CS GROUP),
	Vasily Gorbik, Alexander Gordeev, Christian Borntraeger,
	Sven Schnelle, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT),
	H. Peter Anvin, Dmitry Kasatkin, Eric Snowberg, Paul Moore,
	James Morris, Serge E. Hallyn, Jarkko Sakkinen, open list,
	open list:LINUX FOR POWERPC (32-BIT AND 64-BIT),
	open list:S390 ARCHITECTURE,
	open list:EXTENSIBLE FIRMWARE INTERFACE (EFI),
	open list:SECURITY SUBSYSTEM, open list:KEYS/KEYRINGS_INTEGRITY
In-Reply-To: <66f9d13875e81a965984e2a661e992a3fe43c516.camel@linux.ibm.com>

On Mon, Feb 09, 2026 at 03:43:08PM -0500, Mimi Zohar wrote:
>On Tue, 2026-02-03 at 12:14 +0800, Coiby Xu wrote:
>> EVM and other LSMs need the ability to query the secure boot status of
>> the system, without directly calling the IMA arch_ima_get_secureboot
>> function. Refactor the secure boot status check into a general function
>> named arch_get_secureboot.
>>
>> Reported-and-suggested-by: Mimi Zohar <zohar@linux.ibm.com>
>> Suggested-by: Roberto Sassu <roberto.sassu@huawei.com>
>> Signed-off-by: Coiby Xu <coxu@redhat.com>
>
>Thanks, Coiby.  Other than unnecessarily splitting a line, the patch set looks
>good.  As soon as the open window closes, I'll queue these patches for linux-
>next.

Hi Mimi, thanks for reviewing the patch set! Would you like me to send a
new version with the line splitting issue fixed?

>
>> diff --git a/security/integrity/ima/ima_efi.c b/security/integrity/ima/ima_efi.c
>> index 138029bfcce1..27521d665d33 100644
>> --- a/security/integrity/ima/ima_efi.c
>> +++ b/security/integrity/ima/ima_efi.c
[...]
>>  {
>> -	if (IS_ENABLED(CONFIG_IMA_ARCH_POLICY) && arch_ima_get_secureboot()) {
>> +	if (IS_ENABLED(CONFIG_IMA_ARCH_POLICY) &&
>> +	    arch_get_secureboot()) {
>
>No need to split the line here or below.
>
>
>>  		if (IS_ENABLED(CONFIG_MODULE_SIG))
>>  			set_module_sig_enforced();
>>  		if (IS_ENABLED(CONFIG_KEXEC_SIG))
>> diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
>> index 5770cf691912..6d093ac82a45 100644
>> --- a/security/integrity/ima/ima_main.c
>> +++ b/security/integrity/ima/ima_main.c
>> @@ -949,8 +949,8 @@ static int ima_load_data(enum kernel_load_data_id id, bool contents)
>>
>>  	switch (id) {
>>  	case LOADING_KEXEC_IMAGE:
>> -		if (IS_ENABLED(CONFIG_KEXEC_SIG)
>> -		    && arch_ima_get_secureboot()) {
>> +		if (IS_ENABLED(CONFIG_KEXEC_SIG) &&
>> +		    arch_get_secureboot()) {
>
>===>
>
>Mimi
>
>>  			pr_err("impossible to appraise a kernel image without a file descriptor; try using kexec_file_load syscall.\n");
>>  			return -EACCES;
>>  		}
>

-- 
Best regards,
Coiby


^ permalink raw reply

* [PATCH AUTOSEL 6.19-5.15] char: tpm: cr50: Remove IRQF_ONESHOT
From: Sasha Levin @ 2026-02-12  1:09 UTC (permalink / raw)
  To: patches, stable
  Cc: Sebastian Andrzej Siewior, Thomas Gleixner, Jarkko Sakkinen,
	Sasha Levin, peterhuewe, clrkwllms, rostedt, dlan,
	linux-integrity, linux-rt-devel, linux-riscv, spacemit
In-Reply-To: <20260212010955.3480391-1-sashal@kernel.org>

From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

[ Upstream commit 1affd29ffbd50125a5492c6be1dbb1f04be18d4f ]

Passing IRQF_ONESHOT ensures that the interrupt source is masked until
the secondary (threaded) handler is done. If only a primary handler is
used then the flag makes no sense because the interrupt can not fire
(again) while its handler is running.

The flag also prevents force-threading of the primary handler and the
irq-core will warn about this.

Remove IRQF_ONESHOT from irqflags.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
Link: https://patch.msgid.link/20260128095540.863589-10-bigeasy@linutronix.de
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

Now I have a complete understanding. Let me write up the comprehensive
analysis.

---

## Comprehensive Analysis

### 1. Commit Message Analysis

The commit subject is "char: tpm: cr50: Remove IRQF_ONESHOT" and the
message explains three points:
1. `IRQF_ONESHOT` is for masking the interrupt source until the
   **threaded** (secondary) handler completes
2. These drivers only have primary handlers, so the flag is meaningless
3. The flag **prevents force-threading** of the primary handler, and the
   irq-core will warn about this

The commit is authored by **Sebastian Andrzej Siewior** (bigeasy), the
PREEMPT_RT maintainer, and signed off by **Thomas Gleixner**, the IRQ
subsystem maintainer and co-maintainer of the Linux kernel. It was
reviewed by **Jarkko Sakkinen**, the TPM subsystem maintainer.

### 2. Code Change Analysis

The change is minimal and surgical:
- **`tpm_tis_i2c_cr50.c`**: Removes `IRQF_ONESHOT` from the flags in
  `devm_request_irq()`, keeping `IRQF_TRIGGER_FALLING | IRQF_NO_AUTOEN`
- **`tpm_tis_spi_cr50.c`**: Removes `IRQF_ONESHOT` from the flags in
  `devm_request_irq()`, keeping `IRQF_TRIGGER_RISING`

Both interrupt handlers (`tpm_cr50_i2c_int_handler` at line 74 and
`cr50_spi_irq_handler` at line 65) are trivially simple - they just call
`complete()` and return `IRQ_HANDLED`. There is no thread_fn.
`devm_request_irq()` is a wrapper that calls
`devm_request_threaded_irq()` with `thread_fn = NULL`.

### 3. The Real Bug

The companion commit **`aef30c8d569c`** ("genirq: Warn about using
IRQF_ONESHOT without a threaded handler") was merged on 2026-01-12 and
adds a `WARN_ON_ONCE()` in `__setup_irq()`:

```c
WARN_ON_ONCE(new->flags & IRQF_ONESHOT && !new->thread_fn);
```

This means that **without this cr50 fix**, every time the cr50 TPM
driver probes on a system with the updated IRQ core, it will emit a
`WARN_ON_ONCE` kernel warning at boot. This is a real runtime issue that
would affect all Chromebook and other systems using cr50/ti50 TPM chips.

More importantly, the core technical issue is that `IRQF_ONESHOT`
prevents force-threading of the primary handler. From
`irq_setup_forced_threading()` in `kernel/irq/manage.c`:

```c
if (new->flags & (IRQF_NO_THREAD | IRQF_PERCPU | IRQF_ONESHOT))
    return 0;  // Skip force-threading!
```

On **PREEMPT_RT kernels** (where `force_irqthreads()` returns `true`),
this means the cr50 interrupt handler runs in hardirq context instead of
being force-threaded. While the handler itself (`complete()`) is safe in
hardirq context, this defeats the PREEMPT_RT design goal of having all
interrupt handlers run in thread context. On non-RT systems with
`threadirqs` boot parameter, the same issue occurs.

### 4. Classification

This is a **bug fix** that addresses:
1. **A spurious kernel warning** triggered by the new `WARN_ON_ONCE`
   check added in `aef30c8d569c`
2. **Incorrect IRQ flags** - `IRQF_ONESHOT` has never been semantically
   correct for these drivers since they only use primary handlers
3. **PREEMPT_RT compatibility** - the flag prevents force-threading,
   which can be problematic

The fix is not a feature addition - it removes an incorrect flag that
was always wrong.

### 5. Scope and Risk Assessment

- **Lines changed**: 2 files, 2 lines total (removing `IRQF_ONESHOT`
  from two flag constants)
- **Risk**: Extremely low. `IRQF_ONESHOT` had no functional effect on
  these drivers since they use only primary handlers. The interrupt
  cannot fire while its primary handler is already running (hardware
  guarantee), so removing the flag changes nothing about interrupt
  masking behavior.
- **Subsystem**: TPM drivers, well-understood, mature code
- **Testing**: Reviewed by TPM maintainer (Jarkko Sakkinen), authored by
  PREEMPT_RT maintainer, signed off by IRQ core maintainer

### 6. User Impact

- **Who is affected**: All users with cr50/ti50 TPM chips (primarily
  Chromebooks and Google-based embedded devices)
- **Severity without fix**: Kernel `WARN_ON_ONCE` at boot if the
  `aef30c8d569c` warning commit is also backported; PREEMPT_RT
  degradation
- **Severity of regression risk**: Essentially zero - the flag had no
  functional purpose

### 7. Dependencies

This commit is **self-contained**. It does not require any other patches
to apply cleanly. However, the motivating warning comes from
`aef30c8d569c` - if that commit is backported to stable, this fix
becomes essential to avoid warnings. Even without the warning commit,
this fix is correct and beneficial (enables proper force-threading on RT
systems).

The i2c-spacemit driver already got a similar fix (`e351836a54e3`) with
`Cc: stable@vger.kernel.org` tag, establishing precedent that these
IRQF_ONESHOT removal patches are considered stable material.

### 8. Stability Indicators

- Author: Sebastian Andrzej Siewior (PREEMPT_RT maintainer) - domain
  expert
- Signed-off-by: Thomas Gleixner (IRQ subsystem maintainer) - domain
  expert
- Reviewed-by: Jarkko Sakkinen (TPM maintainer) - domain expert
- Part of a systematic cleanup pattern with prior art (i2c-exynos5,
  i2c-hix5hd2, i2c-spacemit, drm/msm)

### Conclusion

This is a small, surgical, obviously correct bug fix. The `IRQF_ONESHOT`
flag was always semantically wrong for these primary-only handlers. The
fix removes a flag that had no functional benefit but actively prevented
force-threading on PREEMPT_RT systems and will trigger a `WARN_ON_ONCE`
with the companion IRQ core warning check. The risk is near-zero, the
change is trivial (2 lines across 2 files), it was reviewed by all three
relevant subsystem maintainers, and there is clear precedent for
identical fixes being marked as stable material (the i2c-spacemit fix
had `Cc: stable@vger.kernel.org`).

**YES**

 drivers/char/tpm/tpm_tis_i2c_cr50.c | 3 +--
 drivers/char/tpm/tpm_tis_spi_cr50.c | 2 +-
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/char/tpm/tpm_tis_i2c_cr50.c b/drivers/char/tpm/tpm_tis_i2c_cr50.c
index fc6891a0b6936..b48cacacc0664 100644
--- a/drivers/char/tpm/tpm_tis_i2c_cr50.c
+++ b/drivers/char/tpm/tpm_tis_i2c_cr50.c
@@ -749,8 +749,7 @@ static int tpm_cr50_i2c_probe(struct i2c_client *client)
 
 	if (client->irq > 0) {
 		rc = devm_request_irq(dev, client->irq, tpm_cr50_i2c_int_handler,
-				      IRQF_TRIGGER_FALLING | IRQF_ONESHOT |
-				      IRQF_NO_AUTOEN,
+				      IRQF_TRIGGER_FALLING | IRQF_NO_AUTOEN,
 				      dev->driver->name, chip);
 		if (rc < 0) {
 			dev_err(dev, "Failed to probe IRQ %d\n", client->irq);
diff --git a/drivers/char/tpm/tpm_tis_spi_cr50.c b/drivers/char/tpm/tpm_tis_spi_cr50.c
index f4937280e9406..32920b4cecfb4 100644
--- a/drivers/char/tpm/tpm_tis_spi_cr50.c
+++ b/drivers/char/tpm/tpm_tis_spi_cr50.c
@@ -287,7 +287,7 @@ int cr50_spi_probe(struct spi_device *spi)
 	if (spi->irq > 0) {
 		ret = devm_request_irq(&spi->dev, spi->irq,
 				       cr50_spi_irq_handler,
-				       IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+				       IRQF_TRIGGER_RISING,
 				       "cr50_spi", cr50_phy);
 		if (ret < 0) {
 			if (ret == -EPROBE_DEFER)
-- 
2.51.0


^ permalink raw reply related

* Re: [GIT PULL] integrity: subsystem updates for v7.0
From: pr-tracker-bot @ 2026-02-12  0:04 UTC (permalink / raw)
  To: Mimi Zohar; +Cc: Linus Torvalds, linux-integrity, linux-kernel, Roberto Sassu
In-Reply-To: <a6da3d9309492557026cee3b5a50c6aea8967365.camel@linux.ibm.com>

The pull request you sent on Tue, 10 Feb 2026 09:54:41 -0500:

> https://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity.git/ tags/integrity-v7.0

has been merged into torvalds/linux.git:
https://git.kernel.org/torvalds/c/d0e91e401e31959154b6518c29d130b1973e3785

Thank you!

-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/prtracker.html

^ permalink raw reply

* Re: [RFC][PATCH v2] ima: Add support for staging measurements for deletion and trimming
From: steven chen @ 2026-02-11  0:09 UTC (permalink / raw)
  To: Roberto Sassu, corbet, zohar, dmitry.kasatkin, eric.snowberg,
	paul, jmorris, serge
  Cc: linux-doc, linux-kernel, linux-integrity, linux-security-module,
	gregorylumen, nramas, Roberto Sassu, steven chen
In-Reply-To: <52069703-98fc-4667-8c29-446ea73249cb@huaweicloud.com>

On 1/29/2026 12:20 AM, Roberto Sassu wrote:
> On 1/28/2026 10:30 PM, steven chen wrote:
>> On 12/12/2025 9:19 AM, Roberto Sassu wrote:
>>> From: Roberto Sassu <roberto.sassu@huawei.com>
>>>
>>> Introduce the ability of staging the entire (or a portion of the) IMA
>>> measurement list for deletion. Staging means moving the current 
>>> content of
>>> the measurement list to a separate location, and allowing users to 
>>> read and
>>> delete it. This causes the measurement list to be atomically truncated
>>> before new measurements can be added. Staging can be done only once 
>>> at a
>>> time. In the event of kexec(), staging is reverted and staged 
>>> entries will
>>> be carried over to the new kernel.
>>>
>>> User space is responsible to concatenate the staged IMA measurements 
>>> list
>>> portions following the temporal order in which the operations were 
>>> done,
>>> together with the current measurement list. Then, it can send the 
>>> collected
>>> data to the remote verifiers.
>>>
>>> Also introduce the ability of trimming N measurements entries from 
>>> the IMA
>>> measurements list, provided that user space has already read them. 
>>> Trimming
>>> combines staging and deletion in one operation.
>>>
>>> The benefit of these solutions is the ability to free precious kernel
>>> memory, in exchange of delegating user space to reconstruct the full
>>> measurement list from the chunks. No trust needs to be given to user 
>>> space,
>>> since the integrity of the measurement list is protected by the TPM.
>>>
>>> By default, staging/trimming the measurements list does not alter 
>>> the hash
>>> table. When staging/trimming are done, IMA is still able to detect
>>> collisions on the staged and later deleted measurement entries, by 
>>> keeping
>>> the entry digests (only template data are freed).
>>>
>>> However, since during the measurements list serialization only the SHA1
>>> digest is passed, and since there are no template data to 
>>> recalculate the
>>> other digests from, the hash table is currently not populated with 
>>> digests
>>> from staged/deleted entries after kexec().
>>>
>>> Introduce the new kernel option ima_flush_htable to decide whether 
>>> or not
>>> the digests of staged measurement entries are flushed from the hash 
>>> table.
>>>
>>> Then, introduce ascii_runtime_measurements_staged_<algo> and
>>> binary_runtime_measurement_staged_<algo> interfaces to 
>>> stage/trim/delete
>>> the measurements. Use 'echo A > <IMA interface>' and
>>> 'echo D > <IMA interface>' to respectively stage and delete the entire
>>> measurements list. Use 'echo N > <IMA interface>', with N between 1 and
>>> LONG_MAX, to stage the selected portion of the measurements list, and
>>> 'echo -N > <IMA interface>' to trim N measurements entries.
>>>
>>> The ima_measure_users counter (protected by the ima_measure_lock 
>>> mutex) has
>>> been introduced to protect access to the measurements list and the 
>>> staged
>>> part. The open method of all the measurement interfaces has been 
>>> extended
>>> to allow only one writer at a time or, in alternative, multiple 
>>> readers.
>>> The write permission is used to stage/trim/delete the measurements, the
>>> read permission to read them. Write requires also the CAP_SYS_ADMIN
>>> capability.
>>>
>>> Finally, introduce and maintain dedicate counters for the number of
>>> measurement entries and binary size, for the current measurements list
>>> (BINARY_SIZE), for the current measurements list plus staged entries
>>> (BINARY_SIZE_STAGED) useful for kexec() segment allocation, and for the
>>> entire measurement list without staging/trimming (BINARY_SIZE_FULL) 
>>> useful
>>> for the kexec-related critical data records.
>> Is the following possible race condition for staged list:
>>
>> Agent A: create staged list            Staged list A1
>>           new measurement added    Measurement list M1
>>           Two lists in kernel: A1 and M1
>>
>> Agent B: read staged list (A1) to do verification
>>           new measurement added    Measurement list M2
>>           Two lists in kernel: A1 and M2
>>
>> Agent A: verified and remove staged list (A1)
>>           new measurement added    Measurement list M3
>>           One list in kernel: M3
>>
>> Agent C: create staged list            Staged list C1
>>           new measurement added    Measurement list M4
>>           Two lists in kernel: C1 and M4
>>
>> Agent B: remove staged list (?), C1 removed ---this will cause problem
>>           new measurement added    Measurement list M5
>>           One list in kernel: M5
>>
>> Agent C: try to remove staged list(?)
>
> If you remember the patch, we added a read-write protection to the 
> measurements interfaces. As long as you keep the interface open for 
> write no one else can make change on the staging. Sure, you can drop 
> the write, and reopen for read, but then you should expect someone 
> else to operate on the interface.
>
> If you want to be sure no one else changes the staged measurements, 
> just keep the interface open for write, read the staged measurements 
> and delete them.
>
> Roberto
>
For different use cases, we can compare lock time for both staged method 
and trim N method:

t1: user space measurement list lock time
t2: kernel measurement list lock time

     Stage approach use case 1:
               1. read PCR quote
               2. read list
               3. attestation
               4. get N from attestation response
---          5. hold the list in the user space
  ^   ---    6. hold the measurement list
        ^     7. stage the list
t1    t2   8. trim N
        v     9. put the rest of stage back to measurement list
  v   ---    10. release the measurement list
---          11. release the list in the user space
  For this case, agent race condition may happen

   Stage approach use case 2:
               1. read PCR quote
---          2. hold the list in the user space
  ^           3. stage the list
               4. read list
               5. attestation
t1    ---  6. hold the measurement list
          ^   7. get N from attestation response
          t2  8. trim N
          v    9. put the rest of stage back to measurement list
  v    ---   10. release the measurement list
---          11. release the list in the user space
  For this case, no agent race condition happen

the following use case for trim N method

    Trim N approach use case:
              1. read total trimmed T
              2. read PCR quote
              3. read list,
              4. attestation
              5. get N from attestation response
---         6. hold the list in the user space
  ^   ---   7. hold the measurement list
        ^
t1   t2   8. trim with format T:N, update T
        v
  v   ---    9 . release the measurement list
---          10. release the list in the user space
     no agent race condition happen

For all use cases, I think for both t1 and t2, trim N method has better 
result.

Steven

>> Possible solution?
>>    Save the total number trimmed T or tag
>>
>>    Trim request sync this parameter to trim the staged list
>>
>> Regards,
>>
>> Steven
>>
>>> Note: This code derives from the Alt-IMA Huawei project, and is being
>>>        released under the dual license model (GPL-2.0 OR MIT).
>>>
>>> Link: https://github.com/linux-integrity/linux/issues/1
>>> Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
>>> --- 


^ permalink raw reply

* [GIT PULL] integrity: subsystem updates for v7.0
From: Mimi Zohar @ 2026-02-10 14:54 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-integrity, linux-kernel, Roberto Sassu

Hi Linus,

There are just two bug fixes: IMA's detecting scripts (bprm_creds_for_exec), 
calculating the EVM HMAC.

thanks,

Mimi


The following changes since commit f8f9c1f4d0c7a64600e2ca312dec824a0bc2f1da:

  Linux 6.19-rc3 (2025-12-28 13:24:26 -0800)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity.git/ tags/integrity-v7.0

for you to fetch changes up to 0496fc9cdc384f67be4413b1c6156eb64fccd5c4:

  evm: Use ordered xattrs list to calculate HMAC in evm_init_hmac() (2026-01-23 14:31:41 -0500)

----------------------------------------------------------------
integrity-v7.0

----------------------------------------------------------------
Chris J Arges (1):
      ima: Fix stack-out-of-bounds in is_bprm_creds_for_exec()

Roberto Sassu (1):
      evm: Use ordered xattrs list to calculate HMAC in evm_init_hmac()

 security/integrity/evm/evm_crypto.c   | 14 ++++++++++----
 security/integrity/ima/ima.h          |  6 ++++--
 security/integrity/ima/ima_appraise.c | 16 +++-------------
 security/integrity/ima/ima_main.c     | 22 +++++++++++++---------
 4 files changed, 30 insertions(+), 28 deletions(-)

^ 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