Linux Integrity Measurement development
 help / color / mirror / Atom feed
* Re: [PATCH v2 00/17] tee: Use bus callbacks instead of driver callbacks
From: Herbert Xu @ 2026-01-06  5:04 UTC (permalink / raw)
  To: Jens Wiklander
  Cc: Alexandre Belloni, Uwe Kleine-König, Jonathan Corbet,
	Sumit Garg, Olivia Mackall, Clément Léger,
	Ard Biesheuvel, Maxime Coquelin, Alexandre Torgue, Sumit Garg,
	Ilias Apalodimas, Jan Kiszka, Sudeep Holla, Christophe JAILLET,
	Rafał Miłecki, Michael Chan, Pavan Chebbi,
	James Bottomley, Jarkko Sakkinen, Mimi Zohar, David Howells,
	Paul Moore, James Morris, Serge E. Hallyn, Peter Huewe, op-tee,
	linux-kernel, linux-doc, linux-crypto, linux-rtc, linux-efi,
	linux-stm32, linux-arm-kernel, Cristian Marussi, arm-scmi,
	linux-mips, netdev, linux-integrity, keyrings,
	linux-security-module, Jason Gunthorpe
In-Reply-To: <CAHUa44HqRbCJTXsrTCm0G5iwtkQtq+Si=yOspCjpAn-N2uVSVg@mail.gmail.com>

On Mon, Jan 05, 2026 at 10:16:09AM +0100, Jens Wiklander wrote:
>
> Herbert, you seem happy with the following patches
> - hwrng: optee - Make use of module_tee_client_driver()
> - hwrng: optee - Make use of tee bus methods
> OK if I take them via my tree, or would you rather take them yourself?

Feel free to take them through your tree.

Thanks,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply

* Re: [PATCH v2 5/6] keys/trusted_keys: establish PKWM as a trusted source
From: Srish Srinivasan @ 2026-01-06  5:09 UTC (permalink / raw)
  To: Mimi Zohar, linux-integrity, keyrings, linuxppc-dev
  Cc: maddy, mpe, npiggin, christophe.leroy, James.Bottomley, jarkko,
	nayna, rnsastry, linux-kernel, linux-security-module
In-Reply-To: <14a30e37e0cf8ef373b63d3b905ec1a7d807118a.camel@linux.ibm.com>

Hi Mimi,
thanks for taking a look.

On 1/2/26 11:14 PM, Mimi Zohar wrote:
> On Wed, 2025-12-17 at 22:55 +0530, Srish Srinivasan wrote:
>> The wrapping key does not exist by default and is generated by the
>> hypervisor as a part of PKWM initialization. This key is then persisted by
>> the hypervisor and is used to wrap trusted keys. These are variable length
>> symmetric keys, which in the case of PowerVM Key Wrapping Module (PKWM) are
>> generated using the kernel RNG. PKWM can be used as a trust source through
>> the following example keyctl command
> -> commands:

Yes, I will fix this.

>
>> keyctl add trusted my_trusted_key "new 32" @u
>>
>> Use the wrap_flags command option to set the secure boot requirement for
>> the wrapping request through the following keyctl commands
>>
>> case1: no secure boot requirement. (default)
>> keyctl usage: keyctl add trusted my_trusted_key "new 32" @u
>> 	      OR
>> 	      keyctl add trusted my_trusted_key "new 32 wrap_flags=0x00" @u
>>
>> case2: secure boot required to in either audit or enforce mode. set bit 0
>> keyctl usage: keyctl add trusted my_trusted_key "new 32 wrap_flags=0x01" @u
>>
>> case3: secure boot required to be in enforce mode. set bit 1
>> keyctl usage: keyctl add trusted my_trusted_key "new 32 wrap_flags=0x02" @u
>>
>> NOTE:
>> -> Setting the secure boot requirement is NOT a must.
>> -> Only either of the secure boot requirement options should be set. Not
>> both.
>> -> All the other bits are requied to be not set.
> -> required

Noted.
Will fix this.

>
>> -> Set the kernel parameter trusted.source=pkwm to choose PKWM as the
>> backend for trusted keys implementation.
>> -> CONFIG_PSERIES_PLPKS must be enabled to build PKWM.
>>
>> Add PKWM, which is a combination of IBM PowerVM and Power LPAR Platform
>> KeyStore, as a new trust source for trusted keys.
>>
>> Signed-off-by: Srish Srinivasan <ssrish@linux.ibm.com>
> Thanks, Srish.  Other than fixing the typo and other suggestion above,
> Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>

Thanks for the review Mimi.
Will fix these typos and send out v3.

thanks,
Srish.

^ permalink raw reply

* Re: [PATCH v2 4/6] pseries/plpks: add HCALLs for PowerVM Key Wrapping Module
From: Srish Srinivasan @ 2026-01-06  5:06 UTC (permalink / raw)
  To: Mimi Zohar, linux-integrity, keyrings, linuxppc-dev
  Cc: maddy, mpe, npiggin, christophe.leroy, James.Bottomley, jarkko,
	nayna, rnsastry, linux-kernel, linux-security-module
In-Reply-To: <d0d9315f3d907bd6bb172278e2746eda3482b475.camel@linux.ibm.com>

Hi Mimi,
thanks for taking  a look.

On 1/2/26 10:55 PM, Mimi Zohar wrote:
> Hi Srish,
>
> On Wed, 2025-12-17 at 22:55 +0530, Srish Srinivasan wrote:
>> The hypervisor generated wrapping key is an AES-GCM-256 symmetric key which
>> is stored in a non-volatile, secure, and encrypted storage called the Power
>> LPAR Platform KeyStore. It has policy based protections that prevent it
>> from being read out or exposed to the user.
>>
>> Implement H_PKS_GEN_KEY, H_PKS_WRAP_OBJECT, and H_PKS_UNWRAP_OBJECT HCALLs
>> to enable using the PowerVM Key Wrapping Module (PKWM) as a new trust
>> source for trusted keys. Disallow H_PKS_READ_OBJECT, H_PKS_SIGNED_UPDATE,
>> and H_PKS_WRITE_OBJECT for objects with the 'wrapping key' policy set.
>> Capture the availability status for the H_PKS_WRAP_OBJECT interface.
>>
>> Signed-off-by: Srish Srinivasan <ssrish@linux.ibm.com>
> scripts/checkpatch.pl --codespell caught a couple of typos.  Please fix the
> typos here in in this patch and the one in v2 5/6.

Sure, I will fix them and send out v3.
Thanks for pointing these out.

>> ---
>>   Documentation/arch/powerpc/papr_hcalls.rst |  43 +++
>>   arch/powerpc/include/asm/plpks.h           |  10 +
>>   arch/powerpc/platforms/pseries/plpks.c     | 345 ++++++++++++++++++++-
>>   3 files changed, 396 insertions(+), 2 deletions(-)
>>
>> diff --git a/Documentation/arch/powerpc/papr_hcalls.rst b/Documentation/arch/powerpc/papr_hcalls.rst
>> index 805e1cb9bab9..14e39f095a1c 100644
>> --- a/Documentation/arch/powerpc/papr_hcalls.rst
>> +++ b/Documentation/arch/powerpc/papr_hcalls.rst
>> @@ -300,6 +300,49 @@ H_HTM supports setup, configuration, control and dumping of Hardware Trace
>>   Macro (HTM) function and its data. HTM buffer stores tracing data for functions
>>   like core instruction, core LLAT and nest.
>>   
>> +**H_PKS_GEN_KEY**
>> +
>> +| Input: authorization, objectlabel, objectlabellen, policy, out, outlen
>> +| Out: *Hypervisor Generated Key, or None when the wrapping key policy is set*
>> +| Return Value: *H_SUCCESS, H_Function, H_State, H_R_State, H_Parameter, H_P2,
>> +                H_P3, H_P4, H_P5, H_P6, H_Authority, H_Nomem, H_Busy, H_Resource,
>> +                H_Aborted*
>> +
>> +H_PKS_GEN_KEY is used to have the hypervisor generate a new random key.
>> +This key is stored as an object in the Power LPAR Platform KeyStore with
>> +the provided object label. With the wrapping key policy set the key is only
>> +visible to the hypervisor, while the key's label would still be visible to
>> +the user. Generation of wrapping keys is supported only for a key size of
>> +32 bytes.
>> +
>> +**H_PKS_WRAP_OBJECT**
>> +
>> +| Input: authorization, wrapkeylabel, wrapkeylabellen, objectwrapflags, in,
>> +|        inlen, out, outlen, continue-token
>> +| Out: *continue-token, byte size of wrapped object, wrapped object*
>> +| Return Value: *H_SUCCESS, H_Function, H_State, H_R_State, H_Parameter, H_P2,
>> +                H_P3, H_P4, H_P5, H_P6, H_P7, H_P8, H_P9, H_Authority, H_Invalid_Key,
>> +                H_NOT_FOUND, H_Busy, H_LongBusy, H_Aborted*
>> +
>> +H_PKS_WRAP_OBJECT is used to wrap an object using a wrapping key stored in the
>> +Power LPAR Platform KeyStore and return the wrapped object to the caller. The
>> +caller provides a label to a wrapping key with the 'wrapping key' policy set,
>> +which must have been previously created with H_PKS_GEN_KEY. The provided object
>> +is then encrypted with the wrapping key and additional metadata and the result
>> +is returned to the caller.
>> +
>> +
>> +**H_PKS_UNWRAP_OBJECT**
>> +
>> +| Input: authorization, objectwrapflags, in, inlen, out, outlen, continue-token
>> +| Out: *continue-token, byte size of unwrapped object, unwrapped object*
>> +| Return Value: *H_SUCCESS, H_Function, H_State, H_R_State, H_Parameter, H_P2,
>> +                H_P3, H_P4, H_P5, H_P6, H_P7, H_Authority, H_Unsupported, H_Bad_Data,
>> +                H_NOT_FOUND, H_Invalid_Key, H_Busy, H_LongBusy, H_Aborted*
>> +
>> +H_PKS_UNWRAP_OBJECT is used to unwrap an object that was previously warapped with
>> +H_PKS_WRAP_OBJECT.
>> +
>>   References
>>   ==========
>>   .. [1] "Power Architecture Platform Reference"
>> diff --git a/arch/powerpc/include/asm/plpks.h b/arch/powerpc/include/asm/plpks.h
>> index 8f034588fdf7..e87f90e40d4e 100644
>> --- a/arch/powerpc/include/asm/plpks.h
>> +++ b/arch/powerpc/include/asm/plpks.h
>> @@ -113,6 +113,16 @@ void plpks_early_init_devtree(void);
>>   int plpks_populate_fdt(void *fdt);
>>   
>>   int plpks_config_create_softlink(struct kobject *from);
>> +
>> +bool plpks_wrapping_is_supported(void);
>> +
>> +int plpks_gen_wrapping_key(void);
>> +
>> +int plpks_wrap_object(u8 **input_buf, u32 input_len, u16 wrap_flags,
>> +		      u8 **output_buf, u32 *output_len);
>> +
>> +int plpks_unwrap_object(u8 **input_buf, u32 input_len,
>> +			u8 **output_buf, u32 *output_len);
>>   #else // CONFIG_PSERIES_PLPKS
>>   static inline bool plpks_is_available(void) { return false; }
>>   static inline u16 plpks_get_passwordlen(void) { BUILD_BUG(); }
>> diff --git a/arch/powerpc/platforms/pseries/plpks.c b/arch/powerpc/platforms/pseries/plpks.c
>> index 4a08f51537c8..2ec04908b057 100644
>> --- a/arch/powerpc/platforms/pseries/plpks.c
>> +++ b/arch/powerpc/platforms/pseries/plpks.c
>> @@ -9,6 +9,32 @@
>>   
>>   #define pr_fmt(fmt) "plpks: " fmt
>>   
>> +#define PLPKS_WRAPKEY_COMPONENT	"PLPKSWR"
>> +#define PLPKS_WRAPKEY_NAME	"default-wrapping-key"
>> +
>> +/*
>> + * To 4K align the {input, output} buffers to the {UN}WRAP H_CALLs
>> + */
>> +#define PLPKS_WRAPPING_BUF_ALIGN	4096
>> +
>> +/*
>> + * To ensure the output buffer's length is at least 1024 bytes greater
>> + * than the input buffer's length during the WRAP H_CALL
>> + */
>> +#define PLPKS_WRAPPING_BUF_DIFF	1024
>> +
>> +#define PLPKS_WRAP_INTERFACE_BIT	3
>> +#define PLPKS_WRAPPING_KEY_LENGTH	32
>> +
>> +#define WRAPFLAG_BE_BIT_SET(be_bit) \
>> +	BIT_ULL(63 - (be_bit))
>> +
>> +#define WRAPFLAG_BE_GENMASK(be_bit_hi, be_bit_lo) \
>> +	GENMASK_ULL(63 - (be_bit_hi), 63 - (be_bit_lo))
>> +
>> +#define WRAPFLAG_BE_FIELD_PREP(be_bit_hi, be_bit_lo, val) \
>> +	FIELD_PREP(WRAPFLAG_BE_GENMASK(be_bit_hi, be_bit_lo), (val))
>> +
>>   #include <linux/delay.h>
>>   #include <linux/errno.h>
>>   #include <linux/io.h>
>> @@ -39,6 +65,7 @@ static u32 supportedpolicies;
>>   static u32 maxlargeobjectsize;
>>   static u64 signedupdatealgorithms;
>>   static u64 wrappingfeatures;
>> +static bool wrapsupport;
>>   
>>   struct plpks_auth {
>>   	u8 version;
>> @@ -283,6 +310,7 @@ static int _plpks_get_config(void)
>>   	maxlargeobjectsize = be32_to_cpu(config->maxlargeobjectsize);
>>   	signedupdatealgorithms = be64_to_cpu(config->signedupdatealgorithms);
>>   	wrappingfeatures = be64_to_cpu(config->wrappingfeatures);
>> +	wrapsupport = config->flags & PPC_BIT8(PLPKS_WRAP_INTERFACE_BIT);
>>   
>>   	// Validate that the numbers we get back match the requirements of the spec
>>   	if (maxpwsize < 32) {
>> @@ -614,6 +642,9 @@ int plpks_signed_update_var(struct plpks_var *var, u64 flags)
>>   	if (!(var->policy & PLPKS_SIGNEDUPDATE))
>>   		return -EINVAL;
>>   
>> +	if (var->policy & PLPKS_WRAPPINGKEY)
>> +		return -EINVAL;
>> +
>>   	// Signed updates need the component to be NULL.
>>   	if (var->component)
>>   		return -EINVAL;
>> @@ -696,6 +727,9 @@ int plpks_write_var(struct plpks_var var)
>>   	if (var.policy & PLPKS_SIGNEDUPDATE)
>>   		return -EINVAL;
>>   
>> +	if (var.policy & PLPKS_WRAPPINGKEY)
>> +		return -EINVAL;
>> +
>>   	auth = construct_auth(PLPKS_OS_OWNER);
>>   	if (IS_ERR(auth))
>>   		return PTR_ERR(auth);
>> @@ -790,6 +824,9 @@ static int plpks_read_var(u8 consumer, struct plpks_var *var)
>>   	if (var->namelen > PLPKS_MAX_NAME_SIZE)
>>   		return -EINVAL;
>>   
>> +	if (var->policy & PLPKS_WRAPPINGKEY)
>> +		return -EINVAL;
>> +
>>   	auth = construct_auth(consumer);
>>   	if (IS_ERR(auth))
>>   		return PTR_ERR(auth);
>> @@ -845,8 +882,312 @@ static int plpks_read_var(u8 consumer, struct plpks_var *var)
>>   }
>>   
>>   /**
>> - * plpks_read_os_var() - Fetch the data for the specified variable that is
>> - * owned by the OS consumer.
>> + * plpks_wrapping_is_supported() - Get the H_PKS_WRAP_OBJECT interface
>> + * availability status for the LPAR.
>> + *
>> + * Successful execution of the H_PKS_GET_CONFIG HCALL during initialization
>> + * sets bit 3 of the flags variable in the PLPKS config structure if the
>> + * H_PKS_WRAP_OBJECT interface is supported.
>> + *
>> + * Returns: true if the H_PKS_WRAP_OBJECT interface is supported, false if not.
>> + */
>> +bool plpks_wrapping_is_supported(void)
>> +{
>> +	return wrapsupport;
>> +}
>> +
>> +/**
>> + * plpks_gen_wrapping_key() - Generate a new random key with the 'wrapping key'
>> + * policy set.
>> + *
>> + * The H_PKS_GEN_KEY HCALL makes the hypervisor generate a new random key and
>> + * store the key in a PLPKS object with the provided object label. With the
>> + * 'wrapping key' policy set, only the label to the newly generated random key
>> + * would be visible to the user.
>> + *
>> + * Possible reasons for the returned errno values:
>> + *
>> + * -ENXIO	if PLPKS is not supported
>> + * -EIO		if PLPKS access is blocked due to the LPAR's state
>> + *		if PLPKS modification is blocked due to the LPAR's state
>> + *		if an error occurred while processing the request
>> + * -EINVAL	if invalid authorization parameter
>> + *		if invalid object label parameter
>> + *		if invalid object label len parameter
>> + *		if invalid or unsupported policy declaration
>> + *		if invalid output buffer parameter
>> + *		if invalid output buffer length parameter
>> + * -EPERM	if access is denied
>> + * -ENOMEM	if there is inadequate memory to perform this operation
>> + * -EBUSY	if unable to handle the request
>> + * -EEXIST	if the object label already exists
>> + *
>> + * Returns: On success 0 is returned, a negative errno if not.
>> + */
>> +int plpks_gen_wrapping_key(void)
>> +{
>> +	unsigned long retbuf[PLPAR_HCALL_BUFSIZE] = { 0 };
>> +	struct plpks_auth *auth;
>> +	struct label *label;
>> +	int rc = 0, pseries_status = 0;
>> +	struct plpks_var var = {
>> +		.name = PLPKS_WRAPKEY_NAME,
>> +		.namelen = strlen(var.name),
>> +		.policy = PLPKS_WRAPPINGKEY,
>> +		.os = PLPKS_VAR_LINUX,
>> +		.component = PLPKS_WRAPKEY_COMPONENT
>> +	};
>> +
>> +	auth = construct_auth(PLPKS_OS_OWNER);
>> +	if (IS_ERR(auth))
>> +		return PTR_ERR(auth);
>> +
>> +	label = construct_label(var.component, var.os, var.name, var.namelen);
>> +	if (IS_ERR(label)) {
>> +		rc = PTR_ERR(label);
>> +		goto out;
>> +	}
>> +
>> +	rc = plpar_hcall(H_PKS_GEN_KEY, retbuf,
>> +			 virt_to_phys(auth), virt_to_phys(label),
>> +			 label->size, var.policy,
>> +			 NULL, PLPKS_WRAPPING_KEY_LENGTH);
>> +
>> +	if (!rc)
>> +		rc = plpks_confirm_object_flushed(label, auth);
>> +
>> +	pseries_status = rc;
>> +	rc = pseries_status_to_err(rc);
>> +
>> +	if (rc && rc != -EEXIST) {
>> +		pr_err("H_PKS_GEN_KEY failed.");
>> +		pr_err("pseries_status = %d, error code = %d", pseries_status,
>> +		       rc);
>> +	} else {
>> +		rc = 0;
>> +	}
>> +
>> +	kfree(label);
>> +out:
>> +	kfree(auth);
>> +	return rc;
>> +}
>> +EXPORT_SYMBOL_GPL(plpks_gen_wrapping_key);
>> +
>> +/**
>> + * plpks_wrap_object() - Wrap an object using the default wrapping key stored in
>> + * the PLPKS.
>> + * @input_buf: buffer containing the data to be wrapped
>> + * @input_len: length of the input buffer
>> + * @wrap_flags: object wrapping flags
>> + * @output_buf: buffer to store the wrapped data
>> + * @output_len: length of the output buffer
>> + *
>> + * The H_PKS_WRAP_OBJECT HCALL wraps an object using a wrapping key stored in
>> + * the PLPKS and returns the wrapped object to the caller. The caller provides a
>> + * label to the wrapping key with the 'wrapping key' policy set that must have
>> + * been previously created with the H_PKS_GEN_KEY HCALL. The provided object is
>> + * then encrypted with the wrapping key and additional metadata and the result
>> + * is returned to the user. The metadata includes the wrapping algorithm and the
>> + * wrapping key name so those parameters are not required during unwrap.
>> + *
>> + * Possible reasons for the returned errno values:
>> + *
>> + * -ENXIO	if PLPKS is not supported
>> + * -EIO		if PLPKS access is blocked due to the LPAR's state
>> + *		if PLPKS modification is blocked due to the LPAR's state
>> + *		if an error occurred while processing the request
>> + * -EINVAL	if invalid authorization parameter
>> + *		if invalid wraping key label parameter
> -> wrapping

Noted.
Will fix this.

>
>> + *		if invalid wrapping key label length parameter
>> + *		if invalid or unsupported object wrapping flags
>> + *		if invalid inut buffer parameter
> -> input

Noted.
Will fix this.

>> + *		if invalid input buffer length parameter
>> + *		if invalid output buffer parameter
>> + *		if invalid output buffer length parameter
>> + *		if invalid continue token parameter
>> + *		if the wrapping key is not compatible with the wrapping
>> + *		algorithm
>> + * -EPERM	if access is denied
>> + * -ENOENT	if the requested wrapping key was not found
>> + * -EBUSY	if unable to handle the request or long running operation
>> + *		initiated, retry later.
>> + *
>> + * Returns: On success 0 is returned, a negative errno if not.
>> + */
>> +int plpks_wrap_object(u8 **input_buf, u32 input_len, u16 wrap_flags,
>> +		      u8 **output_buf, u32 *output_len)
>> +{
>> +	unsigned long retbuf[PLPAR_HCALL9_BUFSIZE] = { 0 };
>> +	struct plpks_auth *auth;
>> +	struct label *label;
>> +	u64 continuetoken = 0;
>> +	u64 objwrapflags = 0;
>> +	int rc = 0, pseries_status = 0;
>> +	bool sb_audit_or_enforce_bit = wrap_flags & BIT(0);
>> +	bool sb_enforce_bit = wrap_flags & BIT(1);
>> +	struct plpks_var var = {
>> +		.name = PLPKS_WRAPKEY_NAME,
>> +		.namelen = strlen(var.name),
>> +		.os = PLPKS_VAR_LINUX,
>> +		.component = PLPKS_WRAPKEY_COMPONENT
>> +	};
>> +
>> +	auth = construct_auth(PLPKS_OS_OWNER);
>> +	if (IS_ERR(auth))
>> +		return PTR_ERR(auth);
>> +
>> +	label = construct_label(var.component, var.os, var.name, var.namelen);
>> +	if (IS_ERR(label)) {
>> +		rc = PTR_ERR(label);
>> +		goto out;
>> +	}
>> +
>> +	/* Set the consumer password requirement bit. A must have. */
>> +	objwrapflags |= WRAPFLAG_BE_BIT_SET(3);
>> +
>> +	/* Set the wrapping algorithm bit. Just one algorithm option for now */
>> +	objwrapflags |= WRAPFLAG_BE_FIELD_PREP(60, 63, 0x1);
>> +
>> +	if (sb_audit_or_enforce_bit & sb_enforce_bit) {
>> +		pr_err("Cannot set both audit/enforce and enforce bits.");
>> +		rc = -EINVAL;
>> +		goto out_free_label;
>> +	} else if (sb_audit_or_enforce_bit) {
>> +		objwrapflags |= WRAPFLAG_BE_BIT_SET(1);
>> +	} else if (sb_enforce_bit) {
>> +		objwrapflags |= WRAPFLAG_BE_BIT_SET(2);
>> +	}
>> +
>> +	*output_len = input_len + PLPKS_WRAPPING_BUF_DIFF;
>> +
>> +	*output_buf = kzalloc(ALIGN(*output_len, PLPKS_WRAPPING_BUF_ALIGN),
>> +			      GFP_KERNEL);
>> +	if (!(*output_buf)) {
>> +		pr_err("Output buffer allocation failed. Returning -ENOMEM.");
>> +		rc = -ENOMEM;
>> +		goto out_free_label;
>> +	}
>> +
>> +	do {
>> +		rc = plpar_hcall9(H_PKS_WRAP_OBJECT, retbuf,
>> +				  virt_to_phys(auth), virt_to_phys(label),
>> +				  label->size, objwrapflags,
>> +				  virt_to_phys(*input_buf), input_len,
>> +				  virt_to_phys(*output_buf), *output_len,
>> +				  continuetoken);
>> +
>> +		continuetoken = retbuf[0];
>> +		pseries_status = rc;
>> +		rc = pseries_status_to_err(rc);
>> +	} while (rc == -EBUSY);
>> +
>> +	if (rc) {
>> +		pr_err("H_PKS_WRAP_OBJECT failed.");
>> +		pr_err("pseries_status = %d, return code = %d", pseries_status,
>> +		       rc);
>> +		kfree(*output_buf);
>> +		*output_buf = NULL;
>> +	} else {
>> +		*output_len = retbuf[1];
>> +	}
>> +
>> +out_free_label:
>> +	kfree(label);
>> +out:
>> +	kfree(auth);
>> +	return rc;
>> +}
>> +EXPORT_SYMBOL_GPL(plpks_wrap_object);
>> +
>> +/**
>> + * plpks_unwrap_object() - Unwrap an object using the default wrapping key
>> + * stored in the PLPKS.
>> + * @input_buf: buffer containing the data to be unwrapped
>> + * @input_len: length of the input buffer
>> + * @output_buf: buffer to store the unwrapped data
>> + * @output_len: length of the output buffer
>> + *
>> + * The H_PKS_UNWRAP_OBJECT HCALL unwraps an object that was previously wrapped
>> + * using the H_PKS_WRAP_OBJECT HCALL.
>> + *
>> + * Possible reasons for the returned errno values:
>> + *
>> + * -ENXIO	if PLPKS is not supported
>> + * -EIO		if PLPKS access is blocked due to the LPAR's state
>> + *		if PLPKS modification is blocked due to the LPAR's state
>> + *		if an error occurred while processing the request
>> + * -EINVAL	if invalid authorization parameter
>> + *		if invalid or unsupported object unwrapping flags
>> + *		if invalid inut buffer parameter
> -> input

Noted.
Will fix this.

>
>> + *		if invalid input buffer length parameter
>> + *		if invalid output buffer parameter
>> + *		if invalid output buffer length parameter
>> + *		if invalid continue token parameter
>> + *		if the wrapping key is not compatible with the wrapping
>> + *		algorithm
>> + *		if the wrapped object's format is not supported
>> + *		if the wrapped object is invalid
>> + * -EPERM	if access is denied
>> + * -ENOENT	if the wrapping key for the provided object was not found
>> + * -EBUSY	if unable to handle the request or long running operation
>> + *		initiated, retry later.
>> + *
>> + * Returns: On success 0 is returned, a negative errno if not.
>> + */
>> +int plpks_unwrap_object(u8 **input_buf, u32 input_len, u8 **output_buf,
>> +			u32 *output_len)
>> +{
>> +	unsigned long retbuf[PLPAR_HCALL9_BUFSIZE] = { 0 };
>> +	struct plpks_auth *auth;
>> +	u64 continuetoken = 0;
>> +	u64 objwrapflags = 0;
>> +	int rc = 0, pseries_status = 0;
>> +
>> +	auth = construct_auth(PLPKS_OS_OWNER);
>> +	if (IS_ERR(auth))
>> +		return PTR_ERR(auth);
>> +
>> +	*output_len = input_len - PLPKS_WRAPPING_BUF_DIFF;
>> +	*output_buf = kzalloc(ALIGN(*output_len, PLPKS_WRAPPING_BUF_ALIGN),
>> +			      GFP_KERNEL);
>> +	if (!(*output_buf)) {
>> +		pr_err("Output buffer allocation failed. Returning -ENOMEM.");
>> +		rc = -ENOMEM;
>> +		goto out;
>> +	}
>> +
>> +	do {
>> +		rc = plpar_hcall9(H_PKS_UNWRAP_OBJECT, retbuf,
>> +				  virt_to_phys(auth), objwrapflags,
>> +				  virt_to_phys(*input_buf), input_len,
>> +				  virt_to_phys(*output_buf), *output_len,
>> +				  continuetoken);
>> +
>> +		continuetoken = retbuf[0];
>> +		pseries_status = rc;
>> +		rc = pseries_status_to_err(rc);
>> +	} while (rc == -EBUSY);
>> +
>> +	if (rc) {
>> +		pr_err("H_PKS_UNWRAP_OBJECT failed.");
>> +		pr_err("pseries_status = %d, return code = %d", pseries_status,
>> +		       rc);
>> +		kfree(*output_buf);
>> +		*output_buf = NULL;
>> +	} else {
>> +		*output_len = retbuf[1];
>> +	}
>> +
>> +out:
>> +	kfree(auth);
>> +	return rc;
>> +}
>> +EXPORT_SYMBOL_GPL(plpks_unwrap_object);
>> +
>> +/**
>> + * plpks_read_os_var() - Fetch the data for the specified variable that is owned
>> + * by the OS consumer.
>>    * @var: variable to be read from the PLPKS
>>    *
>>    * The consumer or the owner of the object is the os kernel. The

Thanks,
Srish.

^ permalink raw reply

* [PATCH v3 3/3] ima: add new critical data record to measure log trimming
From: steven chen @ 2026-01-06  2:07 UTC (permalink / raw)
  To: linux-integrity
  Cc: zohar, roberto.sassu, dmitry.kasatkin, eric.snowberg, corbet,
	serge, paul, jmorris, linux-security-module, anirudhve, chenste,
	gregorylumen, nramas, sushring, linux-doc
In-Reply-To: <20260106020713.3994-1-chenste@linux.microsoft.com>

Add a new critical data record to measure the trimming event when
ima event records are deleted for this time.

If all IMA event logs are saved in the userspace, use this type of
logs to get total numbers of records deleted from beginning.

Signed-off-by: steven chen <chenste@linux.microsoft.com>
---
 security/integrity/ima/ima_fs.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index 67ff0cfc3d3f..6d3d34d07b2b 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -364,6 +364,22 @@ static const struct file_operations ima_ascii_measurements_ops = {
 	.release = ima_measurements_release,
 };
 
+static void ima_measure_trim_event(const long number_logs)
+{
+	char ima_log_trim_event[IMA_LOG_TRIM_EVENT_LEN];
+	struct timespec64 ts;
+	u64 time_ns;
+	int n;
+
+	ktime_get_real_ts64(&ts);
+	time_ns = (u64)ts.tv_sec * 1000000000ULL + ts.tv_nsec;
+	n = scnprintf(ima_log_trim_event, IMA_LOG_TRIM_EVENT_LEN,
+		      "time= %llu; number= %lu;", time_ns, number_logs);
+
+	ima_measure_critical_data("ima_log_trim", "trim ima event logs",
+				  ima_log_trim_event, n, false, NULL, 0);
+}
+
 static int ima_log_trim_open(struct inode *inode, struct file *file)
 {
 	bool write = !!(file->f_mode & FMODE_WRITE);
@@ -407,6 +423,8 @@ static ssize_t ima_log_trim_write(struct file *file,
 		goto out;
 
 	trimcount = ret;
+	if (trimcount > 0)
+		ima_measure_trim_event(trimcount);
 
 	ret = datalen;
 out:
-- 
2.43.0


^ permalink raw reply related

* [PATCH v3 2/3] ima: trim N IMA event log records
From: steven chen @ 2026-01-06  2:07 UTC (permalink / raw)
  To: linux-integrity
  Cc: zohar, roberto.sassu, dmitry.kasatkin, eric.snowberg, corbet,
	serge, paul, jmorris, linux-security-module, anirudhve, chenste,
	gregorylumen, nramas, sushring, linux-doc
In-Reply-To: <20260106020713.3994-1-chenste@linux.microsoft.com>

Trim N entries of the IMA event logs. Clean the hash table if
ima_flush_htable is set.

Provide a userspace interface ima_trim_log that can be used to input
number N to let kernel to trim N entries of IMA event logs. When read
this interface, it returns number of entries trimmed last time.

Signed-off-by: steven chen <chenste@linux.microsoft.com>
---
 .../admin-guide/kernel-parameters.txt         |   4 +
 security/integrity/ima/ima.h                  |   2 +
 security/integrity/ima/ima_fs.c               | 164 +++++++++++++++++-
 security/integrity/ima/ima_queue.c            |  85 +++++++++
 4 files changed, 251 insertions(+), 4 deletions(-)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index e92c0056e4e0..cd1a1d0bf0e2 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -2197,6 +2197,10 @@
 			Use the canonical format for the binary runtime
 			measurements, instead of host native format.
 
+	ima_flush_htable  [IMA]
+			Flush the measurement list hash table when trim all
+			or a part of it for deletion.
+
 	ima_hash=	[IMA]
 			Format: { md5 | sha1 | rmd160 | sha256 | sha384
 				   | sha512 | ... }
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index e3d71d8d56e3..2102c523dca0 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -246,8 +246,10 @@ void ima_post_key_create_or_update(struct key *keyring, struct key *key,
 
 #ifdef CONFIG_IMA_KEXEC
 void ima_measure_kexec_event(const char *event_name);
+long ima_delete_event_log(long req_val);
 #else
 static inline void ima_measure_kexec_event(const char *event_name) {}
+static inline long ima_delete_event_log(long req_val) { return 0; }
 #endif
 
 /*
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index 87045b09f120..67ff0cfc3d3f 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -21,6 +21,9 @@
 #include <linux/rcupdate.h>
 #include <linux/parser.h>
 #include <linux/vmalloc.h>
+#include <linux/ktime.h>
+#include <linux/timekeeping.h>
+#include <linux/ima.h>
 
 #include "ima.h"
 
@@ -38,6 +41,17 @@ __setup("ima_canonical_fmt", default_canonical_fmt_setup);
 
 static int valid_policy = 1;
 
+#define IMA_LOG_TRIM_REQ_LENGTH 11
+#define IMA_LOG_TRIM_EVENT_LEN 256
+
+static long trimcount;
+/* mutex protects atomicity of trimming measurement list
+ * and also protects atomicity the measurement list read
+ * write operation.
+ */
+static DEFINE_MUTEX(ima_measure_lock);
+static long ima_measure_users;
+
 static ssize_t ima_show_htable_value(char __user *buf, size_t count,
 				     loff_t *ppos, atomic_long_t *val)
 {
@@ -202,16 +216,77 @@ static const struct seq_operations ima_measurments_seqops = {
 	.show = ima_measurements_show
 };
 
+/*
+ * _ima_measurements_open - open the IMA measurements file
+ * @inode: inode of the file being opened
+ * @file: file being opened
+ * @seq_ops: sequence operations for the file
+ *
+ * Returns 0 on success, or negative error code.
+ * Implements mutual exclusion between readers and writer
+ * of the measurements file. Multiple readers are allowed,
+ * but writer get exclusive access only no other readers/writers.
+ * Readers is not allowed when there is a writer.
+ */
+static int _ima_measurements_open(struct inode *inode, struct file *file,
+				  const struct seq_operations *seq_ops)
+{
+	bool write = !!(file->f_mode & FMODE_WRITE);
+	int ret;
+
+	if (write && !capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	mutex_lock(&ima_measure_lock);
+	if ((write && ima_measure_users != 0) ||
+	    (!write && ima_measure_users < 0)) {
+		mutex_unlock(&ima_measure_lock);
+		return -EBUSY;
+	}
+
+	ret = seq_open(file, seq_ops);
+	if (ret < 0) {
+		mutex_unlock(&ima_measure_lock);
+		return ret;
+	}
+
+	if (write)
+		ima_measure_users--;
+	else
+		ima_measure_users++;
+
+	mutex_unlock(&ima_measure_lock);
+	return ret;
+}
+
 static int ima_measurements_open(struct inode *inode, struct file *file)
 {
-	return seq_open(file, &ima_measurments_seqops);
+	return _ima_measurements_open(inode, file, &ima_measurments_seqops);
+}
+
+static int ima_measurements_release(struct inode *inode, struct file *file)
+{
+	bool write = !!(file->f_mode & FMODE_WRITE);
+	int ret;
+
+	mutex_lock(&ima_measure_lock);
+	ret = seq_release(inode, file);
+	if (!ret) {
+		if (write)
+			ima_measure_users++;
+		else
+			ima_measure_users--;
+	}
+
+	mutex_unlock(&ima_measure_lock);
+	return ret;
 }
 
 static const struct file_operations ima_measurements_ops = {
 	.open = ima_measurements_open,
 	.read = seq_read,
 	.llseek = seq_lseek,
-	.release = seq_release,
+	.release = ima_measurements_release,
 };
 
 void ima_print_digest(struct seq_file *m, u8 *digest, u32 size)
@@ -279,14 +354,83 @@ static const struct seq_operations ima_ascii_measurements_seqops = {
 
 static int ima_ascii_measurements_open(struct inode *inode, struct file *file)
 {
-	return seq_open(file, &ima_ascii_measurements_seqops);
+	return _ima_measurements_open(inode, file, &ima_ascii_measurements_seqops);
 }
 
 static const struct file_operations ima_ascii_measurements_ops = {
 	.open = ima_ascii_measurements_open,
 	.read = seq_read,
 	.llseek = seq_lseek,
-	.release = seq_release,
+	.release = ima_measurements_release,
+};
+
+static int ima_log_trim_open(struct inode *inode, struct file *file)
+{
+	bool write = !!(file->f_mode & FMODE_WRITE);
+
+	if (!write && capable(CAP_SYS_ADMIN))
+		return 0;
+	else if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	return _ima_measurements_open(inode, file, &ima_measurments_seqops);
+}
+
+static ssize_t ima_log_trim_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
+{
+	char tmpbuf[IMA_LOG_TRIM_REQ_LENGTH];	/* greater than largest 'long' string value */
+	ssize_t len;
+
+	len = scnprintf(tmpbuf, sizeof(tmpbuf), "%li\n", trimcount);
+	return simple_read_from_buffer(buf, size, ppos, tmpbuf, len);
+}
+
+static ssize_t ima_log_trim_write(struct file *file,
+				  const char __user *buf, size_t datalen, loff_t *ppos)
+{
+	long count, n, ret;
+
+	if (*ppos > 0 || datalen > IMA_LOG_TRIM_REQ_LENGTH || datalen < 2) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	n = (int)datalen;
+
+	ret = kstrtol_from_user(buf, n, 10, &count);
+	if (ret < 0)
+		goto out;
+
+	ret = ima_delete_event_log(count);
+
+	if (ret < 0)
+		goto out;
+
+	trimcount = ret;
+
+	ret = datalen;
+out:
+	return ret;
+}
+
+static int ima_log_trim_release(struct inode *inode, struct file *file)
+{
+	bool write = !!(file->f_mode & FMODE_WRITE);
+
+	if (!write && capable(CAP_SYS_ADMIN))
+		return 0;
+	else if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	return ima_measurements_release(inode, file);
+}
+
+static const struct file_operations ima_log_trim_ops = {
+	.open = ima_log_trim_open,
+	.read = ima_log_trim_read,
+	.write = ima_log_trim_write,
+	.llseek = generic_file_llseek,
+	.release = ima_log_trim_release
 };
 
 static ssize_t ima_read_policy(char *path)
@@ -528,6 +672,18 @@ int __init ima_fs_init(void)
 		goto out;
 	}
 
+	if (IS_ENABLED(CONFIG_IMA_LOG_TRIMMING)) {
+		dentry = securityfs_create_file("ima_trim_log",
+						S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP,
+						ima_dir, NULL, &ima_log_trim_ops);
+		if (IS_ERR(dentry)) {
+			ret = PTR_ERR(dentry);
+			goto out;
+		}
+	}
+
+	trimcount = 0;
+
 	dentry = securityfs_create_file("runtime_measurements_count",
 				   S_IRUSR | S_IRGRP, ima_dir, NULL,
 				   &ima_measurements_count_ops);
diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c
index 590637e81ad1..33bb5414b8cc 100644
--- a/security/integrity/ima/ima_queue.c
+++ b/security/integrity/ima/ima_queue.c
@@ -22,6 +22,14 @@
 
 #define AUDIT_CAUSE_LEN_MAX 32
 
+bool ima_flush_htable;
+static int __init ima_flush_htable_setup(char *str)
+{
+	ima_flush_htable = true;
+	return 1;
+}
+__setup("ima_flush_htable", ima_flush_htable_setup);
+
 /* pre-allocated array of tpm_digest structures to extend a PCR */
 static struct tpm_digest *digests;
 
@@ -220,6 +228,83 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation,
 	return result;
 }
 
+/**
+ * ima_delete_event_log - delete IMA event entry
+ * @num_records: number of records to delete
+ *
+ * delete num_records entries off the measurement list.
+ * Returns the number of entries deleted, or negative error code.
+ */
+long ima_delete_event_log(long num_records)
+{
+	long len, cur = num_records, tmp_len = 0;
+	struct ima_queue_entry *qe, *qe_tmp;
+	LIST_HEAD(ima_measurements_staged);
+	struct list_head *list_ptr;
+
+	if (num_records <= 0)
+		return num_records;
+
+	if (!IS_ENABLED(CONFIG_IMA_LOG_TRIMMING))
+		return -EOPNOTSUPP;
+
+	mutex_lock(&ima_extend_list_mutex);
+	len = atomic_long_read(&ima_htable.len);
+
+	if (num_records > len) {
+		mutex_unlock(&ima_extend_list_mutex);
+		return -ENOENT;
+	}
+
+	list_ptr = &ima_measurements;
+
+	if (cur == len) {
+		list_replace(&ima_measurements, &ima_measurements_staged);
+		INIT_LIST_HEAD(&ima_measurements);
+		atomic_long_set(&ima_htable.len, 0);
+		list_ptr = &ima_measurements_staged;
+		if (IS_ENABLED(CONFIG_IMA_KEXEC))
+			binary_runtime_size = 0;
+	}
+
+	list_for_each_entry(qe, list_ptr, later) {
+		if (num_records > 0) {
+			if (!IS_ENABLED(CONFIG_IMA_DISABLE_HTABLE) && ima_flush_htable)
+				hlist_del_rcu(&qe->hnext);
+
+			--num_records;
+			if (num_records == 0)
+				qe_tmp = qe;
+			continue;
+		}
+		if (len != cur && IS_ENABLED(CONFIG_IMA_KEXEC))
+			tmp_len += get_binary_runtime_size(qe->entry);
+		else
+			break;
+	}
+
+	if (len != cur) {
+		__list_cut_position(&ima_measurements_staged, &ima_measurements,
+				    &qe_tmp->later);
+		atomic_long_sub(cur, &ima_htable.len);
+		if (IS_ENABLED(CONFIG_IMA_KEXEC))
+			binary_runtime_size = tmp_len;
+	}
+
+	mutex_unlock(&ima_extend_list_mutex);
+
+	if (ima_flush_htable)
+		synchronize_rcu();
+
+	list_for_each_entry_safe(qe, qe_tmp, &ima_measurements_staged, later) {
+		ima_free_template_entry(qe->entry);
+		list_del(&qe->later);
+		kfree(qe);
+	}
+
+	return cur;
+}
+
 int ima_restore_measurement_entry(struct ima_template_entry *entry)
 {
 	int result = 0;
-- 
2.43.0


^ permalink raw reply related

* [PATCH v3 1/3] ima: make ima event log trimming configurable
From: steven chen @ 2026-01-06  2:07 UTC (permalink / raw)
  To: linux-integrity
  Cc: zohar, roberto.sassu, dmitry.kasatkin, eric.snowberg, corbet,
	serge, paul, jmorris, linux-security-module, anirudhve, chenste,
	gregorylumen, nramas, sushring, linux-doc
In-Reply-To: <20260106020713.3994-1-chenste@linux.microsoft.com>

Make ima event log trimming function configurable.

Signed-off-by: steven chen <chenste@linux.microsoft.com>
---
 security/integrity/ima/Kconfig | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index 976e75f9b9ba..322964ae4772 100644
--- a/security/integrity/ima/Kconfig
+++ b/security/integrity/ima/Kconfig
@@ -332,4 +332,16 @@ config IMA_KEXEC_EXTRA_MEMORY_KB
 	  If set to the default value of 0, an extra half page of memory for those
 	  additional measurements will be allocated.
 
+config IMA_LOG_TRIMMING
+	bool "IMA Event Log Trimming"
+	default n
+	help
+	  Say Y here if you want support for IMA Event Log Trimming.
+		This creates the file /sys/kernel/security/integrity/ima/ima_trim_log.
+		Userspace
+		  - writes to this file to trigger IMA event log trimming
+		  - reads this file to get number of entried trimming last time
+
+	  If unsure, say N.
+
 endif
-- 
2.43.0


^ permalink raw reply related

* [PATCH v3 0/1] Trim N entries of IMA event logs
From: steven chen @ 2026-01-06  2:07 UTC (permalink / raw)
  To: linux-integrity
  Cc: zohar, roberto.sassu, dmitry.kasatkin, eric.snowberg, corbet,
	serge, paul, jmorris, linux-security-module, anirudhve, chenste,
	gregorylumen, nramas, sushring, linux-doc

The Integrity Measurement Architecture (IMA) maintains a measurement list
—a record of system events used for integrity verification. The IMA event
logs are the entries within this measurement list, each representing a
specific event or measurement that contributes to the system's integrity
assessment.

This update introduces the ability to trim, or remove, N entries from the
current measurement list. Trimming involves deleting N entries from the
list and clearing the corresponding entries from the hash table. This
action atomically truncates the measurement list, ensuring that no new
measurements can be added until the operation is complete. Importantly,
only one writer can initiate this trimming process at a time, maintaining
consistency and preventing race conditions.

A userspace interface, ima_trim_log, has been provided for this purpose.
By writing a number N to this interface, userspace can request the kernel
to trim N entries from the IMA event logs. When this interface is read,
it returns the number of entries trimmed during the last operation. This
value is not preserved across kexec soft reboots, as it is not considered
important information.

To maintain a complete record, userspace is responsible for concatenating
and storing the logs before initiating trimming. Userspace can then send
the collected data to remote verifiers for validation. After receiving
confirmation from the remote verifiers, userspace may instruct the kernel
to proceed with trimming the IMA event logs accordingly.

The primary benefit of this solution is the ability to free valuable
kernel memory by delegating the task of reconstructing the full
measurement list from log chunks to userspace. Trust is not required in
userspace for the integrity of the measurement list, as its integrity is
cryptographically protected by the Trusted Platform Module (TPM).

Multiple readers are allowed to access the ima_trim_log interface
concurrently, while only one writer can trigger log trimming at any time.
During trimming, readers do not see the list and cannot access it while
deletion is in progress, ensuring atomicity.

Introduce the new kernel option ima_flush_htable to decide whether or not
the digests of measurement entries are flushed from the hash table (from
reference [2]).

The ima_measure_users counter (protected by the ima_measure_lock mutex) has
been introduced to protect access to the measurement list 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/delete the measurements, the read permission
to read them. Write requires also the CAP_SYS_ADMIN capability (from
reference [2]).

New IMA log trim event is added when trimming finish. For kernel soft
reboot case, there is no need to transfer extra data from old kernel to
new kernel after trimming.

The time required for trimming is minimal, and IMA event logs are briefly
on hold during this process, preventing read or add operations. This short
interruption has no impact on the overall functionality of IMA.

A new critical data record "ima_log_trim" is added in this solution. This
record logs the trim event with number of entries deleted and time when
this happened. User space can get the total number of entries trimmed by
checking all "ima_log_trim" event in the measurement list.

The following are how user space to use the measurement list and
ima_log_trim interface
1. check any read/write measurement list/ima_log_trim operation, if any,
wait until released
2. when no app read/write measurement list/ima_log_trim operation, set
read/write flag
3. get the PCR quote first
4. read the measurement list file, close the file, send for verification
with other IMA information to verifier
5. wait for response from verifier, until get the good response from
verifier with number N that matched the PCR quote got in step 3
6. get the number N from the above message 
7. write the N to the ima_log_trim interface
8. save total N entries of the measurement list read in step 4 to userspace
9. release read/write flag

References:
-----------
[1] [PATCH 0/1] Trim N entries of IMA event logs
https://lore.kernel.org/linux-integrity/20251202232857.8211-1-chenste@linux.microsoft.com/T/#t

[2] [RFC][PATCH] ima: Add support for staging measurements for deletion
https://lore.kernel.org/linux-integrity/207fd6d7-53c-57bb-36d8-13a0902052d1@linux.microsoft.com/T/#t

[3] PATCH v2 0/1] Trim N entries of IMA event logs
https://lore.kernel.org/linux-integrity/20251210235314.3341-1-chenste@linux.microsoft.com/T/#t

Change Log v3:
 - Incorporated feedback from Mimi on v2 series.
 - split patch into multiple patches
 - lock time performance improvement
 - Updated patch descriptions as necessary.

Change Log v2:
 - Incorporated feedback from the Roberto on v1 series.
 - Adapted code from Roberto's RFC [Reference 2]
 - Add IMA log trim event log to record trim event
 - Updated patch descriptions as necessary.

steven chen (3):
  ima: make ima event log trimming configurable
  ima: trim N IMA event log records
  ima: add new critical data record to measure log trimming

 .../admin-guide/kernel-parameters.txt         |   4 +
 security/integrity/ima/Kconfig                |  12 ++
 security/integrity/ima/ima.h                  |   2 +
 security/integrity/ima/ima_fs.c               | 182 +++++++++++++++++-
 security/integrity/ima/ima_queue.c            |  85 ++++++++
 5 files changed, 281 insertions(+), 4 deletions(-)

-- 
2.43.0


^ permalink raw reply

* Re: [PATCH RFC] ima: Fallback to a ctime guard without i_version updates
From: Mimi Zohar @ 2026-01-06  0:45 UTC (permalink / raw)
  To: Frederick Lawler
  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: <aVxEv3k9YeG1or8z@CMGLRV3>

On Mon, 2026-01-05 at 17:09 -0600, Frederick Lawler wrote:
> Hi Mimi,
> 
> On Mon, Jan 05, 2026 at 05:15:15PM -0500, Mimi Zohar wrote:
> > On Mon, 2025-12-29 at 11:52 -0600, Frederick Lawler wrote:
> > > Since commit 1cf7e834a6fb ("xfs: switch to multigrain timestamps"), IMA
> > > is no longer able to correctly track inode.i_version due to the struct
> > > kstat.change_cookie no longer containing an updated i_version.
> > > 
> > > Introduce a fallback mechanism for IMA that instead tracks a
> > > integrity_ctime_guard() in absence of or outdated i_version
> > > for stacked file systems.
> > 
> > Thanks, Frederick.
> > 
> > Instead of using the new function name integrity_ctime_guard() to describe the
> > change, please describe the change in words.  Perhaps something like: rely on
> > the inode's ctime to detect a file data or metadata change.
> > 
> 
> Sure thing, I'll change for the v1.
> 
> > The purpose of generating a ctime guard value, as opposed to using the tv_sec
> > and tv_nsec, I assume is to minimize the amount of memory being saved in the
> > iint.
> 
> This was Jeff's suggestion. It does serve the purpose on saving
> some memory, but also has some value in the event nsec or sec is zero'd.
> It just needs to be different enough from the last cache'd evaluation.

All of this needs to be described in the patch description and, probably, a
comment before the function.
> 
> > 
> > > 
> > > EVM is left alone since it mostly cares about the backing inode.
> > > 
> > > Link: https://lore.kernel.org/all/aTspr4_h9IU4EyrR@CMGLRV3
> > > Fixes: 1cf7e834a6fb ("xfs: switch to multigrain timestamps")
> > > Suggested-by: Jeff Layton <jlayton@kernel.org>
> > > Signed-off-by: Frederick Lawler <fred@cloudflare.com>
> > > ---
> > > The motivation behind this was that file systems that use the
> > > cookie to set the i_version for stacked file systems may still do so.
> > > Then add in the ctime_guard as a fallback if there's a detected change.
> > > The assumption is that the ctime will be different if the i_version is
> > > different anyway for non-stacked file systems.
> > 
> > Agreed. This patch inverts the i_version test to return immediately if the
> > i_version hasn't changed and then checks the ctime guard value.  Is the ctime
> > guard value test simply a performance improvement?
> > 
> 
> Kinda. The thought was to make already-audited files that have an
> unchanged i_version since last audit succeed early.
> 
> Stacking tempfs on XFS for instance, would incur the stat cost each
> evaluation, since the cookie that used to set the i_version on
> evaluation with XFS on 6.12, is now always setting it to zero since 6.13.

So without this patch, there aren't any missing measurements, verifications, or
audit records.  Please clarify in the patch description that this is a
performance improvement.

> 
> > > 
> > > I'm not too pleased with passing in struct file* to
> > > integrity_inode_attrs_changed() since EVM doesn't currently use
> > > that for now, but I couldn't come up with another idea to get the
> > > stat without coming up with a new stat function to accommodate just
> > > the file path, fully separate out IMA/EVM checks, or lastly add stacked
> > > file system support to EVM (which doesn't make much sense to me
> > > at the moment).
> > > 
> > > I plan on adding in self test infrastructure for the v1, but I would
> > > like to get some early feedback on the approach first.
> > 
> > I really appreciate your adding a self test.
> > 
> 
> I was poking around last week at some testing platforms, and instead of
> adding to kernel sefltests & setup a VM etc..., to instead add to 
> Linux Test Project (LTP) if that's fine?

That's perfect.

> 
> In any case, I can add my test snippet to v1, so you have something
> to review with the patch. That snippet works the same on 6.12 as it
> does on 6.19 with this patch.

Thanks!

^ permalink raw reply

* Re: [PATCH RFC] ima: Fallback to a ctime guard without i_version updates
From: Frederick Lawler @ 2026-01-05 23:09 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: <4a4778ff395e533cad86ff3ffbf0ba90c3eb8798.camel@linux.ibm.com>

Hi Mimi,

On Mon, Jan 05, 2026 at 05:15:15PM -0500, Mimi Zohar wrote:
> On Mon, 2025-12-29 at 11:52 -0600, Frederick Lawler wrote:
> > Since commit 1cf7e834a6fb ("xfs: switch to multigrain timestamps"), IMA
> > is no longer able to correctly track inode.i_version due to the struct
> > kstat.change_cookie no longer containing an updated i_version.
> > 
> > Introduce a fallback mechanism for IMA that instead tracks a
> > integrity_ctime_guard() in absence of or outdated i_version
> > for stacked file systems.
> 
> Thanks, Frederick.
> 
> Instead of using the new function name integrity_ctime_guard() to describe the
> change, please describe the change in words.  Perhaps something like: rely on
> the inode's ctime to detect a file data or metadata change.
> 

Sure thing, I'll change for the v1.

> The purpose of generating a ctime guard value, as opposed to using the tv_sec
> and tv_nsec, I assume is to minimize the amount of memory being saved in the
> iint.

This was Jeff's suggestion. It does serve the purpose on saving
some memory, but also has some value in the event nsec or sec is zero'd.
It just needs to be different enough from the last cache'd evaluation.

> 
> > 
> > EVM is left alone since it mostly cares about the backing inode.
> > 
> > Link: https://lore.kernel.org/all/aTspr4_h9IU4EyrR@CMGLRV3
> > Fixes: 1cf7e834a6fb ("xfs: switch to multigrain timestamps")
> > Suggested-by: Jeff Layton <jlayton@kernel.org>
> > Signed-off-by: Frederick Lawler <fred@cloudflare.com>
> > ---
> > The motivation behind this was that file systems that use the
> > cookie to set the i_version for stacked file systems may still do so.
> > Then add in the ctime_guard as a fallback if there's a detected change.
> > The assumption is that the ctime will be different if the i_version is
> > different anyway for non-stacked file systems.
> 
> Agreed. This patch inverts the i_version test to return immediately if the
> i_version hasn't changed and then checks the ctime guard value.  Is the ctime
> guard value test simply a performance improvement?
> 

Kinda. The thought was to make already-audited files that have an
unchanged i_version since last audit succeed early.

Stacking tempfs on XFS for instance, would incur the stat cost each
evaluation, since the cookie that used to set the i_version on
evaluation with XFS on 6.12, is now always setting it to zero since 6.13.

> > 
> > I'm not too pleased with passing in struct file* to
> > integrity_inode_attrs_changed() since EVM doesn't currently use
> > that for now, but I couldn't come up with another idea to get the
> > stat without coming up with a new stat function to accommodate just
> > the file path, fully separate out IMA/EVM checks, or lastly add stacked
> > file system support to EVM (which doesn't make much sense to me
> > at the moment).
> > 
> > I plan on adding in self test infrastructure for the v1, but I would
> > like to get some early feedback on the approach first.
> 
> I really appreciate your adding a self test.
>

I was poking around last week at some testing platforms, and instead of
adding to kernel sefltests & setup a VM etc..., to instead add to 
Linux Test Project (LTP) if that's fine?

In any case, I can add my test snippet to v1, so you have something
to review with the patch. That snippet works the same on 6.12 as it
does on 6.19 with this patch.

> thanks,
> 
> Mimi

^ permalink raw reply

* Re: [PATCH RFC] ima: Fallback to a ctime guard without i_version updates
From: Mimi Zohar @ 2026-01-05 22:15 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: <20251229-xfs-ima-fixup-v1-1-6a717c939f7c@cloudflare.com>

On Mon, 2025-12-29 at 11:52 -0600, Frederick Lawler wrote:
> Since commit 1cf7e834a6fb ("xfs: switch to multigrain timestamps"), IMA
> is no longer able to correctly track inode.i_version due to the struct
> kstat.change_cookie no longer containing an updated i_version.
> 
> Introduce a fallback mechanism for IMA that instead tracks a
> integrity_ctime_guard() in absence of or outdated i_version
> for stacked file systems.

Thanks, Frederick.

Instead of using the new function name integrity_ctime_guard() to describe the
change, please describe the change in words.  Perhaps something like: rely on
the inode's ctime to detect a file data or metadata change.

The purpose of generating a ctime guard value, as opposed to using the tv_sec
and tv_nsec, I assume is to minimize the amount of memory being saved in the
iint.

> 
> EVM is left alone since it mostly cares about the backing inode.
> 
> Link: https://lore.kernel.org/all/aTspr4_h9IU4EyrR@CMGLRV3
> Fixes: 1cf7e834a6fb ("xfs: switch to multigrain timestamps")
> Suggested-by: Jeff Layton <jlayton@kernel.org>
> Signed-off-by: Frederick Lawler <fred@cloudflare.com>
> ---
> The motivation behind this was that file systems that use the
> cookie to set the i_version for stacked file systems may still do so.
> Then add in the ctime_guard as a fallback if there's a detected change.
> The assumption is that the ctime will be different if the i_version is
> different anyway for non-stacked file systems.

Agreed. This patch inverts the i_version test to return immediately if the
i_version hasn't changed and then checks the ctime guard value.  Is the ctime
guard value test simply a performance improvement?

> 
> I'm not too pleased with passing in struct file* to
> integrity_inode_attrs_changed() since EVM doesn't currently use
> that for now, but I couldn't come up with another idea to get the
> stat without coming up with a new stat function to accommodate just
> the file path, fully separate out IMA/EVM checks, or lastly add stacked
> file system support to EVM (which doesn't make much sense to me
> at the moment).
> 
> I plan on adding in self test infrastructure for the v1, but I would
> like to get some early feedback on the approach first.

I really appreciate your adding a self test.

thanks,

Mimi

^ permalink raw reply

* Re: [PATCH v2 00/17] tee: Use bus callbacks instead of driver callbacks
From: Jens Wiklander @ 2026-01-05  9:16 UTC (permalink / raw)
  To: Alexandre Belloni
  Cc: Uwe Kleine-König, Jonathan Corbet, Sumit Garg,
	Olivia Mackall, Herbert Xu, Clément Léger,
	Ard Biesheuvel, Maxime Coquelin, Alexandre Torgue, Sumit Garg,
	Ilias Apalodimas, Jan Kiszka, Sudeep Holla, Christophe JAILLET,
	Rafał Miłecki, Michael Chan, Pavan Chebbi,
	James Bottomley, Jarkko Sakkinen, Mimi Zohar, David Howells,
	Paul Moore, James Morris, Serge E. Hallyn, Peter Huewe, op-tee,
	linux-kernel, linux-doc, linux-crypto, linux-rtc, linux-efi,
	linux-stm32, linux-arm-kernel, Cristian Marussi, arm-scmi,
	linux-mips, netdev, linux-integrity, keyrings,
	linux-security-module, Jason Gunthorpe
In-Reply-To: <CAHUa44GpW5aO26GDyL9RZub9vVYvVcJ7etwO0yXBN_mUi0W4AA@mail.gmail.com>

Hi,

On Thu, Dec 18, 2025 at 5:29 PM Jens Wiklander
<jens.wiklander@linaro.org> wrote:
>
> On Thu, Dec 18, 2025 at 2:53 PM Alexandre Belloni
> <alexandre.belloni@bootlin.com> wrote:
> >
> > On 18/12/2025 08:21:27+0100, Jens Wiklander wrote:
> > > Hi,
> > >
> > > On Mon, Dec 15, 2025 at 3:17 PM Uwe Kleine-König
> > > <u.kleine-koenig@baylibre.com> wrote:
> > > >
> > > > Hello,
> > > >
> > > > the objective of this series is to make tee driver stop using callbacks
> > > > in struct device_driver. These were superseded by bus methods in 2006
> > > > (commit 594c8281f905 ("[PATCH] Add bus_type probe, remove, shutdown
> > > > methods.")) but nobody cared to convert all subsystems accordingly.
> > > >
> > > > Here the tee drivers are converted. The first commit is somewhat
> > > > unrelated, but simplifies the conversion (and the drivers). It
> > > > introduces driver registration helpers that care about setting the bus
> > > > and owner. (The latter is missing in all drivers, so by using these
> > > > helpers the drivers become more correct.)
> > > >
> > > > v1 of this series is available at
> > > > https://lore.kernel.org/all/cover.1765472125.git.u.kleine-koenig@baylibre.com
> > > >
> > > > Changes since v1:
> > > >
> > > >  - rebase to v6.19-rc1 (no conflicts)
> > > >  - add tags received so far
> > > >  - fix whitespace issues pointed out by Sumit Garg
> > > >  - fix shutdown callback to shutdown and not remove
> > > >
> > > > As already noted in v1's cover letter, this series should go in during a
> > > > single merge window as there are runtime warnings when the series is
> > > > only applied partially. Sumit Garg suggested to apply the whole series
> > > > via Jens Wiklander's tree.
> > > > If this is done the dependencies in this series are honored, in case the
> > > > plan changes: Patches #4 - #17 depend on the first two.
> > > >
> > > > Note this series is only build tested.
> > > >
> > > > Uwe Kleine-König (17):
> > > >   tee: Add some helpers to reduce boilerplate for tee client drivers
> > > >   tee: Add probe, remove and shutdown bus callbacks to tee_client_driver
> > > >   tee: Adapt documentation to cover recent additions
> > > >   hwrng: optee - Make use of module_tee_client_driver()
> > > >   hwrng: optee - Make use of tee bus methods
> > > >   rtc: optee: Migrate to use tee specific driver registration function
> > > >   rtc: optee: Make use of tee bus methods
> > > >   efi: stmm: Make use of module_tee_client_driver()
> > > >   efi: stmm: Make use of tee bus methods
> > > >   firmware: arm_scmi: optee: Make use of module_tee_client_driver()
> > > >   firmware: arm_scmi: Make use of tee bus methods
> > > >   firmware: tee_bnxt: Make use of module_tee_client_driver()
> > > >   firmware: tee_bnxt: Make use of tee bus methods
> > > >   KEYS: trusted: Migrate to use tee specific driver registration
> > > >     function
> > > >   KEYS: trusted: Make use of tee bus methods
> > > >   tpm/tpm_ftpm_tee: Make use of tee specific driver registration
> > > >   tpm/tpm_ftpm_tee: Make use of tee bus methods
> > > >
> > > >  Documentation/driver-api/tee.rst             | 18 +----
> > > >  drivers/char/hw_random/optee-rng.c           | 26 ++----
> > > >  drivers/char/tpm/tpm_ftpm_tee.c              | 31 +++++---
> > > >  drivers/firmware/arm_scmi/transports/optee.c | 32 +++-----
> > > >  drivers/firmware/broadcom/tee_bnxt_fw.c      | 30 ++-----
> > > >  drivers/firmware/efi/stmm/tee_stmm_efi.c     | 25 ++----
> > > >  drivers/rtc/rtc-optee.c                      | 27 ++-----
> > > >  drivers/tee/tee_core.c                       | 84 ++++++++++++++++++++
> > > >  include/linux/tee_drv.h                      | 12 +++
> > > >  security/keys/trusted-keys/trusted_tee.c     | 17 ++--
> > > >  10 files changed, 164 insertions(+), 138 deletions(-)
> > > >
> > > > base-commit: 8f0b4cce4481fb22653697cced8d0d04027cb1e8
> > > > --
> > > > 2.47.3
> > > >
> > >
> > > Thank you for the nice cleanup, Uwe.
> > >
> > > I've applied patch 1-3 to the branch tee_bus_callback_for_6.20 in my
> > > tree at https://git.kernel.org/pub/scm/linux/kernel/git/jenswi/linux-tee.git/
> > >
> > > The branch is based on v6.19-rc1, and I'll try to keep it stable for
> > > others to depend on, if needed. Let's see if we can agree on taking
> > > the remaining patches via that branch.
> >
> > 6 and 7 can go through your branch.
>
> Good, I've added them to my branch now.

This entire patch set should go in during a single merge window. I
will not send any pull request until I'm sure all patches will be
merged.

So far (if I'm not mistaken), only the patches I've already added to
next have appeared next. I can take the rest of the patches, too, but
I need OK for the following:

Jarkko, you seem happy with the following patches
- KEYS: trusted: Migrate to use tee specific driver registration function
- KEYS: trusted: Make use of tee bus methods
- tpm/tpm_ftpm_tee: Make use of tee specific driver registration
- tpm/tpm_ftpm_tee: Make use of tee bus methods
OK if I take them via my tree, or would you rather take them yourself?

Herbert, you seem happy with the following patches
- hwrng: optee - Make use of module_tee_client_driver()
- hwrng: optee - Make use of tee bus methods
OK if I take them via my tree, or would you rather take them yourself?

Sudeep, you seem happy with the following patches
- firmware: arm_scmi: optee: Make use of module_tee_client_driver()
- firmware: arm_scmi: Make use of tee bus methods
OK if I take them via my tree, or would you rather take them yourself?

Michael, Pavan, are you OK with the following patches
- firmware: tee_bnxt: Make use of module_tee_client_driver()
- firmware: tee_bnxt: Make use of tee bus methods
OK if I take them via my tree, or would you rather take them yourself?

Thanks,
Jens

^ permalink raw reply

* Re: [PATCH v15 19/28] x86/tpm: Early TPM PCR extending driver
From: Dave Hansen @ 2026-01-03 20:44 UTC (permalink / raw)
  To: Daniel P. Smith, Ross Philipson, linux-kernel, x86,
	linux-integrity, linux-doc, linux-crypto, kexec, linux-efi, iommu
  Cc: tglx, mingo, bp, hpa, dave.hansen, ardb, mjg59, James.Bottomley,
	peterhuewe, jarkko, jgg, luto, nivedita, herbert, davem, corbet,
	ebiederm, dwmw2, baolu.lu, kanth.ghatraju, andrew.cooper3,
	trenchboot-devel
In-Reply-To: <62227ed3-3804-4795-93c9-ce2bbad3f2a7@apertussolutions.com>

On 12/19/25 13:26, Daniel P. Smith wrote:
...
>> I also seem to remember that there are special rules around the US
>> federal government's inability to hold copyrights. This seems worth at
>> least a mention ... somewhere.
> 
> IANAL either, but in general the safest/correct approach is to retain
> any CRs placed on the code being reused, and the above is the CR on the
> source from the Xen tree.

Yeah, in general, that's a good thing to do.

But I'm puzzled by your response. Are you making an attempt to justify
the past choice to copy the copyrights verbatim? Or are you declining to
follow my request to involve your companies' legal experts given that
you used the "safest/correct approach"?

FWIW, I don't think what you did was bad here. You _did_ use a quite
reasonable approach in the case that a copyright was copied verbatim
from an existing legitimate* project.

 * I'll give Xen the benefit of the doubt just this one time and put it
   in the "legitimate" bucket. :P

^ permalink raw reply

* Re: [RFC][PATCH v2 2/2] ima: measure buffer sent to securityfs policy file
From: Enrico  Bravi @ 2026-01-03 15:21 UTC (permalink / raw)
  To: roberto.sassu@huawei.com, linux-integrity@vger.kernel.org,
	zohar@linux.ibm.com, dmitry.kasatkin@gmail.com
  Cc: eric.snowberg@oracle.com
In-Reply-To: <1878eed2d61b7fe3879c6d911ae709ef08089f16.camel@linux.ibm.com>

On Mon, 2025-12-22 at 09:01 -0500, Mimi Zohar wrote:
> Hi Enrico,
> 
> On Tue, 2025-12-16 at 17:56 +0100, Enrico Bravi wrote:
> > When signed a policy is not mandatory, it is possile to write the IMA
> > policy directly on the corresponding securityfs file:
> > 
> > echo -e "measure func=BPRM_CHECK mask=MAY_EXEC\n" \
> >         "audit func=BPRM_CHECK mask=MAY_EXEC\n" \
> >      > /sys/kernel/security/ima/policy
> > 
> > Add input buffer measurement that can be caught when 'measure
> > func=POLICY_CHECK' is enabled (e.g., ima_policy=tcb).
> > 
> > Suggested-by: Roberto Sassu <roberto.sassu@huawei.com>
> > Signed-off-by: Enrico Bravi <enrico.bravi@polito.it>
> > ---
> >  security/integrity/ima/ima.h      |  1 +
> >  security/integrity/ima/ima_fs.c   |  1 +
> >  security/integrity/ima/ima_main.c | 38 +++++++++++++++++++++++++++++++
> >  3 files changed, 40 insertions(+)
> > 
> > diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
> > index ca7b96663623..3b00c298355b 100644
> > --- a/security/integrity/ima/ima.h
> > +++ b/security/integrity/ima/ima.h
> > @@ -426,6 +426,7 @@ void *ima_policy_next(struct seq_file *m, void *v,
> > loff_t *pos);
> >  void ima_policy_stop(struct seq_file *m, void *v);
> >  int ima_policy_show(struct seq_file *m, void *v);
> >  void ima_measure_loaded_policy(void);
> > +int ima_measure_policy_write(char *buf, size_t size);
> >  
> >  /* Appraise integrity measurements */
> >  #define IMA_APPRAISE_ENFORCE 0x01
> > diff --git a/security/integrity/ima/ima_fs.c
> > b/security/integrity/ima/ima_fs.c
> > index 89946d803d44..f1a5edd060ad 100644
> > --- a/security/integrity/ima/ima_fs.c
> > +++ b/security/integrity/ima/ima_fs.c
> > @@ -362,6 +362,7 @@ static ssize_t ima_write_policy(struct file *file, const
> > char __user *buf,
> >       1, 0);
> >   result = -EACCES;
> >   } else {
> > + ima_measure_policy_write(data, datalen);
> >   result = ima_parse_add_rule(data);
> >   }
> >   mutex_unlock(&ima_write_mutex);
> > diff --git a/security/integrity/ima/ima_main.c
> > b/security/integrity/ima/ima_main.c
> > index cdd225f65a62..6a8ad4714881 100644
> > --- a/security/integrity/ima/ima_main.c
> > +++ b/security/integrity/ima/ima_main.c
> > @@ -28,6 +28,7 @@
> >  #include <linux/iversion.h>
> >  #include <linux/evm.h>
> >  #include <linux/crash_dump.h>
> > +#include <linux/shmem_fs.h>
> >  
> >  #include "ima.h"
> >  
> > @@ -986,6 +987,43 @@ static int ima_post_load_data(char *buf, loff_t size,
> >   return 0;
> >  }
> >  
> > +/**
> > + * ima_measure_policy_write - Measure the policy write buffer
> > + * @buf: pointer to the buffer containing the policy write data
> > + * @size: size of the buffer
> > + *
> > + * Measure the buffer sent to the IMA policy securityfs file.
> > + *
> > + * Return 0 on success, a negative value otherwise.
> > + */
> > +int ima_measure_policy_write(char *buf, size_t size0
> > +{
> > + static const char op[] = "measure_ima_policy_write";
> > + const char *file_name = "ima_write_policy_buffer";
> > + static char *audit_cause = "ENOMEM";
> > + struct file *policy_file = NULL;
> > + struct lsm_prop prop;
> > + int ret = 0;
> > +
> > + policy_file = shmem_kernel_file_setup(file_name, 0, 0);
> > + if (IS_ERR(policy_file)) {
> > + ret = PTR_ERR(policy_file);
> > + audit_cause = "alloc_file";
> > + integrity_audit_msg(AUDIT_INTEGRITY_PCR, NULL, "ima_policy_write",
> > +     op, audit_cause, ret, 1);
> > + goto out;
> > + }
> > +
> > + security_current_getlsmprop_subj(&prop);
> > +
> > + ret = process_measurement(policy_file, current_cred(), &prop, buf, size,
> > +   MAY_READ, POLICY_CHECK);
> 
> The purpose of this patch is to measure IMA policy rules as they're written to
> the <securityfs> IMA policy file, based on the IMA "measure func=POLICY_CHECK"
> policy rule.
> 
> Like critical data, it should be calling process_buffer_measurement(), not
> process_measurement().
> 
> The functions ima_match_rules() and ima_match_rule_data() need to be updated
> to support POLICY_CHECK.

Hi Mimi,

ok sure, I can switch to process_buffer_measurement().

> This function naming is off and should be renamed to ima_measure_policy_buf().
> 
> Please update the patch description accordingly.

Will do.

Thanks again for your feedback.

Enrico

> Mimi
> 
> > + fput(policy_file);
> > +
> > +out:
> > + return ret;
> > +}
> > +
> >  /**
> >   * process_buffer_measurement - Measure the buffer or the buffer data hash
> >   * @idmap: idmap of the mount the inode was found from

^ permalink raw reply

* Re: [RFC][PATCH v2 1/2] ima: measure loaded policy after write on securityfs policy file
From: Enrico  Bravi @ 2026-01-03 15:18 UTC (permalink / raw)
  To: roberto.sassu@huawei.com, linux-integrity@vger.kernel.org,
	zohar@linux.ibm.com, dmitry.kasatkin@gmail.com
  Cc: eric.snowberg@oracle.com
In-Reply-To: <8808db9a7abcc3299b688537d19d53310be5c17e.camel@linux.ibm.com>

On Fri, 2025-12-19 at 14:13 -0500, Mimi Zohar wrote:
> On Tue, 2025-12-16 at 17:56 +0100, Enrico Bravi wrote:
> > IMA policy can be written multiple times in the securityfs policy file
> > at runtime if CONFIG_IMA_WRITE_POLICY=y. When IMA_APPRAISE_POLICY is
> > required, the policy needs to be signed to be loaded, writing the absolute
> > path of the file containing the new policy:
> > 
> > echo /path/of/custom_ima_policy > /sys/kernel/security/ima/policy
> > 
> > When this is not required, policy can be written directly, rule by rule:
> > 
> > echo -e "measure func=BPRM_CHECK mask=MAY_EXEC\n" \
> >         "audit func=BPRM_CHECK mask=MAY_EXEC\n" \
> >      > /sys/kernel/security/ima/policy
> > 
> > In this case, a new policy can be loaded without being measured or
> > appraised.
> > 
> > Add a new critical data record to measure the textual policy
> > representation when it becomes effective.

Hi Mimi,

sorry for the delay in answering you.

> The IMA policy could be really large.  Do we really want to include all the
> policy rules in the template data?  The other option would be to include a
> hash of the policy rules, in lieu of the policy rules themselves.

I thought to include all the policy rules because the policy can be defined
using the same rules in a different order. For large policy this would mean that
a verifier should have several hash values for the same policy.

> Please include directions for verifying the critical-data (e.g. using xxd).

Yes, sure.

> > 
> > Signed-off-by: Enrico Bravi <enrico.bravi@polito.it>
> > ---
> >  security/integrity/ima/ima.h        |  1 +
> >  security/integrity/ima/ima_efi.c    |  1 +
> >  security/integrity/ima/ima_fs.c     |  1 +
> >  security/integrity/ima/ima_policy.c | 63 ++++++++++++++++++++++++++++-
> >  4 files changed, 64 insertions(+), 2 deletions(-)
> > 
> > diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
> > index e3d71d8d56e3..ca7b96663623 100644
> > --- a/security/integrity/ima/ima.h
> > +++ b/security/integrity/ima/ima.h
> > @@ -425,6 +425,7 @@ void *ima_policy_start(struct seq_file *m, loff_t *pos);
> >  void *ima_policy_next(struct seq_file *m, void *v, loff_t *pos);
> >  void ima_policy_stop(struct seq_file *m, void *v);
> >  int ima_policy_show(struct seq_file *m, void *v);
> > +void ima_measure_loaded_policy(void);
> >  
> >  /* Appraise integrity measurements */
> >  #define IMA_APPRAISE_ENFORCE 0x01
> > diff --git a/security/integrity/ima/ima_efi.c
> > b/security/integrity/ima/ima_efi.c
> > index 138029bfcce1..199c42d0f8b3 100644
> > --- a/security/integrity/ima/ima_efi.c
> > +++ b/security/integrity/ima/ima_efi.c
> > @@ -62,6 +62,7 @@ static const char * const sb_arch_rules[] = {
> >   "appraise func=POLICY_CHECK appraise_type=imasig",
> >  #endif
> >   "measure func=MODULE_CHECK",
> > + "measure func=CRITICAL_DATA label=ima_policy",
> 
> With this rule, the policy will always be measured, even when loading a signed
> policy file.  It that necessary?

No you're right. I can include it only in the case the policy is not apprised.

> >   NULL
> >  };
> >  
> > diff --git a/security/integrity/ima/ima_fs.c
> > b/security/integrity/ima/ima_fs.c
> > index 87045b09f120..89946d803d44 100644
> > --- a/security/integrity/ima/ima_fs.c
> > +++ b/security/integrity/ima/ima_fs.c
> > @@ -476,6 +476,7 @@ static int ima_release_policy(struct inode *inode,
> > struct file *file)
> >   }
> >  
> >   ima_update_policy();
> > + ima_measure_loaded_policy();
> >  #if !defined(CONFIG_IMA_WRITE_POLICY) && !defined(CONFIG_IMA_READ_POLICY)
> >   securityfs_remove(file->f_path.dentry);
> >  #elif defined(CONFIG_IMA_WRITE_POLICY)
> > diff --git a/security/integrity/ima/ima_policy.c
> > b/security/integrity/ima/ima_policy.c
> > index 128fab897930..956063748008 100644
> > --- a/security/integrity/ima/ima_policy.c
> > +++ b/security/integrity/ima/ima_policy.c
> > @@ -17,6 +17,7 @@
> >  #include <linux/slab.h>
> >  #include <linux/rculist.h>
> >  #include <linux/seq_file.h>
> > +#include <linux/vmalloc.h>
> >  #include <linux/ima.h>
> >  
> >  #include "ima.h"
> > @@ -1983,7 +1984,6 @@ const char *const func_tokens[] = {
> >   __ima_hooks(__ima_hook_stringify)
> >  };
> >  
> > -#ifdef CONFIG_IMA_READ_POLICY
> >  enum {
> >   mask_exec = 0, mask_write, mask_read, mask_append
> >  };
> > @@ -2277,7 +2277,6 @@ int ima_policy_show(struct seq_file *m, void *v)
> >   seq_puts(m, "\n");
> >   return 0;
> >  }
> > -#endif /* CONFIG_IMA_READ_POLICY */
> >  
> >  #if defined(CONFIG_IMA_APPRAISE) &&
> > defined(CONFIG_INTEGRITY_TRUSTED_KEYRING)
> >  /*
> > @@ -2334,3 +2333,63 @@ bool ima_appraise_signature(enum kernel_read_file_id
> > id)
> >   return found;
> >  }
> >  #endif /* CONFIG_IMA_APPRAISE && CONFIG_INTEGRITY_TRUSTED_KEYRING */
> > +
> > +static size_t ima_policy_text_len(void)
> > +{
> > + struct list_head *ima_rules_tmp;
> > + struct ima_rule_entry *entry;
> > + struct seq_file file;
> > + size_t size = 0;
> > + char rule[255];
> > +
> > + file.buf = rule;
> > + file.read_pos = 0;
> > + file.size = 255;
> > + file.count = 0;
> > +
> > + rcu_read_lock();
> > + ima_rules_tmp = rcu_dereference(ima_rules);
> > + list_for_each_entry_rcu(entry, ima_rules_tmp, list) {
> > + ima_policy_show(&file, entry);
> > + size += file.count;
> > + file.count = 0;
> > + }
> > + rcu_read_unlock();
> > +
> > + return size;
> > +}
> > +
> > +void ima_measure_loaded_policy(void)
> > +{
> > + const char *event_name = "ima_policy_loaded";
> > + const char *op = "measure_loaded_ima_policy";
> > + const char *audit_cause = "ENOMEM";
> > + struct ima_rule_entry *rule_entry;
> > + struct list_head *ima_rules_tmp;
> > + struct seq_file file;
> > + int result = -ENOMEM;
> > + size_t file_len = ima_policy_text_len();
> 
> Normally a function is defined to prevent code duplication or for readability.
> In this case, it doesn't achieve either.

Ok, yes you're right. I'll move the ima_policy_text_len() code in
ima_measure_loaded_policy().

Thank you very much for your feedback.

Enrico

> Add a comment here, something like:
> /* calculate IMA policy rules memory size */
> 
> > +
> > + file.buf = vmalloc(file_len);
> > + if (!file.buf) {
> > + integrity_audit_msg(AUDIT_INTEGRITY_PCR, NULL, event_name,
> > +     op, audit_cause, result, 1);
> > + return;
> > + }
> > 
> > 
> 
> And another comment below, something like:
> /* copy IMA policy rules to a buffer */
> 
> > +
> > + file.read_pos = 0;
> > + file.size = file_len;
> > + file.count = 0;
> > +
> > + rcu_read_lock();
> > + ima_rules_tmp = rcu_dereference(ima_rules);
> > + list_for_each_entry_rcu(rule_entry, ima_rules_tmp, list) {
> > + ima_policy_show(&file, rule_entry);
> > + }
> > + rcu_read_unlock();
> > +
> > + ima_measure_critical_data("ima_policy", event_name, file.buf,
> > +   file.count, false, NULL, 0);
> > +
> > + vfree(file.buf);
> > +}
> 
> Thanks,
> 
> Mimi

^ permalink raw reply

* Re: [PATCH v2 6/6] docs: trusted-encryped: add PKWM as a new trust source
From: Mimi Zohar @ 2026-01-02 17:48 UTC (permalink / raw)
  To: Srish Srinivasan, linux-integrity, keyrings, linuxppc-dev
  Cc: maddy, mpe, npiggin, christophe.leroy, James.Bottomley, jarkko,
	nayna, rnsastry, linux-kernel, linux-security-module
In-Reply-To: <20251217172505.112398-7-ssrish@linux.ibm.com>

On Wed, 2025-12-17 at 22:55 +0530, Srish Srinivasan wrote:
> From: Nayna Jain <nayna@linux.ibm.com>
> 
> Update Documentation/security/keys/trusted-encrypted.rst and Documentation/
> admin-guide/kernel-parameters.txt with PowerVM Key Wrapping Module (PKWM)
> as a new trust source
> 
> Signed-off-by: Nayna Jain <nayna@linux.ibm.com>
> Signed-off-by: Srish Srinivasan <ssrish@linux.ibm.com>

Thanks, Nayna, Srish.

Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>



^ permalink raw reply

* Re: [PATCH v2 5/6] keys/trusted_keys: establish PKWM as a trusted source
From: Mimi Zohar @ 2026-01-02 17:44 UTC (permalink / raw)
  To: Srish Srinivasan, linux-integrity, keyrings, linuxppc-dev
  Cc: maddy, mpe, npiggin, christophe.leroy, James.Bottomley, jarkko,
	nayna, rnsastry, linux-kernel, linux-security-module
In-Reply-To: <20251217172505.112398-6-ssrish@linux.ibm.com>

On Wed, 2025-12-17 at 22:55 +0530, Srish Srinivasan wrote:
> The wrapping key does not exist by default and is generated by the
> hypervisor as a part of PKWM initialization. This key is then persisted by
> the hypervisor and is used to wrap trusted keys. These are variable length
> symmetric keys, which in the case of PowerVM Key Wrapping Module (PKWM) are
> generated using the kernel RNG. PKWM can be used as a trust source through
> the following example keyctl command

-> commands:

> 
> keyctl add trusted my_trusted_key "new 32" @u
> 
> Use the wrap_flags command option to set the secure boot requirement for
> the wrapping request through the following keyctl commands
> 
> case1: no secure boot requirement. (default)
> keyctl usage: keyctl add trusted my_trusted_key "new 32" @u
> 	      OR
> 	      keyctl add trusted my_trusted_key "new 32 wrap_flags=0x00" @u
> 
> case2: secure boot required to in either audit or enforce mode. set bit 0
> keyctl usage: keyctl add trusted my_trusted_key "new 32 wrap_flags=0x01" @u
> 
> case3: secure boot required to be in enforce mode. set bit 1
> keyctl usage: keyctl add trusted my_trusted_key "new 32 wrap_flags=0x02" @u
> 
> NOTE:
> -> Setting the secure boot requirement is NOT a must.
> -> Only either of the secure boot requirement options should be set. Not
> both.
> -> All the other bits are requied to be not set.

-> required

> -> Set the kernel parameter trusted.source=pkwm to choose PKWM as the
> backend for trusted keys implementation.
> -> CONFIG_PSERIES_PLPKS must be enabled to build PKWM.
> 
> Add PKWM, which is a combination of IBM PowerVM and Power LPAR Platform
> KeyStore, as a new trust source for trusted keys.
> 
> Signed-off-by: Srish Srinivasan <ssrish@linux.ibm.com>

Thanks, Srish.  Other than fixing the typo and other suggestion above,
Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>

^ permalink raw reply

* Re: [PATCH] tpm: st33zp24: Fix missing cleanup on get_burstcount() error
From: Jarkko Sakkinen @ 2026-01-02 17:29 UTC (permalink / raw)
  To: Alper Ak
  Cc: peterhuewe, Jason Gunthorpe, Stefano Garzarella,
	Christophe Ricard, linux-integrity, linux-kernel
In-Reply-To: <20251226120929.61630-1-alperyasinak1@gmail.com>

On Fri, Dec 26, 2025 at 03:09:27PM +0300, Alper Ak wrote:
> get_burstcount() can return -EBUSY on timeout. When this happens,
> st33zp24_send() returns directly without releasing the locality
> acquired earlier.
> 
> Use goto out_err to ensure proper cleanup when get_burstcount() fails.
> 
> Fixes: bf38b8710892 ("tpm/tpm_i2c_stm_st33: Split tpm_i2c_tpm_st33 in 2 layers (core + phy)")
> Signed-off-by: Alper Ak <alperyasinak1@gmail.com>
> ---
>  drivers/char/tpm/st33zp24/st33zp24.c | 6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/char/tpm/st33zp24/st33zp24.c b/drivers/char/tpm/st33zp24/st33zp24.c
> index 2ed7815e4899..e2b7451ea7cc 100644
> --- a/drivers/char/tpm/st33zp24/st33zp24.c
> +++ b/drivers/char/tpm/st33zp24/st33zp24.c
> @@ -328,8 +328,10 @@ static int st33zp24_send(struct tpm_chip *chip, unsigned char *buf,
>  
>  	for (i = 0; i < len - 1;) {
>  		burstcnt = get_burstcount(chip);
> -		if (burstcnt < 0)
> -			return burstcnt;
> +		if (burstcnt < 0) {
> +			ret = burstcnt;
> +			goto out_err;
> +		}
>  		size = min_t(int, len - i - 1, burstcnt);
>  		ret = tpm_dev->ops->send(tpm_dev->phy_id, TPM_DATA_FIFO,
>  					 buf + i, size);
> -- 
> 2.43.0
> 

Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>

BR, Jarkko

^ permalink raw reply

* Re: [PATCH v2 2/6] powerpc/pseries: move the PLPKS config inside its own sysfs directory
From: Mimi Zohar @ 2026-01-02 17:28 UTC (permalink / raw)
  To: Srish Srinivasan, linux-integrity, keyrings, linuxppc-dev
  Cc: maddy, mpe, npiggin, christophe.leroy, James.Bottomley, jarkko,
	nayna, rnsastry, linux-kernel, linux-security-module
In-Reply-To: <20251217172505.112398-3-ssrish@linux.ibm.com>

On Wed, 2025-12-17 at 22:55 +0530, Srish Srinivasan wrote:
> The /sys/firmware/secvar/config directory represents Power LPAR Platform
> KeyStore (PLPKS) configuration properties such as max_object_size, signed_
> update_algorithms, supported_policies, total_size, used_space, and version.
> These attributes describe the PLPKS, and not the secure boot variables
> (secvars).
> 
> Create /sys/firmware/plpks directory and move the PLPKS config inside this
> directory. For backwards compatibility, create a soft link from the secvar
> sysfs directory to this config and emit a warning stating that the older
> sysfs path has been deprecated. Separate out the plpks specific
> documentation from secvar.
> 
> Signed-off-by: Srish Srinivasan <ssrish@linux.ibm.com>

LGTM.

Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>

^ permalink raw reply

* Re: [PATCH] tpm: tpm_tis_spi: Initialize ret variable in tpm_tis_spi_transfer_half()
From: Jarkko Sakkinen @ 2026-01-02 17:28 UTC (permalink / raw)
  To: Alper Ak
  Cc: peterhuewe, Jason Gunthorpe, Krishna Yarlagadda, linux-integrity,
	linux-kernel
In-Reply-To: <20251226113505.53740-1-alperyasinak1@gmail.com>

On Fri, Dec 26, 2025 at 02:35:04PM +0300, Alper Ak wrote:
> When len is 0, the while loop in tpm_tis_spi_transfer_half() is never
> entered and the function returns an uninitialized ret variable.
> 
> Initialize ret to 0 to correctly handle this case. This is consistent
> with tpm_tis_spi_transfer_full(), which already initializes ret to 0
> before the loop.
> 
> Fixes: a86a42ac2bd6 ("tpm_tis_spi: Add hardware wait polling")
> Signed-off-by: Alper Ak <alperyasinak1@gmail.com>
> ---
>  drivers/char/tpm/tpm_tis_spi_main.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/char/tpm/tpm_tis_spi_main.c b/drivers/char/tpm/tpm_tis_spi_main.c
> index 61b42c83ced8..1b6d79662ca1 100644
> --- a/drivers/char/tpm/tpm_tis_spi_main.c
> +++ b/drivers/char/tpm/tpm_tis_spi_main.c
> @@ -85,7 +85,7 @@ static int tpm_tis_spi_transfer_half(struct tpm_tis_data *data,	u32 addr,
>  	struct spi_transfer spi_xfer[3];
>  	struct spi_message m;
>  	u8 transfer_len;
> -	int ret;
> +	int ret = 0;
>  
>  	while (len) {
>  		transfer_len = min_t(u16, len, MAX_SPI_FRAMESIZE);
> -- 
> 2.43.0
> 

OK, despite agreeing that 'ret' should be initialized I did not find a
call path where 'len' would end up being zero.

While acking the change in the sense that this function should be robust
enough to handle zero value for 'len', I'm just trying to figure out if
this is a regression from reproducability perspective, or just an 
improvement.

BR, Jarkko

^ permalink raw reply

* Re: [PATCH v2 4/6] pseries/plpks: add HCALLs for PowerVM Key Wrapping Module
From: Mimi Zohar @ 2026-01-02 17:25 UTC (permalink / raw)
  To: Srish Srinivasan, linux-integrity, keyrings, linuxppc-dev
  Cc: maddy, mpe, npiggin, christophe.leroy, James.Bottomley, jarkko,
	nayna, rnsastry, linux-kernel, linux-security-module
In-Reply-To: <20251217172505.112398-5-ssrish@linux.ibm.com>

Hi Srish,

On Wed, 2025-12-17 at 22:55 +0530, Srish Srinivasan wrote:
> The hypervisor generated wrapping key is an AES-GCM-256 symmetric key which
> is stored in a non-volatile, secure, and encrypted storage called the Power
> LPAR Platform KeyStore. It has policy based protections that prevent it
> from being read out or exposed to the user.
> 
> Implement H_PKS_GEN_KEY, H_PKS_WRAP_OBJECT, and H_PKS_UNWRAP_OBJECT HCALLs
> to enable using the PowerVM Key Wrapping Module (PKWM) as a new trust
> source for trusted keys. Disallow H_PKS_READ_OBJECT, H_PKS_SIGNED_UPDATE,
> and H_PKS_WRITE_OBJECT for objects with the 'wrapping key' policy set.
> Capture the availability status for the H_PKS_WRAP_OBJECT interface.
> 
> Signed-off-by: Srish Srinivasan <ssrish@linux.ibm.com>

scripts/checkpatch.pl --codespell caught a couple of typos.  Please fix the
typos here in in this patch and the one in v2 5/6.

> ---
>  Documentation/arch/powerpc/papr_hcalls.rst |  43 +++
>  arch/powerpc/include/asm/plpks.h           |  10 +
>  arch/powerpc/platforms/pseries/plpks.c     | 345 ++++++++++++++++++++-
>  3 files changed, 396 insertions(+), 2 deletions(-)
> 
> diff --git a/Documentation/arch/powerpc/papr_hcalls.rst b/Documentation/arch/powerpc/papr_hcalls.rst
> index 805e1cb9bab9..14e39f095a1c 100644
> --- a/Documentation/arch/powerpc/papr_hcalls.rst
> +++ b/Documentation/arch/powerpc/papr_hcalls.rst
> @@ -300,6 +300,49 @@ H_HTM supports setup, configuration, control and dumping of Hardware Trace
>  Macro (HTM) function and its data. HTM buffer stores tracing data for functions
>  like core instruction, core LLAT and nest.
>  
> +**H_PKS_GEN_KEY**
> +
> +| Input: authorization, objectlabel, objectlabellen, policy, out, outlen
> +| Out: *Hypervisor Generated Key, or None when the wrapping key policy is set*
> +| Return Value: *H_SUCCESS, H_Function, H_State, H_R_State, H_Parameter, H_P2,
> +                H_P3, H_P4, H_P5, H_P6, H_Authority, H_Nomem, H_Busy, H_Resource,
> +                H_Aborted*
> +
> +H_PKS_GEN_KEY is used to have the hypervisor generate a new random key.
> +This key is stored as an object in the Power LPAR Platform KeyStore with
> +the provided object label. With the wrapping key policy set the key is only
> +visible to the hypervisor, while the key's label would still be visible to
> +the user. Generation of wrapping keys is supported only for a key size of
> +32 bytes.
> +
> +**H_PKS_WRAP_OBJECT**
> +
> +| Input: authorization, wrapkeylabel, wrapkeylabellen, objectwrapflags, in,
> +|        inlen, out, outlen, continue-token
> +| Out: *continue-token, byte size of wrapped object, wrapped object*
> +| Return Value: *H_SUCCESS, H_Function, H_State, H_R_State, H_Parameter, H_P2,
> +                H_P3, H_P4, H_P5, H_P6, H_P7, H_P8, H_P9, H_Authority, H_Invalid_Key,
> +                H_NOT_FOUND, H_Busy, H_LongBusy, H_Aborted*
> +
> +H_PKS_WRAP_OBJECT is used to wrap an object using a wrapping key stored in the
> +Power LPAR Platform KeyStore and return the wrapped object to the caller. The
> +caller provides a label to a wrapping key with the 'wrapping key' policy set,
> +which must have been previously created with H_PKS_GEN_KEY. The provided object
> +is then encrypted with the wrapping key and additional metadata and the result
> +is returned to the caller.
> +
> +
> +**H_PKS_UNWRAP_OBJECT**
> +
> +| Input: authorization, objectwrapflags, in, inlen, out, outlen, continue-token
> +| Out: *continue-token, byte size of unwrapped object, unwrapped object*
> +| Return Value: *H_SUCCESS, H_Function, H_State, H_R_State, H_Parameter, H_P2,
> +                H_P3, H_P4, H_P5, H_P6, H_P7, H_Authority, H_Unsupported, H_Bad_Data,
> +                H_NOT_FOUND, H_Invalid_Key, H_Busy, H_LongBusy, H_Aborted*
> +
> +H_PKS_UNWRAP_OBJECT is used to unwrap an object that was previously warapped with
> +H_PKS_WRAP_OBJECT.
> +
>  References
>  ==========
>  .. [1] "Power Architecture Platform Reference"
> diff --git a/arch/powerpc/include/asm/plpks.h b/arch/powerpc/include/asm/plpks.h
> index 8f034588fdf7..e87f90e40d4e 100644
> --- a/arch/powerpc/include/asm/plpks.h
> +++ b/arch/powerpc/include/asm/plpks.h
> @@ -113,6 +113,16 @@ void plpks_early_init_devtree(void);
>  int plpks_populate_fdt(void *fdt);
>  
>  int plpks_config_create_softlink(struct kobject *from);
> +
> +bool plpks_wrapping_is_supported(void);
> +
> +int plpks_gen_wrapping_key(void);
> +
> +int plpks_wrap_object(u8 **input_buf, u32 input_len, u16 wrap_flags,
> +		      u8 **output_buf, u32 *output_len);
> +
> +int plpks_unwrap_object(u8 **input_buf, u32 input_len,
> +			u8 **output_buf, u32 *output_len);
>  #else // CONFIG_PSERIES_PLPKS
>  static inline bool plpks_is_available(void) { return false; }
>  static inline u16 plpks_get_passwordlen(void) { BUILD_BUG(); }
> diff --git a/arch/powerpc/platforms/pseries/plpks.c b/arch/powerpc/platforms/pseries/plpks.c
> index 4a08f51537c8..2ec04908b057 100644
> --- a/arch/powerpc/platforms/pseries/plpks.c
> +++ b/arch/powerpc/platforms/pseries/plpks.c
> @@ -9,6 +9,32 @@
>  
>  #define pr_fmt(fmt) "plpks: " fmt
>  
> +#define PLPKS_WRAPKEY_COMPONENT	"PLPKSWR"
> +#define PLPKS_WRAPKEY_NAME	"default-wrapping-key"
> +
> +/*
> + * To 4K align the {input, output} buffers to the {UN}WRAP H_CALLs
> + */
> +#define PLPKS_WRAPPING_BUF_ALIGN	4096
> +
> +/*
> + * To ensure the output buffer's length is at least 1024 bytes greater
> + * than the input buffer's length during the WRAP H_CALL
> + */
> +#define PLPKS_WRAPPING_BUF_DIFF	1024
> +
> +#define PLPKS_WRAP_INTERFACE_BIT	3
> +#define PLPKS_WRAPPING_KEY_LENGTH	32
> +
> +#define WRAPFLAG_BE_BIT_SET(be_bit) \
> +	BIT_ULL(63 - (be_bit))
> +
> +#define WRAPFLAG_BE_GENMASK(be_bit_hi, be_bit_lo) \
> +	GENMASK_ULL(63 - (be_bit_hi), 63 - (be_bit_lo))
> +
> +#define WRAPFLAG_BE_FIELD_PREP(be_bit_hi, be_bit_lo, val) \
> +	FIELD_PREP(WRAPFLAG_BE_GENMASK(be_bit_hi, be_bit_lo), (val))
> +
>  #include <linux/delay.h>
>  #include <linux/errno.h>
>  #include <linux/io.h>
> @@ -39,6 +65,7 @@ static u32 supportedpolicies;
>  static u32 maxlargeobjectsize;
>  static u64 signedupdatealgorithms;
>  static u64 wrappingfeatures;
> +static bool wrapsupport;
>  
>  struct plpks_auth {
>  	u8 version;
> @@ -283,6 +310,7 @@ static int _plpks_get_config(void)
>  	maxlargeobjectsize = be32_to_cpu(config->maxlargeobjectsize);
>  	signedupdatealgorithms = be64_to_cpu(config->signedupdatealgorithms);
>  	wrappingfeatures = be64_to_cpu(config->wrappingfeatures);
> +	wrapsupport = config->flags & PPC_BIT8(PLPKS_WRAP_INTERFACE_BIT);
>  
>  	// Validate that the numbers we get back match the requirements of the spec
>  	if (maxpwsize < 32) {
> @@ -614,6 +642,9 @@ int plpks_signed_update_var(struct plpks_var *var, u64 flags)
>  	if (!(var->policy & PLPKS_SIGNEDUPDATE))
>  		return -EINVAL;
>  
> +	if (var->policy & PLPKS_WRAPPINGKEY)
> +		return -EINVAL;
> +
>  	// Signed updates need the component to be NULL.
>  	if (var->component)
>  		return -EINVAL;
> @@ -696,6 +727,9 @@ int plpks_write_var(struct plpks_var var)
>  	if (var.policy & PLPKS_SIGNEDUPDATE)
>  		return -EINVAL;
>  
> +	if (var.policy & PLPKS_WRAPPINGKEY)
> +		return -EINVAL;
> +
>  	auth = construct_auth(PLPKS_OS_OWNER);
>  	if (IS_ERR(auth))
>  		return PTR_ERR(auth);
> @@ -790,6 +824,9 @@ static int plpks_read_var(u8 consumer, struct plpks_var *var)
>  	if (var->namelen > PLPKS_MAX_NAME_SIZE)
>  		return -EINVAL;
>  
> +	if (var->policy & PLPKS_WRAPPINGKEY)
> +		return -EINVAL;
> +
>  	auth = construct_auth(consumer);
>  	if (IS_ERR(auth))
>  		return PTR_ERR(auth);
> @@ -845,8 +882,312 @@ static int plpks_read_var(u8 consumer, struct plpks_var *var)
>  }
>  
>  /**
> - * plpks_read_os_var() - Fetch the data for the specified variable that is
> - * owned by the OS consumer.
> + * plpks_wrapping_is_supported() - Get the H_PKS_WRAP_OBJECT interface
> + * availability status for the LPAR.
> + *
> + * Successful execution of the H_PKS_GET_CONFIG HCALL during initialization
> + * sets bit 3 of the flags variable in the PLPKS config structure if the
> + * H_PKS_WRAP_OBJECT interface is supported.
> + *
> + * Returns: true if the H_PKS_WRAP_OBJECT interface is supported, false if not.
> + */
> +bool plpks_wrapping_is_supported(void)
> +{
> +	return wrapsupport;
> +}
> +
> +/**
> + * plpks_gen_wrapping_key() - Generate a new random key with the 'wrapping key'
> + * policy set.
> + *
> + * The H_PKS_GEN_KEY HCALL makes the hypervisor generate a new random key and
> + * store the key in a PLPKS object with the provided object label. With the
> + * 'wrapping key' policy set, only the label to the newly generated random key
> + * would be visible to the user.
> + *
> + * Possible reasons for the returned errno values:
> + *
> + * -ENXIO	if PLPKS is not supported
> + * -EIO		if PLPKS access is blocked due to the LPAR's state
> + *		if PLPKS modification is blocked due to the LPAR's state
> + *		if an error occurred while processing the request
> + * -EINVAL	if invalid authorization parameter
> + *		if invalid object label parameter
> + *		if invalid object label len parameter
> + *		if invalid or unsupported policy declaration
> + *		if invalid output buffer parameter
> + *		if invalid output buffer length parameter
> + * -EPERM	if access is denied
> + * -ENOMEM	if there is inadequate memory to perform this operation
> + * -EBUSY	if unable to handle the request
> + * -EEXIST	if the object label already exists
> + *
> + * Returns: On success 0 is returned, a negative errno if not.
> + */
> +int plpks_gen_wrapping_key(void)
> +{
> +	unsigned long retbuf[PLPAR_HCALL_BUFSIZE] = { 0 };
> +	struct plpks_auth *auth;
> +	struct label *label;
> +	int rc = 0, pseries_status = 0;
> +	struct plpks_var var = {
> +		.name = PLPKS_WRAPKEY_NAME,
> +		.namelen = strlen(var.name),
> +		.policy = PLPKS_WRAPPINGKEY,
> +		.os = PLPKS_VAR_LINUX,
> +		.component = PLPKS_WRAPKEY_COMPONENT
> +	};
> +
> +	auth = construct_auth(PLPKS_OS_OWNER);
> +	if (IS_ERR(auth))
> +		return PTR_ERR(auth);
> +
> +	label = construct_label(var.component, var.os, var.name, var.namelen);
> +	if (IS_ERR(label)) {
> +		rc = PTR_ERR(label);
> +		goto out;
> +	}
> +
> +	rc = plpar_hcall(H_PKS_GEN_KEY, retbuf,
> +			 virt_to_phys(auth), virt_to_phys(label),
> +			 label->size, var.policy,
> +			 NULL, PLPKS_WRAPPING_KEY_LENGTH);
> +
> +	if (!rc)
> +		rc = plpks_confirm_object_flushed(label, auth);
> +
> +	pseries_status = rc;
> +	rc = pseries_status_to_err(rc);
> +
> +	if (rc && rc != -EEXIST) {
> +		pr_err("H_PKS_GEN_KEY failed.");
> +		pr_err("pseries_status = %d, error code = %d", pseries_status,
> +		       rc);
> +	} else {
> +		rc = 0;
> +	}
> +
> +	kfree(label);
> +out:
> +	kfree(auth);
> +	return rc;
> +}
> +EXPORT_SYMBOL_GPL(plpks_gen_wrapping_key);
> +
> +/**
> + * plpks_wrap_object() - Wrap an object using the default wrapping key stored in
> + * the PLPKS.
> + * @input_buf: buffer containing the data to be wrapped
> + * @input_len: length of the input buffer
> + * @wrap_flags: object wrapping flags
> + * @output_buf: buffer to store the wrapped data
> + * @output_len: length of the output buffer
> + *
> + * The H_PKS_WRAP_OBJECT HCALL wraps an object using a wrapping key stored in
> + * the PLPKS and returns the wrapped object to the caller. The caller provides a
> + * label to the wrapping key with the 'wrapping key' policy set that must have
> + * been previously created with the H_PKS_GEN_KEY HCALL. The provided object is
> + * then encrypted with the wrapping key and additional metadata and the result
> + * is returned to the user. The metadata includes the wrapping algorithm and the
> + * wrapping key name so those parameters are not required during unwrap.
> + *
> + * Possible reasons for the returned errno values:
> + *
> + * -ENXIO	if PLPKS is not supported
> + * -EIO		if PLPKS access is blocked due to the LPAR's state
> + *		if PLPKS modification is blocked due to the LPAR's state
> + *		if an error occurred while processing the request
> + * -EINVAL	if invalid authorization parameter
> + *		if invalid wraping key label parameter

-> wrapping 

> + *		if invalid wrapping key label length parameter
> + *		if invalid or unsupported object wrapping flags
> + *		if invalid inut buffer parameter

-> input
> + *		if invalid input buffer length parameter
> + *		if invalid output buffer parameter
> + *		if invalid output buffer length parameter
> + *		if invalid continue token parameter
> + *		if the wrapping key is not compatible with the wrapping
> + *		algorithm
> + * -EPERM	if access is denied
> + * -ENOENT	if the requested wrapping key was not found
> + * -EBUSY	if unable to handle the request or long running operation
> + *		initiated, retry later.
> + *
> + * Returns: On success 0 is returned, a negative errno if not.
> + */
> +int plpks_wrap_object(u8 **input_buf, u32 input_len, u16 wrap_flags,
> +		      u8 **output_buf, u32 *output_len)
> +{
> +	unsigned long retbuf[PLPAR_HCALL9_BUFSIZE] = { 0 };
> +	struct plpks_auth *auth;
> +	struct label *label;
> +	u64 continuetoken = 0;
> +	u64 objwrapflags = 0;
> +	int rc = 0, pseries_status = 0;
> +	bool sb_audit_or_enforce_bit = wrap_flags & BIT(0);
> +	bool sb_enforce_bit = wrap_flags & BIT(1);
> +	struct plpks_var var = {
> +		.name = PLPKS_WRAPKEY_NAME,
> +		.namelen = strlen(var.name),
> +		.os = PLPKS_VAR_LINUX,
> +		.component = PLPKS_WRAPKEY_COMPONENT
> +	};
> +
> +	auth = construct_auth(PLPKS_OS_OWNER);
> +	if (IS_ERR(auth))
> +		return PTR_ERR(auth);
> +
> +	label = construct_label(var.component, var.os, var.name, var.namelen);
> +	if (IS_ERR(label)) {
> +		rc = PTR_ERR(label);
> +		goto out;
> +	}
> +
> +	/* Set the consumer password requirement bit. A must have. */
> +	objwrapflags |= WRAPFLAG_BE_BIT_SET(3);
> +
> +	/* Set the wrapping algorithm bit. Just one algorithm option for now */
> +	objwrapflags |= WRAPFLAG_BE_FIELD_PREP(60, 63, 0x1);
> +
> +	if (sb_audit_or_enforce_bit & sb_enforce_bit) {
> +		pr_err("Cannot set both audit/enforce and enforce bits.");
> +		rc = -EINVAL;
> +		goto out_free_label;
> +	} else if (sb_audit_or_enforce_bit) {
> +		objwrapflags |= WRAPFLAG_BE_BIT_SET(1);
> +	} else if (sb_enforce_bit) {
> +		objwrapflags |= WRAPFLAG_BE_BIT_SET(2);
> +	}
> +
> +	*output_len = input_len + PLPKS_WRAPPING_BUF_DIFF;
> +
> +	*output_buf = kzalloc(ALIGN(*output_len, PLPKS_WRAPPING_BUF_ALIGN),
> +			      GFP_KERNEL);
> +	if (!(*output_buf)) {
> +		pr_err("Output buffer allocation failed. Returning -ENOMEM.");
> +		rc = -ENOMEM;
> +		goto out_free_label;
> +	}
> +
> +	do {
> +		rc = plpar_hcall9(H_PKS_WRAP_OBJECT, retbuf,
> +				  virt_to_phys(auth), virt_to_phys(label),
> +				  label->size, objwrapflags,
> +				  virt_to_phys(*input_buf), input_len,
> +				  virt_to_phys(*output_buf), *output_len,
> +				  continuetoken);
> +
> +		continuetoken = retbuf[0];
> +		pseries_status = rc;
> +		rc = pseries_status_to_err(rc);
> +	} while (rc == -EBUSY);
> +
> +	if (rc) {
> +		pr_err("H_PKS_WRAP_OBJECT failed.");
> +		pr_err("pseries_status = %d, return code = %d", pseries_status,
> +		       rc);
> +		kfree(*output_buf);
> +		*output_buf = NULL;
> +	} else {
> +		*output_len = retbuf[1];
> +	}
> +
> +out_free_label:
> +	kfree(label);
> +out:
> +	kfree(auth);
> +	return rc;
> +}
> +EXPORT_SYMBOL_GPL(plpks_wrap_object);
> +
> +/**
> + * plpks_unwrap_object() - Unwrap an object using the default wrapping key
> + * stored in the PLPKS.
> + * @input_buf: buffer containing the data to be unwrapped
> + * @input_len: length of the input buffer
> + * @output_buf: buffer to store the unwrapped data
> + * @output_len: length of the output buffer
> + *
> + * The H_PKS_UNWRAP_OBJECT HCALL unwraps an object that was previously wrapped
> + * using the H_PKS_WRAP_OBJECT HCALL.
> + *
> + * Possible reasons for the returned errno values:
> + *
> + * -ENXIO	if PLPKS is not supported
> + * -EIO		if PLPKS access is blocked due to the LPAR's state
> + *		if PLPKS modification is blocked due to the LPAR's state
> + *		if an error occurred while processing the request
> + * -EINVAL	if invalid authorization parameter
> + *		if invalid or unsupported object unwrapping flags
> + *		if invalid inut buffer parameter

-> input 

> + *		if invalid input buffer length parameter
> + *		if invalid output buffer parameter
> + *		if invalid output buffer length parameter
> + *		if invalid continue token parameter
> + *		if the wrapping key is not compatible with the wrapping
> + *		algorithm
> + *		if the wrapped object's format is not supported
> + *		if the wrapped object is invalid
> + * -EPERM	if access is denied
> + * -ENOENT	if the wrapping key for the provided object was not found
> + * -EBUSY	if unable to handle the request or long running operation
> + *		initiated, retry later.
> + *
> + * Returns: On success 0 is returned, a negative errno if not.
> + */
> +int plpks_unwrap_object(u8 **input_buf, u32 input_len, u8 **output_buf,
> +			u32 *output_len)
> +{
> +	unsigned long retbuf[PLPAR_HCALL9_BUFSIZE] = { 0 };
> +	struct plpks_auth *auth;
> +	u64 continuetoken = 0;
> +	u64 objwrapflags = 0;
> +	int rc = 0, pseries_status = 0;
> +
> +	auth = construct_auth(PLPKS_OS_OWNER);
> +	if (IS_ERR(auth))
> +		return PTR_ERR(auth);
> +
> +	*output_len = input_len - PLPKS_WRAPPING_BUF_DIFF;
> +	*output_buf = kzalloc(ALIGN(*output_len, PLPKS_WRAPPING_BUF_ALIGN),
> +			      GFP_KERNEL);
> +	if (!(*output_buf)) {
> +		pr_err("Output buffer allocation failed. Returning -ENOMEM.");
> +		rc = -ENOMEM;
> +		goto out;
> +	}
> +
> +	do {
> +		rc = plpar_hcall9(H_PKS_UNWRAP_OBJECT, retbuf,
> +				  virt_to_phys(auth), objwrapflags,
> +				  virt_to_phys(*input_buf), input_len,
> +				  virt_to_phys(*output_buf), *output_len,
> +				  continuetoken);
> +
> +		continuetoken = retbuf[0];
> +		pseries_status = rc;
> +		rc = pseries_status_to_err(rc);
> +	} while (rc == -EBUSY);
> +
> +	if (rc) {
> +		pr_err("H_PKS_UNWRAP_OBJECT failed.");
> +		pr_err("pseries_status = %d, return code = %d", pseries_status,
> +		       rc);
> +		kfree(*output_buf);
> +		*output_buf = NULL;
> +	} else {
> +		*output_len = retbuf[1];
> +	}
> +
> +out:
> +	kfree(auth);
> +	return rc;
> +}
> +EXPORT_SYMBOL_GPL(plpks_unwrap_object);
> +
> +/**
> + * plpks_read_os_var() - Fetch the data for the specified variable that is owned
> + * by the OS consumer.
>   * @var: variable to be read from the PLPKS
>   *
>   * The consumer or the owner of the object is the os kernel. The


^ permalink raw reply

* Re: [PATCH v2 1/6] pseries/plpks: fix kernel-doc comment inconsistencies
From: Mimi Zohar @ 2026-01-02 17:23 UTC (permalink / raw)
  To: Srish Srinivasan, linux-integrity, keyrings, linuxppc-dev
  Cc: maddy, mpe, npiggin, christophe.leroy, James.Bottomley, jarkko,
	nayna, rnsastry, linux-kernel, linux-security-module
In-Reply-To: <20251217172505.112398-2-ssrish@linux.ibm.com>

On Wed, 2025-12-17 at 22:55 +0530, Srish Srinivasan wrote:
> Fix issues with comments for all the applicable functions to be
> consistent with kernel-doc format. Move them before the function
> definition as opposed to the function prototype.
> 
> Signed-off-by: Srish Srinivasan <ssrish@linux.ibm.com>

Thanks Srish for moving and fixing the kernel documentation.

-- 
Mimi



^ permalink raw reply

* Re: [PATCH] tpm: tpm_i2c_infineon: Fix locality leak on get_burstcount() failure
From: Jarkko Sakkinen @ 2026-01-02 17:17 UTC (permalink / raw)
  To: Alper Ak
  Cc: peterhuewe, Jason Gunthorpe, Bryan Freed, Andi Shyti, Kent Yoder,
	Marcel Selhorst, linux-integrity, linux-kernel
In-Reply-To: <20251226102339.45054-1-alperyasinak1@gmail.com>

On Fri, Dec 26, 2025 at 01:23:38PM +0300, Alper Ak wrote:
> get_burstcount() can return -EBUSY on timeout. When this happens, the
> function returns directly without releasing the locality that was
> acquired at the beginning of tpm_tis_i2c_send().
> 
> Use goto out_err to ensure proper cleanup when get_burstcount() fails.
> 
> Fixes: aad628c1d91a ("char/tpm: Add new driver for Infineon I2C TIS TPM")
> Signed-off-by: Alper Ak <alperyasinak1@gmail.com>
> ---
>  drivers/char/tpm/tpm_i2c_infineon.c | 6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c
> index bdf1f329a679..8b7d32de0b2e 100644
> --- a/drivers/char/tpm/tpm_i2c_infineon.c
> +++ b/drivers/char/tpm/tpm_i2c_infineon.c
> @@ -544,8 +544,10 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t bufsiz,
>  		burstcnt = get_burstcount(chip);
>  
>  		/* burstcnt < 0 = TPM is busy */
> -		if (burstcnt < 0)
> -			return burstcnt;
> +		if (burstcnt < 0) {
> +			rc = burstcnt;
> +			goto out_err;
> +		}
>  
>  		if (burstcnt > (len - 1 - count))
>  			burstcnt = len - 1 - count;
> -- 
> 2.43.0
> 

Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>

BR, Jarkko

^ permalink raw reply

* Re: [PATCH] tpm: tpm2-space: Skip handle check when context load returns -ENOENT
From: Jarkko Sakkinen @ 2026-01-02 16:52 UTC (permalink / raw)
  To: Alper Ak
  Cc: peterhuewe, Jason Gunthorpe, James Bottomley, linux-integrity,
	linux-kernel
In-Reply-To: <20251226111217.50747-1-alperyasinak1@gmail.com>

On Fri, Dec 26, 2025 at 02:12:16PM +0300, Alper Ak wrote:
> When tpm2_load_context() returns -ENOENT, the session is marked as
> forgotten by setting session_tbl[i] to 0. Although tpm2_load_context()
> also sets handle to 0 in this case, the subsequent comparison
> "handle != space->session_tbl[i]" (0 != 0) is always false and serves
> no purpose.
> 
> Add continue to skip this unnecessary comparison when load fails with
> -ENOENT, making the control flow clearer and fix possible
> uninitialized 'handle' variable.
> 
> Fixes: 4d57856a21ed2 ("tpm2: add session handle context saving and restoring to the space code")
> Signed-off-by: Alper Ak <alperyasinak1@gmail.com>

There is no regression here.

> ---
>  drivers/char/tpm/tpm2-space.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2-space.c
> index 60354cd53b5c..7dfbe07ecf5b 100644
> --- a/drivers/char/tpm/tpm2-space.c
> +++ b/drivers/char/tpm/tpm2-space.c
> @@ -213,6 +213,7 @@ static int tpm2_load_space(struct tpm_chip *chip)
>  		if (rc == -ENOENT) {
>  			/* load failed, just forget session */
>  			space->session_tbl[i] = 0;
> +			continue;
>  		} else if (rc) {
>  			tpm2_flush_space(chip);
>  			return rc;
> -- 
> 2.43.0
> 

This really does nothing too useful to the code, which we really want
to be conservative to change to begin with.

BR, Jarkko

^ permalink raw reply

* Re: [PATCH v8 03/12] tpm: Orchestrate TPM commands in tpm_get_random()
From: Jarkko Sakkinen @ 2026-01-02 16:40 UTC (permalink / raw)
  To: Jonathan McDowell
  Cc: linux-integrity, Eric Biggers, Peter Huewe, Jason Gunthorpe,
	David Howells, Paul Moore, James Morris, Serge E. Hallyn,
	open list, open list:KEYS/KEYRINGS, open list:SECURITY SUBSYSTEM
In-Reply-To: <aUUeP5qhEISjythp@earth.li>

On Fri, Dec 19, 2025 at 09:43:27AM +0000, Jonathan McDowell wrote:
> On Tue, Dec 16, 2025 at 11:21:37AM +0200, Jarkko Sakkinen wrote:
> > tpm1_get_random() and tpm2_get_random() contain duplicate orchestration
> > code. Consolidate orchestration to tpm_get_random().
> 
> Does keeping the respective tpm1/tpm2 bits in their -cmd.c files not make
> more sense, still allowing for the consolidation of orchestration in
> tpm_get_random?

Yeah, especially after not paying attention to this for couple of weeks
this really feels like unnecessary. It would also reduce the overall
delta caused by these patches. I will take here step back and retain
the helpers in tpm1/tpm2-cmd.c files.

BR, Jarkko

^ permalink raw reply

* Re: [PATCH v8 04/12] tpm: Change tpm_get_random() opportunistic
From: Jarkko Sakkinen @ 2026-01-02 16:37 UTC (permalink / raw)
  To: Jonathan McDowell
  Cc: linux-integrity, David S . Miller, Herbert Xu, Eric Biggers,
	Peter Huewe, Jason Gunthorpe, David Howells, Paul Moore,
	James Morris, Serge E. Hallyn, open list, open list:KEYS/KEYRINGS,
	open list:SECURITY SUBSYSTEM
In-Reply-To: <aUUd760l89lrNOs-@earth.li>

On Fri, Dec 19, 2025 at 09:42:07AM +0000, Jonathan McDowell wrote:
> On Tue, Dec 16, 2025 at 11:21:38AM +0200, Jarkko Sakkinen wrote:
> > hwrng framework does not have a requirement that the all bytes requested
> > need to be provided. By enforcing such a requirement internally, TPM driver
> > can cause unpredictability in latency, as a single tpm_get_random() call
> > can result multiple TPM commands.
> > 
> > Especially, when TCG_TPM2_HMAC is enabled, extra roundtrips could have
> > significant effect to the system latency.
> > 
> > Thus, send TPM command only once and return bytes received instead of
> > committing to the number of requested bytes.
> 
> Function comment for tpm_get_random needs updated as well, as it currently
> says "until all of the @max bytes have been received", which is no longer
> true with this patch. With that:
> 
> Reviewed-by: Jonathan McDowell <noodles@meta.com>

Thank you and definitely can refine that comment. After holidays it is
probably to go through this patch set with time and send +1 iteration
:-)

BR, Jarkko

^ 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